diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 1784e4a6c63a8..c8fd96309a6cd 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1,16 +1,19 @@ use super::{AnonymousLifetimeMode, LoweringContext, ParamMode}; -use super::{ImplTraitContext, ImplTraitPosition}; +use super::{AstOwner, ImplTraitContext, ImplTraitPosition, ResolverAstLowering}; use crate::{Arena, FnDeclKind}; use rustc_ast::ptr::P; -use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; +use rustc_ast::visit::AssocCtxt; use rustc_ast::*; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::sorted_map::SortedMap; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::LocalDefId; -use rustc_index::vec::Idx; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; +use rustc_index::vec::{Idx, IndexVec}; +use rustc_session::utils::NtToTokenstream; +use rustc_session::Session; use rustc_span::source_map::{respan, DesugaringKind}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; @@ -19,10 +22,14 @@ use smallvec::{smallvec, SmallVec}; use tracing::debug; use std::iter; -use std::mem; -pub(super) struct ItemLowerer<'a, 'lowering, 'hir> { - pub(super) lctx: &'a mut LoweringContext<'lowering, 'hir>, +pub(super) struct ItemLowerer<'a, 'hir> { + pub(super) sess: &'a Session, + pub(super) resolver: &'a mut dyn ResolverAstLowering, + pub(super) nt_to_tokenstream: NtToTokenstream, + pub(super) arena: &'hir Arena<'hir>, + pub(super) ast_index: &'a IndexVec>, + pub(super) owners: &'a mut IndexVec>>, } /// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span @@ -45,130 +52,140 @@ fn add_ty_alias_where_clause( } } -impl ItemLowerer<'_, '_, '_> { - fn with_trait_impl_ref( +impl<'a, 'hir> ItemLowerer<'a, 'hir> { + fn with_lctx( &mut self, - impl_ref: &Option, - f: impl FnOnce(&mut Self) -> T, - ) -> T { - let old = self.lctx.is_in_trait_impl; - self.lctx.is_in_trait_impl = impl_ref.is_some(); - let ret = f(self); - self.lctx.is_in_trait_impl = old; - ret - } -} - -impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> { - fn visit_attribute(&mut self, _: &'a Attribute) { - // We do not want to lower expressions that appear in attributes, - // as they are not accessible to the rest of the HIR. - } + owner: NodeId, + f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>, + ) { + let mut lctx = LoweringContext { + // Pseudo-globals. + sess: &self.sess, + resolver: self.resolver, + nt_to_tokenstream: self.nt_to_tokenstream, + arena: self.arena, + + // HirId handling. + bodies: Vec::new(), + attrs: SortedMap::default(), + children: FxHashMap::default(), + current_hir_id_owner: CRATE_DEF_ID, + item_local_id_counter: hir::ItemLocalId::new(0), + node_id_to_local_id: Default::default(), + local_id_to_def_id: SortedMap::new(), + trait_map: Default::default(), + + // Lowering state. + catch_scope: None, + loop_scope: None, + is_in_loop_condition: false, + is_in_trait_impl: false, + is_in_dyn_type: false, + anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough, + generator_kind: None, + task_context: None, + current_item: None, + lifetimes_to_define: Vec::new(), + is_collecting_anonymous_lifetimes: None, + in_scope_lifetimes: Vec::new(), + allow_try_trait: Some([sym::try_trait_v2][..].into()), + allow_gen_future: Some([sym::gen_future][..].into()), + allow_into_future: Some([sym::into_future][..].into()), + }; + lctx.with_hir_id_owner(owner, |lctx| f(lctx)); - fn visit_item(&mut self, item: &'a Item) { - let hir_id = self.lctx.with_hir_id_owner(item.id, |lctx| { - let node = lctx.without_in_scope_lifetime_defs(|lctx| lctx.lower_item(item)); - hir::OwnerNode::Item(node) - }); - - self.lctx.with_parent_item_lifetime_defs(hir_id, |this| { - let this = &mut ItemLowerer { lctx: this }; - match item.kind { - ItemKind::Impl(box Impl { ref of_trait, .. }) => { - this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item)); - } - _ => visit::walk_item(this, item), - } - }); + for (def_id, info) in lctx.children { + self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); + debug_assert!(matches!(self.owners[def_id], hir::MaybeOwner::Phantom)); + self.owners[def_id] = info; + } } - fn visit_fn(&mut self, fk: FnKind<'a>, sp: Span, _: NodeId) { - match fk { - FnKind::Fn(FnCtxt::Foreign, _, sig, _, _) => { - self.visit_fn_header(&sig.header); - visit::walk_fn_decl(self, &sig.decl); - // Don't visit the foreign function body even if it has one, since lowering the - // body would have no meaning and will have already been caught as a parse error. + pub(super) fn lower_node( + &mut self, + def_id: LocalDefId, + ) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> { + self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); + if let hir::MaybeOwner::Phantom = self.owners[def_id] { + let node = self.ast_index[def_id]; + match node { + AstOwner::NonOwner => {} + AstOwner::Crate(c) => self.lower_crate(c), + AstOwner::Item(item) => self.lower_item(item), + AstOwner::AssocItem(item, ctxt) => self.lower_assoc_item(item, ctxt), + AstOwner::ForeignItem(item) => self.lower_foreign_item(item), } - _ => visit::walk_fn(self, fk, sp), } - } - - fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { - debug!(in_scope_lifetimes = ?self.lctx.in_scope_lifetimes); - self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt { - AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)), - AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)), - }); - visit::walk_assoc_item(self, item, ctxt); + self.owners[def_id] } - fn visit_foreign_item(&mut self, item: &'a ForeignItem) { - self.lctx.with_hir_id_owner(item.id, |lctx| { - hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)) - }); + fn lower_crate(&mut self, c: &Crate) { + debug_assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID); - visit::walk_foreign_item(self, item); + self.with_lctx(CRATE_NODE_ID, |lctx| { + let module = lctx.lower_mod(&c.items, c.spans.inner_span); + lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs); + hir::OwnerNode::Crate(lctx.arena.alloc(module)) + }) } -} -impl<'hir> LoweringContext<'_, 'hir> { - // Same as the method above, but accepts `hir::GenericParam`s - // instead of `ast::GenericParam`s. - // This should only be used with generics that have already had their - // in-band lifetimes added. In practice, this means that this function is - // only used when lowering a child item of a trait or impl. - #[tracing::instrument(level = "debug", skip(self, f))] - fn with_parent_item_lifetime_defs( - &mut self, - parent_hir_id: LocalDefId, - f: impl FnOnce(&mut Self) -> T, - ) -> T { - let parent_generics = match self.owners[parent_hir_id].unwrap().node().expect_item().kind { - hir::ItemKind::Impl(hir::Impl { ref generics, .. }) - | hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params, - _ => &[], - }; - let lt_def_names = parent_generics - .iter() - .filter_map(|param| match param.kind { - hir::GenericParamKind::Lifetime { .. } => { - Some(param.name.normalize_to_macros_2_0()) - } - _ => None, - }) - .collect(); - let old_in_scope_lifetimes = mem::replace(&mut self.in_scope_lifetimes, lt_def_names); - debug!(in_scope_lifetimes = ?self.in_scope_lifetimes); - - let res = f(self); - - self.in_scope_lifetimes = old_in_scope_lifetimes; - res + fn lower_item(&mut self, item: &Item) { + self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item))) } - // Clears (and restores) the `in_scope_lifetimes` field. Used when - // visiting nested items, which never inherit in-scope lifetimes - // from their surrounding environment. - #[tracing::instrument(level = "debug", skip(self, f))] - fn without_in_scope_lifetime_defs(&mut self, f: impl FnOnce(&mut Self) -> T) -> T { - let old_in_scope_lifetimes = mem::replace(&mut self.in_scope_lifetimes, vec![]); - debug!(?old_in_scope_lifetimes); + fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) { + let def_id = self.resolver.local_def_id(item.id); - // this vector is only used when walking over impl headers, - // input types, and the like, and should not be non-empty in - // between items - assert!(self.lifetimes_to_define.is_empty()); + let parent_id = { + let parent = self.resolver.definitions().def_key(def_id).parent; + let local_def_index = parent.unwrap(); + LocalDefId { local_def_index } + }; - let res = f(self); + let parent_hir = self.lower_node(parent_id).unwrap().node().expect_item(); + self.with_lctx(item.id, |lctx| { + // Evaluate with the lifetimes in `params` in-scope. + // 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.kind { + hir::ItemKind::Impl(hir::Impl { ref of_trait, ref generics, .. }) => { + 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| param.name) + .collect(); + } + hir::ItemKind::Trait(_, _, ref generics, ..) => { + lctx.in_scope_lifetimes = generics + .params + .iter() + .filter(|param| { + matches!(param.kind, hir::GenericParamKind::Lifetime { .. }) + }) + .map(|param| param.name) + .collect(); + } + _ => {} + }; - assert!(self.in_scope_lifetimes.is_empty()); - self.in_scope_lifetimes = old_in_scope_lifetimes; + match ctxt { + AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)), + AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)), + } + }) + } - res + fn lower_foreign_item(&mut self, item: &ForeignItem) { + self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))) } +} +impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_mod(&mut self, items: &[P], inner: Span) -> hir::Mod<'hir> { hir::Mod { inner: self.lower_span(inner), @@ -548,12 +565,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let new_id = self.resolver.local_def_id(new_node_id); let Some(res) = resolutions.next() else { // Associate an HirId to both ids even if there is no resolution. - self.owners.ensure_contains_elem(new_id, || hir::MaybeOwner::Phantom); - let _old = std::mem::replace( - &mut self.owners[new_id], + let _old = self.children.insert( + new_id, hir::MaybeOwner::NonOwner(hir::HirId::make_owner(new_id)), ); - debug_assert!(matches!(_old, hir::MaybeOwner::Phantom)); + debug_assert!(_old.is_none()); continue; }; let ident = *ident; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d684a0e67e20b..e4ed48d4b530d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -57,7 +57,6 @@ use rustc_hir::intravisit; use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; use rustc_index::vec::{Idx, IndexVec}; use rustc_query_system::ich::StableHashingContext; -use rustc_session::lint::LintBuffer; use rustc_session::parse::feature_err; use rustc_session::utils::{FlattenNonterminals, NtToTokenstream}; use rustc_session::Session; @@ -100,12 +99,12 @@ struct LoweringContext<'a, 'hir: 'a> { /// Used to allocate HIR nodes. arena: &'hir Arena<'hir>, - /// The items being lowered are collected here. - owners: IndexVec>>, /// Bodies inside the owner being lowered. bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, /// Attributes inside the owner being lowered. attrs: SortedMap, + /// Collect items that were created by lowering the current owner. + children: FxHashMap>>, generator_kind: Option, @@ -159,7 +158,7 @@ struct LoweringContext<'a, 'hir: 'a> { } pub trait ResolverAstLowering { - fn def_key(&mut self, id: DefId) -> DefKey; + fn def_key(&self, id: DefId) -> DefKey; fn def_span(&self, id: LocalDefId) -> Span; @@ -171,18 +170,14 @@ pub trait ResolverAstLowering { fn get_partial_res(&self, id: NodeId) -> Option; /// Obtains per-namespace resolutions for `use` statement with the given `NodeId`. - fn get_import_res(&mut self, id: NodeId) -> PerNS>>; + fn get_import_res(&self, id: NodeId) -> PerNS>>; /// Obtains resolution for a label with the given `NodeId`. - fn get_label_res(&mut self, id: NodeId) -> Option; - - /// We must keep the set of definitions up to date as we add nodes that weren't in the AST. - /// This should only return `None` during testing. - fn definitions(&mut self) -> &mut Definitions; + fn get_label_res(&self, id: NodeId) -> Option; fn create_stable_hashing_context(&self) -> StableHashingContext<'_>; - fn lint_buffer(&mut self) -> &mut LintBuffer; + fn definitions(&self) -> &Definitions; fn next_node_id(&mut self) -> NodeId; @@ -337,6 +332,81 @@ impl FnDeclKind { } } +#[derive(Copy, Clone)] +enum AstOwner<'a> { + NonOwner, + Crate(&'a ast::Crate), + Item(&'a ast::Item), + AssocItem(&'a ast::AssocItem, visit::AssocCtxt), + ForeignItem(&'a ast::ForeignItem), +} + +fn index_crate<'a>( + resolver: &dyn ResolverAstLowering, + krate: &'a Crate, +) -> IndexVec> { + let mut indexer = Indexer { resolver, index: IndexVec::new() }; + indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner); + indexer.index[CRATE_DEF_ID] = AstOwner::Crate(krate); + visit::walk_crate(&mut indexer, krate); + return indexer.index; + + struct Indexer<'s, 'a> { + resolver: &'s dyn ResolverAstLowering, + index: IndexVec>, + } + + impl<'a> visit::Visitor<'a> for Indexer<'_, 'a> { + fn visit_attribute(&mut self, _: &'a Attribute) { + // We do not want to lower expressions that appear in attributes, + // as they are not accessible to the rest of the HIR. + } + + fn visit_item(&mut self, item: &'a ast::Item) { + let def_id = self.resolver.local_def_id(item.id); + self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner); + self.index[def_id] = AstOwner::Item(item); + visit::walk_item(self, item) + } + + fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: visit::AssocCtxt) { + let def_id = self.resolver.local_def_id(item.id); + self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner); + self.index[def_id] = AstOwner::AssocItem(item, ctxt); + visit::walk_assoc_item(self, item, ctxt); + } + + fn visit_foreign_item(&mut self, item: &'a ast::ForeignItem) { + let def_id = self.resolver.local_def_id(item.id); + self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner); + self.index[def_id] = AstOwner::ForeignItem(item); + visit::walk_foreign_item(self, item); + } + } +} + +/// Compute the hash for the HIR of the full crate. +/// This hash will then be part of the crate_hash which is stored in the metadata. +fn compute_hir_hash( + resolver: &mut dyn ResolverAstLowering, + owners: &IndexVec>>, +) -> Fingerprint { + let mut hir_body_nodes: Vec<_> = owners + .iter_enumerated() + .filter_map(|(def_id, info)| { + let info = info.as_owner()?; + let def_path_hash = resolver.definitions().def_path_hash(def_id); + Some((def_path_hash, info)) + }) + .collect(); + hir_body_nodes.sort_unstable_by_key(|bn| bn.0); + + let mut stable_hasher = StableHasher::new(); + let mut hcx = resolver.create_stable_hashing_context(); + hir_body_nodes.hash_stable(&mut hcx, &mut stable_hasher); + stable_hasher.finish() +} + pub fn lower_crate<'a, 'hir>( sess: &'a Session, krate: &'a Crate, @@ -346,38 +416,26 @@ pub fn lower_crate<'a, 'hir>( ) -> &'hir hir::Crate<'hir> { let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering"); - let owners = + let ast_index = index_crate(resolver, krate); + + let mut owners = IndexVec::from_fn_n(|_| hir::MaybeOwner::Phantom, resolver.definitions().def_index_count()); - LoweringContext { - sess, - resolver, - nt_to_tokenstream, - arena, - owners, - bodies: Vec::new(), - attrs: SortedMap::new(), - catch_scope: None, - loop_scope: None, - is_in_loop_condition: false, - is_in_trait_impl: false, - is_in_dyn_type: false, - anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough, - current_hir_id_owner: CRATE_DEF_ID, - item_local_id_counter: hir::ItemLocalId::new(0), - node_id_to_local_id: FxHashMap::default(), - local_id_to_def_id: SortedMap::new(), - trait_map: FxHashMap::default(), - generator_kind: None, - task_context: None, - current_item: None, - lifetimes_to_define: Vec::new(), - is_collecting_anonymous_lifetimes: None, - in_scope_lifetimes: Vec::new(), - allow_try_trait: Some([sym::try_trait_v2][..].into()), - allow_gen_future: Some([sym::gen_future][..].into()), - allow_into_future: Some([sym::into_future][..].into()), - } - .lower_crate(krate) + + for def_id in ast_index.indices() { + item::ItemLowerer { + sess, + resolver, + nt_to_tokenstream, + arena, + ast_index: &ast_index, + owners: &mut owners, + } + .lower_node(def_id); + } + + let hir_hash = compute_hir_hash(resolver, &owners); + let krate = hir::Crate { owners, hir_hash }; + arena.alloc(krate) } #[derive(Copy, Clone, PartialEq)] @@ -446,49 +504,11 @@ enum AnonymousLifetimeMode { } impl<'a, 'hir> LoweringContext<'a, 'hir> { - fn lower_crate(mut self, c: &Crate) -> &'hir hir::Crate<'hir> { - debug_assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID); - - visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c); - - self.with_hir_id_owner(CRATE_NODE_ID, |lctx| { - let module = lctx.lower_mod(&c.items, c.spans.inner_span); - lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs); - hir::OwnerNode::Crate(lctx.arena.alloc(module)) - }); - - let hir_hash = self.compute_hir_hash(); - - let krate = hir::Crate { owners: self.owners, hir_hash }; - self.arena.alloc(krate) - } - - /// Compute the hash for the HIR of the full crate. - /// This hash will then be part of the crate_hash which is stored in the metadata. - fn compute_hir_hash(&mut self) -> Fingerprint { - let definitions = self.resolver.definitions(); - let mut hir_body_nodes: Vec<_> = self - .owners - .iter_enumerated() - .filter_map(|(def_id, info)| { - let info = info.as_owner()?; - let def_path_hash = definitions.def_path_hash(def_id); - Some((def_path_hash, info)) - }) - .collect(); - hir_body_nodes.sort_unstable_by_key(|bn| bn.0); - - let mut stable_hasher = StableHasher::new(); - let mut hcx = self.resolver.create_stable_hashing_context(); - hir_body_nodes.hash_stable(&mut hcx, &mut stable_hasher); - stable_hasher.finish() - } - fn with_hir_id_owner( &mut self, owner: NodeId, f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>, - ) -> LocalDefId { + ) { let def_id = self.resolver.local_def_id(owner); let current_attrs = std::mem::take(&mut self.attrs); @@ -516,15 +536,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.current_hir_id_owner = current_owner; self.item_local_id_counter = current_local_counter; - self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); - self.owners[def_id] = hir::MaybeOwner::Owner(self.arena.alloc(info)); - - def_id + let _old = self.children.insert(def_id, hir::MaybeOwner::Owner(info)); + debug_assert!(_old.is_none()) } - fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> hir::OwnerInfo<'hir> { + fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> { let attrs = std::mem::take(&mut self.attrs); let mut bodies = std::mem::take(&mut self.bodies); + let local_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id); + let trait_map = std::mem::take(&mut self.trait_map); #[cfg(debug_assertions)] for (id, attrs) in attrs.iter() { @@ -544,7 +564,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hash_without_bodies, nodes, bodies, - local_id_to_def_id: std::mem::take(&mut self.local_id_to_def_id), + local_id_to_def_id, }; let attrs = { let mut hcx = self.resolver.create_stable_hashing_context(); @@ -554,7 +574,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::AttributeMap { map: attrs, hash } }; - hir::OwnerInfo { nodes, parenting, attrs, trait_map: std::mem::take(&mut self.trait_map) } + self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map }) } /// Hash the HIR node twice, one deep and one shallow hash. This allows to differentiate @@ -602,11 +622,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { assert_ne!(local_id, hir::ItemLocalId::new(0)); if let Some(def_id) = self.resolver.opt_local_def_id(ast_node_id) { - self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); - if let o @ hir::MaybeOwner::Phantom = &mut self.owners[def_id] { - // Do not override a `MaybeOwner::Owner` that may already here. - *o = hir::MaybeOwner::NonOwner(hir_id); - } + // Do not override a `MaybeOwner::Owner` that may already here. + self.children.entry(def_id).or_insert(hir::MaybeOwner::NonOwner(hir_id)); self.local_id_to_def_id.insert(local_id, def_id); } diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 1ff9395c5892b..c62d3b9be2fcc 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -99,6 +99,7 @@ impl DefPathTable { #[derive(Clone, Debug)] pub struct Definitions { table: DefPathTable, + next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>, /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. expansions_that_defined: FxHashMap, @@ -340,6 +341,7 @@ impl Definitions { Definitions { table, + next_disambiguator: Default::default(), expansions_that_defined: Default::default(), def_id_to_span, stable_crate_id, @@ -357,7 +359,6 @@ impl Definitions { parent: LocalDefId, data: DefPathData, expn_id: ExpnId, - mut next_disambiguator: impl FnMut(LocalDefId, DefPathData) -> u32, span: Span, ) -> LocalDefId { debug!("create_def(parent={:?}, data={:?}, expn_id={:?})", parent, data, expn_id); @@ -365,7 +366,13 @@ impl Definitions { // The root node must be created with `create_root_def()`. assert!(data != DefPathData::CrateRoot); - let disambiguator = next_disambiguator(parent, data); + // Find the next free disambiguator for this key. + let disambiguator = { + let next_disamb = self.next_disambiguator.entry((parent, data)).or_insert(0); + let disambiguator = *next_disamb; + *next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow"); + disambiguator + }; let key = DefKey { parent: Some(parent.local_def_index), disambiguated_data: DisambiguatedDefPathData { data, disambiguator }, diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index ea4955e9a549a..f2164bccc3e9b 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -487,12 +487,24 @@ pub fn configure_and_expand( } }); + sess.time("early_lint_checks", || { + let lint_buffer = Some(std::mem::take(resolver.lint_buffer())); + rustc_lint::check_ast_node( + sess, + false, + lint_store, + resolver.registered_tools(), + lint_buffer, + rustc_lint::BuiltinCombinedEarlyLintPass::new(), + &krate, + ) + }); + Ok(krate) } pub fn lower_to_hir<'res, 'tcx>( sess: &'tcx Session, - lint_store: &LintStore, resolver: &'res mut Resolver<'_>, krate: Rc, arena: &'tcx rustc_ast_lowering::Arena<'tcx>, @@ -506,19 +518,6 @@ pub fn lower_to_hir<'res, 'tcx>( arena, ); - sess.time("early_lint_checks", || { - let lint_buffer = Some(std::mem::take(resolver.lint_buffer())); - rustc_lint::check_ast_node( - sess, - false, - lint_store, - resolver.registered_tools(), - lint_buffer, - rustc_lint::BuiltinCombinedEarlyLintPass::new(), - &*krate, - ) - }); - // Drop AST to free memory sess.time("drop_ast", || std::mem::drop(krate)); @@ -852,9 +851,8 @@ pub fn create_global_ctxt<'tcx>( dep_graph.assert_ignored(); let sess = &compiler.session(); - let krate = resolver - .borrow_mut() - .access(|resolver| lower_to_hir(sess, &lint_store, resolver, krate, hir_arena)); + let krate = + resolver.borrow_mut().access(|resolver| lower_to_hir(sess, resolver, krate, hir_arena)); let resolver_outputs = BoxedResolver::to_resolver_outputs(resolver); let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 48675fa88270a..1f0a6e5ce9716 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1061,7 +1061,6 @@ pub struct Resolver<'a> { /// and how the `impl Trait` fragments were introduced. invocation_parents: FxHashMap, - next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>, /// Some way to know that we are in a *trait* impl in `visit_assoc_item`. /// FIXME: Replace with a more general AST map (together with some other fields). trait_impl_items: FxHashSet, @@ -1160,9 +1159,9 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> { /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that /// the resolver is no longer needed as all the relevant information is inline. impl ResolverAstLowering for Resolver<'_> { - fn def_key(&mut self, id: DefId) -> DefKey { + fn def_key(&self, id: DefId) -> DefKey { if let Some(id) = id.as_local() { - self.definitions().def_key(id) + self.definitions.def_key(id) } else { self.cstore().def_key(id) } @@ -1189,24 +1188,20 @@ impl ResolverAstLowering for Resolver<'_> { self.partial_res_map.get(&id).cloned() } - fn get_import_res(&mut self, id: NodeId) -> PerNS> { + fn get_import_res(&self, id: NodeId) -> PerNS> { self.import_res_map.get(&id).cloned().unwrap_or_default() } - fn get_label_res(&mut self, id: NodeId) -> Option { + fn get_label_res(&self, id: NodeId) -> Option { self.label_res_map.get(&id).cloned() } - fn definitions(&mut self) -> &mut Definitions { - &mut self.definitions - } - fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { StableHashingContext::new(self.session, &self.definitions, self.crate_loader.cstore()) } - fn lint_buffer(&mut self) -> &mut LintBuffer { - &mut self.lint_buffer + fn definitions(&self) -> &Definitions { + &self.definitions } fn next_node_id(&mut self) -> NodeId { @@ -1249,16 +1244,7 @@ impl ResolverAstLowering for Resolver<'_> { self.definitions.def_key(self.node_id_to_def_id[&node_id]), ); - // Find the next free disambiguator for this key. - let next_disambiguator = &mut self.next_disambiguator; - let next_disambiguator = |parent, data| { - let next_disamb = next_disambiguator.entry((parent, data)).or_insert(0); - let disambiguator = *next_disamb; - *next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow"); - disambiguator - }; - - let def_id = self.definitions.create_def(parent, data, expn_id, next_disambiguator, span); + let def_id = self.definitions.create_def(parent, data, expn_id, span); // Some things for which we allocate `LocalDefId`s don't correspond to // anything in the AST, so they don't have a `NodeId`. For these cases @@ -1430,7 +1416,6 @@ impl<'a> Resolver<'a> { def_id_to_node_id, placeholder_field_indices: Default::default(), invocation_parents, - next_disambiguator: Default::default(), trait_impl_items: Default::default(), legacy_const_generic_args: Default::default(), item_generics_num_lifetimes: Default::default(),