Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ef6abe7

Browse files
committedApr 17, 2025·
Split the resolver tables into per-owner tables, starting with node_id_to_def_id
1 parent 8fcd278 commit ef6abe7

File tree

10 files changed

+313
-97
lines changed

10 files changed

+313
-97
lines changed
 

‎compiler/rustc_ast_lowering/src/item.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
8787

8888
#[instrument(level = "debug", skip(self, c))]
8989
fn lower_crate(&mut self, c: &Crate) {
90-
debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID);
90+
debug_assert_eq!(
91+
self.resolver.owners[&CRATE_NODE_ID].node_id_to_def_id[&CRATE_NODE_ID],
92+
CRATE_DEF_ID
93+
);
9194
self.with_lctx(CRATE_NODE_ID, |lctx| {
9295
let module = lctx.lower_mod(&c.items, &c.spans);
9396
// FIXME(jdonszelman): is dummy span ever a problem here?
@@ -101,6 +104,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
101104
self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item)))
102105
}
103106

107+
#[instrument(level = "debug", skip(self))]
104108
fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) {
105109
self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt))
106110
}

‎compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#![doc(rust_logo)]
3636
#![feature(assert_matches)]
3737
#![feature(box_patterns)]
38+
#![feature(closure_track_caller)]
3839
#![feature(exact_size_is_empty)]
3940
#![feature(if_let_guard)]
4041
#![feature(let_chains)]
@@ -59,7 +60,7 @@ use rustc_hir::{
5960
};
6061
use rustc_index::{Idx, IndexSlice, IndexVec};
6162
use rustc_middle::span_bug;
62-
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
63+
use rustc_middle::ty::{PerOwnerResolverData, ResolverAstLowering, TyCtxt};
6364
use rustc_session::parse::{add_feature_diagnostics, feature_err};
6465
use rustc_span::symbol::{Ident, Symbol, kw, sym};
6566
use rustc_span::{DUMMY_SP, DesugaringKind, Span};
@@ -151,7 +152,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
151152
Self {
152153
// Pseudo-globals.
153154
tcx,
154-
resolver: PerOwnerResolver { general: resolver },
155+
resolver: PerOwnerResolver {
156+
general: resolver,
157+
item: PerOwnerResolverData::new(DUMMY_NODE_ID),
158+
},
155159
arena: tcx.hir_arena,
156160

157161
// HirId handling.
@@ -201,6 +205,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
201205

202206
pub(crate) struct PerOwnerResolver<'a> {
203207
pub general: &'a mut ResolverAstLowering,
208+
pub item: PerOwnerResolverData,
209+
}
210+
211+
impl<'a> std::ops::Deref for PerOwnerResolver<'a> {
212+
type Target = PerOwnerResolverData;
213+
214+
fn deref(&self) -> &Self::Target {
215+
&self.item
216+
}
204217
}
205218

206219
impl PerOwnerResolver<'_> {
@@ -368,17 +381,22 @@ enum AstOwner<'a> {
368381
}
369382

370383
fn index_crate<'a>(
371-
node_id_to_def_id: &NodeMap<LocalDefId>,
384+
owners: &NodeMap<PerOwnerResolverData>,
372385
krate: &'a Crate,
373386
) -> IndexVec<LocalDefId, AstOwner<'a>> {
374-
let mut indexer = Indexer { node_id_to_def_id, index: IndexVec::new() };
387+
let mut indexer = Indexer {
388+
owners,
389+
node_id_to_def_id: &owners[&CRATE_NODE_ID].node_id_to_def_id,
390+
index: IndexVec::new(),
391+
};
375392
*indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner) =
376393
AstOwner::Crate(krate);
377394
visit::walk_crate(&mut indexer, krate);
378395
return indexer.index;
379396

380397
struct Indexer<'s, 'a> {
381398
node_id_to_def_id: &'s NodeMap<LocalDefId>,
399+
owners: &'s NodeMap<PerOwnerResolverData>,
382400
index: IndexVec<LocalDefId, AstOwner<'a>>,
383401
}
384402

@@ -389,23 +407,38 @@ fn index_crate<'a>(
389407
}
390408

391409
fn visit_item(&mut self, item: &'a ast::Item) {
410+
let old = std::mem::replace(
411+
&mut self.node_id_to_def_id,
412+
&self.owners[&item.id].node_id_to_def_id,
413+
);
392414
let def_id = self.node_id_to_def_id[&item.id];
393415
*self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) = AstOwner::Item(item);
394-
visit::walk_item(self, item)
416+
visit::walk_item(self, item);
417+
self.node_id_to_def_id = old;
395418
}
396419

397420
fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: visit::AssocCtxt) {
421+
let old = std::mem::replace(
422+
&mut self.node_id_to_def_id,
423+
&self.owners[&item.id].node_id_to_def_id,
424+
);
398425
let def_id = self.node_id_to_def_id[&item.id];
399426
*self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) =
400427
AstOwner::AssocItem(item, ctxt);
401428
visit::walk_assoc_item(self, item, ctxt);
429+
self.node_id_to_def_id = old;
402430
}
403431

