Auto merge of #90204 - cjgillot:owner-pull, r=michaelwoerister

Make lowering pull-based

~Based on https://github.com/rust-lang/rust/pull/90451~
Part of https://github.com/rust-lang/rust/pull/88186

The current lowering code visits all the item-likes in the AST in order, and lowers them one by one.
This PR changes it to index the AST and then proceed to lowering on-demand. This is closer to the logic of query-based lowering.
This commit is contained in:
bors 2022-03-31 15:20:59 +00:00
commit bd1a8692f6
5 changed files with 277 additions and 254 deletions

View File

@ -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<LocalDefId, AstOwner<'a>>,
pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
}
/// 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<T>(
impl<'a, 'hir> ItemLowerer<'a, 'hir> {
fn with_lctx(
&mut self,
impl_ref: &Option<TraitRef>,
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
}
}
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,
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.
}
// 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(),
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)
});
// 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));
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),
}
});
}
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.
}
_ => visit::walk_fn(self, fk, sp),
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_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)),
});
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_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))
})
}
fn lower_item(&mut self, item: &Item) {
self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item)))
}
fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) {
let def_id = self.resolver.local_def_id(item.id);
let parent_id = {
let parent = self.resolver.definitions().def_key(def_id).parent;
let local_def_index = parent.unwrap();
LocalDefId { local_def_index }
};
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();
}
_ => {}
};
match ctxt {
AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)),
}
})
}
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> {
// 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<T>(
&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
}
// 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<T>(&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);
// 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 res = f(self);
assert!(self.in_scope_lifetimes.is_empty());
self.in_scope_lifetimes = old_in_scope_lifetimes;
res
}
pub(super) fn lower_mod(&mut self, items: &[P<Item>], 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;

View File

@ -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<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
/// Bodies inside the owner being lowered.
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
/// Attributes inside the owner being lowered.
attrs: SortedMap<hir::ItemLocalId, &'hir [Attribute]>,
/// Collect items that were created by lowering the current owner.
children: FxHashMap<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
generator_kind: Option<hir::GeneratorKind>,
@ -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<PartialRes>;
/// Obtains per-namespace resolutions for `use` statement with the given `NodeId`.
fn get_import_res(&mut self, id: NodeId) -> PerNS<Option<Res<NodeId>>>;
fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>>;
/// Obtains resolution for a label with the given `NodeId`.
fn get_label_res(&mut self, id: NodeId) -> Option<NodeId>;
/// 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<NodeId>;
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<LocalDefId, AstOwner<'a>> {
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<LocalDefId, AstOwner<'a>>,
}
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<LocalDefId, hir::MaybeOwner<&hir::OwnerInfo<'_>>>,
) -> 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()),
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);
}
.lower_crate(krate)
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);
}

View File

@ -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<LocalDefId, ExpnId>,
@ -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 },

View File

@ -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<ast::Crate>,
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);

View File

@ -1061,7 +1061,6 @@ pub struct Resolver<'a> {
/// and how the `impl Trait` fragments were introduced.
invocation_parents: FxHashMap<LocalExpnId, (LocalDefId, ImplTraitContext)>,
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<LocalDefId>,
@ -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<Option<Res>> {
fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res>> {
self.import_res_map.get(&id).cloned().unwrap_or_default()
}
fn get_label_res(&mut self, id: NodeId) -> Option<NodeId> {
fn get_label_res(&self, id: NodeId) -> Option<NodeId> {
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(),