diff options
| author | Jack Huey <jack.huey@umassmed.edu> | 2020-11-15 17:06:58 -0500 |
|---|---|---|
| committer | Jack Huey <jack.huey@umassmed.edu> | 2021-03-31 10:15:56 -0400 |
| commit | 666859a6f85a9ddad1e29de2daa4b8eef190c062 (patch) | |
| tree | 2da158ad955819854c184ad7ecd9c592a898e36a /compiler/rustc_resolve | |
| parent | 84f82d348c1b9d9c20579ded7e2dd2981ed454b9 (diff) | |
| download | rust-666859a6f85a9ddad1e29de2daa4b8eef190c062.tar.gz rust-666859a6f85a9ddad1e29de2daa4b8eef190c062.zip | |
Make late and late_anon regions track the bound var position
Diffstat (limited to 'compiler/rustc_resolve')
| -rw-r--r-- | compiler/rustc_resolve/src/late/lifetimes.rs | 114 |
1 files changed, 75 insertions, 39 deletions
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 698e5048f7b..8e0309225de 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -42,9 +42,9 @@ pub enum LifetimeUseSet<'tcx> { trait RegionExt { fn early(hir_map: &Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (ParamName, Region); - fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region); + fn late(index: u32, hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region); - fn late_anon(index: &Cell<u32>) -> Region; + fn late_anon(named_late_bound_vars: u32, anon_index: &Cell<u32>) -> Region; fn id(&self) -> Option<DefId>; @@ -67,7 +67,7 @@ impl RegionExt for Region { (param.name.normalize_to_macros_2_0(), Region::EarlyBound(i, def_id.to_def_id(), origin)) } - fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) { + fn late(idx: u32, hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) { let depth = ty::INNERMOST; let def_id = hir_map.local_def_id(param.hir_id); let origin = LifetimeDefOrigin::from_param(param); @@ -75,21 +75,24 @@ impl RegionExt for Region { "Region::late: param={:?} depth={:?} def_id={:?} origin={:?}", param, depth, def_id, origin, ); - (param.name.normalize_to_macros_2_0(), Region::LateBound(depth, def_id.to_def_id(), origin)) + ( + param.name.normalize_to_macros_2_0(), + Region::LateBound(depth, idx, def_id.to_def_id(), origin), + ) } - fn late_anon(index: &Cell<u32>) -> Region { + fn late_anon(named_late_bound_vars: u32, index: &Cell<u32>) -> Region { let i = index.get(); index.set(i + 1); let depth = ty::INNERMOST; - Region::LateBoundAnon(depth, i) + Region::LateBoundAnon(depth, named_late_bound_vars + i, i) } fn id(&self) -> Option<DefId> { match *self { Region::Static | Region::LateBoundAnon(..) => None, - Region::EarlyBound(_, id, _) | Region::LateBound(_, id, _) | Region::Free(_, id) => { + Region::EarlyBound(_, id, _) | Region::LateBound(_, _, id, _) | Region::Free(_, id) => { Some(id) } } @@ -97,11 +100,11 @@ impl RegionExt for Region { fn shifted(self, amount: u32) -> Region { match self { - Region::LateBound(debruijn, id, origin) => { - Region::LateBound(debruijn.shifted_in(amount), id, origin) + Region::LateBound(debruijn, idx, id, origin) => { + Region::LateBound(debruijn.shifted_in(amount), idx, id, origin) } - Region::LateBoundAnon(debruijn, index) => { - Region::LateBoundAnon(debruijn.shifted_in(amount), index) + Region::LateBoundAnon(debruijn, index, anon_index) => { + Region::LateBoundAnon(debruijn.shifted_in(amount), index, anon_index) } _ => self, } @@ -109,11 +112,11 @@ impl RegionExt for Region { fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region { match self { - Region::LateBound(debruijn, id, origin) => { - Region::LateBound(debruijn.shifted_out_to_binder(binder), id, origin) + Region::LateBound(debruijn, index, id, origin) => { + Region::LateBound(debruijn.shifted_out_to_binder(binder), index, id, origin) } - Region::LateBoundAnon(debruijn, index) => { - Region::LateBoundAnon(debruijn.shifted_out_to_binder(binder), index) + Region::LateBoundAnon(debruijn, index, anon_index) => { + Region::LateBoundAnon(debruijn.shifted_out_to_binder(binder), index, anon_index) } _ => self, } @@ -225,6 +228,8 @@ enum Scope<'a> { /// of the resulting opaque type. opaque_type_parent: bool, + named_late_bound_vars: u32, + s: ScopeRef<'a>, }, @@ -266,6 +271,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { next_early_index, track_lifetime_uses, opaque_type_parent, + named_late_bound_vars, s: _, } => f .debug_struct("Binder") @@ -273,6 +279,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("named_late_bound_vars", named_late_bound_vars) .field("s", &"..") .finish(), Scope::Body { id, s: _ } => { @@ -294,8 +301,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { #[derive(Clone, Debug)] enum Elide { /// Use a fresh anonymous late-bound lifetime each time, by - /// incrementing the counter to generate sequential indices. - FreshLateAnon(Cell<u32>), + /// incrementing the counter to generate sequential indices. All + /// anonymous lifetimes must start *after* named bound vars. + FreshLateAnon(u32, Cell<u32>), /// Always use this one lifetime. Exact(Region), /// Less or more than one lifetime were found, error on unspecified. @@ -626,6 +634,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index: index + non_lifetime_count, opaque_type_parent: true, track_lifetime_uses, + named_late_bound_vars: 0, s: ROOT_SCOPE, }; self.with(scope, |old_scope, this| { @@ -676,9 +685,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { lifetimes: c .generic_params .iter() - .filter_map(|param| match param.kind { + .enumerate() + .filter_map(|(idx, param)| match param.kind { GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir(), param)) + Some(Region::late(idx as u32, &self.tcx.hir(), param)) } _ => None, }) @@ -687,6 +697,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index, track_lifetime_uses: true, opaque_type_parent: false, + named_late_bound_vars: c.generic_params.len() as u32, }; self.with(scope, |old_scope, this| { // a bare fn has no bounds, so everything @@ -721,7 +732,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // resolved the same as the `'_` in `&'_ Foo`. // // cc #48468 - self.resolve_elided_lifetimes(vec![lifetime]) + self.resolve_elided_lifetimes(&[lifetime]) } LifetimeName::Param(_) | LifetimeName::Static => { // If the user wrote an explicit name, use that. @@ -784,7 +795,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // well-supported at the moment, so this doesn't work. // In the future, this should be fixed and this error should be removed. let def = self.map.defs.get(&lifetime.hir_id).cloned(); - if let Some(Region::LateBound(_, def_id, _)) = def { + if let Some(Region::LateBound(_, _, def_id, _)) = def { if let Some(def_id) = def_id.as_local() { let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); // Ensure that the parent of the def is an item, not HRTB @@ -874,6 +885,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: this.scope, track_lifetime_uses: true, opaque_type_parent: false, + named_late_bound_vars: 0, }; this.with(scope, |_old_scope, this| { this.visit_generics(generics); @@ -889,6 +901,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: false, + named_late_bound_vars: 0, }; self.with(scope, |_old_scope, this| { this.visit_generics(generics); @@ -941,6 +954,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, + named_late_bound_vars: 0, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1003,6 +1017,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { s: self.scope, track_lifetime_uses: true, opaque_type_parent: true, + named_late_bound_vars: 0, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -1024,7 +1039,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { #[tracing::instrument(level = "debug", skip(self))] fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { if lifetime_ref.is_elided() { - self.resolve_elided_lifetimes(vec![lifetime_ref]); + self.resolve_elided_lifetimes(&[lifetime_ref]); return; } if lifetime_ref.is_static() { @@ -1087,9 +1102,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }) => { let lifetimes: FxHashMap<_, _> = bound_generic_params .iter() - .filter_map(|param| match param.kind { + .enumerate() + .filter_map(|(idx, param)| match param.kind { GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir(), param)) + Some(Region::late(idx as u32, &self.tcx.hir(), param)) } _ => None, }) @@ -1102,6 +1118,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index, track_lifetime_uses: true, opaque_type_parent: false, + named_late_bound_vars: bound_generic_params.len() as u32, }; let result = self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &bound_generic_params); @@ -1145,6 +1162,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, + named_late_bound_vars: 0, }; self.with(scope, |_, this| { intravisit::walk_param_bound(this, bound); @@ -1184,9 +1202,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { lifetimes: trait_ref .bound_generic_params .iter() - .filter_map(|param| match param.kind { + .enumerate() + .filter_map(|(idx, param)| match param.kind { GenericParamKind::Lifetime { .. } => { - Some(Region::late(&self.tcx.hir(), param)) + Some(Region::late(idx as u32, &self.tcx.hir(), param)) } _ => None, }) @@ -1195,6 +1214,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { next_early_index, track_lifetime_uses: true, opaque_type_parent: false, + named_late_bound_vars: trait_ref.bound_generic_params.len() as u32, }; self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); @@ -1715,7 +1735,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .values() .flat_map(|region| match region { Region::EarlyBound(_, def_id, _) - | Region::LateBound(_, def_id, _) + | Region::LateBound(_, _, def_id, _) | Region::Free(_, def_id) => Some(*def_id), Region::LateBoundAnon(..) | Region::Static => None, @@ -1886,13 +1906,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } let mut non_lifetime_count = 0; + let mut named_late_bound_vars = 0; let lifetimes = generics .params .iter() - .filter_map(|param| match param.kind { + .enumerate() + .filter_map(|(idx, param)| match param.kind { GenericParamKind::Lifetime { .. } => { if self.map.late_bound.contains(¶m.hir_id) { - Some(Region::late(&self.tcx.hir(), param)) + named_late_bound_vars += 1; + Some(Region::late(idx as u32, &self.tcx.hir(), param)) } else { Some(Region::early(&self.tcx.hir(), &mut index, param)) } @@ -1911,6 +1934,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { s: self.scope, opaque_type_parent: true, track_lifetime_uses: false, + named_late_bound_vars, }; self.with(scope, move |old_scope, this| { this.check_lifetime_params(old_scope, &generics.params); @@ -2025,7 +2049,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { if !self.trait_definition_only && self.is_in_fn_syntax { match def { Region::EarlyBound(_, _, LifetimeDefOrigin::InBand) - | Region::LateBound(_, _, LifetimeDefOrigin::InBand) => { + | Region::LateBound(_, _, _, LifetimeDefOrigin::InBand) => { struct_span_err!( self.tcx.sess, lifetime_ref.span, @@ -2046,6 +2070,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { | Region::LateBound( _, _, + _, LifetimeDefOrigin::ExplicitOrElided | LifetimeDefOrigin::Error, ) | Region::LateBoundAnon(..) @@ -2079,7 +2104,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } let mut elide_lifetimes = true; - let lifetimes = generic_args + let lifetimes: Vec<_> = generic_args .args .iter() .filter_map(|arg| match arg { @@ -2093,7 +2118,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }) .collect(); if elide_lifetimes { - self.resolve_elided_lifetimes(lifetimes); + self.resolve_elided_lifetimes(&lifetimes); } else { lifetimes.iter().for_each(|lt| self.visit_lifetime(lt)); } @@ -2261,7 +2286,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { inputs: &'tcx [hir::Ty<'tcx>], output: Option<&'tcx hir::Ty<'tcx>>, ) { - let arg_scope = Scope::Elision { elide: Elide::FreshLateAnon(Cell::new(0)), s: self.scope }; + debug!("visit_fn_like_elision: enter"); + let named_late_bound_vars = match *self.scope { + Scope::Binder { named_late_bound_vars, .. } => named_late_bound_vars, + Scope::Body { .. } => 0, + _ => bug!("{:?}", self.scope), + }; + let arg_scope = Scope::Elision { + elide: Elide::FreshLateAnon(named_late_bound_vars, Cell::new(0)), + s: self.scope, + }; self.with(arg_scope, |_, this| { for input in inputs { this.visit_ty(input); @@ -2516,7 +2550,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) { if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.hir_id) { match lifetime { - Region::LateBound(debruijn, _, _) | Region::LateBoundAnon(debruijn, _) + Region::LateBound(debruijn, _, _, _) + | Region::LateBoundAnon(debruijn, _, _) if debruijn < self.outer_index => { self.have_bound_regions = true; @@ -2530,7 +2565,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } - fn resolve_elided_lifetimes(&mut self, lifetime_refs: Vec<&'tcx hir::Lifetime>) { + fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) { debug!("resolve_elided_lifetimes(lifetime_refs={:?})", lifetime_refs); if lifetime_refs.is_empty() { @@ -2563,9 +2598,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Elision { ref elide, ref s, .. } => { let lifetime = match *elide { - Elide::FreshLateAnon(ref counter) => { + Elide::FreshLateAnon(named_late_bound_vars, ref counter) => { for lifetime_ref in lifetime_refs { - let lifetime = Region::late_anon(counter).shifted(late_depth); + let lifetime = Region::late_anon(named_late_bound_vars, counter) + .shifted(late_depth); self.insert_lifetime(lifetime_ref, lifetime); } return; @@ -2890,7 +2926,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // A lifetime only used in a fn argument could as well // be replaced with `'_`, as that would generate a // fresh name, too. - Scope::Elision { elide: Elide::FreshLateAnon(_), .. } => break true, + Scope::Elision { elide: Elide::FreshLateAnon(_, _), .. } => break true, // In the return type or other such place, `'_` is not // going to make a fresh name, so we cannot @@ -2919,7 +2955,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } Region::Free(_, def_id) - | Region::LateBound(_, def_id, _) + | Region::LateBound(_, _, def_id, _) | Region::EarlyBound(_, def_id, _) => { // A lifetime declared by the user. let track_lifetime_uses = self.track_lifetime_uses(); |