404432
fn visit_foreign_item(&mut self, item: &'a ast::ForeignItem) {
433+
let old = std::mem::replace(
434+
&mut self.node_id_to_def_id,
435+
&self.owners[&item.id].node_id_to_def_id,
436+
);
405437
let def_id = self.node_id_to_def_id[&item.id];
406438
*self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) =
407439
AstOwner::ForeignItem(item);
408440
visit::walk_item(self, item);
441+
self.node_id_to_def_id = old;
409442
}
410443
}
411444
}
@@ -442,7 +475,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
442475
tcx.ensure_done().get_lang_items(());
443476
let (mut resolver, krate) = tcx.resolver_for_lowering().steal();
444477

445-
let ast_index = index_crate(&resolver.node_id_to_def_id, &krate);
478+
let ast_index = index_crate(&resolver.owners, &krate);
446479
let mut owners = IndexVec::from_fn_n(
447480
|_| hir::MaybeOwner::Phantom,
448481
tcx.definitions_untracked().def_index_count(),
@@ -517,7 +550,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
517550
self.tcx.at(span).create_def(self.current_hir_id_owner.def_id, name, def_kind).def_id();
518551

519552
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
520-
self.resolver.general.node_id_to_def_id.insert(node_id, def_id);
553+
self.resolver.item.node_id_to_def_id.insert(node_id, def_id);
521554

522555
def_id
523556
}
@@ -532,16 +565,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
532565
/// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name
533566
/// resolver (if any).
534567
fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
535-
self.resolver.general.node_id_to_def_id.get(&node).copied()
568+
self.resolver.node_id_to_def_id.get(&node).copied()
536569
}
537570

538571
fn local_def_id(&self, node: NodeId) -> LocalDefId {
539-
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
572+
self.opt_local_def_id(node).unwrap_or_else(|| {
573+
self.resolver.general.owners.items().any(|(id, items)| {
574+
items.node_id_to_def_id.items().any(|(node_id, def_id)| {
575+
if *node_id == node {
576+
panic!(
577+
"{def_id:?} ({node_id}) was found in {:?} ({id})",
578+
items.node_id_to_def_id.get(id),
579+
)
580+
}
581+
false
582+
})
583+
});
584+
panic!("no entry for node id: `{node:?}`");
585+
})
540586
}
541587

542588
/// Given the id of an owner node in the AST, returns the corresponding `OwnerId`.
543589
fn owner_id(&self, node: NodeId) -> hir::OwnerId {
544-
hir::OwnerId { def_id: self.local_def_id(node) }
590+
hir::OwnerId { def_id: self.resolver.general.owners[&node].node_id_to_def_id[&node] }
545591
}
546592

547593
/// Freshen the `LoweringContext` and ready it to lower a nested item.
@@ -560,6 +606,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
560606
let current_attrs = std::mem::take(&mut self.attrs);
561607
let current_bodies = std::mem::take(&mut self.bodies);
562608
let current_define_opaque = std::mem::take(&mut self.define_opaque);
609+
let current_ast_owner = std::mem::replace(
610+
&mut self.resolver.item,
611+
self.resolver.general.owners.remove(&owner).unwrap(),
612+
);
563613
let current_ident_and_label_to_local_id =
564614
std::mem::take(&mut self.ident_and_label_to_local_id);
565615

@@ -605,6 +655,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
605655
self.impl_trait_defs = current_impl_trait_defs;
606656
self.impl_trait_bounds = current_impl_trait_bounds;
607657

658+
let _prev_owner_data = std::mem::replace(&mut self.resolver.item, current_ast_owner);
659+
#[cfg(debug_assertions)]
660+
self.resolver.general.owners.insert(owner, _prev_owner_data);
661+
608662
debug_assert!(!self.children.iter().any(|(id, _)| id == &owner_id.def_id));
609663
self.children.push((owner_id.def_id, hir::MaybeOwner::Owner(info)));
610664
}

‎compiler/rustc_expand/src/base.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,13 @@ pub trait ResolverExpand {
11161116
trait_def_id: DefId,
11171117
impl_def_id: LocalDefId,
11181118
) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate>;
1119+
1120+
/// Set a new owner and return the old one. Use only in the implementation
1121+
/// of `with_owner` and always call [Self::reset_owner] afterwards
1122+
fn set_owner(&mut self, id: NodeId) -> NodeId;
1123+
1124+
/// Switch back to the original owner.
1125+
fn reset_owner(&mut self, id: NodeId);
11191126
}
11201127

