Skip to content

Commit aa33354

Browse files
Rollup merge of #155547 - aerooneqq:better-disambiguators, r=oli-obk
Use per-parent disambiguators everywhere This PR addressing the following concerns about per-parent disambiguators (#153955): - DisambiguatorState is removed, PerParentDisambiguatorState is now used everywhere, - Steals were removed from every per-parent disambiguator in resolver, - It adds `parent` field in `PerParentDisambiguatorState` in `#[cfg(debug_assertions)]` for asserting that per-parent disambiguator corresponds to the same `LocalDefId` which is passed into `create_def`, - ~Removes `Disambiguator` trait replacing it with `Disambiguator` enum, with this change we no longer expose `next` method (as trait should be public otherwise the warning will be emitted). It may affect perf in a negative way though.~ ~Those changes should not fix perf issues that were [reported](#153955 (comment)), perf run that was attempted [before](#153955 (comment)) showed much better results. Performance can be probably fixed by removing per-parent disambiguators replacing them with a single one as it was before, then it will be passed to AST -> HIR lowering and modified. For delayed owners we can store ~followup disambiguators as it was in the beginning of the #153955~ per-parent disambiguators. This solution should save achievements from #153955 (removed `DefPathData` variants). However, I would prefer to keep per-parent disambiguators as it seems a better architectural solution for me.~ r? @petrochenkov cc @oli-obk
2 parents 63b6bd9 + 2e6a082 commit aa33354

12 files changed

Lines changed: 129 additions & 109 deletions

File tree

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
use std::mem;
2+
use std::sync::Arc;
23

34
use rustc_abi::ExternAbi;
45
use rustc_ast::visit::AssocCtxt;
56
use rustc_ast::*;
67
use rustc_data_structures::fx::FxIndexMap;
8+
use rustc_data_structures::steal::Steal;
79
use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
810
use rustc_hir::attrs::{AttributeKind, EiiImplResolution};
911
use rustc_hir::def::{DefKind, PerNS, Res};
10-
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
12+
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId, LocalDefIdMap};
13+
use rustc_hir::definitions::PerParentDisambiguatorState;
1114
use rustc_hir::{
1215
self as hir, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin, Target, find_attr,
1316
};
@@ -48,11 +51,21 @@ impl<'hir> Owners<'_, 'hir> {
4851
}
4952
}
5053

54+
/// Default disambiguators are used during default lowering, when we lower
55+
/// AST owners in a loop we can use the whole map, in contrast delayed lowering
56+
/// lowers each AST owner separately, so we use readonly disambiguators map
57+
/// with `Steal`s to get disambiguators.
58+
pub(super) enum Disambiguators {
59+
Default(LocalDefIdMap<PerParentDisambiguatorState>),
60+
Delayed(Arc<LocalDefIdMap<Steal<PerParentDisambiguatorState>>>),
61+
}
62+
5163
pub(super) struct ItemLowerer<'a, 'hir, R> {
5264
pub(super) tcx: TyCtxt<'hir>,
5365
pub(super) resolver: &'a mut R,
5466
pub(super) ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
5567
pub(super) owners: Owners<'a, 'hir>,
68+
pub(super) disambiguators: &'a mut Disambiguators,
5669
}
5770

