diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 7ae9709e4d6..90339f8ee2b 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -84,9 +84,6 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { generator_kind: None, task_context: None, current_item: None, - lifetimes_to_define: Default::default(), - is_collecting_anonymous_lifetimes: None, - in_scope_lifetimes: Vec::new(), captured_lifetimes: None, allow_try_trait: Some([sym::try_trait_v2][..].into()), allow_gen_future: Some([sym::gen_future][..].into()), @@ -149,36 +146,8 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { // This is used to track which lifetimes have already been defined, // and which need to be replicated when lowering an async fn. match parent_hir.node().expect_item().kind { - hir::ItemKind::Impl(hir::Impl { ref of_trait, ref generics, .. }) => { + hir::ItemKind::Impl(hir::Impl { ref of_trait, .. }) => { lctx.is_in_trait_impl = of_trait.is_some(); - lctx.in_scope_lifetimes = generics - .params - .iter() - .filter(|param| { - matches!(param.kind, hir::GenericParamKind::Lifetime { .. }) - }) - .map(|param| { - let def_id = - parent_hir.nodes.local_id_to_def_id[¶m.hir_id.local_id]; - let name = param.name; - (name, def_id) - }) - .collect(); - } - hir::ItemKind::Trait(_, _, ref generics, ..) => { - lctx.in_scope_lifetimes = generics - .params - .iter() - .filter(|param| { - matches!(param.kind, hir::GenericParamKind::Lifetime { .. }) - }) - .map(|param| { - let def_id = - parent_hir.nodes.local_id_to_def_id[¶m.hir_id.local_id]; - let name = param.name; - (name, def_id) - }) - .collect(); } _ => {} }; @@ -286,7 +255,6 @@ impl<'hir> LoweringContext<'_, 'hir> { ref body, .. }) => { - let fn_def_id = self.resolver.local_def_id(id); self.with_new_scopes(|this| { this.current_item = Some(ident.span); @@ -299,7 +267,7 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_maybe_async_body(span, &decl, asyncness, body.as_deref()); let (generics, decl) = - this.add_implicit_generics(generics, fn_def_id, |this, idty| { + this.add_implicit_generics(generics, id, |this, idty| { let ret_id = asyncness.opt_return_id(); this.lower_fn_decl(&decl, Some((id, idty)), FnDeclKind::Fn, ret_id) }); @@ -415,9 +383,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // method, it will not be considered an in-band // lifetime to be added, but rather a reference to a // parent lifetime. - let lowered_trait_def_id = hir_id.expect_owner(); let (generics, (trait_ref, lowered_ty)) = - self.add_implicit_generics(ast_generics, lowered_trait_def_id, |this, _| { + self.add_implicit_generics(ast_generics, id, |this, _| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { this.lower_trait_ref( trait_ref, @@ -431,12 +398,9 @@ impl<'hir> LoweringContext<'_, 'hir> { (trait_ref, lowered_ty) }); - let new_impl_items = - self.with_in_scope_lifetime_defs(&ast_generics.params, |this| { - this.arena.alloc_from_iter( - impl_items.iter().map(|item| this.lower_impl_item_ref(item)), - ) - }); + let new_impl_items = self + .arena + .alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item))); // `defaultness.has_value()` is never called for an `impl`, always `true` in order // to not cause an assertion failure inside the `lower_defaultness` function. @@ -743,7 +707,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => { let fdec = &sig.decl; let (generics, (fn_dec, fn_args)) = - self.add_implicit_generics(generics, def_id, |this, _| { + self.add_implicit_generics(generics, i.id, |this, _| { ( // Disallow `impl Trait` in foreign items. this.lower_fn_decl(fdec, None, FnDeclKind::ExternFn, None), @@ -1343,9 +1307,8 @@ impl<'hir> LoweringContext<'_, 'hir> { kind: FnDeclKind, is_async: Option<NodeId>, ) -> (hir::Generics<'hir>, hir::FnSig<'hir>) { - let fn_def_id = self.resolver.local_def_id(id); let header = self.lower_fn_header(sig.header); - let (generics, decl) = self.add_implicit_generics(generics, fn_def_id, |this, idty| { + let (generics, decl) = self.add_implicit_generics(generics, id, |this, idty| { this.lower_fn_decl(&sig.decl, Some((id, idty)), kind, is_async) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) @@ -1487,24 +1450,20 @@ impl<'hir> LoweringContext<'_, 'hir> { ref bounded_ty, ref bounds, span, - }) => self.with_in_scope_lifetime_defs(&bound_generic_params, |this| { - hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { - bound_generic_params: this.lower_generic_params( - bound_generic_params, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - ), - bounded_ty: this.lower_ty( - bounded_ty, - ImplTraitContext::Disallowed(ImplTraitPosition::Type), - ), - bounds: this.arena.alloc_from_iter(bounds.iter().map(|bound| { - this.lower_param_bound( - bound, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), - ) - })), - span: this.lower_span(span), - }) + }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + bound_generic_params: self.lower_generic_params( + bound_generic_params, + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ), + bounded_ty: self + .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| { + self.lower_param_bound( + bound, + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ) + })), + span: self.lower_span(span), }), WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b9e6c2516e0..b71d81f11da 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -45,7 +45,7 @@ use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust; use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; @@ -122,20 +122,6 @@ struct LoweringContext<'a, 'hir: 'a> { is_in_trait_impl: bool, is_in_dyn_type: bool, - /// Used to create lifetime definitions for anonymous lifetimes. - /// When an anonymous lifetime is encountered in a function or impl header and - /// requires to create a fresh lifetime parameter, it is added - /// to this list. The results of this list are then added to the list of - /// lifetime definitions in the corresponding impl or function generics. - lifetimes_to_define: FxIndexMap<NodeId, Span>, - - /// If anonymous lifetimes are being collected, this field holds the parent - /// `LocalDefId` to create the fresh lifetime parameters' `LocalDefId`. - is_collecting_anonymous_lifetimes: Option<LocalDefId>, - - /// Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB. - in_scope_lifetimes: Vec<(ParamName, LocalDefId)>, - /// Used to handle lifetimes appearing in impl-traits. captured_lifetimes: Option<LifetimeCaptureContext>, @@ -173,8 +159,6 @@ pub enum LifetimeRes { Fresh { /// Id of the generic parameter that introduced it. param: LocalDefId, - /// Id to create the HirId. This is used when creating the `Fresh` lifetime parameters. - introducer: Option<NodeId>, /// Id of the introducing place. See `Param`. binder: NodeId, }, @@ -237,6 +221,9 @@ pub trait ResolverAstLowering { /// Obtains resolution for a lifetime with the given `NodeId`. fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>; + /// Obtain the list of lifetimes parameters to add to an item. + fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>; + fn create_stable_hashing_context(&self) -> StableHashingContext<'_>; fn definitions(&self) -> &Definitions; @@ -694,46 +681,34 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } /// Converts a lifetime into a new generic parameter. - fn fresh_lifetime_to_generic_param( + fn lifetime_res_to_generic_param( &mut self, - span: Span, + ident: Ident, node_id: NodeId, - ) -> hir::GenericParam<'hir> { - let hir_id = self.lower_node_id(node_id); - let def_id = self.resolver.local_def_id(node_id); - hir::GenericParam { - hir_id, - name: hir::ParamName::Fresh(def_id), - bounds: &[], - span: self.lower_span(span), - pure_wrt_drop: false, - kind: hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided }, - } - } - - /// Evaluates `f` with the lifetimes in `params` in-scope. - /// This is used to track which lifetimes have already been defined, - /// which need to be duplicated for async fns. - fn with_in_scope_lifetime_defs<T>( - &mut self, - params: &[GenericParam], - f: impl FnOnce(&mut Self) -> T, - ) -> T { - let old_len = self.in_scope_lifetimes.len(); - let lt_def_names = params.iter().filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => { - let def_id = self.resolver.local_def_id(param.id); - let name = ParamName::Plain(param.ident); - Some((name, def_id)) + res: LifetimeRes, + ) -> Option<hir::GenericParam<'hir>> { + let (name, kind) = match res { + LifetimeRes::Param { .. } => { + (hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit) } - _ => None, - }); - self.in_scope_lifetimes.extend(lt_def_names); - - let res = f(self); - - self.in_scope_lifetimes.truncate(old_len); - res + LifetimeRes::Fresh { param, .. } => { + (hir::ParamName::Fresh(param), hir::LifetimeParamKind::Elided) + } + LifetimeRes::Static | LifetimeRes::Error => return None, + res => panic!( + "Unexpected lifetime resolution {:?} for {:?} at {:?}", + res, ident, ident.span + ), + }; + let hir_id = self.lower_node_id(node_id); + Some(hir::GenericParam { + hir_id, + name, + bounds: &[], + span: self.lower_span(ident.span), + pure_wrt_drop: false, + kind: hir::GenericParamKind::Lifetime { kind }, + }) } /// Creates a new `hir::GenericParam` for every new `Fresh` lifetime and @@ -742,39 +717,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn add_implicit_generics<T>( &mut self, generics: &Generics, - parent_def_id: LocalDefId, + parent_node_id: NodeId, f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T, ) -> (hir::Generics<'hir>, T) { - let lifetime_stash = std::mem::take(&mut self.lifetimes_to_define); - let was_collecting = - std::mem::replace(&mut self.is_collecting_anonymous_lifetimes, Some(parent_def_id)); - let mut impl_trait_defs = Vec::new(); + let mut lowered_generics = self.lower_generics_mut( + generics, + ImplTraitContext::Universal(&mut impl_trait_defs, self.current_hir_id_owner), + ); + let res = f(self, &mut impl_trait_defs); - let (mut lowered_generics, res) = - self.with_in_scope_lifetime_defs(&generics.params, |this| { - // Note: it is necessary to lower generics *before* calling `f`. - // When lowering `async fn`, there's a final step when lowering - // the return type that assumes that all in-scope lifetimes have - // already been added to either `in_scope_lifetimes` or - // `lifetimes_to_define`. If we swapped the order of these two, - // fresh lifetimes introduced by generics or where-clauses - // wouldn't have been added yet. - let generics = this.lower_generics_mut( - generics, - ImplTraitContext::Universal(&mut impl_trait_defs, this.current_hir_id_owner), - ); - let res = f(this, &mut impl_trait_defs); - (generics, res) - }); - - self.is_collecting_anonymous_lifetimes = was_collecting; - let lifetimes_to_define = std::mem::replace(&mut self.lifetimes_to_define, lifetime_stash); - + let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id); lowered_generics.params.extend( - lifetimes_to_define + extra_lifetimes .into_iter() - .map(|(node_id, span)| self.fresh_lifetime_to_generic_param(span, node_id)) + .filter_map(|(ident, node_id, res)| { + self.lifetime_res_to_generic_param(ident, node_id, res) + }) .chain(impl_trait_defs), ); @@ -1227,19 +1186,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lifetime = self.lower_lifetime(®ion); hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx)) } - TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(&f.generic_params, |this| { - this.with_lifetime_binder(t.id, |this| { - hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy { - generic_params: this.lower_generic_params( - &f.generic_params, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - ), - unsafety: this.lower_unsafety(f.unsafety), - abi: this.lower_extern(f.ext), - decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), - param_names: this.lower_fn_params_to_names(&f.decl), - })) - }) + TyKind::BareFn(ref f) => self.with_lifetime_binder(t.id, |this| { + hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy { + generic_params: this.lower_generic_params( + &f.generic_params, + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ), + unsafety: this.lower_unsafety(f.unsafety), + abi: this.lower_extern(f.ext), + decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), + param_names: this.lower_fn_params_to_names(&f.decl), + })) }), TyKind::Never => hir::TyKind::Never, TyKind::Tup(ref tys) => { @@ -1676,70 +1633,50 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // should be figured out using the ordinary elision rules, and // this desugaring achieves that. - debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", self.in_scope_lifetimes); - debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", self.lifetimes_to_define); - // Calculate all the lifetimes that should be captured // by the opaque type. This should include all in-scope // lifetime parameters, including those defined in-band. - // Input lifetime like `'a`: let mut captures = FxHashMap::default(); - for &(p_name, def_id) in &self.in_scope_lifetimes { - let Ident { name, span } = p_name.ident(); - let node_id = self.resolver.next_node_id(); + + let extra_lifetime_params = self.resolver.take_extra_lifetime_params(opaque_ty_node_id); + debug!(?extra_lifetime_params); + for (ident, outer_node_id, outer_res) in extra_lifetime_params { + let Ident { name, span } = ident; + let outer_def_id = self.resolver.local_def_id(outer_node_id); + let inner_node_id = self.resolver.next_node_id(); // Add a definition for the in scope lifetime def. self.resolver.create_def( opaque_ty_def_id, - node_id, + inner_node_id, DefPathData::LifetimeNs(name), ExpnId::root(), span.with_parent(None), ); - let res = match p_name { - hir::ParamName::Plain(_) => { - LifetimeRes::Param { param: def_id, binder: fn_node_id } + let (p_name, inner_res) = match outer_res { + // Input lifetime like `'a`: + LifetimeRes::Param { param, .. } => { + (hir::ParamName::Plain(ident), LifetimeRes::Param { param, binder: fn_node_id }) } - hir::ParamName::Fresh(_) => { - LifetimeRes::Fresh { param: def_id, introducer: None, binder: fn_node_id } + // Input lifetime like `'1`: + LifetimeRes::Fresh { param, .. } => ( + hir::ParamName::Fresh(outer_def_id), + LifetimeRes::Fresh { param, binder: fn_node_id }, + ), + LifetimeRes::Static | LifetimeRes::Error => continue, + res => { + panic!("Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, span) } - hir::ParamName::Error => LifetimeRes::Error, }; - captures.insert(def_id, (span, node_id, p_name, res)); - } - - // Input lifetime like `'1`: - for (&node_id, &span) in &self.lifetimes_to_define { - let def_id = self.resolver.local_def_id(node_id); - let new_node_id = self.resolver.next_node_id(); - - // Add a definition for the `Fresh` lifetime def. - let new_def_id = self.resolver.create_def( - opaque_ty_def_id, - new_node_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ExpnId::root(), - span.with_parent(None), - ); - - captures.insert( - def_id, - ( - span, - new_node_id, - hir::ParamName::Fresh(new_def_id), - LifetimeRes::Fresh { param: def_id, introducer: None, binder: fn_node_id }, - ), - ); + captures.insert(outer_def_id, (span, inner_node_id, p_name, inner_res)); } debug!(?captures); self.with_hir_id_owner(opaque_ty_node_id, |this| { - debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define); let future_bound = this.while_capturing_lifetimes(opaque_ty_def_id, &mut captures, |this| { // We have to be careful to get elision right here. The @@ -1923,11 +1860,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } hir::LifetimeName::Param(p_name) } - LifetimeRes::Fresh { mut param, introducer, binder } => { + LifetimeRes::Fresh { mut param, binder } => { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); - // Only items are allowed to introduce fresh lifetimes, - // so we know `binder` has a `LocalDefId`. - let binder_def_id = self.resolver.local_def_id(binder); if let Some(LifetimeCaptureContext { parent_def_id, captures, binders_to_ignore }) = &mut self.captured_lifetimes && !binders_to_ignore.contains(&binder) @@ -1949,16 +1883,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param = p_def_id; } } - } else if let Some(introducer) = introducer { - if self.is_collecting_anonymous_lifetimes == Some(binder_def_id) - && self.resolver.opt_local_def_id(introducer) == Some(param) - { - debug!( - "lifetime_to_define += id={:?} span={:?} res={:?}", - introducer, span, res - ); - self.lifetimes_to_define.insert(introducer, span); - } } let p_name = ParamName::Fresh(param); hir::LifetimeName::Param(p_name) @@ -2091,10 +2015,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let bound_generic_params = self.lower_generic_params(&p.bound_generic_params, itctx.reborrow()); - let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| { - this.with_lifetime_binder(p.trait_ref.ref_id, |this| { - this.lower_trait_ref(&p.trait_ref, itctx.reborrow()) - }) + let trait_ref = self.with_lifetime_binder(p.trait_ref.ref_id, |this| { + this.lower_trait_ref(&p.trait_ref, itctx.reborrow()) }); hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0d940c05169..b3197977d6f 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -15,7 +15,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::DiagnosticId; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS}; @@ -244,7 +244,8 @@ impl LifetimeBinderKind { #[derive(Debug)] struct LifetimeRib { kind: LifetimeRibKind, - bindings: IdentMap<LifetimeRes>, + // We need to preserve insertion order for async fns. + bindings: FxIndexMap<Ident, (NodeId, LifetimeRes)>, } impl LifetimeRib { @@ -718,6 +719,32 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { }, ); + // Construct the list of in-scope lifetime parameters for async lowering. + // We include all lifetime parameters, either named or "Fresh". + // The order of those parameters does not matter, as long as it is + // deterministic. + let mut extra_lifetime_params = + this.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default(); + for rib in this.lifetime_ribs.iter().rev() { + extra_lifetime_params.extend( + rib.bindings + .iter() + .map(|(&ident, &(node_id, res))| (ident, node_id, res)), + ); + match rib.kind { + LifetimeRibKind::Item => break, + LifetimeRibKind::AnonymousCreateParameter(id) => { + if let Some(earlier_fresh) = + this.r.extra_lifetime_params_map.get(&id) + { + extra_lifetime_params.extend(earlier_fresh); + } + } + _ => {} + } + } + this.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params); + this.with_lifetime_rib( LifetimeRibKind::AnonymousPassThrough(async_node_id), |this| visit::walk_fn_ret_ty(this, &declaration.output), @@ -1126,7 +1153,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { for i in &mut indices { let rib = &self.lifetime_ribs[i]; let normalized_ident = ident.normalize_to_macros_2_0(); - if let Some(®ion) = rib.bindings.get(&normalized_ident) { + if let Some(&(_, region)) = rib.bindings.get(&normalized_ident) { self.record_lifetime_res(lifetime.id, region); return; } @@ -1229,12 +1256,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ); debug!(?def_id); - let region = LifetimeRes::Fresh { - param: def_id, - introducer: Some(def_node_id), - binder: item_node_id, - }; + let region = LifetimeRes::Fresh { param: def_id, binder: item_node_id }; self.record_lifetime_res(id, region); + self.r.extra_lifetime_params_map.entry(item_node_id).or_insert_with(Vec::new).push(( + ident, + def_node_id, + region, + )); } #[tracing::instrument(level = "debug", skip(self))] @@ -1818,7 +1846,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let LifetimeRibKind::Generics { parent, .. } = lifetime_kind else { panic!() }; let res = LifetimeRes::Param { param: def_id, binder: parent }; self.record_lifetime_res(param.id, res); - function_lifetime_rib.bindings.insert(ident, res); + function_lifetime_rib.bindings.insert(ident, (param.id, res)); continue; } }; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 180198326bb..8df2ae5c33b 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -903,6 +903,8 @@ pub struct Resolver<'a> { label_res_map: NodeMap<NodeId>, /// Resolutions for lifetimes. lifetimes_res_map: NodeMap<LifetimeRes>, + /// Lifetime parameters that lowering will have to introduce. + extra_lifetime_params_map: NodeMap<Vec<(Ident, NodeId, LifetimeRes)>>, /// `CrateNum` resolutions of `extern crate` items. extern_crate_map: FxHashMap<LocalDefId, CrateNum>, @@ -1159,6 +1161,10 @@ impl ResolverAstLowering for Resolver<'_> { self.lifetimes_res_map.get(&id).copied() } + fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> { + self.extra_lifetime_params_map.remove(&id).unwrap_or_default() + } + fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { StableHashingContext::new(self.session, &self.definitions, self.crate_loader.cstore()) } @@ -1308,6 +1314,7 @@ impl<'a> Resolver<'a> { import_res_map: Default::default(), label_res_map: Default::default(), lifetimes_res_map: Default::default(), + extra_lifetime_params_map: Default::default(), extern_crate_map: Default::default(), reexport_map: FxHashMap::default(), trait_map: NodeMap::default(),