11211128
pub trait LintStoreExpand {

‎compiler/rustc_expand/src/expand.rs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,15 @@ use std::rc::Rc;
44
use std::sync::Arc;
55
use std::{iter, mem};
66

7-
use rustc_ast as ast;
87
use rustc_ast::mut_visit::*;
98
use rustc_ast::ptr::P;
109
use rustc_ast::token::{self, Delimiter};
1110
use rustc_ast::tokenstream::TokenStream;
1211
use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list};
1312
use rustc_ast::{
14-
AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind, ForeignItemKind,
15-
HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner, MetaItemKind, ModKind,
16-
NodeId, PatKind, StmtKind, TyKind,
13+
self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, CRATE_NODE_ID,
14+
DUMMY_NODE_ID, ExprKind, ForeignItemKind, HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle,
15+
MetaItemInner, MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind,
1716
};
1817
use rustc_ast_pretty::pprust;
1918
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
@@ -2178,34 +2177,45 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
21782177
};
21792178
}
21802179
}
2180+
2181+
fn with_owner<T>(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
2182+
if id == DUMMY_NODE_ID {
2183+
f(self)
2184+
} else {
2185+
let old = self.cx.resolver.set_owner(id);
2186+
let val = f(self);
2187+
self.cx.resolver.reset_owner(old);
2188+
val
2189+
}
2190+
}
21812191
}
21822192

21832193
impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
21842194
fn flat_map_item(&mut self, node: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
2185-
self.flat_map_node(node)
2195+
self.with_owner(node.id, |this| this.flat_map_node(node))
21862196
}
21872197

21882198
fn flat_map_assoc_item(
21892199
&mut self,
21902200
node: P<ast::AssocItem>,
21912201
ctxt: AssocCtxt,
21922202
) -> SmallVec<[P<ast::AssocItem>; 1]> {
2193-
match ctxt {
2194-
AssocCtxt::Trait => self.flat_map_node(AstNodeWrapper::new(node, TraitItemTag)),
2203+
self.with_owner(node.id, |this| match ctxt {
2204+
AssocCtxt::Trait => this.flat_map_node(AstNodeWrapper::new(node, TraitItemTag)),
21952205
AssocCtxt::Impl { of_trait: false } => {
2196-
self.flat_map_node(AstNodeWrapper::new(node, ImplItemTag))
2206+
this.flat_map_node(AstNodeWrapper::new(node, ImplItemTag))
21972207
}
21982208
AssocCtxt::Impl { of_trait: true } => {
2199-
self.flat_map_node(AstNodeWrapper::new(node, TraitImplItemTag))
2209+
this.flat_map_node(AstNodeWrapper::new(node, TraitImplItemTag))
22002210
}
2201-
}
2211+
})
22022212
}
22032213

22042214
fn flat_map_foreign_item(
22052215
&mut self,
22062216
node: P<ast::ForeignItem>,
22072217
) -> SmallVec<[P<ast::ForeignItem>; 1]> {
2208-
self.flat_map_node(node)
2218+
self.with_owner(node.id, |this| this.flat_map_node(node))
22092219
}
22102220

22112221
fn flat_map_variant(&mut self, node: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
@@ -2276,7 +2286,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
22762286
}
22772287

22782288
fn visit_crate(&mut self, node: &mut ast::Crate) {
2279-
self.visit_node(node)
2289+
self.with_owner(CRATE_NODE_ID, |this| this.visit_node(node))
22802290
}
22812291