5871
/// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span
@@ -80,7 +93,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> ItemLowerer<'_, 'hir, R> {
8093
owner: NodeId,
8194
f: impl FnOnce(&mut LoweringContext<'_, 'hir, R>) -> hir::OwnerNode<'hir>,
8295
) {
83-
let mut lctx = LoweringContext::new(self.tcx, self.resolver);
96+
let mut lctx = LoweringContext::new(self.tcx, self.resolver, self.disambiguators);
8497
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
8598

8699
for (def_id, info) in lctx.children {

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ use thin_vec::ThinVec;
7070
use tracing::{debug, instrument, trace};
7171

7272
use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait};
73-
use crate::item::Owners;
73+
use crate::item::{Disambiguators, Owners};
7474

7575
macro_rules! arena_vec {
7676
($this:expr; $($x:expr),*) => (
@@ -94,7 +94,8 @@ pub mod stability;
9494
struct LoweringContext<'a, 'hir, R> {
9595
tcx: TyCtxt<'hir>,
9696
resolver: &'a mut R,
97-
disambiguator: PerParentDisambiguatorState,
97+
disambiguators: &'a mut Disambiguators,
98+
current_disambiguator: PerParentDisambiguatorState,
9899

99100
/// Used to allocate HIR nodes.
100101
arena: &'hir hir::Arena<'hir>,
@@ -154,12 +155,13 @@ struct LoweringContext<'a, 'hir, R> {
154155
}
155156

156157
impl<'a, 'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'a, 'hir, R> {
157-
fn new(tcx: TyCtxt<'hir>, resolver: &'a mut R) -> Self {
158+
fn new(tcx: TyCtxt<'hir>, resolver: &'a mut R, disambiguators: &'a mut Disambiguators) -> Self {
158159
let registered_tools = tcx.registered_tools(()).iter().map(|x| x.name).collect();
159160
Self {
160161
tcx,
161162
resolver,
162-
disambiguator: Default::default(),
163+
disambiguators,
164+
current_disambiguator: Default::default(),
163165
arena: tcx.hir_arena,
164166

165167
// HirId handling.
@@ -302,10 +304,6 @@ impl<'a, 'tcx> ResolverAstLoweringExt<'tcx> for ResolverDelayedAstLowering<'a, '
302304
fn next_node_id(&mut self) -> NodeId {
303305
next_node_id(&mut self.next_node_id)
304306
}
305-
306-
fn steal_or_create_disambiguator(&self, parent: LocalDefId) -> PerParentDisambiguatorState {
307-
self.base.steal_or_create_disambiguator(parent)
308-
}
309307
}
310308

311309
fn next_node_id(current_id: &mut NodeId) -> NodeId {
@@ -408,10 +406,6 @@ impl<'tcx> ResolverAstLowering<'tcx> {
408406
fn next_node_id(&mut self) -> NodeId {
409407
next_node_id(&mut self.next_node_id)
410408
}
411-
412-
fn steal_or_create_disambiguator(&self, parent: LocalDefId) -> PerParentDisambiguatorState {
413-
self.per_parent_disambiguators.get(&parent).map(|s| s.steal()).unwrap_or_default()
414-
}
415409
}
416410

417411
/// How relaxed bounds `?Trait` should be treated.
@@ -632,11 +626,13 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> {
632626
tcx.definitions_untracked().def_index_count(),
633627
);
634628

629+
let mut disambiguators = Disambiguators::Default(resolver.disambiguators.steal());
635630
let mut lowerer = item::ItemLowerer {
636631
tcx,
637632
resolver: &mut resolver,
638633
ast_index: &ast_index,
639634
owners: Owners::IndexVec(&mut owners),
635+
disambiguators: &mut disambiguators,
640636
};
641637

642638
let mut delayed_ids: FxIndexSet<LocalDefId> = Default::default();
@@ -655,15 +651,19 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> {
655651
let opt_hir_hash =
656652
if tcx.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None };
657653

658-
let delayed_resolver = Steal::new((resolver, krate));
654+
let Disambiguators::Default(disambiguators) = disambiguators else { unreachable!() };
655+
let delayed_disambigs =
656+
Arc::new(disambiguators.into_items().map(|(id, d)| (id, Steal::new(d))).collect());
657+
658+
let delayed_resolver = Steal::new((resolver, krate, delayed_disambigs));
659659
mid_hir::Crate::new(owners, delayed_ids, delayed_resolver, opt_hir_hash)
660660
}
661661

662662
/// Lowers an AST owner corresponding to `def_id`, now only delegations are lowered this way.
663663
pub fn lower_delayed_owner(tcx: TyCtxt<'_>, def_id: LocalDefId) {
664664
let krate = tcx.hir_crate(());
665665

666-
let (resolver, krate) = &*krate.delayed_resolver.borrow();
666+
let (resolver, krate, delayed_disambigs) = &*krate.delayed_resolver.borrow();
667667

668668
// FIXME!!!(fn_delegation): make ast index lifetime same as resolver,
669669
// as it is too bad to reindex whole crate on each delegation lowering.
@@ -677,12 +677,12 @@ pub fn lower_delayed_owner(tcx: TyCtxt<'_>, def_id: LocalDefId) {
677677
};
678678

679679
let mut map = Default::default();
680-
681680
let mut lowerer = item::ItemLowerer {
682681
tcx,
683682
resolver: &mut resolver,
684683
ast_index: &ast_index,
685684
owners: Owners::Map(&mut map),
685+
disambiguators: &mut Disambiguators::Delayed(Arc::clone(delayed_disambigs)),
686686
};
687687

688688
lowerer.lower_node(def_id);
@@ -740,7 +740,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
740740
let def_id = self
741741
.tcx
742742
.at(span)
743-
.create_def(parent, name, def_kind, None, &mut self.disambiguator)
743+
.create_def(parent, name, def_kind, None, &mut self.current_disambiguator)
744744
.def_id();
745745

746746
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
@@ -780,9 +780,16 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
780780
f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>,
781781
) {
782782
let owner_id = self.owner_id(owner);
783+
let def_id = owner_id.def_id;
784+
785+
let new_disambig = match &mut self.disambiguators {
786+
Disambiguators::Default(map) => map.remove(&def_id),
787+
Disambiguators::Delayed(map) => map.get(&def_id).map(Steal::steal),
788+
};
789+
790+
let new_disambig = new_disambig.unwrap_or_else(|| PerParentDisambiguatorState::new(def_id));
783791

784-
let new_disambig = self.resolver.steal_or_create_disambiguator(owner_id.def_id);
785-
let disambiguator = std::mem::replace(&mut self.disambiguator, new_disambig);
792+
let disambiguator = std::mem::replace(&mut self.current_disambiguator, new_disambig);
786793
let current_attrs = std::mem::take(&mut self.attrs);
787794
let current_bodies = std::mem::take(&mut self.bodies);
788795
let current_define_opaque = std::mem::take(&mut self.define_opaque);
@@ -817,7 +824,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
817824
assert!(self.impl_trait_bounds.is_empty());
818825
let info = self.make_owner_info(item);
819826

820-
self.disambiguator = disambiguator;
827+
self.current_disambiguator = disambiguator;
821828
self.attrs = current_attrs;
822829
self.bodies = current_bodies;
823830
self.define_opaque = current_define_opaque;

compiler/rustc_const_eval/src/interpret/intern.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616
use hir::def::DefKind;
1717
use rustc_ast::Mutability;
1818
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
19-
use rustc_hir as hir;
20-
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
19+
use rustc_hir::def_id::LocalDefIdMap;
20+
use rustc_hir::definitions::{
21+
DefPathData, PerParentDisambiguatorState, PerParentDisambiguatorsMap,
22+
};
23+
use rustc_hir::{self as hir};
2124
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
2225
use rustc_middle::mir::interpret::{
2326
AllocBytes, ConstAllocation, CtfeProvenance, InterpResult, Provenance,
@@ -105,7 +108,7 @@ fn intern_shallow<'tcx, M: CompileTimeMachine<'tcx>>(
105108
ecx: &mut InterpCx<'tcx, M>,
106109
alloc_id: AllocId,
107110
mutability: Mutability,
108-
disambiguator: Option<&mut DisambiguatorState>,
111+
disambiguators: Option<&mut LocalDefIdMap<PerParentDisambiguatorState>>,
109112
) -> Result<impl Iterator<Item = CtfeProvenance> + 'tcx, InternError> {
110113
trace!("intern_shallow {:?}", alloc_id);
111114
// remove allocation
@@ -129,7 +132,7 @@ fn intern_shallow<'tcx, M: CompileTimeMachine<'tcx>>(
129132
static_id,
130133
alloc_id,
131134
alloc,
132-
disambiguator.expect("disambiguator needed"),
135+
disambiguators.expect("disambiguators needed"),
133136
);
134137
} else {
135138
ecx.tcx.set_alloc_id_memory(alloc_id, alloc);
@@ -144,7 +147,7 @@ fn intern_as_new_static<'tcx>(
144147
static_id: LocalDefId,
145148
alloc_id: AllocId,
146149
alloc: ConstAllocation<'tcx>,
147-
disambiguator: &mut DisambiguatorState,
150+
disambiguators: &mut LocalDefIdMap<PerParentDisambiguatorState>,
148151
) {
149152
// `intern_const_alloc_recursive` is called once per static and it contains the `DisambiguatorState`.
150153
// The `<static_id>::{{nested}}` path is thus unique to `intern_const_alloc_recursive` and the
@@ -155,7 +158,8 @@ fn intern_as_new_static<'tcx>(
155158
None,
156159
DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true },
157160
Some(DefPathData::NestedStatic),
158-
disambiguator,
161+
//FIXME(oli-obk): cleanup (https://github.com/rust-lang/rust/pull/155547#discussion_r3110792640)
162+
disambiguators.get_or_create(static_id),
159163
);
160164
tcx.set_nested_alloc_id_static(alloc_id, feed.def_id());
161165

@@ -205,7 +209,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx>>(
205209
intern_kind: InternKind,
206210
ret: &MPlaceTy<'tcx>,
207211
) -> Result<(), InternError> {
208-
let mut disambiguator = DisambiguatorState::new();
212+
let mut disambiguators = Default::default();
209213

210214
// We are interning recursively, and for mutability we are distinguishing the "root" allocation
211215
// that we are starting in, and all other allocations that we are encountering recursively.
@@ -250,7 +254,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx>>(
250254
prepare_alloc(*ecx.tcx, *kind, alloc, base_mutability)?;
251255
alloc.provenance().ptrs().iter().map(|&(_, prov)| prov).collect()
252256
} else {
253-
intern_shallow(ecx, base_alloc_id, base_mutability, Some(&mut disambiguator))?.collect()
257+
intern_shallow(ecx, base_alloc_id, base_mutability, Some(&mut disambiguators))?.collect()
254258
};
255259
// We need to distinguish "has just been interned" from "was already in `tcx`",
256260
// so we track this in a separate set.
@@ -332,7 +336,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx>>(
332336
// okay with losing some potential for immutability here. This can anyway only affect
333337
// `static mut`.
334338
just_interned.insert(alloc_id);
335-
let next = intern_shallow(ecx, alloc_id, inner_mutability, Some(&mut disambiguator))?;
339+
let next = intern_shallow(ecx, alloc_id, inner_mutability, Some(&mut disambiguators))?;
336340
todo.extend(next);
337341
}
338342
if found_bad_mutable_ptr {

compiler/rustc_hir/src/definitions.rs

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
use std::fmt::{self, Write};
88
use std::hash::Hash;
99

10+
use rustc_data_structures::fx::FxHashMap;
1011
use rustc_data_structures::stable_hasher::StableHasher;
11-
use rustc_data_structures::unord::UnordMap;
1212
use rustc_hashes::Hash64;
1313
use rustc_index::IndexVec;
14-
use rustc_macros::{BlobDecodable, Decodable, Encodable};
14+
use rustc_macros::{BlobDecodable, Decodable, Encodable, extension};
15+
use rustc_span::def_id::LocalDefIdMap;
1516
use rustc_span::{Symbol, kw, sym};
1617
use tracing::{debug, instrument};
1718

@@ -97,45 +98,28 @@ impl DefPathTable {
9798
}
9899
}
99100

100-
pub trait Disambiguator {
101-
fn entry(&mut self, parent: LocalDefId, data: DefPathData) -> &mut u32;
102-
}
103-
104101
#[derive(Debug, Default, Clone)]
105102
pub struct PerParentDisambiguatorState {
106-
next: UnordMap<DefPathData, u32>,
107-
}
108-
109-
impl Disambiguator for PerParentDisambiguatorState {
110-
#[inline]
111-
fn entry(&mut self, _: LocalDefId, data: DefPathData) -> &mut u32 {
112-
self.next.entry(data).or_insert(0)
113-
}
114-
}
115-
116-
#[derive(Debug, Default, Clone)]
117-
pub struct DisambiguatorState {
118-
next: UnordMap<(LocalDefId, DefPathData), u32>,
103+
#[cfg(debug_assertions)]
104+
parent: Option<LocalDefId>,
105+
next: FxHashMap<DefPathData, u32>,
119106
}
120107

121-
impl Disambiguator for DisambiguatorState {
122-
#[inline]
123-
fn entry(&mut self, parent: LocalDefId, data: DefPathData) -> &mut u32 {
124-
self.next.entry((parent, data)).or_insert(0)
108+
impl PerParentDisambiguatorState {
109+
#[inline(always)]
110+
pub fn new(_parent: LocalDefId) -> PerParentDisambiguatorState {
111+
PerParentDisambiguatorState {
112+
#[cfg(debug_assertions)]
113+
parent: Some(_parent),
114+
next: Default::default(),
115+
}
125116
}
126117
}
127118

128-
impl DisambiguatorState {
129-
pub const fn new() -> Self {
130-
Self { next: Default::default() }
131-
}
132-
133-
/// Creates a `DisambiguatorState` where the next allocated `(LocalDefId, DefPathData)` pair
134-
/// will have `index` as the disambiguator.
135-
pub fn with(def_id: LocalDefId, data: DefPathData, index: u32) -> Self {
136-
let mut this = Self::new();
137-
this.next.insert((def_id, data), index);
138-
this
119+
#[extension(pub trait PerParentDisambiguatorsMap)]
120+
impl LocalDefIdMap<PerParentDisambiguatorState> {
121+
fn get_or_create(&mut self, parent: LocalDefId) -> &mut PerParentDisambiguatorState {
122+
self.entry(parent).or_insert_with(|| PerParentDisambiguatorState::new(parent))
139123
}
140124
}
141125

@@ -408,7 +392,7 @@ impl Definitions {
408392
&mut self,
409393
parent: LocalDefId,
410394
data: DefPathData,
411-
disambiguator: &mut impl Disambiguator,
395+
disambiguator: &mut PerParentDisambiguatorState,
412396
) -> LocalDefId {
413397
// We can't use `Debug` implementation for `LocalDefId` here, since it tries to acquire a
414398
// reference to `Definitions` and we're already holding a mutable reference.
@@ -422,7 +406,14 @@ impl Definitions {
422406

423407
// Find the next free disambiguator for this key.
424408
let disambiguator = {
425-
let next_disamb = disambiguator.entry(parent, data);
409+
#[cfg(debug_assertions)]
410+
debug_assert_eq!(
411+
parent,
412+
disambiguator.parent.expect("must be set"),
413+
"provided parent and parent in disambiguator must be the same"
414+
);
415+
416+
let next_disamb = disambiguator.next.entry(data).or_insert(0);
426417
let disambiguator = *next_disamb;
427418
*next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow");
428419
disambiguator

0 commit comments

Comments
 (0)