-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Remove global next_disambiguator
state and handle it with a DisambiguatorState
type
#140453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,7 +68,7 @@ impl DefPathTable { | |
// | ||
// See the documentation for DefPathHash for more information. | ||
panic!( | ||
"found DefPathHash collision between {def_path1:?} and {def_path2:?}. \ | ||
"found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \ | ||
Compilation cannot continue." | ||
); | ||
} | ||
|
@@ -97,13 +97,31 @@ impl DefPathTable { | |
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct DisambiguatorState { | ||
next: UnordMap<(LocalDefId, DefPathData), u32>, | ||
} | ||
|
||
impl DisambiguatorState { | ||
pub fn new() -> Self { | ||
Self { next: Default::default() } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
/// Creates a `DisambiguatorState` where the next allocated `(LocalDefId, DefPathData)` pair | ||
/// will have `index` as the disambiguator. | ||
pub fn with(def_id: LocalDefId, data: DefPathData, index: u32) -> Self { | ||
let mut this = Self::new(); | ||
this.next.insert((def_id, data), index); | ||
this | ||
} | ||
} | ||
|
||
/// The definition table containing node definitions. | ||
/// It holds the `DefPathTable` for `LocalDefId`s/`DefPath`s. | ||
/// It also stores mappings to convert `LocalDefId`s to/from `HirId`s. | ||
#[derive(Debug)] | ||
pub struct Definitions { | ||
table: DefPathTable, | ||
next_disambiguator: UnordMap<(LocalDefId, DefPathData), u32>, | ||
} | ||
|
||
/// A unique identifier that we can use to lookup a definition | ||
|
@@ -173,7 +191,11 @@ impl DisambiguatedDefPathData { | |
} | ||
} | ||
DefPathDataName::Anon { namespace } => { | ||
write!(writer, "{{{}#{}}}", namespace, self.disambiguator) | ||
if let DefPathData::AnonAssocTy(method) = self.data { | ||
write!(writer, "{}::{{{}#{}}}", method, namespace, self.disambiguator) | ||
} else { | ||
write!(writer, "{{{}#{}}}", namespace, self.disambiguator) | ||
} | ||
} | ||
} | ||
} | ||
|
@@ -288,7 +310,7 @@ pub enum DefPathData { | |
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name. | ||
OpaqueTy, | ||
/// An anonymous associated type from an RPITIT. | ||
AnonAssocTy, | ||
AnonAssocTy(Symbol), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need a comment telling what the symbol is. |
||
/// A synthetic body for a coroutine's by-move body. | ||
SyntheticCoroutineBody, | ||
} | ||
|
@@ -342,24 +364,33 @@ impl Definitions { | |
let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) }; | ||
assert_eq!(root.local_def_index, CRATE_DEF_INDEX); | ||
|
||
Definitions { table, next_disambiguator: Default::default() } | ||
Definitions { table } | ||
} | ||
|
||
/// Adds a definition with a parent definition. | ||
pub fn create_def(&mut self, parent: LocalDefId, data: DefPathData) -> LocalDefId { | ||
/// Creates a definition with a parent definition. | ||
/// If there are multiple definitions with the same DefPathData and the same parent, use | ||
/// `disambiguator` to differentiate them. Distinct `DisambiguatorState` instances are not | ||
/// guaranteed to generate unique disambiguators and should instead ensure that the `parent` | ||
/// and `data` pair is distinct from other instances. | ||
pub fn create_def( | ||
&mut self, | ||
parent: LocalDefId, | ||
data: DefPathData, | ||
disambiguator: &mut DisambiguatorState, | ||
) -> LocalDefId { | ||
// We can't use `Debug` implementation for `LocalDefId` here, since it tries to acquire a | ||
// reference to `Definitions` and we're already holding a mutable reference. | ||
debug!( | ||
"create_def(parent={}, data={data:?})", | ||
self.def_path(parent).to_string_no_crate_verbose(), | ||
); | ||
|
||
// The root node must be created with `create_root_def()`. | ||
// The root node must be created in `new()`. | ||
assert!(data != DefPathData::CrateRoot); | ||
|
||
// Find the next free disambiguator for this key. | ||
let disambiguator = { | ||
let next_disamb = self.next_disambiguator.entry((parent, data)).or_insert(0); | ||
let next_disamb = disambiguator.next.entry((parent, data)).or_insert(0); | ||
let disambiguator = *next_disamb; | ||
*next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow"); | ||
disambiguator | ||
|
@@ -411,7 +442,9 @@ impl DefPathData { | |
pub fn get_opt_name(&self) -> Option<Symbol> { | ||
use self::DefPathData::*; | ||
match *self { | ||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), | ||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does seem a little bit odd. I could duplicate |
||
Some(name) | ||
} | ||
|
||
Impl | ||
| ForeignMod | ||
|
@@ -422,7 +455,6 @@ impl DefPathData { | |
| Ctor | ||
| AnonConst | ||
| OpaqueTy | ||
| AnonAssocTy | ||
| SyntheticCoroutineBody => None, | ||
} | ||
} | ||
|
@@ -443,7 +475,7 @@ impl DefPathData { | |
Ctor => DefPathDataName::Anon { namespace: sym::constructor }, | ||
AnonConst => DefPathDataName::Anon { namespace: sym::constant }, | ||
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque }, | ||
AnonAssocTy => DefPathDataName::Anon { namespace: sym::anon_assoc }, | ||
AnonAssocTy(..) => DefPathDataName::Anon { namespace: sym::anon_assoc }, | ||
SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic }, | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doc comment should be updated to explain the role of this
DisambiguatorState
component.Looking at the const_eval diff in this PR, I am completely clueless about what is happening.^^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Const eval is generating statics (not quite sure why, that's should probably be part of the comment) and
DisambiguatorState
is used to ensure these have unique names (def paths).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That part I can explain. :D Though it's way outside the scope for this comment I think -- this field is not directly related to generating those statics.
A
static
can require more than one allocation for its result, e.g. if you dostatic S = &Vec::new();
. We generate anonymous statics for those inner allocations. (Note that this example does not involve any const promotion.)It seems like what you are doing is funneling some state through to the allocation interner. That is the place where we should have comments explaining why and how we generate anonymous statics.
Seems like ideally this would be managed by the interner. It's not relevant during const-eval, only after the end of const-eval, so ideally it should not be present during const-eval.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yea that one is my fault. It was just the minimal diff allowing this, doing it solely in the interner... I guess would work unconditionally, not even basing it off on whether we are interning a static item, but just generally. Most code won't use it, but initializing an empty map is not more expensive than wrapping it in an option
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which interner are you talking about? It could also just be a counter, if it's per-source static.
I also noticed it's using a
nested
symbol. That's should probably be aDefPathData
variant to avoid collisions with source items.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
compiler/rustc_const_eval/src/interpret/intern.rs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That doesn't look like it has any query local state to put
DisambiguatorState
in?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not a query, so I don't know what you mean.
intern_const_alloc_recursive
would take an&mut DisambiguatorState
and forward it to where it is needed; the other entry points should never hitintern_as_new_static
.