22822292
fn visit_ty(&mut self, node: &mut P<ast::Ty>) {

‎compiler/rustc_middle/src/ty/mod.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,19 @@ pub struct ResolverGlobalCtxt {
185185
pub stripped_cfg_items: Steal<Vec<StrippedCfgItem>>,
186186
}
187187

188+
#[derive(Debug)]
189+
pub struct PerOwnerResolverData {
190+
pub node_id_to_def_id: NodeMap<LocalDefId>,
191+
/// The id of the owner
192+
pub id: ast::NodeId,
193+
}
194+
195+
impl PerOwnerResolverData {
196+
pub fn new(id: ast::NodeId) -> Self {
197+
Self { node_id_to_def_id: Default::default(), id }
198+
}
199+
}
200+
188201
/// Resolutions that should only be used for lowering.
189202
/// This struct is meant to be consumed by lowering.
190203
#[derive(Debug)]
@@ -202,9 +215,9 @@ pub struct ResolverAstLowering {
202215
/// Lifetime parameters that lowering will have to introduce.
203216
pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, LifetimeRes)>>,
204217

205-
pub next_node_id: ast::NodeId,
218+
pub owners: NodeMap<PerOwnerResolverData>,
206219

207-
pub node_id_to_def_id: NodeMap<LocalDefId>,
220+
pub next_node_id: ast::NodeId,
208221

209222
pub trait_map: NodeMap<Vec<hir::TraitCandidate>>,
210223
/// List functions and methods for which lifetime elision was successful.

‎compiler/rustc_passes/src/lang_items.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
291291

292292
self.check_for_lang(
293293
target,
294-
self.resolver.node_id_to_def_id[&i.id],
294+
self.resolver.owners[&i.id].node_id_to_def_id[&i.id],
295295
&i.attrs,
296296
i.span,
297297
i.opt_generics(),
@@ -306,7 +306,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
306306
for variant in &enum_definition.variants {
307307
self.check_for_lang(
308308
Target::Variant,
309-
self.resolver.node_id_to_def_id[&variant.id],
309+
self.resolver.owners[&self.parent_item.unwrap().id].node_id_to_def_id[&variant.id],
310310
&variant.attrs,
311311
variant.span,
312312
None,
@@ -348,7 +348,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
348348

349349
self.check_for_lang(
350350
target,
351-
self.resolver.node_id_to_def_id[&i.id],
351+
self.resolver.owners[&i.id].node_id_to_def_id[&i.id],
352352
&i.attrs,
353353
i.span,
354354
generics,

‎compiler/rustc_resolve/src/def_collector.rs

Lines changed: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_expand::expand::AstFragment;
88
use rustc_hir as hir;
99
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
1010
use rustc_hir::def_id::LocalDefId;
11+
use rustc_middle::ty::PerOwnerResolverData;
1112
use rustc_span::hygiene::LocalExpnId;
1213
use rustc_span::{Span, Symbol, sym};
1314
use tracing::debug;
@@ -20,8 +21,13 @@ pub(crate) fn collect_definitions(
2021
expansion: LocalExpnId,
2122
) {
2223
let invocation_parent = resolver.invocation_parents[&expansion];
24+
assert_eq!(resolver.current_owner.id, DUMMY_NODE_ID);
25+
resolver.current_owner = resolver.owners.remove(&invocation_parent.owner).unwrap();
2326
let mut visitor = DefCollector { resolver, expansion, invocation_parent };
2427
fragment.visit_with(&mut visitor);
28+
let tables =
29+
mem::replace(&mut resolver.current_owner, PerOwnerResolverData::new(DUMMY_NODE_ID));
30+
assert!(resolver.owners.insert(invocation_parent.owner, tables).is_none());
2531
}
2632

2733
/// Creates `DefId`s for nodes in the AST.
@@ -44,7 +50,8 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
4450
"create_def(node_id={:?}, def_kind={:?}, parent_def={:?})",
4551
node_id, def_kind, parent_def
4652
);
47-
self.resolver
53+
let def_id = self
54+
.resolver
4855
.create_def(
4956
parent_def,
5057
node_id,
@@ -53,7 +60,9 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
5360
self.expansion.to_expn_id(),
5461
span.with_parent(None),
5562
)
56-
.def_id()
63+
.def_id();
64+
assert!(self.resolver.node_id_to_def_id.insert(node_id, def_id).is_none());
65+
def_id
5766
}
5867

5968
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
@@ -62,6 +71,25 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
6271
self.invocation_parent.parent_def = orig_parent_def;
6372
}
6473

74+
fn with_owner<F: FnOnce(&mut Self)>(&mut self, owner: NodeId, f: F) {
75+
assert_ne!(owner, DUMMY_NODE_ID);
76+
if owner == CRATE_NODE_ID {
77+
// Special case: we always have an invocation parent of at least the crate root,
78+
// even for visiting the crate root, which would then remove the crate root from the tables
79+
// list twice and try to insert it twice afterwards.
80+
assert_eq!(self.resolver.current_owner.id, CRATE_NODE_ID);
81+
return f(self);
82+
}
83+
let tables =
84+
self.resolver.owners.remove(&owner).unwrap_or_else(|| PerOwnerResolverData::new(owner));
85+
let orig_owner = mem::replace(&mut self.resolver.current_owner, tables);
86+
let orig_invoc_owner = mem::replace(&mut self.invocation_parent.owner, owner);
87+
f(self);
88+
let tables = mem::replace(&mut self.resolver.current_owner, orig_owner);
89+
assert!(self.resolver.owners.insert(owner, tables).is_none());
90+
assert_eq!(mem::replace(&mut self.invocation_parent.owner, orig_invoc_owner), owner);
91+
}
92+
6593
fn with_impl_trait<F: FnOnce(&mut Self)>(
6694
&mut self,
6795
impl_trait_context: ImplTraitContext,
@@ -152,31 +180,34 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
152180
return self.visit_macro_invoc(i.id);
153181
}
154182
};
155-
let def_id =
156-
self.create_def(i.id, i.kind.ident().map(|ident| ident.name), def_kind, i.span);
183+
self.with_owner(i.id, |this| {
184+
let def_id =
185+
this.create_def(i.id, i.kind.ident().map(|ident| ident.name), def_kind, i.span);
157186

158-
if let Some(macro_data) = opt_macro_data {
159-
self.resolver.macro_map.insert(def_id.to_def_id(), macro_data);
160-
}
187+
if let Some(macro_data) = opt_macro_data {
188+
this.resolver.macro_map.insert(def_id.to_def_id(), macro_data);
189+
}
161190

162-
self.with_parent(def_id, |this| {
163-
this.with_impl_trait(ImplTraitContext::Existential, |this| {
164-
match i.kind {
165-
ItemKind::Struct(_, ref struct_def, _)
166-
| ItemKind::Union(_, ref struct_def, _) => {
167-
// If this is a unit or tuple-like struct, register the constructor.
168-
if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) {
169-
this.create_def(
170-
ctor_node_id,
171-
None,
172-
DefKind::Ctor(CtorOf::Struct, ctor_kind),
173-
i.span,
174-
);
191+
this.with_parent(def_id, |this| {
192+
this.with_impl_trait(ImplTraitContext::Existential, |this| {
193+
match i.kind {
194+
ItemKind::Struct(_, ref struct_def, _)
195+
| ItemKind::Union(_, ref struct_def, _) => {
196+
// If this is a unit or tuple-like struct, register the constructor.
197+
if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def)
198+
{
199+
this.create_def(
200+
ctor_node_id,
201+
None,
202+
DefKind::Ctor(CtorOf::Struct, ctor_kind),
203+
i.span,
204+
);
205+
}
175206
}
207+
_ => {}
176208
}
177-
_ => {}
178-
}
179-
visit::walk_item(this, i);
209+
visit::walk_item(this, i);
210+
})
180211
})
181212
});
182213
}
@@ -233,8 +264,10 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
233264
}
234265

235266
fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
236-
self.create_def(id, None, DefKind::Use, use_tree.span);
237-
visit::walk_use_tree(self, use_tree, id);
267+
self.with_owner(id, |this| {
268+
this.create_def(id, None, DefKind::Use, use_tree.span);
269+
visit::walk_use_tree(this, use_tree, id);
270+
})
238271
}
239272

240273
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
@@ -259,9 +292,11 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
259292
ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id),
260293
};
261294

