Fix delegation def path hash collision, add per-parent disambiguators

This commit is contained in:
aerooneqq
2026-04-10 22:39:28 +03:00
parent 0204aca066
commit 699eb29443
14 changed files with 135 additions and 53 deletions
@@ -295,10 +295,9 @@ fn uplift_delegation_generic_params(
let param_ident = Ident::new(p.name, span);
let def_name = Some(param_ident.name);
let path_data = def_kind.def_path_data(def_name);
let node_id = self.next_node_id();
let def_id = self.create_def(node_id, def_name, def_kind, path_data, span);
let def_id = self.create_def(node_id, def_name, def_kind, span);
let kind = match p.kind {
GenericParamDefKind::Lifetime => {
+1 -8
View File
@@ -8,7 +8,6 @@
use rustc_errors::msg;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::definitions::DefPathData;
use rustc_hir::{HirId, Target, find_attr};
use rustc_middle::span_bug;
use rustc_middle::ty::TyCtxt;
@@ -472,13 +471,7 @@ fn lower_legacy_const_generics(
for (idx, arg) in args.iter().cloned().enumerate() {
if legacy_args_idx.contains(&idx) {
let node_id = self.next_node_id();
self.create_def(
node_id,
None,
DefKind::AnonConst,
DefPathData::LateAnonConst,
f.span,
);
self.create_def(node_id, None, DefKind::AnonConst, f.span);
let const_value =
if let ControlFlow::Break(span) = WillCreateDefIdsVisitor.visit_expr(&arg) {
Box::new(Expr {
+16 -13
View File
@@ -51,7 +51,7 @@
use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle};
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
use rustc_hir::definitions::PerParentDisambiguatorState;
use rustc_hir::lints::{AttributeLint, DelayedLint};
use rustc_hir::{
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,
@@ -94,7 +94,7 @@ macro_rules! arena_vec {
struct LoweringContext<'a, 'hir, R> {
tcx: TyCtxt<'hir>,
resolver: &'a mut R,
disambiguator: DisambiguatorState,
disambiguator: PerParentDisambiguatorState,
/// Used to allocate HIR nodes.
arena: &'hir hir::Arena<'hir>,
@@ -159,7 +159,7 @@ fn new(tcx: TyCtxt<'hir>, resolver: &'a mut R) -> Self {
Self {
tcx,
resolver,
disambiguator: DisambiguatorState::new(),
disambiguator: Default::default(),
arena: tcx.hir_arena,
// HirId handling.
@@ -302,6 +302,10 @@ fn trait_candidates(&self, node_id: NodeId) -> Option<&'tcx [hir::TraitCandidate
fn next_node_id(&mut self) -> NodeId {
next_node_id(&mut self.next_node_id)
}
fn steal_or_create_disambiguator(&self, parent: LocalDefId) -> PerParentDisambiguatorState {
self.base.steal_or_create_disambiguator(parent)
}
}
fn next_node_id(current_id: &mut NodeId) -> NodeId {
@@ -404,6 +408,10 @@ fn trait_candidates(&self, node_id: NodeId) -> Option<&'tcx [hir::TraitCandidate
fn next_node_id(&mut self) -> NodeId {
next_node_id(&mut self.next_node_id)
}
fn steal_or_create_disambiguator(&self, parent: LocalDefId) -> PerParentDisambiguatorState {
self.per_parent_disambiguators.get(&parent).map(|s| s.steal()).unwrap_or_default()
}
}
/// How relaxed bounds `?Trait` should be treated.
@@ -717,7 +725,6 @@ fn create_def(
node_id: ast::NodeId,
name: Option<Symbol>,
def_kind: DefKind,
def_path_data: DefPathData,
span: Span,
) -> LocalDefId {
let parent = self.current_hir_id_owner.def_id;
@@ -733,7 +740,7 @@ fn create_def(
let def_id = self
.tcx
.at(span)
.create_def(parent, name, def_kind, Some(def_path_data), &mut self.disambiguator)
.create_def(parent, name, def_kind, None, &mut self.disambiguator)
.def_id();
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
@@ -774,6 +781,8 @@ fn with_hir_id_owner(
) {
let owner_id = self.owner_id(owner);
let new_disambig = self.resolver.steal_or_create_disambiguator(owner_id.def_id);
let disambiguator = std::mem::replace(&mut self.disambiguator, new_disambig);
let current_attrs = std::mem::take(&mut self.attrs);
let current_bodies = std::mem::take(&mut self.bodies);
let current_define_opaque = std::mem::take(&mut self.define_opaque);
@@ -808,6 +817,7 @@ fn with_hir_id_owner(
assert!(self.impl_trait_bounds.is_empty());
let info = self.make_owner_info(item);
self.disambiguator = disambiguator;
self.attrs = current_attrs;
self.bodies = current_bodies;
self.define_opaque = current_define_opaque;
@@ -1015,7 +1025,6 @@ fn lifetime_res_to_generic_param(
param,
Some(kw::UnderscoreLifetime),
DefKind::LifetimeParam,
DefPathData::DesugaredAnonymousLifetime,
ident.span,
);
debug!(?_def_id);
@@ -2504,13 +2513,7 @@ fn lower_const_path_to_const_arg(
// We're lowering a const argument that was originally thought to be a type argument,
// so the def collector didn't create the def ahead of time. That's why we have to do
// it here.
let def_id = self.create_def(
node_id,
None,
DefKind::AnonConst,
DefPathData::LateAnonConst,
span,
);
let def_id = self.create_def(node_id, None, DefKind::AnonConst, span);
let hir_id = self.lower_node_id(node_id);
let path_expr = Expr {
+1 -3
View File
@@ -3,7 +3,6 @@
use rustc_ast::*;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::definitions::DefPathData;
use rustc_hir::{self as hir, LangItem, Target};
use rustc_middle::span_bug;
use rustc_span::{DesugaringKind, Ident, Span, Spanned, respan};
@@ -538,8 +537,7 @@ fn lower_ty_pat_range_end(
// We're generating a range end that didn't exist in the AST,
// so the def collector didn't create the def ahead of time. That's why we have to do
// it here.
let def_id =
self.create_def(node_id, None, DefKind::AnonConst, DefPathData::LateAnonConst, span);
let def_id = self.create_def(node_id, None, DefKind::AnonConst, span);
let hir_id = self.lower_node_id(node_id);
let unstable_span = self.mark_span_with_reason(
+27 -15
View File
@@ -97,11 +97,34 @@ pub fn enumerated_keys_and_path_hashes(
}
}
#[derive(Debug)]
pub trait Disambiguator {
fn entry(&mut self, parent: LocalDefId, data: DefPathData) -> &mut u32;
}
#[derive(Debug, Default, Clone)]
pub struct PerParentDisambiguatorState {
next: UnordMap<DefPathData, u32>,
}
impl Disambiguator for PerParentDisambiguatorState {
#[inline]
fn entry(&mut self, _: LocalDefId, data: DefPathData) -> &mut u32 {
self.next.entry(data).or_insert(0)
}
}
#[derive(Debug, Default, Clone)]
pub struct DisambiguatorState {
next: UnordMap<(LocalDefId, DefPathData), u32>,
}
impl Disambiguator for DisambiguatorState {
#[inline]
fn entry(&mut self, parent: LocalDefId, data: DefPathData) -> &mut u32 {
self.next.entry((parent, data)).or_insert(0)
}
}
impl DisambiguatorState {
pub const fn new() -> Self {
Self { next: Default::default() }
@@ -302,10 +325,6 @@ pub enum DefPathData {
Ctor,
/// A constant expression (see `{ast,hir}::AnonConst`).
AnonConst,
/// A constant expression created during AST->HIR lowering..
LateAnonConst,
/// A fresh anonymous lifetime created by desugaring elided lifetimes.
DesugaredAnonymousLifetime,
/// An existential `impl Trait` type node.
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
OpaqueTy,
@@ -389,7 +408,7 @@ pub fn create_def(
&mut self,
parent: LocalDefId,
data: DefPathData,
disambiguator: &mut DisambiguatorState,
disambiguator: &mut impl Disambiguator,
) -> 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.
@@ -403,7 +422,7 @@ pub fn create_def(
// Find the next free disambiguator for this key.
let disambiguator = {
let next_disamb = disambiguator.next.entry((parent, data)).or_insert(0);
let next_disamb = disambiguator.entry(parent, data);
let disambiguator = *next_disamb;
*next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow");
disambiguator
@@ -458,8 +477,6 @@ pub fn get_opt_name(&self) -> Option<Symbol> {
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name)
| OpaqueLifetime(name) => Some(name),
DesugaredAnonymousLifetime => Some(kw::UnderscoreLifetime),
Impl
| ForeignMod
| CrateRoot
@@ -468,7 +485,6 @@ pub fn get_opt_name(&self) -> Option<Symbol> {
| Closure
| Ctor
| AnonConst
| LateAnonConst
| OpaqueTy
| AnonAssocTy(..)
| SyntheticCoroutineBody
@@ -482,8 +498,6 @@ fn hashed_symbol(&self) -> Option<Symbol> {
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name)
| OpaqueLifetime(name) => Some(name),
DesugaredAnonymousLifetime => Some(kw::UnderscoreLifetime),
Impl
| ForeignMod
| CrateRoot
@@ -492,7 +506,6 @@ fn hashed_symbol(&self) -> Option<Symbol> {
| Closure
| Ctor
| AnonConst
| LateAnonConst
| OpaqueTy
| SyntheticCoroutineBody
| NestedStatic => None,
@@ -512,8 +525,7 @@ pub fn name(&self) -> DefPathDataName {
GlobalAsm => DefPathDataName::Anon { namespace: sym::global_asm },
Closure => DefPathDataName::Anon { namespace: sym::closure },
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
AnonConst | LateAnonConst => DefPathDataName::Anon { namespace: sym::constant },
DesugaredAnonymousLifetime => DefPathDataName::Named(kw::UnderscoreLifetime),
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
AnonAssocTy(..) => DefPathDataName::Anon { namespace: sym::anon_assoc },
SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic },
@@ -1523,7 +1523,7 @@ fn remap_opaque_captures(
None,
DefKind::LifetimeParam,
Some(DefPathData::OpaqueLifetime(ident.name)),
&mut self.disambiguator,
self.disambiguator,
);
feed.def_span(ident.span);
feed.def_ident_span(Some(ident.span));
+3 -3
View File
@@ -32,7 +32,7 @@
use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, MultiSpan};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState};
use rustc_hir::definitions::{DefPathData, Definitions, Disambiguator};
use rustc_hir::intravisit::VisitorExt;
use rustc_hir::lang_items::LangItem;
use rustc_hir::limit::Limit;
@@ -1355,7 +1355,7 @@ pub fn create_def(
name: Option<Symbol>,
def_kind: DefKind,
override_def_path_data: Option<DefPathData>,
disambiguator: &mut DisambiguatorState,
disambiguator: &mut impl Disambiguator,
) -> TyCtxtFeed<'tcx, LocalDefId> {
let feed =
self.tcx.create_def(parent, name, def_kind, override_def_path_data, disambiguator);
@@ -1373,7 +1373,7 @@ pub fn create_def(
name: Option<Symbol>,
def_kind: DefKind,
override_def_path_data: Option<DefPathData>,
disambiguator: &mut DisambiguatorState,
disambiguator: &mut impl Disambiguator,
) -> TyCtxtFeed<'tcx, LocalDefId> {
let data = override_def_path_data.unwrap_or_else(|| def_kind.def_path_data(name));
// The following call has the side effect of modifying the tables inside `definitions`.
+3
View File
@@ -40,6 +40,7 @@
use rustc_hir::attrs::StrippedCfgItem;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
use rustc_hir::definitions::PerParentDisambiguatorState;
use rustc_hir::{LangItem, attrs as attr, find_attr};
use rustc_index::IndexVec;
use rustc_index::bit_set::BitMatrix;
@@ -224,6 +225,8 @@ pub struct ResolverAstLowering<'tcx> {
// Information about delegations which is used when handling recursive delegations
pub delegation_infos: LocalDefIdMap<DelegationInfo>,
pub per_parent_disambiguators: LocalDefIdMap<Steal<PerParentDisambiguatorState>>,
}
#[derive(Debug)]
@@ -2172,7 +2172,6 @@ fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace {
DefPathData::ValueNs(..)
| DefPathData::AnonConst
| DefPathData::LateAnonConst
| DefPathData::Closure
| DefPathData::Ctor => Namespace::ValueNS,
+15 -3
View File
@@ -57,7 +57,7 @@
PerNS,
};
use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
use rustc_hir::definitions::DisambiguatorState;
use rustc_hir::definitions::PerParentDisambiguatorState;
use rustc_hir::{PrimTy, TraitCandidate, find_attr};
use rustc_index::bit_set::DenseBitSet;
use rustc_metadata::creader::CStore;
@@ -1353,7 +1353,7 @@ pub struct Resolver<'ra, 'tcx> {
node_id_to_def_id: NodeMap<Feed<'tcx, LocalDefId>>,
disambiguator: DisambiguatorState = DisambiguatorState::new(),
per_parent_disambiguators: LocalDefIdMap<PerParentDisambiguatorState>,
/// Indices of unnamed struct or variant fields with unresolved attributes.
placeholder_field_indices: FxHashMap<NodeId, usize> = default::fx_hash_map(),
@@ -1557,7 +1557,13 @@ fn create_def(
);
// FIXME: remove `def_span` body, pass in the right spans here and call `tcx.at().create_def()`
let feed = self.tcx.create_def(parent, name, def_kind, None, &mut self.disambiguator);
let feed = self.tcx.create_def(
parent,
name,
def_kind,
None,
self.per_parent_disambiguators.entry(parent).or_default(),
);
let def_id = feed.def_id();
// Create the definition.
@@ -1739,6 +1745,7 @@ pub fn new(
doc_link_resolutions: Default::default(),
doc_link_traits_in_scope: Default::default(),
current_crate_outer_attr_insert_span,
per_parent_disambiguators: Default::default(),
..
};
@@ -1870,6 +1877,11 @@ pub fn into_outputs(self) -> ResolverOutputs<'tcx> {
lifetime_elision_allowed: self.lifetime_elision_allowed,
lint_buffer: Steal::new(self.lint_buffer),
delegation_infos: self.delegation_infos,
per_parent_disambiguators: self
.per_parent_disambiguators
.into_items()
.map(|(k, d)| (k, Steal::new(d)))
.collect(),
};
ResolverOutputs { global_ctxt, ast_lowering }
}
@@ -680,7 +680,6 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
hir::definitions::DefPathData::Closure => "C",
hir::definitions::DefPathData::Ctor => "c",
hir::definitions::DefPathData::AnonConst => "K",
hir::definitions::DefPathData::LateAnonConst => "k",
hir::definitions::DefPathData::OpaqueTy => "i",
hir::definitions::DefPathData::SyntheticCoroutineBody => "s",
hir::definitions::DefPathData::NestedStatic => "n",
@@ -690,7 +689,6 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
| hir::definitions::DefPathData::MacroNs(..)
| hir::definitions::DefPathData::OpaqueLifetime(..)
| hir::definitions::DefPathData::LifetimeNs(..)
| hir::definitions::DefPathData::DesugaredAnonymousLifetime
| hir::definitions::DefPathData::AnonAssocTy(..) => {
bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data);
}
-2
View File
@@ -888,7 +888,6 @@ fn print_path_with_simple(
DefPathData::Closure => 'C',
DefPathData::Ctor => 'c',
DefPathData::AnonConst => 'K',
DefPathData::LateAnonConst => 'k',
DefPathData::OpaqueTy => 'i',
DefPathData::SyntheticCoroutineBody => 's',
DefPathData::NestedStatic => 'n',
@@ -900,7 +899,6 @@ fn print_path_with_simple(
| DefPathData::Impl
| DefPathData::MacroNs(_)
| DefPathData::LifetimeNs(_)
| DefPathData::DesugaredAnonymousLifetime
| DefPathData::OpaqueLifetime(_)
| DefPathData::AnonAssocTy(..) => {
bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)
@@ -0,0 +1,27 @@
//@ compile-flags: -Z deduplicate-diagnostics=yes
//@ edition:2024
#![feature(fn_delegation)]
#![feature(iter_advance_by)]
#![feature(iter_array_chunks)]
#![feature(iterator_try_collect)]
#![feature(iterator_try_reduce)]
#![feature(iter_collect_into)]
#![feature(iter_intersperse)]
#![feature(iter_is_partitioned)]
#![feature(iter_map_windows)]
#![feature(iter_next_chunk)]
#![feature(iter_order_by)]
#![feature(iter_partition_in_place)]
#![feature(trusted_random_access)]
#![feature(try_find)]
#![allow(incomplete_features)]
impl Iterator {
//~^ ERROR: expected a type, found a trait [E0782]
reuse< < <for<'a> fn()>::Output>::Item as Iterator>::*;
//~^ ERROR: expected method or associated constant, found associated type `Iterator::Item`
//~| ERROR: ambiguous associated type
}
fn main() {}
@@ -0,0 +1,40 @@
error[E0575]: expected method or associated constant, found associated type `Iterator::Item`
--> $DIR/def-path-hash-collision-ice-153410.rs:22:10
|
LL | reuse< < <for<'a> fn()>::Output>::Item as Iterator>::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a method or associated constant
error[E0782]: expected a type, found a trait
--> $DIR/def-path-hash-collision-ice-153410.rs:20:6
|
LL | impl Iterator {
| ^^^^^^^^
|
help: you can add the `dyn` keyword if you want a trait object
|
LL | impl dyn Iterator {
| +++
help: you might have intended to implement this trait for a given type
|
LL | impl Iterator for /* Type */ {
| ++++++++++++++
error[E0223]: ambiguous associated type
--> $DIR/def-path-hash-collision-ice-153410.rs:22:14
|
LL | reuse< < <for<'a> fn()>::Output>::Item as Iterator>::*;
| ^^^^^^^^^^^^^^^^^^^^^^
|
help: use fully-qualified syntax
|
LL - reuse< < <for<'a> fn()>::Output>::Item as Iterator>::*;
LL + reuse< < <fn() as BitOr>::Output>::Item as Iterator>::*;
|
LL - reuse< < <for<'a> fn()>::Output>::Item as Iterator>::*;
LL + reuse< < <fn() as IntoFuture>::Output>::Item as Iterator>::*;
|
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0223, E0575, E0782.
For more information about an error, try `rustc --explain E0223`.