rust-lang/rust · #162120

Introduce `PerOwnerLoweringState`

nnethercote · merged Sep 3, 202610 files · 241 + / 250
compiler/rustc_ast_lowering/src/delegation/attributes.rs3 + / 3
@@ -43,17 +43,17 @@ impl<'hir> LoweringContext<'_, 'hir> {         let &DelegationResolution { span, sig_id, .. } = resolution;          const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;-        let new_attrs = self.create_new_attrs(span, sig_id, self.attrs.get(&PARENT_ID));+        let new_attrs = self.create_new_attrs(span, sig_id, self.curr_owner.attrs.get(&PARENT_ID));          if !new_attrs.is_empty() {-            let new_attrs = match self.attrs.get(&PARENT_ID) {+            let new_attrs = match self.curr_owner.attrs.get(&PARENT_ID) {                 Some(existing_attrs) => self.arena.alloc_from_iter(                     existing_attrs.iter().map(|a| a.clone()).chain(new_attrs.into_iter()),                 ),                 None => self.arena.alloc_from_iter(new_attrs.into_iter()),             }; -            self.attrs.insert(PARENT_ID, new_attrs);+            self.curr_owner.attrs.insert(PARENT_ID, new_attrs);         }     } 
compiler/rustc_ast_lowering/src/delegation/generics.rs1 + / 1
@@ -587,7 +587,7 @@ impl<'hir> LoweringContext<'_, 'hir> {             };              // Important: we don't use `self.next_id()` as we want to execute-            // `lower_node_id` routine so param's id is added to `self.children`.+            // `lower_node_id` routine so param's id is added to `self.curr_owner.children`.             let hir_id = self.lower_node_id(node_id);              Some(hir::GenericParam {
compiler/rustc_ast_lowering/src/delegation/mod.rs6 + / 4
@@ -140,9 +140,11 @@ impl<'hir> LoweringContext<'_, 'hir> {                         let id = match source {                             DelegationSource::Single => None,                             DelegationSource::List(expn_id) => Some(expn_id),-                            DelegationSource::Glob => {-                                Some(self.tcx.expn_that_defined(self.owner.def_id).expect_local())-                            }+                            DelegationSource::Glob => Some(+                                self.tcx+                                    .expn_that_defined(self.curr_owner.owner.def_id)+                                    .expect_local(),+                            ),                         };                          id.map(|id| (id, unused_target_expr))@@ -335,7 +337,7 @@ impl<'hir> LoweringContext<'_, 'hir> {         let overwrites = self_resolver.overwrites;          // Target expr needs to lower `self` path.-        self.ident_and_label_to_local_id.insert(pat_node_id, param_local_id);+        self.curr_owner.ident_and_label_to_local_id.insert(pat_node_id, param_local_id);          let block = cfg_select! {             debug_assertions => {
compiler/rustc_ast_lowering/src/delegation/resolution.rs2 + / 2
@@ -73,7 +73,7 @@ pub(super) mod resolver {          #[inline]         pub(crate) fn owner_id(&self) -> LocalDefId {-            self.0.owner.def_id+            self.0.curr_owner.owner.def_id         }          /// (from `tests\ui\delegation\target-expr-removal-defs-inside.rs`):@@ -91,7 +91,7 @@ pub(super) mod resolver {         #[inline]         pub(crate) fn is_definition(&self, id: NodeId) -> bool {             self.0.resolver.owners.contains_key(&id)-                || self.0.owner.node_id_to_def_id.contains_key(&id)+                || self.0.curr_owner.owner.node_id_to_def_id.contains_key(&id)         }          #[inline]
compiler/rustc_ast_lowering/src/expr.rs9 + / 8
@@ -172,7 +172,8 @@ impl<'hir> LoweringContext<'_, 'hir> {                 }                 // Merge attributes into the inner expression.                 if !e.attrs.is_empty() {-                    let old_attrs = self.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]);+                    let old_attrs =+                        self.curr_owner.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]);                     let new_attrs = self                         .lower_attrs_vec(&e.attrs, e.span, ex.hir_id, Target::from_expr(e))                         .into_iter()@@ -181,7 +182,7 @@ impl<'hir> LoweringContext<'_, 'hir> {                     if new_attrs.is_empty() {                         return ex;                     }-                    self.attrs.insert(ex.hir_id.local_id, new_attrs);+                    self.curr_owner.attrs.insert(ex.hir_id.local_id, new_attrs);                 }                 return ex;             }@@ -884,15 +885,15 @@ impl<'hir> LoweringContext<'_, 'hir> {     /// `inner_hir_id` in case the `async_fn_track_caller` feature is enabled.     pub(super) fn maybe_forward_track_caller(&mut self, outer_hir_id: HirId, inner_hir_id: HirId) {         if self.tcx.features().async_fn_track_caller()-            && let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)+            && let Some(attrs) = self.curr_owner.attrs.get(&outer_hir_id.local_id)             && let Some(t) = attrs.iter().find(|a| {                 matches!(                     a,                     rustc_attr_ir::Attribute::Parsed(rustc_attr_ir::AttributeKind::TrackCaller(_))                 )             })         {-            self.attrs.insert(inner_hir_id.local_id, std::slice::from_ref(t));+            self.curr_owner.attrs.insert(inner_hir_id.local_id, std::slice::from_ref(t));         }     } @@ -1505,16 +1506,16 @@ impl<'hir> LoweringContext<'_, 'hir> {         dest_hir_id: hir::HirId,     ) -> Option<Label> {         let label = opt_label?;-        self.ident_and_label_to_local_id.insert(dest_id, dest_hir_id.local_id);+        self.curr_owner.ident_and_label_to_local_id.insert(dest_id, dest_hir_id.local_id);         Some(Label { ident: self.lower_ident(label.ident) })     }      fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {         let target_id = match destination {             Some((id, _)) => {-                if let Some(loop_id) = self.owner.get_label_res(id) {-                    let local_id = self.ident_and_label_to_local_id[&loop_id];-                    let loop_hir_id = HirId { owner: self.current_hir_id_owner, local_id };+                if let Some(loop_id) = self.curr_owner.owner.get_label_res(id) {+                    let local_id = self.curr_owner.ident_and_label_to_local_id[&loop_id];+                    let loop_hir_id = HirId { owner: self.curr_owner.owner_id, local_id };                     Ok(loop_hir_id)                 } else {                     Err(hir::LoopIdError::UnresolvedLabel)
compiler/rustc_ast_lowering/src/item.rs20 + / 22
@@ -61,17 +61,15 @@ impl<'hir> ItemLowerer<'_, 'hir> {         let mut lctx = LoweringContext::new(self.tcx, self.resolver, owner);          let item = f(&mut lctx);-        debug_assert_eq!(lctx.current_hir_id_owner, item.def_id());--        let info = lctx.make_owner_info(item); +        let info = lctx.curr_owner.into_owner_info(self.tcx, item);         hir::MaybeOwner::Owner(lctx.arena.alloc(info))     }      #[instrument(level = "debug", skip(self, c))]     pub(super) fn lower_crate(&mut self, c: &Crate) -> hir::MaybeOwner<'hir> {         self.with_lctx(CRATE_NODE_ID, |lctx| {-            debug_assert_eq!(lctx.current_hir_id_owner, CRATE_OWNER_ID);+            debug_assert_eq!(lctx.curr_owner.owner_id, CRATE_OWNER_ID);             let module = lctx.lower_mod(&c.items, &c.spans);             lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, c.spans.inner_span, Target::Crate);             hir::OwnerNode::Crate(module)@@ -206,7 +204,7 @@ impl<'hir> LoweringContext<'_, 'hir> {     }      fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {-        let owner_id = self.current_hir_id_owner;+        let owner_id = self.curr_owner.owner_id;         let hir_id: HirId = owner_id.into();         let vis_span = self.lower_span(i.vis.span); @@ -399,7 +397,7 @@ impl<'hir> LoweringContext<'_, 'hir> {                             ty,                             ImplTraitContext::OpaqueTy {                                 origin: hir::OpaqueTyOrigin::TyAlias {-                                    parent: this.owner.def_id,+                                    parent: this.curr_owner.owner.def_id,                                     in_assoc_ty: false,                                 },                             },@@ -547,7 +545,7 @@ impl<'hir> LoweringContext<'_, 'hir> {             ItemKind::MacroDef(ident, MacroDef { body, macro_rules, eii_declaration: _ }) => {                 let ident = self.lower_ident(*ident);                 let body = Box::new(self.lower_delim_args(body));-                let def_id = self.owner.def_id;+                let def_id = self.curr_owner.owner.def_id;                 let def_kind = self.tcx.def_kind(def_id);                 let DefKind::Macro(macro_kinds) = def_kind else {                     unreachable!(@@ -695,7 +693,7 @@ impl<'hir> LoweringContext<'_, 'hir> {                         // `ItemLocalId` and the new owner. (See `lower_node_id`)                         let kind = this.lower_use_tree(use_tree, &prefix, id, vis_span, attrs);                         if !attrs.is_empty() {-                            this.attrs.insert(hir::ItemLocalId::ZERO, attrs);+                            this.curr_owner.attrs.insert(hir::ItemLocalId::ZERO, attrs);                         }                          let item = hir::Item {@@ -731,7 +729,7 @@ impl<'hir> LoweringContext<'_, 'hir> {     }      fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {-        let owner_id = self.current_hir_id_owner;+        let owner_id = self.curr_owner.owner_id;         let hir_id: HirId = owner_id.into();         let attrs =             self.lower_attrs(hir_id, &i.attrs, i.span, Target::from_foreign_item_kind(&i.kind));@@ -914,7 +912,7 @@ impl<'hir> LoweringContext<'_, 'hir> {     }      fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {-        let trait_item_def_id = self.current_hir_id_owner;+        let trait_item_def_id = self.curr_owner.owner_id;         let hir_id: HirId = trait_item_def_id.into();         let attrs = self.lower_attrs(             hir_id,@@ -1169,7 +1167,7 @@ impl<'hir> LoweringContext<'_, 'hir> {     }      fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {-        let owner_id = self.current_hir_id_owner;+        let owner_id = self.curr_owner.owner_id;         let hir_id: HirId = owner_id.into();         let parent_id = self.tcx.local_parent(owner_id.def_id);         let is_in_trait_impl =@@ -1258,7 +1256,7 @@ impl<'hir> LoweringContext<'_, 'hir> {                                     ty,                                     ImplTraitContext::OpaqueTy {                                         origin: hir::OpaqueTyOrigin::TyAlias {-                                            parent: this.owner.def_id,+                                            parent: this.curr_owner.owner.def_id,                                             in_assoc_ty: true,                                         },                                     },@@ -1336,8 +1334,8 @@ impl<'hir> LoweringContext<'_, 'hir> {     ) -> hir::BodyId {         let body = hir::Body { params, value: self.arena.alloc(value) };         let id = body.id();-        assert_eq!(id.hir_id.owner, self.current_hir_id_owner);-        self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));+        assert_eq!(id.hir_id.owner, self.curr_owner.owner_id);+        self.curr_owner.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));         id     } @@ -1545,7 +1543,7 @@ impl<'hir> LoweringContext<'_, 'hir> {             //             // If this is the simple case, this parameter will end up being the same as the             // original parameter, but with a different pattern id.-            let stmt_attrs = self.attrs.get(&parameter.hir_id.local_id).copied();+            let stmt_attrs = self.curr_owner.attrs.get(&parameter.hir_id.local_id).copied();             let (new_parameter_pat, new_parameter_id) = self.pat_ident(desugared_span, ident);             let new_parameter = hir::Param {                 hir_id: parameter.hir_id,@@ -1883,8 +1881,8 @@ impl<'hir> LoweringContext<'_, 'hir> {         itctx: ImplTraitContext,         f: impl FnOnce(&mut Self) -> T,     ) -> (&'hir hir::Generics<'hir>, T) {-        assert!(self.impl_trait_defs.is_empty());-        assert!(self.impl_trait_bounds.is_empty());+        assert!(self.curr_owner.impl_trait_defs.is_empty());+        assert!(self.curr_owner.impl_trait_bounds.is_empty());          let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();         // We need to make sure that generic params don't have multiple relaxed bounds for the same trait@@ -1914,7 +1912,7 @@ impl<'hir> LoweringContext<'_, 'hir> {             .collect();          // Introduce extra lifetimes if late resolution tells us to.-        let extra_lifetimes = self.owner.extra_lifetime_params(self.owner.id);+        let extra_lifetimes = self.curr_owner.owner.extra_lifetime_params(self.curr_owner.owner.id);         params.extend(extra_lifetimes.into_iter().map(|&(ident, node_id, kind)| {             self.lifetime_res_to_generic_param(                 ident,@@ -1929,10 +1927,10 @@ impl<'hir> LoweringContext<'_, 'hir> {         let span = self.lower_span(generics.span);         let res = f(self); -        let impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);+        let impl_trait_defs = std::mem::take(&mut self.curr_owner.impl_trait_defs);         params.extend(impl_trait_defs.into_iter()); -        let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);+        let impl_trait_bounds = std::mem::take(&mut self.curr_owner.impl_trait_bounds);         predicates.extend(impl_trait_bounds.into_iter());          let lowered_generics = self.arena.alloc(hir::Generics {@@ -1951,7 +1949,7 @@ impl<'hir> LoweringContext<'_, 'hir> {         hir_id: HirId,         define_opaque: &Option<ThinVec<(NodeId, Path)>>,     ) {-        assert_eq!(self.define_opaque, None);+        assert_eq!(self.curr_owner.define_opaque, None);         assert!(hir_id.is_owner());         let Some(define_opaque) = define_opaque.as_ref() else {             return;@@ -1972,7 +1970,7 @@ impl<'hir> LoweringContext<'_, 'hir> {             Some((self.lower_span(path.span), did))         });         let define_opaque = self.arena.alloc_from_iter(define_opaque);-        self.define_opaque = Some(define_opaque);+        self.curr_owner.define_opaque = Some(define_opaque);     }      pub(super) fn lower_generic_bound_predicate(
compiler/rustc_ast_lowering/src/lib.rs191 + / 202
@@ -131,36 +131,155 @@ pub(crate) mod re_lowering {             ctx: &mut LoweringContext<'a, 'hir>,             op: impl FnOnce(&mut LoweringContext<'a, 'hir>) -> TRes,         ) -> TRes {-            assert!(!ctx.relowering_checker.can_relower, "reentrant relowering is not supported");+            assert!(+                !ctx.curr_owner.relowering_checker.can_relower,+                "reentrant relowering is not supported"+            ); -            ctx.relowering_checker.can_relower = true;+            ctx.curr_owner.relowering_checker.can_relower = true;              let res = op(ctx); -            ctx.relowering_checker.can_relower = false;+            ctx.curr_owner.relowering_checker.can_relower = false;              res         }     } } -struct LoweringContext<'a, 'hir> {-    tcx: TyCtxt<'hir>,-    resolver: &'a ResolverAstLowering<'hir>,-    current_disambiguator: PerParentDisambiguatorState,+struct PerOwnerLoweringState<'a, 'hir> {+    // -- Identity --+    owner: &'a PerOwnerResolverData<'hir>,+    owner_id: hir::OwnerId,+    disambiguator: PerParentDisambiguatorState, -    /// Used to allocate HIR nodes.-    arena: &'hir hir::Arena<'hir>,+    // -- HirId allocation --+    item_local_id_counter: hir::ItemLocalId,+    /// NodeIds of pattern identifiers and labelled nodes that are lowered inside the current HIR+    /// owner.+    ident_and_label_to_local_id: NodeMap<hir::ItemLocalId>,+    /// NodeIds that are lowered inside the current HIR owner. Only used for duplicate lowering+    /// check.+    #[cfg(debug_assertions)]+    relowering_checker: re_lowering::ReloweringChecker, +    // -- Accumulated outputs --+    /// Attributes inside the owner being lowered.+    attrs: SortedMap<hir::ItemLocalId, &'hir [hir::Attribute]>,     /// Bodies inside the owner being lowered.     bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,     /// `#[define_opaque]` attributes     define_opaque: Option<&'hir [(Span, LocalDefId)]>,-    /// Attributes inside the owner being lowered.-    attrs: SortedMap<hir::ItemLocalId, &'hir [hir::Attribute]>,+    trait_map: ItemLocalMap<&'hir [TraitCandidate<'hir>]>,+    delayed_lints: Vec<DelayedLint>,     /// Collect items that were created by lowering the current owner.     children: LocalDefIdMap<hir::MaybeOwner<'hir>>, +    // -- Transient --+    impl_trait_defs: Vec<hir::GenericParam<'hir>>,+    impl_trait_bounds: Vec<hir::WherePredicate<'hir>>,+}++impl<'a, 'hir> PerOwnerLoweringState<'a, 'hir> {+    fn new(resolver: &'a ResolverAstLowering<'hir>, owner: NodeId) -> Self {+        let owner = &resolver.owners[&owner];++        let disambiguator = resolver+            .disambiguators+            .get(&owner.def_id)+            .map(|s| s.steal())+            .unwrap_or_else(|| PerParentDisambiguatorState::new(owner.def_id));++        PerOwnerLoweringState {+            owner,+            owner_id: hir::OwnerId { def_id: owner.def_id },+            disambiguator,+            // 0 corresponds to `owner` lowered as `owner_id`, and we never call+            // `lower_node_id(owner)`.+            item_local_id_counter: hir::ItemLocalId::new(1),+            ident_and_label_to_local_id: Default::default(),+            #[cfg(debug_assertions)]+            relowering_checker: Default::default(),+            attrs: SortedMap::default(),+            bodies: Vec::new(),+            define_opaque: None,+            trait_map: Default::default(),+            delayed_lints: Vec::new(),+            children: LocalDefIdMap::default(),+            impl_trait_defs: Vec::new(),+            impl_trait_bounds: Vec::new(),+        }+    }++    fn into_owner_info(+        self,+        tcx: TyCtxt<'hir>,+        node: hir::OwnerNode<'hir>,+    ) -> &'hir hir::OwnerInfo<'hir> {+        assert_eq!(self.owner_id, node.def_id());+        assert!(self.impl_trait_defs.is_empty());+        assert!(self.impl_trait_bounds.is_empty());++        let attrs = self.attrs;+        let mut bodies = self.bodies;+        let define_opaque = self.define_opaque;+        let trait_map = self.trait_map;+        let delayed_lints = Steal::new(self.delayed_lints.into_boxed_slice());+        let children = self.children;++        #[cfg(debug_assertions)]+        for (id, attrs) in attrs.iter() {+            // Verify that we do not store empty slices in the map.+            if attrs.is_empty() {+                panic!("Stored empty attributes for {:?}", id);+            }+        }++        bodies.sort_by_key(|(k, _)| *k);+        let bodies = SortedMap::from_presorted_elements(bodies);++        // Don't hash unless necessary, because it's expensive.+        let rustc_middle::hir::Hashes { bodies_hash, attrs_hash } =+            tcx.hash_owner_nodes(node, &bodies, &attrs, define_opaque);+        let num_nodes = self.item_local_id_counter.as_usize();+        let (nodes, parenting) = index::index_hir(tcx, node, &bodies, num_nodes);+        let nodes = hir::OwnerNodes { opt_hash: bodies_hash, nodes, bodies };+        let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash, define_opaque };++        let opt_hash = tcx.needs_hir_hash().then(|| {+            tcx.with_stable_hashing_context(|mut hcx| {+                let mut stable_hasher = StableHasher::new();+                bodies_hash.unwrap().stable_hash(&mut hcx, &mut stable_hasher);+                attrs_hash.unwrap().stable_hash(&mut hcx, &mut stable_hasher);+                // Do not hash delayed_lints.+                parenting.stable_hash(&mut hcx, &mut stable_hasher);+                trait_map.stable_hash(&mut hcx, &mut stable_hasher);+                children.stable_hash(&mut hcx, &mut stable_hasher);+                stable_hasher.finish()+            })+        });++        tcx.hir_arena.alloc(hir::OwnerInfo {+            opt_hash,+            nodes,+            parenting,+            attrs,+            trait_map,+            delayed_lints,+            children,+        })+    }+}++struct LoweringContext<'a, 'hir> {+    tcx: TyCtxt<'hir>,+    resolver: &'a ResolverAstLowering<'hir>,++    curr_owner: PerOwnerLoweringState<'a, 'hir>,++    /// Used to allocate HIR nodes.+    arena: &'hir hir::Arena<'hir>,+     contract_ensures: Option<(Span, Ident, HirId)>,      coroutine_kind: Option<hir::CoroutineKind>,@@ -178,19 +297,6 @@ struct LoweringContext<'a, 'hir> {     is_in_loop_condition: bool,     is_in_dyn_type: bool, -    current_hir_id_owner: hir::OwnerId,-    owner: &'a PerOwnerResolverData<'hir>,-    item_local_id_counter: hir::ItemLocalId,-    trait_map: ItemLocalMap<&'hir [TraitCandidate<'hir>]>,--    impl_trait_defs: Vec<hir::GenericParam<'hir>>,-    impl_trait_bounds: Vec<hir::WherePredicate<'hir>>,--    /// NodeIds of pattern identifiers and labelled nodes that are lowered inside the current HIR owner.-    ident_and_label_to_local_id: NodeMap<hir::ItemLocalId>,-    /// NodeIds that are lowered inside the current HIR owner. Only used for duplicate lowering check.-    #[cfg(debug_assertions)]-    relowering_checker: re_lowering::ReloweringChecker,     /// The `NodeId` space is split in two.     /// `0..resolver.next_node_id` are created by the resolver on the AST.     /// The higher part `resolver.next_node_id..next_node_id` are created during lowering.@@ -211,8 +317,6 @@ struct LoweringContext<'a, 'hir> {     allow_for_await: Arc<[Symbol]>,     allow_async_fn_traits: Arc<[Symbol]>, -    delayed_lints: Vec<DelayedLint>,-     /// Stack of `move(...)` collection states. A plain closure body pushes     /// `Some`, so `move(...)` expressions can record the generated locals they     /// should lower to. Nested bodies that cannot use `move(...)` push `None`.@@ -223,37 +327,14 @@ struct LoweringContext<'a, 'hir> {  impl<'a, 'hir> LoweringContext<'a, 'hir> {     fn new(tcx: TyCtxt<'hir>, resolver: &'a ResolverAstLowering<'hir>, owner: NodeId) -> Self {-        let current_ast_owner = &resolver.owners[&owner];-        let current_hir_id_owner = hir::OwnerId { def_id: current_ast_owner.def_id };-        let current_disambiguator = resolver-            .disambiguators-            .get(&current_hir_id_owner.def_id)-            .map(|s| s.steal())-            .unwrap_or_else(|| PerParentDisambiguatorState::new(current_hir_id_owner.def_id));-         Self {             tcx,             resolver,-            current_disambiguator,-            owner: current_ast_owner,+            curr_owner: PerOwnerLoweringState::new(resolver, owner),             arena: tcx.hir_arena, -            // HirId handling.-            bodies: Vec::new(),-            define_opaque: None,-            attrs: SortedMap::default(),-            children: LocalDefIdMap::default(),             contract_ensures: None,-            current_hir_id_owner,-            // 0 corresponds to `owner` lowered as `current_hir_id_owner`,-            // and we never call `lower_node_id(owner)`.-            item_local_id_counter: hir::ItemLocalId::new(1),-            ident_and_label_to_local_id: Default::default(),--            #[cfg(debug_assertions)]-            relowering_checker: Default::default(), -            trait_map: Default::default(),             next_node_id: resolver.next_node_id,             node_id_to_def_id: NodeMap::default(),             partial_res_overrides: NodeMap::default(),@@ -266,8 +347,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {             coroutine_kind: None,             task_context: None,             current_item: None,-            impl_trait_defs: Vec::new(),-            impl_trait_bounds: Vec::new(),             allow_contracts: [sym::contracts_internals].into(),             allow_try_trait: [                 sym::try_trait_v2,@@ -295,7 +374,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {                 tcx.registered_attr_tools(()),                 ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },             ),-            delayed_lints: Vec::new(),         }     } @@ -746,7 +824,7 @@ impl<'hir> LoweringContext<'_, 'hir> {         def_kind: DefKind,         span: Span,     ) -> LocalDefId {-        let parent = self.current_hir_id_owner.def_id;+        let parent = self.curr_owner.owner_id.def_id;         assert_ne!(node_id, ast::DUMMY_NODE_ID);         assert!(             self.opt_local_def_id(node_id).is_none(),@@ -759,7 +837,7 @@ impl<'hir> LoweringContext<'_, 'hir> {         let def_id = self             .tcx             .at(span)-            .create_def(parent, name, def_kind, None, &mut self.current_disambiguator)+            .create_def(parent, name, def_kind, None, &mut self.curr_owner.disambiguator)             .def_id();          debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);@@ -781,7 +859,7 @@ impl<'hir> LoweringContext<'_, 'hir> {     fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {         self.node_id_to_def_id             .get(&node)-            .or_else(|| self.owner.node_id_to_def_id.get(&node))+            .or_else(|| self.curr_owner.owner.node_id_to_def_id.get(&node))             .copied()     } @@ -813,132 +891,40 @@ impl<'hir> LoweringContext<'_, 'hir> {     }      /// Freshen the `LoweringContext` and ready it to lower a nested item.-    /// The lowered item is registered into `self.children`.+    /// The lowered item is registered into `self.curr_owner.children`.     ///     /// This function sets up `HirId` lowering infrastructure,-    /// and stashes the shared mutable state to avoid pollution by the closure.+    /// and stashes the per-owner state to avoid pollution by the closure.     #[instrument(level = "debug", skip(self, f))]     fn with_hir_id_owner(         &mut self,         owner: NodeId,         f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>,     ) {-        let owner_id = self.owner_id(owner);-        let def_id = owner_id.def_id;--        let new_disambig = self-            .resolver-            .disambiguators-            .get(&def_id)-            .map(|s| s.steal())-            .unwrap_or_else(|| PerParentDisambiguatorState::new(def_id));--        let disambiguator = mem::replace(&mut self.current_disambiguator, new_disambig);-        let current_ast_owner = mem::replace(&mut self.owner, &self.resolver.owners[&owner]);-        let current_attrs = mem::take(&mut self.attrs);-        let current_bodies = mem::take(&mut self.bodies);-        let current_define_opaque = mem::take(&mut self.define_opaque);-        let current_ident_and_label_to_local_id = mem::take(&mut self.ident_and_label_to_local_id);--        #[cfg(debug_assertions)]-        let current_relowering_checker = mem::take(&mut self.relowering_checker);-        let current_trait_map = mem::take(&mut self.trait_map);-        let current_owner = mem::replace(&mut self.current_hir_id_owner, owner_id);-        let current_local_counter =-            mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));-        let current_impl_trait_defs = mem::take(&mut self.impl_trait_defs);-        let current_impl_trait_bounds = mem::take(&mut self.impl_trait_bounds);-        let current_delayed_lints = mem::take(&mut self.delayed_lints);-        let current_children = mem::take(&mut self.children);+        let child_owner = PerOwnerLoweringState::new(self.resolver, owner);+        let parent_owner = mem::replace(&mut self.curr_owner, child_owner);          // Do not reset `next_node_id` and `node_id_to_def_id`:         // we want `f` to be able to refer to the `LocalDefId`s that the caller created.         // and the caller to refer to some of the subdefinitions' nodes' `LocalDefId`s.          // Always allocate the first `HirId` for the owner itself.         #[cfg(debug_assertions)]-        self.relowering_checker.assert_node_is_not_relowered(owner, hir::ItemLocalId::ZERO);+        self.curr_owner+            .relowering_checker+            .assert_node_is_not_relowered(owner, hir::ItemLocalId::ZERO);          let item = f(self);-        assert_eq!(owner_id, item.def_id());-        // `f` should have consumed all the elements in these vectors when constructing `item`.-        assert!(self.impl_trait_defs.is_empty());-        assert!(self.impl_trait_bounds.is_empty());-        let info = self.make_owner_info(item);+        let completed_child_owner = mem::replace(&mut self.curr_owner, parent_owner);+        let owner_id = completed_child_owner.owner_id;+        let info = completed_child_owner.into_owner_info(self.tcx, item); -        self.current_disambiguator = disambiguator;-        self.owner = current_ast_owner;-        self.attrs = current_attrs;-        self.bodies = current_bodies;-        self.define_opaque = current_define_opaque;-        self.ident_and_label_to_local_id = current_ident_and_label_to_local_id;+        self.curr_owner+            .children+            .extend_unord(info.children.items().map(|(&def_id, &info)| (def_id, info))); -        #[cfg(debug_assertions)]-        {-            self.relowering_checker = current_relowering_checker;-        }-        self.trait_map = current_trait_map;-        self.current_hir_id_owner = current_owner;-        self.item_local_id_counter = current_local_counter;-        self.impl_trait_defs = current_impl_trait_defs;-        self.impl_trait_bounds = current_impl_trait_bounds;-        self.delayed_lints = current_delayed_lints;-        self.children = current_children;-        self.children.extend_unord(info.children.items().map(|(&def_id, &info)| (def_id, info)));--        debug_assert!(!self.children.contains_key(&owner_id.def_id));-        self.children.insert(owner_id.def_id, hir::MaybeOwner::Owner(info));-    }--    fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {-        let attrs = mem::take(&mut self.attrs);-        let mut bodies = mem::take(&mut self.bodies);-        let define_opaque = mem::take(&mut self.define_opaque);-        let trait_map = mem::take(&mut self.trait_map);-        let delayed_lints = Steal::new(mem::take(&mut self.delayed_lints).into_boxed_slice());-        let children = mem::take(&mut self.children);--        #[cfg(debug_assertions)]-        for (id, attrs) in attrs.iter() {-            // Verify that we do not store empty slices in the map.-            if attrs.is_empty() {-                panic!("Stored empty attributes for {:?}", id);-            }-        }--        bodies.sort_by_key(|(k, _)| *k);-        let bodies = SortedMap::from_presorted_elements(bodies);--        // Don't hash unless necessary, because it's expensive.-        let rustc_middle::hir::Hashes { bodies_hash, attrs_hash } =-            self.tcx.hash_owner_nodes(node, &bodies, &attrs, define_opaque);-        let num_nodes = self.item_local_id_counter.as_usize();-        let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);-        let nodes = hir::OwnerNodes { opt_hash: bodies_hash, nodes, bodies };-        let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash, define_opaque };--        let opt_hash = self.tcx.needs_hir_hash().then(|| {-            self.tcx.with_stable_hashing_context(|mut hcx| {-                let mut stable_hasher = StableHasher::new();-                bodies_hash.unwrap().stable_hash(&mut hcx, &mut stable_hasher);-                attrs_hash.unwrap().stable_hash(&mut hcx, &mut stable_hasher);-                // Do not hash delayed_lints.-                parenting.stable_hash(&mut hcx, &mut stable_hasher);-                trait_map.stable_hash(&mut hcx, &mut stable_hasher);-                children.stable_hash(&mut hcx, &mut stable_hasher);-                stable_hasher.finish()-            })-        });--        self.arena.alloc(hir::OwnerInfo {-            opt_hash,-            nodes,-            parenting,-            attrs,-            trait_map,-            delayed_lints,-            children,-        })+        debug_assert!(!self.curr_owner.children.contains_key(&owner_id.def_id));+        self.curr_owner.children.insert(owner_id.def_id, hir::MaybeOwner::Owner(info));     }      /// This method allocates a new `HirId` for the given `NodeId`.@@ -950,42 +936,43 @@ impl<'hir> LoweringContext<'_, 'hir> {     fn lower_node_id(&mut self, ast_node_id: NodeId) -> HirId {         assert_ne!(ast_node_id, DUMMY_NODE_ID); -        let owner = self.current_hir_id_owner;-        let local_id = self.item_local_id_counter;+        let owner = self.curr_owner.owner_id;+        let local_id = self.curr_owner.item_local_id_counter;         assert_ne!(local_id, hir::ItemLocalId::ZERO);-        self.item_local_id_counter.increment_by(1);+        self.curr_owner.item_local_id_counter.increment_by(1);         let hir_id = HirId { owner, local_id };          if let Some(def_id) = self.opt_local_def_id(ast_node_id) {-            self.children.insert(def_id, hir::MaybeOwner::NonOwner(hir_id));+            self.curr_owner.children.insert(def_id, hir::MaybeOwner::NonOwner(hir_id));         } -        if let Some(traits) = self.owner.trait_map.get(&ast_node_id) {-            self.trait_map.insert(hir_id.local_id, *traits);+        if let Some(traits) = self.curr_owner.owner.trait_map.get(&ast_node_id) {+            self.curr_owner.trait_map.insert(hir_id.local_id, *traits);         }          // Check whether the same `NodeId` is lowered more than once.         #[cfg(debug_assertions)]-        self.relowering_checker.assert_node_is_not_relowered(ast_node_id, local_id);+        self.curr_owner.relowering_checker.assert_node_is_not_relowered(ast_node_id, local_id);          hir_id     }      /// Generate a new `HirId` without a backing `NodeId`.     #[instrument(level = "debug", skip(self), ret)]     fn next_id(&mut self) -> HirId {-        let owner = self.current_hir_id_owner;-        let local_id = self.item_local_id_counter;+        let owner = self.curr_owner.owner_id;+        let local_id = self.curr_owner.item_local_id_counter;         assert_ne!(local_id, hir::ItemLocalId::ZERO);-        self.item_local_id_counter.increment_by(1);+        self.curr_owner.item_local_id_counter.increment_by(1);         HirId { owner, local_id }     }      #[instrument(level = "trace", skip(self))]     fn lower_res(&mut self, res: Res<NodeId>) -> Res {         let res: Result<Res, ()> = res.apply_id(|id| {-            let owner = self.current_hir_id_owner;-            let local_id = self.ident_and_label_to_local_id.get(&id).copied().ok_or(())?;+            let owner = self.curr_owner.owner_id;+            let local_id =+                self.curr_owner.ident_and_label_to_local_id.get(&id).copied().ok_or(())?;             Ok(HirId { owner, local_id })         });         trace!(?res);@@ -1003,8 +990,8 @@ impl<'hir> LoweringContext<'_, 'hir> {     }      fn lower_import_res(&mut self, id: NodeId, span: Span) -> PerNS<Option<Res>> {-        debug_assert_eq!(id, self.owner.id);-        let per_ns = self.owner.import_res.map(|res| res.map(|res| self.lower_res(res)));+        debug_assert_eq!(id, self.curr_owner.owner.id);+        let per_ns = self.curr_owner.owner.import_res.map(|res| res.map(|res| self.lower_res(res)));         if per_ns.is_empty() {             // Propagate the error to all namespaces, just to be sure.             self.dcx().span_delayed_bug(span, "no resolution for an import");@@ -1062,7 +1049,7 @@ impl<'hir> LoweringContext<'_, 'hir> {     fn span_lowerer(&self) -> SpanLowerer {         SpanLowerer {             is_incremental: self.tcx.sess.opts.incremental.is_some(),-            def_id: self.current_hir_id_owner.def_id,+            def_id: self.curr_owner.owner_id.def_id,         }     } @@ -1122,7 +1109,7 @@ impl<'hir> LoweringContext<'_, 'hir> {     ) -> &'hir [hir::GenericParam<'hir>] {         // Start by creating params for extra lifetimes params, as this creates the definitions         // that may be referred to by the AST inside `generic_params`.-        let extra_lifetimes = self.owner.extra_lifetime_params(binder);+        let extra_lifetimes = self.curr_owner.owner.extra_lifetime_params(binder);         debug!(?extra_lifetimes);         let extra_lifetimes: Vec<_> = extra_lifetimes             .iter()@@ -1201,7 +1188,7 @@ impl<'hir> LoweringContext<'_, 'hir> {                 self.lower_attrs_vec(attrs, self.lower_span(target_span), id, target);             lowered_attrs.extend(extra_hir_attributes.iter().cloned()); -            assert_eq!(id.owner, self.current_hir_id_owner);+            assert_eq!(id.owner, self.curr_owner.owner_id);             let ret = self.arena.alloc_from_iter(lowered_attrs);              // this is possible if an item contained syntactical attribute,@@ -1213,7 +1200,7 @@ impl<'hir> LoweringContext<'_, 'hir> {             if ret.is_empty() {                 &[]             } else {-                self.attrs.insert(id.local_id, ret);+                self.curr_owner.attrs.insert(id.local_id, ret);                 ret             }         }@@ -1233,7 +1220,7 @@ impl<'hir> LoweringContext<'_, 'hir> {             target,             |s| l.lower(s),             |lint_id, span, kind| {-                self.delayed_lints.push(DelayedLint {+                self.curr_owner.delayed_lints.push(DelayedLint {                     lint_id,                     id: target_hir_id,                     span,@@ -1249,11 +1236,11 @@ impl<'hir> LoweringContext<'_, 'hir> {     }      fn alias_attrs(&mut self, id: HirId, target_id: HirId) {-        assert_eq!(id.owner, self.current_hir_id_owner);-        assert_eq!(target_id.owner, self.current_hir_id_owner);-        if let Some(&a) = self.attrs.get(&target_id.local_id) {+        assert_eq!(id.owner, self.curr_owner.owner_id);+        assert_eq!(target_id.owner, self.curr_owner.owner_id);+        if let Some(&a) = self.curr_owner.attrs.get(&target_id.local_id) {             assert!(!a.is_empty());-            self.attrs.insert(id.local_id, a);+            self.curr_owner.attrs.insert(id.local_id, a);         }     } @@ -1706,9 +1693,9 @@ impl<'hir> LoweringContext<'_, 'hir> {                             ident,                             bounds,                         );-                        self.impl_trait_defs.push(param);+                        self.curr_owner.impl_trait_defs.push(param);                         if let Some(bounds) = bounds {-                            self.impl_trait_bounds.push(bounds);+                            self.curr_owner.impl_trait_bounds.push(bounds);                         }                         path                     }@@ -1812,7 +1799,7 @@ impl<'hir> LoweringContext<'_, 'hir> {              None => {                 let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =-                    self.owner.get_lifetime_res(t.id)+                    self.curr_owner.owner.get_lifetime_res(t.id)                 {                     assert_eq!(start.plus(1), end);                     start@@ -1996,27 +1983,27 @@ impl<'hir> LoweringContext<'_, 'hir> {          let output = match coro {             Some(coro) => {-                let fn_def_id = self.owner.def_id;+                let fn_def_id = self.curr_owner.owner.def_id;                 self.lower_coroutine_fn_ret_ty(&decl.output, fn_def_id, coro, kind)             }             None => match &decl.output {                 FnRetTy::Ty(ty) => {                     let itctx = match kind {                         FnDeclKind::Fn | FnDeclKind::Inherent => ImplTraitContext::OpaqueTy {                             origin: hir::OpaqueTyOrigin::FnReturn {-                                parent: self.owner.def_id,+                                parent: self.curr_owner.owner.def_id,                                 in_trait_or_impl: None,                             },                         },                         FnDeclKind::Trait => ImplTraitContext::OpaqueTy {                             origin: hir::OpaqueTyOrigin::FnReturn {-                                parent: self.owner.def_id,+                                parent: self.curr_owner.owner.def_id,                                 in_trait_or_impl: Some(hir::RpitContext::Trait),                             },                         },                         FnDeclKind::Impl => ImplTraitContext::OpaqueTy {                             origin: hir::OpaqueTyOrigin::FnReturn {-                                parent: self.owner.def_id,+                                parent: self.curr_owner.owner.def_id,                                 in_trait_or_impl: Some(hir::RpitContext::TraitImpl),                             },                         },@@ -2061,7 +2048,8 @@ impl<'hir> LoweringContext<'_, 'hir> {                 }             }))             .set_lifetime_elision_allowed(-                self.owner.id == fn_node_id && self.owner.lifetime_elision_allowed,+                self.curr_owner.owner.id == fn_node_id+                    && self.curr_owner.owner.lifetime_elision_allowed,             )             .set_c_variadic(c_variadic)             .set_splatted(splatted, inputs.len())@@ -2229,7 +2217,7 @@ impl<'hir> LoweringContext<'_, 'hir> {         source: LifetimeSource,         syntax: LifetimeSyntax,     ) -> &'hir hir::Lifetime {-        let res = if let Some(res) = self.owner.get_lifetime_res(id) {+        let res = if let Some(res) = self.curr_owner.owner.get_lifetime_res(id) {             match res {                 LifetimeRes::Param { param, .. } => hir::LifetimeKind::Param(param),                 LifetimeRes::Fresh { param, .. } => {@@ -2315,12 +2303,13 @@ impl<'hir> LoweringContext<'_, 'hir> {                 // AST resolution emitted an error on those parameters, so we lower them using                 // `ParamName::Error`.                 let ident = self.lower_ident(param.ident);-                let param_name =-                    if let Some(LifetimeRes::Error(..)) = self.owner.get_lifetime_res(param.id) {-                        ParamName::Error(ident)-                    } else {-                        ParamName::Plain(ident)-                    };+                let param_name = if let Some(LifetimeRes::Error(..)) =+                    self.curr_owner.owner.get_lifetime_res(param.id)+                {+                    ParamName::Error(ident)+                } else {+                    ParamName::Plain(ident)+                };                 let kind =                     hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }; @@ -3102,7 +3091,7 @@ impl<'hir> LoweringContext<'_, 'hir> {         let hir_id = self.next_id();         if let Some(a) = attrs {             assert!(!a.is_empty());-            self.attrs.insert(hir_id.local_id, a);+            self.curr_owner.attrs.insert(hir_id.local_id, a);         }         let local = hir::LetStmt {             super_: None,
compiler/rustc_ast_lowering/src/pat.rs4 + / 4
@@ -289,17 +289,17 @@ impl<'hir> LoweringContext<'_, 'hir> {                         // will be resolved to the same `Res::Local`. Thus they just share a single                         // `HirId`.                         if id == p.id {-                            self.ident_and_label_to_local_id.insert(id, hir_id.local_id);+                            self.curr_owner.ident_and_label_to_local_id.insert(id, hir_id.local_id);                             hir_id                         } else {                             hir::HirId {-                                owner: self.current_hir_id_owner,-                                local_id: self.ident_and_label_to_local_id[&id],+                                owner: self.curr_owner.owner_id,+                                local_id: self.curr_owner.ident_and_label_to_local_id[&id],                             }                         }                     }                     _ => {-                        self.ident_and_label_to_local_id.insert(p.id, hir_id.local_id);+                        self.curr_owner.ident_and_label_to_local_id.insert(p.id, hir_id.local_id);                         hir_id                     }                 };
compiler/rustc_ast_lowering/src/path.rs1 + / 1
@@ -425,7 +425,7 @@ impl<'hir> LoweringContext<'_, 'hir> {         segment_ident_span: Span,         generic_args: &mut GenericArgsCtor<'hir>,     ) {-        let (start, end) = match self.owner.get_lifetime_res(segment_id) {+        let (start, end) = match self.curr_owner.owner.get_lifetime_res(segment_id) {             Some(LifetimeRes::ElidedAnchor { start, end }) => (start, end),             None => return,             Some(res) => {
compiler/rustc_middle/src/ty/mod.rs4 + / 3
@@ -210,8 +210,8 @@ pub struct PerOwnerResolverData<'tcx> {     pub node_id_to_def_id: NodeMap<LocalDefId> = Default::default(),     /// Whether lifetime elision was successful.     pub lifetime_elision_allowed: bool = false,-    /// Resolutions for labels.-    /// Maps from NodeId of the break/continue expression to the NodeId of their corresponding blocks or loops.+    /// Resolutions for labels. Maps from NodeId of the break/continue expression to the NodeId of+    /// their corresponding blocks or loops.     pub label_res_map: NodeMap<ast::NodeId> = Default::default(),     /// Resolutions for lifetimes.     pub lifetimes_res_map: NodeMap<LifetimeRes> = Default::default(),@@ -221,7 +221,8 @@ pub struct PerOwnerResolverData<'tcx> {     /// Resolution for import nodes, which have multiple resolutions in different namespaces.     pub import_res: hir::def::PerNS<Option<Res<ast::NodeId>>> = Default::default(),     /// Lifetime parameters that lowering will have to introduce.-    pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, hir::MissingLifetimeKind)>> = Default::default(),+    pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, hir::MissingLifetimeKind)>> =+        Default::default(),      /// The id of the owner     pub id: ast::NodeId,