262-
let def = self.create_def(fi.id, Some(ident.name), def_kind, fi.span);
295+
self.with_owner(fi.id, |this| {
296+
let def = this.create_def(fi.id, Some(ident.name), def_kind, fi.span);
263297

264-
self.with_parent(def, |this| visit::walk_item(this, fi));
298+
this.with_parent(def, |this| visit::walk_item(this, fi));
299+
})
265300
}
266301

267302
fn visit_variant(&mut self, v: &'a Variant) {
@@ -333,8 +368,10 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
333368
}
334369
};
335370

336-
let def = self.create_def(i.id, Some(ident.name), def_kind, i.span);
337-
self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt));
371+
self.with_owner(i.id, |this| {
372+
let def = this.create_def(i.id, Some(ident.name), def_kind, i.span);
373+
this.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt));
374+
})
338375
}
339376

340377
fn visit_pat(&mut self, pat: &'a Pat) {
@@ -451,7 +488,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
451488
if krate.is_placeholder {
452489
self.visit_macro_invoc(krate.id)
453490
} else {
454-
visit::walk_crate(self, krate)
491+
self.with_owner(CRATE_NODE_ID, |this| visit::walk_crate(this, krate))
455492
}
456493
}
457494

‎compiler/rustc_resolve/src/late.rs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,9 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
765765
let prev = replace(&mut self.diag_metadata.current_item, Some(item));
766766
// Always report errors in items we just entered.
767767
let old_ignore = replace(&mut self.in_func_body, false);
768-
self.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item));
768+
self.with_owner(item.id, |this| {
769+
this.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item))
770+
});
769771
self.in_func_body = old_ignore;
770772
self.diag_metadata.current_item = prev;
771773
}
@@ -1680,6 +1682,16 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
16801682
})
16811683
}
16821684

1685+
#[instrument(level = "debug", skip(self, work))]
1686+
fn with_owner<T>(&mut self, owner: NodeId, work: impl FnOnce(&mut Self) -> T) -> T {
1687+
let old_owner =
1688+
std::mem::replace(&mut self.r.current_owner, self.r.owners.remove(&owner).unwrap());
1689+
let ret = work(self);
1690+
let prev = std::mem::replace(&mut self.r.current_owner, old_owner);
1691+
self.r.owners.insert(prev.id, prev);
1692+
ret
1693+
}
1694+
16831695
#[instrument(level = "debug", skip(self, work))]
16841696
fn with_lifetime_rib<T>(
16851697
&mut self,
@@ -3098,7 +3110,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
30983110
replace(&mut self.diag_metadata.current_trait_assoc_items, Some(trait_items));
30993111

31003112
for item in trait_items {
3101-
self.resolve_trait_item(item);
3113+
self.with_owner(item.id, |this| {
3114+
this.resolve_trait_item(item);
3115+
})
31023116
}
31033117

31043118
self.diag_metadata.current_trait_assoc_items = trait_assoc_items;
@@ -3296,7 +3310,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
32963310
debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
32973311
let mut seen_trait_items = Default::default();
32983312
for item in impl_items {
3299-
this.resolve_impl_item(&**item, &mut seen_trait_items, trait_id);
3313+
this.with_owner(item.id, |this| {
3314+
this.resolve_impl_item(&**item, &mut seen_trait_items, trait_id);
3315+
})
33003316
}
33013317
});
33023318
});
@@ -5227,18 +5243,21 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
52275243

