Skip to content

Commit 243c5a3

Browse files
committed
Auto merge of rust-lang#140453 - Zoxc:next-disambiguator, r=oli-obk
Remove global `next_disambiguator` state and handle it with a `DisambiguatorState` type This removes `Definitions.next_disambiguator` as it doesn't guarantee deterministic def paths when `create_def` is called in parallel. Instead a new `DisambiguatorState` type is passed as a mutable reference to `create_def` to help create unique def paths. `create_def` calls with distinct `DisambiguatorState` instances must ensure that that the def paths are unique without its help. Anon associated types did rely on this global state for uniqueness and are changed to use (method they're defined in + their position in the method return type) as the `DefPathData` to ensure uniqueness. This also means that the method they're defined in appears in error messages, which is nicer. `DefPathData::NestedStatic` is added to use for nested data inside statics instead of reusing `DefPathData::AnonConst` to avoid conflicts with those. cc `@oli-obk`
2 parents 0eb0b8c + acb50d5 commit 243c5a3

File tree

23 files changed

+246
-117
lines changed

23 files changed

+246
-117
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
492492
let mut generic_args = ThinVec::new();
493493
for (idx, arg) in args.iter().cloned().enumerate() {
494494
if legacy_args_idx.contains(&idx) {
495-
let parent_def_id = self.current_hir_id_owner.def_id;
496495
let node_id = self.next_node_id();
497-
self.create_def(parent_def_id, node_id, None, DefKind::AnonConst, f.span);
496+
self.create_def(node_id, None, DefKind::AnonConst, f.span);
498497
let mut visitor = WillCreateDefIdsVisitor {};
499498
let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) {
500499
AstP(Expr {

compiler/rustc_ast_lowering/src/lib.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -500,12 +500,12 @@ enum GenericArgsMode {
500500
impl<'a, 'hir> LoweringContext<'a, 'hir> {
501501
fn create_def(
502502
&mut self,
503-
parent: LocalDefId,
504503
node_id: ast::NodeId,
505504
name: Option<Symbol>,
506505
def_kind: DefKind,
507506
span: Span,
508507
) -> LocalDefId {
508+
let parent = self.current_hir_id_owner.def_id;
509509
debug_assert_ne!(node_id, ast::DUMMY_NODE_ID);
510510
assert!(
511511
self.opt_local_def_id(node_id).is_none(),
@@ -515,7 +515,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
515515
self.tcx.hir_def_key(self.local_def_id(node_id)),
516516
);
517517

518-
let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id();
518+
let def_id = self
519+
.tcx
520+
.at(span)
521+
.create_def(parent, name, def_kind, None, &mut self.resolver.disambiguator)
522+
.def_id();
519523

520524
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
521525
self.resolver.node_id_to_def_id.insert(node_id, def_id);
@@ -787,7 +791,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
787791
LifetimeRes::Fresh { param, kind, .. } => {
788792
// Late resolution delegates to us the creation of the `LocalDefId`.
789793
let _def_id = self.create_def(
790-
self.current_hir_id_owner.def_id,
791794
param,
792795
Some(kw::UnderscoreLifetime),
793796
DefKind::LifetimeParam,
@@ -2113,16 +2116,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21132116
hir::ConstArgKind::Path(qpath)
21142117
} else {
21152118
// Construct an AnonConst where the expr is the "ty"'s path.
2116-
2117-
let parent_def_id = self.current_hir_id_owner.def_id;
21182119
let node_id = self.next_node_id();
21192120
let span = self.lower_span(span);
21202121

21212122
// Add a definition for the in-band const def.
21222123
// We're lowering a const argument that was originally thought to be a type argument,
21232124
// so the def collector didn't create the def ahead of time. That's why we have to do
21242125
// it here.
2125-
let def_id = self.create_def(parent_def_id, node_id, None, DefKind::AnonConst, span);
2126+
let def_id = self.create_def(node_id, None, DefKind::AnonConst, span);
21262127
let hir_id = self.lower_node_id(node_id);
21272128

21282129
let path_expr = Expr {

compiler/rustc_ast_lowering/src/pat.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -522,14 +522,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
522522
span: Span,
523523
base_type: Span,
524524
) -> &'hir hir::ConstArg<'hir> {
525-
let parent_def_id = self.current_hir_id_owner.def_id;
526525
let node_id = self.next_node_id();
527526

528527
// Add a definition for the in-band const def.
529528
// We're generating a range end that didn't exist in the AST,
530529
// so the def collector didn't create the def ahead of time. That's why we have to do
531530
// it here.
532-
let def_id = self.create_def(parent_def_id, node_id, None, DefKind::AnonConst, span);
531+
let def_id = self.create_def(node_id, None, DefKind::AnonConst, span);
533532
let hir_id = self.lower_node_id(node_id);
534533

535534
let unstable_span = self.mark_span_with_reason(

compiler/rustc_const_eval/src/interpret/intern.rs

+27-8
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ use hir::def::DefKind;
1717
use rustc_ast::Mutability;
1818
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
1919
use rustc_hir as hir;
20+
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
2021
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
2122
use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult};
2223
use rustc_middle::query::TyCtxtAt;
2324
use rustc_middle::span_bug;
2425
use rustc_middle::ty::layout::TyAndLayout;
2526
use rustc_span::def_id::LocalDefId;
26-
use rustc_span::sym;
2727
use tracing::{instrument, trace};
2828

2929
use super::{
@@ -66,6 +66,7 @@ fn intern_shallow<'tcx, T, M: CompileTimeMachine<'tcx, T>>(
6666
ecx: &mut InterpCx<'tcx, M>,
6767
alloc_id: AllocId,
6868
mutability: Mutability,
69+
disambiguator: Option<&mut DisambiguatorState>,
6970
) -> Result<impl Iterator<Item = CtfeProvenance> + 'tcx, ()> {
7071
trace!("intern_shallow {:?}", alloc_id);
7172
// remove allocation
@@ -88,7 +89,13 @@ fn intern_shallow<'tcx, T, M: CompileTimeMachine<'tcx, T>>(
8889
// link the alloc id to the actual allocation
8990
let alloc = ecx.tcx.mk_const_alloc(alloc);
9091
if let Some(static_id) = ecx.machine.static_def_id() {
91-
intern_as_new_static(ecx.tcx, static_id, alloc_id, alloc);
92+
intern_as_new_static(
93+
ecx.tcx,
94+
static_id,
95+
alloc_id,
96+
alloc,
97+
disambiguator.expect("disambiguator needed"),
98+
);
9299
} else {
93100
ecx.tcx.set_alloc_id_memory(alloc_id, alloc);
94101
}
@@ -102,11 +109,18 @@ fn intern_as_new_static<'tcx>(
102109
static_id: LocalDefId,
103110
alloc_id: AllocId,
104111
alloc: ConstAllocation<'tcx>,
112+
disambiguator: &mut DisambiguatorState,
105113
) {
114+
// `intern_const_alloc_recursive` is called once per static and it contains the `DisambiguatorState`.
115+
// The `<static_id>::{{nested}}` path is thus unique to `intern_const_alloc_recursive` and the
116+
// `DisambiguatorState` ensures the generated path is unique for this call as we generate
117+
// `<static_id>::{{nested#n}}` where `n` is the `n`th `intern_as_new_static` call.
106118
let feed = tcx.create_def(
107119
static_id,
108-
Some(sym::nested),
120+
None,
109121
DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true },
122+
Some(DefPathData::NestedStatic),
123+
disambiguator,
110124
);
111125
tcx.set_nested_alloc_id_static(alloc_id, feed.def_id());
112126

@@ -154,6 +168,8 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
154168
intern_kind: InternKind,
155169
ret: &MPlaceTy<'tcx>,
156170
) -> Result<(), InternResult> {
171+
let mut disambiguator = DisambiguatorState::new();
172+
157173
// We are interning recursively, and for mutability we are distinguishing the "root" allocation
158174
// that we are starting in, and all other allocations that we are encountering recursively.
159175
let (base_mutability, inner_mutability, is_static) = match intern_kind {
@@ -197,7 +213,9 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
197213
alloc.1.mutability = base_mutability;
198214
alloc.1.provenance().ptrs().iter().map(|&(_, prov)| prov).collect()
199215
} else {
200-
intern_shallow(ecx, base_alloc_id, base_mutability).unwrap().collect()
216+
intern_shallow(ecx, base_alloc_id, base_mutability, Some(&mut disambiguator))
217+
.unwrap()
218+
.collect()
201219
};
202220
// We need to distinguish "has just been interned" from "was already in `tcx`",
203221
// so we track this in a separate set.
@@ -291,7 +309,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
291309
// okay with losing some potential for immutability here. This can anyway only affect
292310
// `static mut`.
293311
just_interned.insert(alloc_id);
294-
match intern_shallow(ecx, alloc_id, inner_mutability) {
312+
match intern_shallow(ecx, alloc_id, inner_mutability, Some(&mut disambiguator)) {
295313
Ok(nested) => todo.extend(nested),
296314
Err(()) => {
297315
ecx.tcx.dcx().delayed_bug("found dangling pointer during const interning");
@@ -313,8 +331,9 @@ pub fn intern_const_alloc_for_constprop<'tcx, T, M: CompileTimeMachine<'tcx, T>>
313331
return interp_ok(());
314332
}
315333
// Move allocation to `tcx`.
316-
if let Some(_) =
317-
(intern_shallow(ecx, alloc_id, Mutability::Not).map_err(|()| err_ub!(DeadLocal))?).next()
334+
if let Some(_) = intern_shallow(ecx, alloc_id, Mutability::Not, None)
335+
.map_err(|()| err_ub!(DeadLocal))?
336+
.next()
318337
{
319338
// We are not doing recursive interning, so we don't currently support provenance.
320339
// (If this assertion ever triggers, we should just implement a
@@ -340,7 +359,7 @@ impl<'tcx> InterpCx<'tcx, DummyMachine> {
340359
let dest = self.allocate(layout, MemoryKind::Stack)?;
341360
f(self, &dest.clone().into())?;
342361
let alloc_id = dest.ptr().provenance.unwrap().alloc_id(); // this was just allocated, it must have provenance
343-
for prov in intern_shallow(self, alloc_id, Mutability::Not).unwrap() {
362+
for prov in intern_shallow(self, alloc_id, Mutability::Not, None).unwrap() {
344363
// We are not doing recursive interning, so we don't currently support provenance.
345364
// (If this assertion ever triggers, we should just implement a
346365
// proper recursive interning loop -- or just call `intern_const_alloc_recursive`.

compiler/rustc_hir/src/def.rs

+3-11
Original file line numberDiff line numberDiff line change
@@ -269,18 +269,10 @@ impl DefKind {
269269
| DefKind::TyParam
270270
| DefKind::ExternCrate => DefPathData::TypeNs(name.unwrap()),
271271

272-
// An associated type name will be missing for an RPITIT.
273-
DefKind::AssocTy => {
274-
if let Some(name) = name {
275-
DefPathData::TypeNs(name)
276-
} else {
277-
DefPathData::AnonAssocTy
278-
}
279-
}
272+
// An associated type name will be missing for an RPITIT (DefPathData::AnonAssocTy),
273+
// but those provide their own DefPathData.
274+
DefKind::AssocTy => DefPathData::TypeNs(name.unwrap()),
280275

281-
// It's not exactly an anon const, but wrt DefPathData, there
282-
// is no difference.
283-
DefKind::Static { nested: true, .. } => DefPathData::AnonConst,
284276
DefKind::Fn
285277
| DefKind::Const
286278
| DefKind::ConstParam

compiler/rustc_hir/src/definitions.rs

+71-14
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl DefPathTable {
6868
//
6969
// See the documentation for DefPathHash for more information.
7070
panic!(
71-
"found DefPathHash collision between {def_path1:?} and {def_path2:?}. \
71+
"found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \
7272
Compilation cannot continue."
7373
);
7474
}
@@ -97,13 +97,31 @@ impl DefPathTable {
9797
}
9898
}
9999

100+
#[derive(Debug)]
101+
pub struct DisambiguatorState {
102+
next: UnordMap<(LocalDefId, DefPathData), u32>,
103+
}
104+
105+
impl DisambiguatorState {
106+
pub fn new() -> Self {
107+
Self { next: Default::default() }
108+
}
109+
110+
/// Creates a `DisambiguatorState` where the next allocated `(LocalDefId, DefPathData)` pair
111+
/// will have `index` as the disambiguator.
112+
pub fn with(def_id: LocalDefId, data: DefPathData, index: u32) -> Self {
113+
let mut this = Self::new();
114+
this.next.insert((def_id, data), index);
115+
this
116+
}
117+
}
118+
100119
/// The definition table containing node definitions.
101120
/// It holds the `DefPathTable` for `LocalDefId`s/`DefPath`s.
102121
/// It also stores mappings to convert `LocalDefId`s to/from `HirId`s.
103122
#[derive(Debug)]
104123
pub struct Definitions {
105124
table: DefPathTable,
106-
next_disambiguator: UnordMap<(LocalDefId, DefPathData), u32>,
107125
}
108126

109127
/// A unique identifier that we can use to lookup a definition
@@ -127,7 +145,7 @@ impl DefKey {
127145
let DisambiguatedDefPathData { ref data, disambiguator } = self.disambiguated_data;
128146

129147
std::mem::discriminant(data).hash(&mut hasher);
130-
if let Some(name) = data.get_opt_name() {
148+
if let Some(name) = data.hashed_symbol() {
131149
// Get a stable hash by considering the symbol chars rather than
132150
// the symbol index.
133151
name.as_str().hash(&mut hasher);
@@ -173,7 +191,11 @@ impl DisambiguatedDefPathData {
173191
}
174192
}
175193
DefPathDataName::Anon { namespace } => {
176-
write!(writer, "{{{}#{}}}", namespace, self.disambiguator)
194+
if let DefPathData::AnonAssocTy(method) = self.data {
195+
write!(writer, "{}::{{{}#{}}}", method, namespace, self.disambiguator)
196+
} else {
197+
write!(writer, "{{{}#{}}}", namespace, self.disambiguator)
198+
}
177199
}
178200
}
179201
}
@@ -287,10 +309,13 @@ pub enum DefPathData {
287309
/// An existential `impl Trait` type node.
288310
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
289311
OpaqueTy,
290-
/// An anonymous associated type from an RPITIT.
291-
AnonAssocTy,
312+
/// An anonymous associated type from an RPITIT. The symbol refers to the name of the method
313+
/// that defined the type.
314+
AnonAssocTy(Symbol),
292315
/// A synthetic body for a coroutine's by-move body.
293316
SyntheticCoroutineBody,
317+
/// Additional static data referred to by a static.
318+
NestedStatic,
294319
}
295320

296321
impl Definitions {
@@ -342,24 +367,33 @@ impl Definitions {
342367
let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) };
343368
assert_eq!(root.local_def_index, CRATE_DEF_INDEX);
344369

345-
Definitions { table, next_disambiguator: Default::default() }
370+
Definitions { table }
346371
}
347372

348-
/// Adds a definition with a parent definition.
349-
pub fn create_def(&mut self, parent: LocalDefId, data: DefPathData) -> LocalDefId {
373+
/// Creates a definition with a parent definition.
374+
/// If there are multiple definitions with the same DefPathData and the same parent, use
375+
/// `disambiguator` to differentiate them. Distinct `DisambiguatorState` instances are not
376+
/// guaranteed to generate unique disambiguators and should instead ensure that the `parent`
377+
/// and `data` pair is distinct from other instances.
378+
pub fn create_def(
379+
&mut self,
380+
parent: LocalDefId,
381+
data: DefPathData,
382+
disambiguator: &mut DisambiguatorState,
383+
) -> LocalDefId {
350384
// We can't use `Debug` implementation for `LocalDefId` here, since it tries to acquire a
351385
// reference to `Definitions` and we're already holding a mutable reference.
352386
debug!(
353387
"create_def(parent={}, data={data:?})",
354388
self.def_path(parent).to_string_no_crate_verbose(),
355389
);
356390

357-
// The root node must be created with `create_root_def()`.
391+
// The root node must be created in `new()`.
358392
assert!(data != DefPathData::CrateRoot);
359393

360394
// Find the next free disambiguator for this key.
361395
let disambiguator = {
362-
let next_disamb = self.next_disambiguator.entry((parent, data)).or_insert(0);
396+
let next_disamb = disambiguator.next.entry((parent, data)).or_insert(0);
363397
let disambiguator = *next_disamb;
364398
*next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow");
365399
disambiguator
@@ -422,8 +456,30 @@ impl DefPathData {
422456
| Ctor
423457
| AnonConst
424458
| OpaqueTy
425-
| AnonAssocTy
426-
| SyntheticCoroutineBody => None,
459+
| AnonAssocTy(..)
460+
| SyntheticCoroutineBody
461+
| NestedStatic => None,
462+
}
463+
}
464+
465+
fn hashed_symbol(&self) -> Option<Symbol> {
466+
use self::DefPathData::*;
467+
match *self {
468+
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name) => {
469+
Some(name)
470+
}
471+
472+
Impl
473+
| ForeignMod
474+
| CrateRoot
475+
| Use
476+
| GlobalAsm
477+
| Closure
478+
| Ctor
479+
| AnonConst
480+
| OpaqueTy
481+
| SyntheticCoroutineBody
482+
| NestedStatic => None,
427483
}
428484
}
429485

@@ -443,8 +499,9 @@ impl DefPathData {
443499
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
444500
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
445501
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
446-
AnonAssocTy => DefPathDataName::Anon { namespace: sym::anon_assoc },
502+
AnonAssocTy(..) => DefPathDataName::Anon { namespace: sym::anon_assoc },
447503
SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic },
504+
NestedStatic => DefPathDataName::Anon { namespace: sym::nested },
448505
}
449506
}
450507
}

0 commit comments

Comments
 (0)