diff options
Diffstat (limited to 'compiler/rustc_resolve')
| -rw-r--r-- | compiler/rustc_resolve/src/late/lifetimes.rs | 197 |
1 files changed, 86 insertions, 111 deletions
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 4e3e4f2c2bc..58d053aca1a 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -244,12 +244,7 @@ enum Scope<'a> { /// of the resulting opaque type. opaque_type_parent: bool, - /// True only if this `Binder` scope is from the quantifiers on a - /// `PolyTraitRef`. This is necessary for `associated_type_bounds`, which - /// requires binders of nested trait refs to be merged. - from_poly_trait_ref: bool, - - binder_depth: u32, + scope_type: BinderScopeType, /// The late bound vars for a given item are stored by `HirId` to be /// queried later. However, if we enter an elision scope, we have to @@ -335,6 +330,13 @@ enum Scope<'a> { Root, } +#[derive(Copy, Clone, Debug)] +enum BinderScopeType { + Other, + PolyTraitRef, + Concatenating, +} + // A helper struct for debugging scopes without printing parent scopes struct TruncatedScopeDebug<'a>(&'a Scope<'a>); @@ -346,8 +348,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { next_early_index, track_lifetime_uses, opaque_type_parent, - from_poly_trait_ref, - binder_depth, + scope_type, hir_id, s: _, } => f @@ -356,8 +357,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { .field("next_early_index", next_early_index) .field("track_lifetime_uses", track_lifetime_uses) .field("opaque_type_parent", opaque_type_parent) - .field("from_poly_trait_ref", from_poly_trait_ref) - .field("binder_depth", binder_depth) + .field("scope_type", scope_type) .field("hir_id", hir_id) .field("s", &"..") .finish(), @@ -622,48 +622,6 @@ fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty:: } } -impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { - fn depth(&self, concanetate: bool) -> u32 { - let mut passed_boundary = false; - let mut scope = self.scope; - loop { - match *scope { - Scope::Root => { - break 0; - } - - Scope::TraitRefBoundary { s, .. } => { - passed_boundary = true; - scope = s; - } - - Scope::Binder { binder_depth, from_poly_trait_ref, .. } => { - if concanetate && !passed_boundary && !from_poly_trait_ref { - bug!("{:?}", self.scope); - } - break if concanetate { - if passed_boundary || !from_poly_trait_ref { - binder_depth + 1 - } else { - binder_depth - } - } else { - binder_depth + 1 - }; - } - - Scope::Elision { s, .. } - | Scope::ObjectLifetimeDefault { s, .. } - | Scope::TraitRefHackInner { s, .. } - | Scope::Supertrait { s, .. } - | Scope::Body { s, .. } => { - scope = s; - } - } - } - } -} - impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { type Map = Map<'tcx>; @@ -721,8 +679,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: false, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, move |_old_scope, this| { intravisit::walk_fn(this, fk, fd, b, s, hir_id) @@ -847,8 +804,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index: index + non_lifetime_count, opaque_type_parent: true, track_lifetime_uses, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, s: ROOT_SCOPE, }; self.with(scope, |old_scope, this| { @@ -920,8 +876,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index, track_lifetime_uses: true, opaque_type_parent: false, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, |old_scope, this| { // a bare fn has no bounds, so everything @@ -1117,8 +1072,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: this.scope, track_lifetime_uses: true, opaque_type_parent: false, - from_poly_trait_ref: false, - binder_depth: this.depth(false), + scope_type: BinderScopeType::Other, }; this.with(scope, |_old_scope, this| { this.visit_generics(generics); @@ -1138,8 +1092,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: false, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, |_old_scope, this| { let scope = Scope::TraitRefBoundary { s: this.scope }; @@ -1198,8 +1151,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1268,8 +1220,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1373,29 +1324,28 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }) .unzip(); this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone()); - if !lifetimes.is_empty() { - let next_early_index = this.next_early_index(); - let scope = Scope::Binder { - hir_id: bounded_ty.hir_id, - lifetimes, - s: this.scope, - next_early_index, - track_lifetime_uses: true, - opaque_type_parent: false, - from_poly_trait_ref: true, - binder_depth: this.depth(false), - }; - this.with(scope, |old_scope, this| { - this.check_lifetime_params(old_scope, &bound_generic_params); - this.visit_ty(&bounded_ty); - this.trait_ref_hack = Some(bounded_ty.hir_id); - walk_list!(this, visit_param_bound, bounds); - this.trait_ref_hack = None; - }) - } else { + if !lifetimes.is_empty() { + let next_early_index = this.next_early_index(); + let scope = Scope::Binder { + hir_id: bounded_ty.hir_id, + lifetimes, + s: this.scope, + next_early_index, + track_lifetime_uses: true, + opaque_type_parent: false, + scope_type: BinderScopeType::PolyTraitRef, + }; + this.with(scope, |old_scope, this| { + this.check_lifetime_params(old_scope, &bound_generic_params); this.visit_ty(&bounded_ty); + this.trait_ref_hack = Some(bounded_ty.hir_id); walk_list!(this, visit_param_bound, bounds); - } + this.trait_ref_hack = None; + }) + } else { + this.visit_ty(&bounded_ty); + walk_list!(this, visit_param_bound, bounds); + } } &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { ref lifetime, @@ -1429,8 +1379,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index: self.next_early_index(), track_lifetime_uses: true, opaque_type_parent: false, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, |_, this| { intravisit::walk_param_bound(this, bound); @@ -1527,12 +1476,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { break vec![]; } - Scope::Binder { hir_id, from_poly_trait_ref, .. } => { - if !from_poly_trait_ref { - // We should only see super trait lifetimes if there is a `Binder` above - assert!(supertrait_lifetimes.is_empty()); - break vec![]; - } + Scope::Binder { hir_id, .. } => { // Nested poly trait refs have the binders concatenated let mut full_binders = self.map.late_bound_vars.entry(*hir_id).or_default().clone(); @@ -1569,6 +1513,33 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders); if trait_ref_hack.is_none() || has_lifetimes { + let scope_type = { + let mut scope = self.scope; + loop { + match *scope { + Scope::Root | Scope::TraitRefBoundary { .. } => { + break BinderScopeType::PolyTraitRef; + } + + Scope::Binder { scope_type, .. } => { + if let BinderScopeType::Other = scope_type { + bug!( + "Expected all syntacic poly trait refs to be surrounded by a `TraitRefBoundary`" + ) + } + break BinderScopeType::Concatenating; + } + + Scope::Elision { s, .. } + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::TraitRefHackInner { s, .. } + | Scope::Supertrait { s, .. } + | Scope::Body { s, .. } => { + scope = s; + } + } + } + }; let scope = Scope::Binder { hir_id: trait_ref.trait_ref.hir_ref_id, lifetimes, @@ -1576,8 +1547,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index, track_lifetime_uses: true, opaque_type_parent: false, - from_poly_trait_ref: true, - binder_depth: self.depth(true), + scope_type, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); @@ -2327,8 +2297,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { s: self.scope, opaque_type_parent: true, track_lifetime_uses: false, - from_poly_trait_ref: false, - binder_depth: self.depth(false), + scope_type: BinderScopeType::Other, }; self.with(scope, move |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -2386,7 +2355,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // given name or we run out of scopes. // search. let mut late_depth = 0; - let mut first_binder_depth = None; let mut scope = self.scope; let mut outermost_body = None; let result = loop { @@ -2404,7 +2372,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { break None; } - Scope::Binder { ref lifetimes, s, binder_depth, .. } => { + Scope::Binder { ref lifetimes, scope_type, s, .. } => { match lifetime_ref.name { LifetimeName::Param(param_name) => { if let Some(&def) = lifetimes.get(¶m_name.normalize_to_macros_2_0()) @@ -2414,8 +2382,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } _ => bug!("expected LifetimeName::Param"), } - first_binder_depth = first_binder_depth.or(Some(binder_depth)); - late_depth = first_binder_depth.unwrap_or(binder_depth) - binder_depth + 1; + match scope_type { + BinderScopeType::Other => late_depth += 1, + BinderScopeType::PolyTraitRef => late_depth += 1, + BinderScopeType::Concatenating => {} + } scope = s; } @@ -3126,7 +3097,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let span = lifetime_refs[0].span; let mut late_depth = 0; - let mut first_binder_depth = None; let mut scope = self.scope; let mut lifetime_names = FxHashSet::default(); let mut lifetime_spans = vec![]; @@ -3137,7 +3107,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Root => break None, - Scope::Binder { s, ref lifetimes, binder_depth, .. } => { + Scope::Binder { s, ref lifetimes, scope_type, .. } => { // collect named lifetimes for suggestions for name in lifetimes.keys() { if let hir::ParamName::Plain(name) = name { @@ -3145,8 +3115,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { lifetime_spans.push(name.span); } } - first_binder_depth = first_binder_depth.or(Some(binder_depth)); - late_depth = first_binder_depth.unwrap_or(binder_depth) - binder_depth + 1; + match scope_type { + BinderScopeType::Other => late_depth += 1, + BinderScopeType::PolyTraitRef => late_depth += 1, + BinderScopeType::Concatenating => {} + } scope = s; } @@ -3303,13 +3276,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) { debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref); let mut late_depth = 0; - let mut first_binder_depth = None; let mut scope = self.scope; let lifetime = loop { match *scope { - Scope::Binder { s, binder_depth, .. } => { - first_binder_depth = first_binder_depth.or(Some(binder_depth)); - late_depth = first_binder_depth.unwrap_or(binder_depth) - binder_depth + 1; + Scope::Binder { s, scope_type, .. } => { + match scope_type { + BinderScopeType::Other => late_depth += 1, + BinderScopeType::PolyTraitRef => late_depth += 1, + BinderScopeType::Concatenating => {} + } scope = s; } |