52285244
impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
52295245
pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
5230-
visit::walk_crate(&mut ItemInfoCollector { r: self }, krate);
5231-
let mut late_resolution_visitor = LateResolutionVisitor::new(self);
5232-
late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
5233-
visit::walk_crate(&mut late_resolution_visitor, krate);
5234-
for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() {
5235-
self.lint_buffer.buffer_lint(
5236-
lint::builtin::UNUSED_LABELS,
5237-
*id,
5238-
*span,
5239-
BuiltinLintDiag::UnusedLabel,
5240-
);
5241-
}
5246+
self.with_owner(CRATE_NODE_ID, |this| {
5247+
visit::walk_crate(&mut ItemInfoCollector { r: this }, krate);
5248+
let mut late_resolution_visitor = LateResolutionVisitor::new(this);
5249+
late_resolution_visitor
5250+
.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
5251+
visit::walk_crate(&mut late_resolution_visitor, krate);
5252+
for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() {
5253+
this.lint_buffer.buffer_lint(
5254+
lint::builtin::UNUSED_LABELS,
5255+
*id,
5256+
*span,
5257+
BuiltinLintDiag::UnusedLabel,
5258+
);
5259+
}
5260+
})
52425261
}
52435262
}
52445263

‎compiler/rustc_resolve/src/lib.rs

Lines changed: 65 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ use rustc_arena::{DroplessArena, TypedArena};
3939
use rustc_ast::expand::StrippedCfgItem;
4040
use rustc_ast::node_id::NodeMap;
4141
use rustc_ast::{
42-
self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, Expr, ExprKind, GenericArg, GenericArgs,
43-
LitKind, NodeId, Path, attr,
42+
self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, Expr, ExprKind,
43+
GenericArg, GenericArgs, LitKind, NodeId, Path, attr,
4444
};
4545
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
4646
use rustc_data_structures::intern::Interned;
@@ -62,16 +62,16 @@ use rustc_middle::middle::privacy::EffectiveVisibilities;
6262
use rustc_middle::query::Providers;
6363
use rustc_middle::span_bug;
6464
use rustc_middle::ty::{
65-
self, DelegationFnSig, Feed, MainDefinition, RegisteredTools, ResolverGlobalCtxt,
66-
ResolverOutputs, TyCtxt, TyCtxtFeed,
65+
self, DelegationFnSig, Feed, MainDefinition, PerOwnerResolverData, RegisteredTools,
66+
ResolverGlobalCtxt, ResolverOutputs, TyCtxt, TyCtxtFeed,
6767
};
6868
use rustc_query_system::ich::StableHashingContext;
6969
use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
7070
use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
7171
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
7272
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
7373
use smallvec::{SmallVec, smallvec};
74-
use tracing::debug;
74+
use tracing::{debug, instrument};
7575

7676
type Res = def::Res<NodeId>;
7777

@@ -176,13 +176,15 @@ struct InvocationParent {
176176
parent_def: LocalDefId,
177177
impl_trait_context: ImplTraitContext,
178178
in_attr: bool,
179+
owner: NodeId,
179180
}
180181

181182
impl InvocationParent {
182183
const ROOT: Self = Self {
183184
parent_def: CRATE_DEF_ID,
184185
impl_trait_context: ImplTraitContext::Existential,
185186
in_attr: false,
187+
owner: CRATE_NODE_ID,
186188
};
187189
}
188190

@@ -1060,6 +1062,12 @@ pub struct Resolver<'ra, 'tcx> {
10601062
// Used for suggestions during error reporting.
10611063
pat_span_map: NodeMap<Span>,
10621064

1065+
/// Preserves per owner data once the owner is finished resolving.
1066+
owners: NodeMap<PerOwnerResolverData>,
1067+
1068+
/// An entry of `owners` that gets taken out and reinserted whenever an owner is handled.
1069+
current_owner: PerOwnerResolverData,
1070+
10631071
/// Resolutions for nodes that have a single resolution.
10641072
partial_res_map: NodeMap<PartialRes>,
10651073
/// Resolutions for import nodes, which have multiple resolutions in different namespaces.
@@ -1182,7 +1190,7 @@ pub struct Resolver<'ra, 'tcx> {
11821190

11831191
next_node_id: NodeId,
11841192

1185-
node_id_to_def_id: NodeMap<Feed<'tcx, LocalDefId>>,
1193+
feed_for_node_id: NodeMap<Feed<'tcx, LocalDefId>>,
11861194

11871195
/// Indices of unnamed struct or variant fields with unresolved attributes.
11881196
placeholder_field_indices: FxHashMap<NodeId, usize>,
@@ -1229,6 +1237,22 @@ pub struct Resolver<'ra, 'tcx> {
12291237
mods_with_parse_errors: FxHashSet<DefId>,
12301238
}
12311239

1240+
impl<'ra, 'tcx> std::ops::DerefMut for Resolver<'ra, 'tcx> {
1241+
fn deref_mut(&mut self) -> &mut Self::Target {
1242+
assert_ne!(self.current_owner.id, DUMMY_NODE_ID);
1243+
&mut self.current_owner
1244+
}
1245+
}
1246+
1247+
impl<'ra, 'tcx> std::ops::Deref for Resolver<'ra, 'tcx> {
1248+
type Target = PerOwnerResolverData;
1249+
1250+
fn deref(&self) -> &Self::Target {
1251+
assert_ne!(self.current_owner.id, DUMMY_NODE_ID);
1252+
&self.current_owner
1253+
}
1254+
}
1255+
12321256
/// This provides memory for the rest of the crate. The `'ra` lifetime that is
12331257
/// used by many types in this crate is an abbreviation of `ResolverArenas`.
12341258
#[derive(Default)]
@@ -1316,7 +1340,7 @@ impl<'tcx> Resolver<'_, 'tcx> {
13161340
}
13171341

13181342
fn opt_feed(&self, node: NodeId) -> Option<Feed<'tcx, LocalDefId>> {
1319-
self.node_id_to_def_id.get(&node).copied()
1343+
self.feed_for_node_id.get(&node).copied()
13201344
}
13211345

