summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_resolve/src/late/lifetimes.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_resolve/src/late/lifetimes.rs')
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs511
1 files changed, 111 insertions, 400 deletions
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index 94460e33d..4d9704617 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -11,23 +11,21 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefIdMap, LocalDefId};
+use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node};
use rustc_middle::bug;
use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_lifetime::*;
-use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
+use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
-use std::borrow::Cow;
use std::fmt;
-use std::mem::take;
trait RegionExt {
- fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region);
+ fn early(hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region);
fn late(index: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region);
@@ -36,19 +34,13 @@ trait RegionExt {
fn shifted(self, amount: u32) -> Region;
fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region;
-
- fn subst<'a, L>(self, params: L, map: &NamedRegionMap) -> Option<Region>
- where
- L: Iterator<Item = &'a hir::Lifetime>;
}
impl RegionExt for Region {
- fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region) {
- let i = *index;
- *index += 1;
+ fn early(hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region) {
let def_id = hir_map.local_def_id(param.hir_id);
- debug!("Region::early: index={} def_id={:?}", i, def_id);
- (def_id, Region::EarlyBound(i, def_id.to_def_id()))
+ debug!("Region::early: def_id={:?}", def_id);
+ (def_id, Region::EarlyBound(def_id.to_def_id()))
}
fn late(idx: u32, hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region) {
@@ -65,9 +57,7 @@ impl RegionExt for Region {
match *self {
Region::Static => None,
- Region::EarlyBound(_, id) | Region::LateBound(_, _, id) | Region::Free(_, id) => {
- Some(id)
- }
+ Region::EarlyBound(id) | Region::LateBound(_, _, id) | Region::Free(_, id) => Some(id),
}
}
@@ -88,17 +78,6 @@ impl RegionExt for Region {
_ => self,
}
}
-
- fn subst<'a, L>(self, mut params: L, map: &NamedRegionMap) -> Option<Region>
- where
- L: Iterator<Item = &'a hir::Lifetime>,
- {
- if let Region::EarlyBound(index, _) = self {
- params.nth(index as usize).and_then(|lifetime| map.defs.get(&lifetime.hir_id).cloned())
- } else {
- Some(self)
- }
- }
}
/// Maps the id of each lifetime reference to the lifetime decl
@@ -131,9 +110,6 @@ pub(crate) struct LifetimeContext<'a, 'tcx> {
/// be false if the `Item` we are resolving lifetimes for is not a trait or
/// we eventually need lifetimes resolve for trait items.
trait_definition_only: bool,
-
- /// Cache for cross-crate per-definition object lifetime defaults.
- xcrate_object_lifetime_defaults: DefIdMap<Vec<ObjectLifetimeDefault>>,
}
#[derive(Debug)]
@@ -147,25 +123,6 @@ enum Scope<'a> {
/// for diagnostics.
lifetimes: FxIndexMap<LocalDefId, Region>,
- /// if we extend this scope with another scope, what is the next index
- /// we should use for an early-bound region?
- next_early_index: u32,
-
- /// Whether or not this binder would serve as the parent
- /// binder for opaque types introduced within. For example:
- ///
- /// ```text
- /// fn foo<'a>() -> impl for<'b> Trait<Item = impl Trait2<'a>>
- /// ```
- ///
- /// Here, the opaque types we create for the `impl Trait`
- /// and `impl Trait2` references will both have the `foo` item
- /// as their parent. When we get to `impl Trait2`, we find
- /// that it is nested within the `for<>` binder -- this flag
- /// allows us to skip that when looking for the parent binder
- /// of the resulting opaque type.
- opaque_type_parent: bool,
-
scope_type: BinderScopeType,
/// The late bound vars for a given item are stored by `HirId` to be
@@ -245,19 +202,9 @@ struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
- Scope::Binder {
- lifetimes,
- next_early_index,
- opaque_type_parent,
- scope_type,
- hir_id,
- where_bound_origin,
- s: _,
- } => f
+ Scope::Binder { lifetimes, scope_type, hir_id, where_bound_origin, s: _ } => f
.debug_struct("Binder")
.field("lifetimes", lifetimes)
- .field("next_early_index", next_early_index)
- .field("opaque_type_parent", opaque_type_parent)
.field("scope_type", scope_type)
.field("hir_id", hir_id)
.field("where_bound_origin", where_bound_origin)
@@ -294,10 +241,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id),
is_late_bound_map,
- object_lifetime_defaults: |tcx, id| match tcx.hir().find_by_def_id(id) {
- Some(Node::Item(item)) => compute_object_lifetime_defaults(tcx, item),
- _ => None,
- },
+ object_lifetime_default,
late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id),
..*providers
@@ -334,7 +278,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
/// lifetimes into a single binder.) This requires us to resolve the
/// *trait definition* of `Sub`; basically just enough lifetime information
/// to look at the supertraits.
-#[tracing::instrument(level = "debug", skip(tcx))]
+#[instrument(level = "debug", skip(tcx))]
fn resolve_lifetimes_trait_definition(
tcx: TyCtxt<'_>,
local_def_id: LocalDefId,
@@ -345,7 +289,7 @@ fn resolve_lifetimes_trait_definition(
/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
/// You should not read the result of this query directly, but rather use
/// `named_region_map`, `is_late_bound_map`, etc.
-#[tracing::instrument(level = "debug", skip(tcx))]
+#[instrument(level = "debug", skip(tcx))]
fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> ResolveLifetimes {
convert_named_region_map(do_resolve(tcx, local_def_id, false))
}
@@ -363,7 +307,6 @@ fn do_resolve(
map: &mut named_region_map,
scope: ROOT_SCOPE,
trait_definition_only,
- xcrate_object_lifetime_defaults: Default::default(),
};
visitor.visit_item(item);
@@ -432,13 +375,6 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
item
}
-/// In traits, there is an implicit `Self` type parameter which comes before the generics.
-/// We have to account for this when computing the index of the other generic parameters.
-/// This function returns whether there is such an implicit parameter defined on the given item.
-fn sub_items_have_self_param(node: &hir::ItemKind<'_>) -> bool {
- matches!(*node, hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..))
-}
-
fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::BoundVariableKind {
match region {
Region::LateBound(_, _, def_id) => {
@@ -558,7 +494,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
- let next_early_index = self.next_early_index();
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
bound_generic_params
.iter()
@@ -576,8 +511,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
hir_id: e.hir_id,
lifetimes,
s: self.scope,
- next_early_index,
- opaque_type_parent: false,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
@@ -592,6 +525,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
+ #[instrument(level = "debug", skip(self))]
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
match &item.kind {
hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
@@ -603,7 +537,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
match item.kind {
hir::ItemKind::Fn(_, ref generics, _) => {
- self.visit_early_late(None, item.hir_id(), generics, |this| {
+ self.visit_early_late(item.hir_id(), generics, |this| {
intravisit::walk_item(this, item);
});
}
@@ -670,31 +604,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
| hir::ItemKind::TraitAlias(ref generics, ..)
| hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => {
// These kinds of items have only early-bound lifetime parameters.
- let mut index = if sub_items_have_self_param(&item.kind) {
- 1 // Self comes before lifetimes
- } else {
- 0
- };
- let mut non_lifetime_count = 0;
let lifetimes = generics
.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
- Some(Region::early(self.tcx.hir(), &mut index, param))
- }
- GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
- non_lifetime_count += 1;
- None
+ Some(Region::early(self.tcx.hir(), param))
}
+ GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
})
.collect();
self.map.late_bound_vars.insert(item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: item.hir_id(),
lifetimes,
- next_early_index: index + non_lifetime_count,
- opaque_type_parent: true,
scope_type: BinderScopeType::Normal,
s: ROOT_SCOPE,
where_bound_origin: None,
@@ -712,7 +635,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
match item.kind {
hir::ForeignItemKind::Fn(_, _, ref generics) => {
- self.visit_early_late(None, item.hir_id(), generics, |this| {
+ self.visit_early_late(item.hir_id(), generics, |this| {
intravisit::walk_foreign_item(this, item);
})
}
@@ -725,11 +648,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
- #[tracing::instrument(level = "debug", skip(self))]
+ #[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
match ty.kind {
hir::TyKind::BareFn(ref c) => {
- let next_early_index = self.next_early_index();
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) = c
.generic_params
.iter()
@@ -746,8 +668,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
hir_id: ty.hir_id,
lifetimes,
s: self.scope,
- next_early_index,
- opaque_type_parent: false,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
@@ -762,7 +682,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
let scope = Scope::TraitRefBoundary { s: self.scope };
self.with(scope, |this| {
for bound in bounds {
- this.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
+ this.visit_poly_trait_ref(bound);
}
});
match lifetime.name {
@@ -795,7 +715,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
};
self.with(scope, |this| this.visit_ty(&mt.ty));
}
- hir::TyKind::OpaqueDef(item_id, lifetimes) => {
+ hir::TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => {
// Resolve the lifetimes in the bounds to the lifetime defs in the generics.
// `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
// `type MyAnonTy<'b> = impl MyTrait<'b>;`
@@ -886,32 +806,23 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// We want to start our early-bound indices at the end of the parent scope,
// not including any parent `impl Trait`s.
- let mut index = self.next_early_index_for_opaque_type();
- debug!(?index);
-
let mut lifetimes = FxIndexMap::default();
- let mut non_lifetime_count = 0;
debug!(?generics.params);
for param in generics.params {
match param.kind {
GenericParamKind::Lifetime { .. } => {
- let (def_id, reg) = Region::early(self.tcx.hir(), &mut index, &param);
+ let (def_id, reg) = Region::early(self.tcx.hir(), &param);
lifetimes.insert(def_id, reg);
}
- GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
- non_lifetime_count += 1;
- }
+ GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
}
}
- let next_early_index = index + non_lifetime_count;
self.map.late_bound_vars.insert(ty.hir_id, vec![]);
let scope = Scope::Binder {
hir_id: ty.hir_id,
lifetimes,
- next_early_index,
s: self.scope,
- opaque_type_parent: false,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
@@ -929,43 +840,32 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
+ #[instrument(level = "debug", skip(self))]
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
use self::hir::TraitItemKind::*;
match trait_item.kind {
Fn(_, _) => {
- let tcx = self.tcx;
- self.visit_early_late(
- Some(tcx.hir().get_parent_item(trait_item.hir_id())),
- trait_item.hir_id(),
- &trait_item.generics,
- |this| intravisit::walk_trait_item(this, trait_item),
- );
+ self.visit_early_late(trait_item.hir_id(), &trait_item.generics, |this| {
+ intravisit::walk_trait_item(this, trait_item)
+ });
}
Type(bounds, ref ty) => {
let generics = &trait_item.generics;
- let mut index = self.next_early_index();
- debug!("visit_ty: index = {}", index);
- let mut non_lifetime_count = 0;
let lifetimes = generics
.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
- Some(Region::early(self.tcx.hir(), &mut index, param))
- }
- GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
- non_lifetime_count += 1;
- None
+ Some(Region::early(self.tcx.hir(), param))
}
+ GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
})
.collect();
self.map.late_bound_vars.insert(trait_item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: trait_item.hir_id(),
lifetimes,
- next_early_index: index + non_lifetime_count,
s: self.scope,
- opaque_type_parent: true,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
@@ -990,43 +890,30 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
+ #[instrument(level = "debug", skip(self))]
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
use self::hir::ImplItemKind::*;
match impl_item.kind {
- Fn(..) => {
- let tcx = self.tcx;
- self.visit_early_late(
- Some(tcx.hir().get_parent_item(impl_item.hir_id())),
- impl_item.hir_id(),
- &impl_item.generics,
- |this| intravisit::walk_impl_item(this, impl_item),
- );
- }
+ Fn(..) => self.visit_early_late(impl_item.hir_id(), &impl_item.generics, |this| {
+ intravisit::walk_impl_item(this, impl_item)
+ }),
TyAlias(ref ty) => {
let generics = &impl_item.generics;
- let mut index = self.next_early_index();
- let mut non_lifetime_count = 0;
- debug!("visit_ty: index = {}", index);
let lifetimes: FxIndexMap<LocalDefId, Region> = generics
.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
- Some(Region::early(self.tcx.hir(), &mut index, param))
- }
- GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => {
- non_lifetime_count += 1;
- None
+ Some(Region::early(self.tcx.hir(), param))
}
+ GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None,
})
.collect();
self.map.late_bound_vars.insert(ty.hir_id, vec![]);
let scope = Scope::Binder {
hir_id: ty.hir_id,
lifetimes,
- next_early_index: index + non_lifetime_count,
s: self.scope,
- opaque_type_parent: true,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
@@ -1046,7 +933,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
- #[tracing::instrument(level = "debug", skip(self))]
+ #[instrument(level = "debug", skip(self))]
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
match lifetime_ref.name {
hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),
@@ -1129,7 +1016,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
})
.unzip();
this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone());
- let next_early_index = this.next_early_index();
// Even if there are no lifetimes defined here, we still wrap it in a binder
// scope. If there happens to be a nested poly trait ref (an error), that
// will be `Concatenating` anyways, so we don't have to worry about the depth
@@ -1138,8 +1024,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
hir_id: bounded_ty.hir_id,
lifetimes,
s: this.scope,
- next_early_index,
- opaque_type_parent: false,
scope_type: BinderScopeType::Normal,
where_bound_origin: Some(origin),
};
@@ -1210,8 +1094,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
hir_id: *hir_id,
lifetimes: FxIndexMap::default(),
s: self.scope,
- next_early_index: self.next_early_index(),
- opaque_type_parent: false,
scope_type,
where_bound_origin: None,
};
@@ -1223,14 +1105,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
- fn visit_poly_trait_ref(
- &mut self,
- trait_ref: &'tcx hir::PolyTraitRef<'tcx>,
- _modifier: hir::TraitBoundModifier,
- ) {
+ fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) {
debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
- let next_early_index = self.next_early_index();
let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
let initial_bound_vars = binders.len() as u32;
@@ -1260,8 +1137,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
hir_id: trait_ref.trait_ref.hir_ref_id,
lifetimes,
s: self.scope,
- next_early_index,
- opaque_type_parent: false,
scope_type,
where_bound_origin: None,
};
@@ -1272,139 +1147,49 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
-fn compute_object_lifetime_defaults<'tcx>(
- tcx: TyCtxt<'tcx>,
- item: &hir::Item<'_>,
-) -> Option<&'tcx [ObjectLifetimeDefault]> {
- match item.kind {
- hir::ItemKind::Struct(_, ref generics)
- | hir::ItemKind::Union(_, ref generics)
- | hir::ItemKind::Enum(_, ref generics)
- | hir::ItemKind::OpaqueTy(hir::OpaqueTy {
- ref generics,
- origin: hir::OpaqueTyOrigin::TyAlias,
- ..
- })
- | hir::ItemKind::TyAlias(_, ref generics)
- | hir::ItemKind::Trait(_, _, ref generics, ..) => {
- let result = object_lifetime_defaults_for_item(tcx, generics);
-
- // Debugging aid.
- let attrs = tcx.hir().attrs(item.hir_id());
- if tcx.sess.contains_name(attrs, sym::rustc_object_lifetime_default) {
- let object_lifetime_default_reprs: String = result
- .iter()
- .map(|set| match *set {
- Set1::Empty => "BaseDefault".into(),
- Set1::One(Region::Static) => "'static".into(),
- Set1::One(Region::EarlyBound(mut i, _)) => generics
- .params
- .iter()
- .find_map(|param| match param.kind {
- GenericParamKind::Lifetime { .. } => {
- if i == 0 {
- return Some(param.name.ident().to_string().into());
- }
- i -= 1;
- None
- }
- _ => None,
- })
- .unwrap(),
- Set1::One(_) => bug!(),
- Set1::Many => "Ambiguous".into(),
- })
- .collect::<Vec<Cow<'static, str>>>()
- .join(",");
- tcx.sess.span_err(item.span, &object_lifetime_default_reprs);
- }
-
- Some(result)
- }
- _ => None,
- }
-}
-
-/// Scan the bounds and where-clauses on parameters to extract bounds
-/// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
-/// for each type parameter.
-fn object_lifetime_defaults_for_item<'tcx>(
- tcx: TyCtxt<'tcx>,
- generics: &hir::Generics<'_>,
-) -> &'tcx [ObjectLifetimeDefault] {
- fn add_bounds(set: &mut Set1<hir::LifetimeName>, bounds: &[hir::GenericBound<'_>]) {
- for bound in bounds {
- if let hir::GenericBound::Outlives(ref lifetime) = *bound {
- set.insert(lifetime.name.normalize_to_macros_2_0());
- }
- }
- }
-
- let process_param = |param: &hir::GenericParam<'_>| match param.kind {
- GenericParamKind::Lifetime { .. } => None,
+fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> ObjectLifetimeDefault {
+ debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
+ let param_def_id = param_def_id.expect_local();
+ let parent_def_id = tcx.local_parent(param_def_id);
+ let generics = tcx.hir().get_generics(parent_def_id).unwrap();
+ let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
+ let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
+
+ // Scan the bounds and where-clauses on parameters to extract bounds
+ // of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
+ // for each type parameter.
+ match param.kind {
GenericParamKind::Type { .. } => {
let mut set = Set1::Empty;
- let param_def_id = tcx.hir().local_def_id(param.hir_id);
- for predicate in generics.predicates {
- // Look for `type: ...` where clauses.
- let hir::WherePredicate::BoundPredicate(ref data) = *predicate else { continue };
-
+ // Look for `type: ...` where clauses.
+ for bound in generics.bounds_for_param(param_def_id) {
// Ignore `for<'a> type: ...` as they can change what
// lifetimes mean (although we could "just" handle it).
- if !data.bound_generic_params.is_empty() {
+ if !bound.bound_generic_params.is_empty() {
continue;
}
- let res = match data.bounded_ty.kind {
- hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => path.res,
- _ => continue,
- };
-
- if res == Res::Def(DefKind::TyParam, param_def_id.to_def_id()) {
- add_bounds(&mut set, &data.bounds);
+ for bound in bound.bounds {
+ if let hir::GenericBound::Outlives(ref lifetime) = *bound {
+ set.insert(lifetime.name.normalize_to_macros_2_0());
+ }
}
}
- Some(match set {
- Set1::Empty => Set1::Empty,
- Set1::One(name) => {
- if name == hir::LifetimeName::Static {
- Set1::One(Region::Static)
- } else {
- generics
- .params
- .iter()
- .filter_map(|param| match param.kind {
- GenericParamKind::Lifetime { .. } => {
- let param_def_id = tcx.hir().local_def_id(param.hir_id);
- Some((
- param_def_id,
- hir::LifetimeName::Param(param_def_id, param.name),
- ))
- }
- _ => None,
- })
- .enumerate()
- .find(|&(_, (_, lt_name))| lt_name == name)
- .map_or(Set1::Many, |(i, (def_id, _))| {
- Set1::One(Region::EarlyBound(i as u32, def_id.to_def_id()))
- })
- }
+ match set {
+ Set1::Empty => ObjectLifetimeDefault::Empty,
+ Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
+ Set1::One(hir::LifetimeName::Param(param_def_id, _)) => {
+ ObjectLifetimeDefault::Param(param_def_id.to_def_id())
}
- Set1::Many => Set1::Many,
- })
+ _ => ObjectLifetimeDefault::Ambiguous,
+ }
}
- GenericParamKind::Const { .. } => {
- // Generic consts don't impose any constraints.
- //
- // We still store a dummy value here to allow generic parameters
- // in an arbitrary order.
- Some(Set1::Empty)
+ _ => {
+ bug!("object_lifetime_default_raw must only be called on a type parameter")
}
- };
-
- tcx.arena.alloc_from_iter(generics.params.iter().filter_map(process_param))
+ }
}
impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
@@ -1413,20 +1198,17 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>),
{
let LifetimeContext { tcx, map, .. } = self;
- let xcrate_object_lifetime_defaults = take(&mut self.xcrate_object_lifetime_defaults);
let mut this = LifetimeContext {
tcx: *tcx,
map,
scope: &wrap_scope,
trait_definition_only: self.trait_definition_only,
- xcrate_object_lifetime_defaults,
};
- let span = tracing::debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
+ let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
{
let _enter = span.enter();
f(&mut this);
}
- self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults;
}
/// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
@@ -1449,30 +1231,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
/// ordering is not important there.
fn visit_early_late<F>(
&mut self,
- parent_id: Option<LocalDefId>,
hir_id: hir::HirId,
generics: &'tcx hir::Generics<'tcx>,
walk: F,
) where
F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
{
- // Find the start of nested early scopes, e.g., in methods.
- let mut next_early_index = 0;
- if let Some(parent_id) = parent_id {
- let parent = self.tcx.hir().expect_item(parent_id);
- if sub_items_have_self_param(&parent.kind) {
- next_early_index += 1; // Self comes before lifetimes
- }
- match parent.kind {
- hir::ItemKind::Trait(_, _, ref generics, ..)
- | hir::ItemKind::Impl(hir::Impl { ref generics, .. }) => {
- next_early_index += generics.params.len() as u32;
- }
- _ => {}
- }
- }
-
- let mut non_lifetime_count = 0;
let mut named_late_bound_vars = 0;
let lifetimes: FxIndexMap<LocalDefId, Region> = generics
.params
@@ -1484,16 +1248,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
named_late_bound_vars += 1;
Some(Region::late(late_bound_idx, self.tcx.hir(), param))
} else {
- Some(Region::early(self.tcx.hir(), &mut next_early_index, param))
+ Some(Region::early(self.tcx.hir(), param))
}
}
- GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
- non_lifetime_count += 1;
- None
- }
+ GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
})
.collect();
- let next_early_index = next_early_index + non_lifetime_count;
let binders: Vec<_> = generics
.params
@@ -1512,52 +1272,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
let scope = Scope::Binder {
hir_id,
lifetimes,
- next_early_index,
s: self.scope,
- opaque_type_parent: true,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
self.with(scope, walk);
}
- fn next_early_index_helper(&self, only_opaque_type_parent: bool) -> u32 {
- let mut scope = self.scope;
- loop {
- match *scope {
- Scope::Root => return 0,
-
- Scope::Binder { next_early_index, opaque_type_parent, .. }
- if (!only_opaque_type_parent || opaque_type_parent) =>
- {
- return next_early_index;
- }
-
- Scope::Binder { s, .. }
- | Scope::Body { s, .. }
- | Scope::Elision { s, .. }
- | Scope::ObjectLifetimeDefault { s, .. }
- | Scope::Supertrait { s, .. }
- | Scope::TraitRefBoundary { s, .. } => scope = s,
- }
- }
- }
-
- /// Returns the next index one would use for an early-bound-region
- /// if extending the current scope.
- fn next_early_index(&self) -> u32 {
- self.next_early_index_helper(true)
- }
-
- /// Returns the next index one would use for an `impl Trait` that
- /// is being converted into an opaque type alias `impl Trait`. This will be the
- /// next early index from the enclosing item, for the most
- /// part. See the `opaque_type_parent` field for more info.
- fn next_early_index_for_opaque_type(&self) -> u32 {
- self.next_early_index_helper(false)
- }
-
- #[tracing::instrument(level = "debug", skip(self))]
+ #[instrument(level = "debug", skip(self))]
fn resolve_lifetime_ref(
&mut self,
region_def_id: LocalDefId,
@@ -1638,7 +1360,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
return;
}
- // We may fail to resolve higher-ranked lifetimes that are mentionned by APIT.
+ // We may fail to resolve higher-ranked lifetimes that are mentioned by APIT.
// AST-based resolution does not care for impl-trait desugaring, which are the
// responibility of lowering. This may create a mismatch between the resolution
// AST found (`region_def_id`) which points to HRTB, and what HIR allows.
@@ -1679,17 +1401,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
);
}
+ #[instrument(level = "debug", skip(self))]
fn visit_segment_args(
&mut self,
res: Res,
depth: usize,
generic_args: &'tcx hir::GenericArgs<'tcx>,
) {
- debug!(
- "visit_segment_args(res={:?}, depth={:?}, generic_args={:?})",
- res, depth, generic_args,
- );
-
if generic_args.parenthesized {
self.visit_fn_like_elision(
generic_args.inputs(),
@@ -1707,13 +1425,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// Figure out if this is a type/trait segment,
// which requires object lifetime defaults.
- let parent_def_id = |this: &mut Self, def_id: DefId| {
- let def_key = this.tcx.def_key(def_id);
- DefId { krate: def_id.krate, index: def_key.parent.expect("missing parent") }
- };
let type_def_id = match res {
- Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(parent_def_id(self, def_id)),
- Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(parent_def_id(self, def_id)),
+ Res::Def(DefKind::AssocTy, def_id) if depth == 1 => Some(self.tcx.parent(def_id)),
+ Res::Def(DefKind::Variant, def_id) if depth == 0 => Some(self.tcx.parent(def_id)),
Res::Def(
DefKind::Struct
| DefKind::Union
@@ -1725,7 +1439,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
_ => None,
};
- debug!("visit_segment_args: type_def_id={:?}", type_def_id);
+ debug!(?type_def_id);
// Compute a vector of defaults, one for each type parameter,
// per the rules given in RFCs 599 and 1156. Example:
@@ -1763,55 +1477,52 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
};
let map = &self.map;
- let set_to_region = |set: &ObjectLifetimeDefault| match *set {
- Set1::Empty => {
+ let generics = self.tcx.generics_of(def_id);
+
+ // `type_def_id` points to an item, so there is nothing to inherit generics from.
+ debug_assert_eq!(generics.parent_count, 0);
+
+ let set_to_region = |set: ObjectLifetimeDefault| match set {
+ ObjectLifetimeDefault::Empty => {
if in_body {
None
} else {
Some(Region::Static)
}
}
- Set1::One(r) => {
- let lifetimes = generic_args.args.iter().filter_map(|arg| match arg {
- GenericArg::Lifetime(lt) => Some(lt),
+ ObjectLifetimeDefault::Static => Some(Region::Static),
+ ObjectLifetimeDefault::Param(param_def_id) => {
+ // This index can be used with `generic_args` since `parent_count == 0`.
+ let index = generics.param_def_id_to_index[&param_def_id] as usize;
+ generic_args.args.get(index).and_then(|arg| match arg {
+ GenericArg::Lifetime(lt) => map.defs.get(&lt.hir_id).copied(),
_ => None,
- });
- r.subst(lifetimes, map)
+ })
}
- Set1::Many => None,
+ ObjectLifetimeDefault::Ambiguous => None,
};
- if let Some(def_id) = def_id.as_local() {
- let id = self.tcx.hir().local_def_id_to_hir_id(def_id);
- self.tcx
- .object_lifetime_defaults(id.owner)
- .unwrap()
- .iter()
- .map(set_to_region)
- .collect()
- } else {
- let tcx = self.tcx;
- self.xcrate_object_lifetime_defaults
- .entry(def_id)
- .or_insert_with(|| {
- tcx.generics_of(def_id)
- .params
- .iter()
- .filter_map(|param| match param.kind {
- GenericParamDefKind::Type { object_lifetime_default, .. } => {
- Some(object_lifetime_default)
- }
- GenericParamDefKind::Const { .. } => Some(Set1::Empty),
- GenericParamDefKind::Lifetime => None,
- })
- .collect()
- })
- .iter()
- .map(set_to_region)
- .collect()
- }
+ generics
+ .params
+ .iter()
+ .filter_map(|param| {
+ match self.tcx.def_kind(param.def_id) {
+ // Generic consts don't impose any constraints.
+ //
+ // We still store a dummy value here to allow generic parameters
+ // in an arbitrary order.
+ DefKind::ConstParam => Some(ObjectLifetimeDefault::Empty),
+ DefKind::TyParam => Some(self.tcx.object_lifetime_default(param.def_id)),
+ // We may also get a `Trait` or `TraitAlias` because of how generics `Self` parameter
+ // works. Ignore it because it can't have a meaningful lifetime default.
+ DefKind::LifetimeParam | DefKind::Trait | DefKind::TraitAlias => None,
+ dk => bug!("unexpected def_kind {:?}", dk),
+ }
+ })
+ .map(set_to_region)
+ .collect()
});
- debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults);
+ debug!(?object_lifetime_defaults);
let mut i = 0;
for arg in generic_args.args {
@@ -1953,7 +1664,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
}
- #[tracing::instrument(level = "debug", skip(self))]
+ #[instrument(level = "debug", skip(self))]
fn visit_fn_like_elision(
&mut self,
inputs: &'tcx [hir::Ty<'tcx>],
@@ -2001,7 +1712,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth));
}
- #[tracing::instrument(level = "debug", skip(self))]
+ #[instrument(level = "debug", skip(self))]
fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
debug!(
node = ?self.tcx.hir().node_to_string(lifetime_ref.hir_id),
@@ -2112,7 +1823,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
// is, those would be potentially inputs to
// projections
if let Some(last_segment) = path.segments.last() {
- self.visit_path_segment(path.span, last_segment);
+ self.visit_path_segment(last_segment);
}
}