13221346
fn feed(&self, node: NodeId) -> Feed<'tcx, LocalDefId> {
@@ -1338,12 +1362,12 @@ impl<'tcx> Resolver<'_, 'tcx> {
13381362
span: Span,
13391363
) -> TyCtxtFeed<'tcx, LocalDefId> {
13401364
assert!(
1341-
!self.node_id_to_def_id.contains_key(&node_id),
1365+
!self.feed_for_node_id.contains_key(&node_id),
13421366
"adding a def for node-id {:?}, name {:?}, data {:?} but a previous def exists: {:?}",
13431367
node_id,
13441368
name,
13451369
def_kind,
1346-
self.tcx.definitions_untracked().def_key(self.node_id_to_def_id[&node_id].key()),
1370+
self.tcx.definitions_untracked().def_key(self.feed_for_node_id[&node_id].key()),
13471371
);
13481372

13491373
// FIXME: remove `def_span` body, pass in the right spans here and call `tcx.at().create_def()`
@@ -1365,7 +1389,7 @@ impl<'tcx> Resolver<'_, 'tcx> {
13651389
// we don't need a mapping from `NodeId` to `LocalDefId`.
13661390
if node_id != ast::DUMMY_NODE_ID {
13671391
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
1368-
self.node_id_to_def_id.insert(node_id, feed.downgrade());
1392+
self.feed_for_node_id.insert(node_id, feed.downgrade());
13691393
}
13701394

13711395
feed
@@ -1384,11 +1408,11 @@ impl<'tcx> Resolver<'_, 'tcx> {
13841408
}
13851409

13861410
/// This function is very slow, as it iterates over the entire
1387-
/// [Resolver::node_id_to_def_id] map just to find the [NodeId]
1411+
/// [Resolver::feed_for_node_id] map just to find the [NodeId]
13881412
/// that corresponds to the given [LocalDefId]. Only use this in
13891413
/// diagnostics code paths.
13901414
fn def_id_to_node_id(&self, def_id: LocalDefId) -> NodeId {
1391-
self.node_id_to_def_id
1415+
self.feed_for_node_id
13921416
.items()
13931417
.filter(|(_, v)| v.key() == def_id)
13941418
.map(|(k, _)| *k)
@@ -1427,12 +1451,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
14271451
&mut Default::default(),
14281452
);
14291453

1430-
let mut node_id_to_def_id = NodeMap::default();
1454+
let mut feed_for_node_id = NodeMap::default();
1455+
let mut owner_data = PerOwnerResolverData::new(CRATE_NODE_ID);
14311456
let crate_feed = tcx.create_local_crate_def_id(crate_span);
14321457

14331458
crate_feed.def_kind(DefKind::Mod);
14341459
let crate_feed = crate_feed.downgrade();
1435-
node_id_to_def_id.insert(CRATE_NODE_ID, crate_feed);
1460+
owner_data.node_id_to_def_id.insert(CRATE_NODE_ID, crate_feed.key());
1461+
let mut owners = NodeMap::default();
1462+
owners.insert(CRATE_NODE_ID, owner_data);
1463+
feed_for_node_id.insert(CRATE_NODE_ID, crate_feed);
14361464

14371465
let mut invocation_parents = FxHashMap::default();
14381466
invocation_parents.insert(LocalExpnId::ROOT, InvocationParent::ROOT);
@@ -1476,6 +1504,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
14761504
indeterminate_imports: Vec::new(),
14771505

14781506
pat_span_map: Default::default(),
1507+
owners,
1508+
current_owner: PerOwnerResolverData::new(DUMMY_NODE_ID),
14791509
partial_res_map: Default::default(),
14801510
import_res_map: Default::default(),
14811511
import_use_map: Default::default(),
@@ -1560,7 +1590,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15601590
containers_deriving_copy: Default::default(),
15611591
lint_buffer: LintBuffer::default(),
15621592
next_node_id: CRATE_NODE_ID,
1563-
node_id_to_def_id,
1593+
feed_for_node_id,
15641594
placeholder_field_indices: Default::default(),
15651595
invocation_parents,
15661596
legacy_const_generic_args: Default::default(),
@@ -1653,8 +1683,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
16531683
self.stripped_cfg_items
16541684
.into_iter()
16551685
.filter_map(|item| {
1656-
let parent_module =
1657-
self.node_id_to_def_id.get(&item.parent_module)?.key().to_def_id();
1686+
let parent_module = self
1687+
.owners
1688+
.get(&item.parent_module)?
1689+
.node_id_to_def_id
1690+
.get(&item.parent_module)?
1691+
.to_def_id();
16581692
Some(StrippedCfgItem { parent_module, ident: item.ident, cfg: item.cfg })
16591693
})
16601694
.collect(),
@@ -1678,18 +1712,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
16781712
stripped_cfg_items,
16791713
};
16801714
let ast_lowering = ty::ResolverAstLowering {
1715+
owners: self.owners,
16811716
legacy_const_generic_args: self.legacy_const_generic_args,
16821717
partial_res_map: self.partial_res_map,
16831718
import_res_map: self.import_res_map,
16841719
label_res_map: self.label_res_map,
16851720
lifetimes_res_map: self.lifetimes_res_map,
16861721
extra_lifetime_params_map: self.extra_lifetime_params_map,
16871722
next_node_id: self.next_node_id,
1688-
node_id_to_def_id: self
1689-
.node_id_to_def_id
1690-
.into_items()
1691-
.map(|(k, f)| (k, f.key()))
1692-
.collect(),
16931723
trait_map: self.trait_map,
16941724
lifetime_elision_allowed: self.lifetime_elision_allowed,
16951725
lint_buffer: Steal::new(self.lint_buffer),
@@ -2264,6 +2294,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
22642294
}
22652295
self.main_def = Some(MainDefinition { res, is_import, span });
22662296
}
2297+
2298+
#[instrument(level = "debug", skip(self, work))]
2299+
fn with_owner<T>(&mut self, owner: NodeId, work: impl FnOnce(&mut Self) -> T) -> T {
2300+
let old_owner =
2301+
std::mem::replace(&mut self.current_owner, self.owners.remove(&owner).unwrap());
2302+
let ret = work(self);
2303+
assert!(
2304+
self.owners
2305+
.insert(owner, std::mem::replace(&mut self.current_owner, old_owner))
2306+
.is_none()
2307+
);
2308+
ret
2309+
}
22672310
}
22682311

22692312
fn names_to_string(names: impl Iterator<Item = Symbol>) -> String {

‎compiler/rustc_resolve/src/macros.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::mem;
66
use std::sync::Arc;
77

88
use rustc_ast::expand::StrippedCfgItem;
9-
use rustc_ast::{self as ast, Crate, NodeId, attr};
9+
use rustc_ast::{self as ast, Crate, DUMMY_NODE_ID, NodeId, attr};
1010
use rustc_ast_pretty::pprust;
1111
use rustc_attr_parsing::{AttributeKind, StabilityLevel, find_attr};
1212
use rustc_data_structures::intern::Interned;
@@ -21,7 +21,7 @@ use rustc_expand::expand::{
2121
use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind};
2222
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
2323
use rustc_middle::middle::stability;
24-
use rustc_middle::ty::{RegisteredTools, TyCtxt, Visibility};
24+
use rustc_middle::ty::{PerOwnerResolverData, RegisteredTools, TyCtxt, Visibility};
2525
use rustc_session::lint::BuiltinLintDiag;
2626
use rustc_session::lint::builtin::{
2727
LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
@@ -511,6 +511,35 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
511511
});
512512
Ok(idents)
513513
}
514+
515+
fn set_owner(&mut self, id: NodeId) -> NodeId {
516+
assert_ne!(id, DUMMY_NODE_ID);
517+
let old = std::mem::replace(
518+
&mut self.current_owner,
519+
self.owners.remove(&id).unwrap_or_else(|| PerOwnerResolverData::new(id)),
520+
);
521+
let old_id = old.id;
522+
if old.id == DUMMY_NODE_ID {
523+
if cfg!(debug_assertions) {
524+
let PerOwnerResolverData { node_id_to_def_id, id: _ } = old;
525+
assert!(node_id_to_def_id.is_empty());
526+
}
527+
} else {
528+
assert!(self.owners.insert(old.id, old).is_none());
529+
}
530+
old_id
531+
}
532+
533+
fn reset_owner(&mut self, id: NodeId) {
534+
let new = if id == DUMMY_NODE_ID {
535+
PerOwnerResolverData::new(DUMMY_NODE_ID)
536+
} else {
537+
self.owners.remove(&id).unwrap()
538+
};
539+
let old = std::mem::replace(&mut self.current_owner, new);
540+
assert_ne!(old.id, DUMMY_NODE_ID);
541+
assert!(self.owners.insert(old.id, old).is_none());
542+
}
514543
}
515544

516545
impl<'ra, 'tcx> Resolver<'ra, 'tcx> {

0 commit comments

Comments
 (0)
Please sign in to comment.