Remove global next_disambiguator state and handle it with a DisambiguatorState type

This commit is contained in:
John Kåre Alsaker 2025-04-29 12:59:15 +02:00
parent 2ac60bc089
commit e561ec0e03
24 changed files with 190 additions and 93 deletions

View file

@ -509,7 +509,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.tcx.hir_def_key(self.local_def_id(node_id)),
);
let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id();
let def_id = self
.tcx
.at(span)
.create_def(parent, name, def_kind, None, &mut self.resolver.disambiguator)
.def_id();
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
self.resolver.node_id_to_def_id.insert(node_id, def_id);

View file

@ -1,3 +1,5 @@
use rustc_hir::def_id::LocalDefId;
use rustc_hir::definitions::DisambiguatorState;
use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult};
use rustc_middle::mir::*;
use rustc_middle::query::TyCtxtAt;
@ -42,7 +44,7 @@ pub macro throw_machine_stop_str($($tt:tt)*) {{
pub struct DummyMachine;
impl HasStaticRootDefId for DummyMachine {
fn static_def_id(&self) -> Option<rustc_hir::def_id::LocalDefId> {
fn static_parent_and_disambiguator(&mut self) -> Option<(LocalDefId, &mut DisambiguatorState)> {
None
}
}

View file

@ -6,6 +6,7 @@ use rustc_abi::{Align, Size};
use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::definitions::DisambiguatorState;
use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem};
use rustc_middle::mir::AssertMessage;
use rustc_middle::mir::interpret::ReportedErrorInfo;
@ -63,7 +64,7 @@ pub struct CompileTimeMachine<'tcx> {
/// If `Some`, we are evaluating the initializer of the static with the given `LocalDefId`,
/// storing the result in the given `AllocId`.
/// Used to prevent reads from a static's base allocation, as that may allow for self-initialization loops.
pub(crate) static_root_ids: Option<(AllocId, LocalDefId)>,
pub(crate) static_root_ids: Option<(AllocId, LocalDefId, DisambiguatorState)>,
/// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes).
union_data_ranges: FxHashMap<Ty<'tcx>, RangeSet>,
@ -706,7 +707,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
fn before_alloc_read(ecx: &InterpCx<'tcx, Self>, alloc_id: AllocId) -> InterpResult<'tcx> {
// Check if this is the currently evaluated static.
if Some(alloc_id) == ecx.machine.static_root_ids.map(|(id, _)| id) {
if Some(alloc_id) == ecx.machine.static_root_ids.as_ref().map(|(id, ..)| *id) {
return Err(ConstEvalErrKind::RecursiveStatic).into();
}
// If this is another static, make sure we fire off the query to detect cycles.

View file

@ -17,6 +17,7 @@ use hir::def::DefKind;
use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_hir as hir;
use rustc_hir::definitions::DisambiguatorState;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult};
use rustc_middle::query::TyCtxtAt;
@ -46,12 +47,13 @@ pub trait CompileTimeMachine<'tcx, T> = Machine<
pub trait HasStaticRootDefId {
/// Returns the `DefId` of the static item that is currently being evaluated.
/// Used for interning to be able to handle nested allocations.
fn static_def_id(&self) -> Option<LocalDefId>;
fn static_parent_and_disambiguator(&mut self) -> Option<(LocalDefId, &mut DisambiguatorState)>;
}
impl HasStaticRootDefId for const_eval::CompileTimeMachine<'_> {
fn static_def_id(&self) -> Option<LocalDefId> {
Some(self.static_root_ids?.1)
fn static_parent_and_disambiguator(&mut self) -> Option<(LocalDefId, &mut DisambiguatorState)> {
let (_, static_id, d) = self.static_root_ids.as_mut()?;
Some((*static_id, d))
}
}
@ -87,8 +89,8 @@ fn intern_shallow<'tcx, T, M: CompileTimeMachine<'tcx, T>>(
}
// link the alloc id to the actual allocation
let alloc = ecx.tcx.mk_const_alloc(alloc);
if let Some(static_id) = ecx.machine.static_def_id() {
intern_as_new_static(ecx.tcx, static_id, alloc_id, alloc);
if let Some((static_id, disambiguator)) = ecx.machine.static_parent_and_disambiguator() {
intern_as_new_static(ecx.tcx, static_id, alloc_id, alloc, disambiguator);
} else {
ecx.tcx.set_alloc_id_memory(alloc_id, alloc);
}
@ -102,11 +104,14 @@ fn intern_as_new_static<'tcx>(
static_id: LocalDefId,
alloc_id: AllocId,
alloc: ConstAllocation<'tcx>,
disambiguator: &mut DisambiguatorState,
) {
let feed = tcx.create_def(
static_id,
Some(sym::nested),
DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true },
None,
disambiguator,
);
tcx.set_nested_alloc_id_static(alloc_id, feed.def_id());

View file

@ -1,4 +1,5 @@
use rustc_hir::def_id::LocalDefId;
use rustc_hir::definitions::DisambiguatorState;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{AllocInit, Allocation, InterpResult, Pointer};
use rustc_middle::ty::layout::TyAndLayout;
@ -40,8 +41,8 @@ pub(crate) fn create_static_alloc<'tcx>(
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
let alloc = Allocation::try_new(layout.size, layout.align.abi, AllocInit::Uninit)?;
let alloc_id = ecx.tcx.reserve_and_set_static_alloc(static_def_id.into());
assert_eq!(ecx.machine.static_root_ids, None);
ecx.machine.static_root_ids = Some((alloc_id, static_def_id));
assert!(ecx.machine.static_root_ids.is_none());
ecx.machine.static_root_ids = Some((alloc_id, static_def_id, DisambiguatorState::new()));
assert!(ecx.memory.alloc_map.insert(alloc_id, (MemoryKind::Stack, alloc)).is_none());
interp_ok(ecx.ptr_to_mplace(Pointer::from(alloc_id).into(), layout))
}

View file

@ -269,14 +269,9 @@ impl DefKind {
| DefKind::TyParam
| DefKind::ExternCrate => DefPathData::TypeNs(name.unwrap()),
// An associated type name will be missing for an RPITIT.
DefKind::AssocTy => {
if let Some(name) = name {
DefPathData::TypeNs(name)
} else {
DefPathData::AnonAssocTy
}
}
// An associated type name will be missing for an RPITIT (DefPathData::AnonAssocTy),
// but those provide their own DefPathData.
DefKind::AssocTy => DefPathData::TypeNs(name.unwrap()),
// It's not exactly an anon const, but wrt DefPathData, there
// is no difference.

View file

@ -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() }
}
/// 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),
/// A synthetic body for a coroutine's by-move body.
SyntheticCoroutineBody,
}
@ -342,11 +364,20 @@ 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!(
@ -354,12 +385,12 @@ impl Definitions {
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) => {
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 },
}
}

View file

@ -14,6 +14,7 @@ use rustc_ast::visit::walk_list;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::definitions::DisambiguatorState;
use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
use rustc_hir::{
self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeKind, Node,
@ -63,6 +64,7 @@ impl ResolvedArg {
struct BoundVarContext<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
rbv: &'a mut ResolveBoundVars,
disambiguator: &'a mut DisambiguatorState,
scope: ScopeRef<'a>,
}
@ -245,8 +247,12 @@ pub(crate) fn provide(providers: &mut Providers) {
#[instrument(level = "debug", skip(tcx))]
fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
let mut rbv = ResolveBoundVars::default();
let mut visitor =
BoundVarContext { tcx, rbv: &mut rbv, scope: &Scope::Root { opt_parent_item: None } };
let mut visitor = BoundVarContext {
tcx,
rbv: &mut rbv,
scope: &Scope::Root { opt_parent_item: None },
disambiguator: &mut DisambiguatorState::new(),
};
match tcx.hir_owner_node(local_def_id) {
hir::OwnerNode::Item(item) => visitor.visit_item(item),
hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
@ -515,9 +521,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
let capture_all_in_scope_lifetimes = opaque_captures_all_in_scope_lifetimes(opaque);
if capture_all_in_scope_lifetimes {
let tcx = self.tcx;
let lifetime_ident = |def_id: LocalDefId| {
let name = self.tcx.item_name(def_id.to_def_id());
let span = self.tcx.def_span(def_id);
let name = tcx.item_name(def_id.to_def_id());
let span = tcx.def_span(def_id);
Ident::new(name, span)
};
@ -1091,8 +1098,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
where
F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
{
let BoundVarContext { tcx, rbv, .. } = self;
let mut this = BoundVarContext { tcx: *tcx, rbv, scope: &wrap_scope };
let BoundVarContext { tcx, rbv, disambiguator, .. } = self;
let mut this = BoundVarContext { tcx: *tcx, rbv, disambiguator, scope: &wrap_scope };
let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
{
let _enter = span.enter();
@ -1446,7 +1453,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
#[instrument(level = "trace", skip(self, opaque_capture_scopes), ret)]
fn remap_opaque_captures(
&self,
&mut self,
opaque_capture_scopes: &Vec<(LocalDefId, &RefCell<FxIndexMap<ResolvedArg, LocalDefId>>)>,
mut lifetime: ResolvedArg,
ident: Ident,
@ -1462,8 +1469,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
for &(opaque_def_id, captures) in opaque_capture_scopes.iter().rev() {
let mut captures = captures.borrow_mut();
let remapped = *captures.entry(lifetime).or_insert_with(|| {
let feed =
self.tcx.create_def(opaque_def_id, Some(ident.name), DefKind::LifetimeParam);
let feed = self.tcx.create_def(
opaque_def_id,
Some(ident.name),
DefKind::LifetimeParam,
None,
&mut self.disambiguator,
);
feed.def_span(ident.span);
feed.def_ident_span(Some(ident.span));
feed.def_id()

View file

@ -34,7 +34,7 @@ use rustc_errors::{
};
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::definitions::Definitions;
use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState};
use rustc_hir::intravisit::VisitorExt;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{self as hir, Attribute, HirId, Node, TraitCandidate};
@ -1957,8 +1957,10 @@ impl<'tcx> TyCtxtAt<'tcx> {
parent: LocalDefId,
name: Option<Symbol>,
def_kind: DefKind,
def_path_data: Option<DefPathData>,
disambiguator: &mut DisambiguatorState,
) -> TyCtxtFeed<'tcx, LocalDefId> {
let feed = self.tcx.create_def(parent, name, def_kind);
let feed = self.tcx.create_def(parent, name, def_kind, def_path_data, disambiguator);
feed.def_span(self.span);
feed
@ -1972,8 +1974,10 @@ impl<'tcx> TyCtxt<'tcx> {
parent: LocalDefId,
name: Option<Symbol>,
def_kind: DefKind,
def_path_data: Option<DefPathData>,
disambiguator: &mut DisambiguatorState,
) -> TyCtxtFeed<'tcx, LocalDefId> {
let data = def_kind.def_path_data(name);
let data = 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`.
// These very tables are relied on by the incr. comp. engine to decode DepNodes and to
// decode the on-disk cache.
@ -1983,12 +1987,7 @@ impl<'tcx> TyCtxt<'tcx> {
// - has been created by this call to `create_def`.
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
// comp. engine itself.
//
// This call also writes to the value of the `source_span` query.
// This is fine because:
// - that query is `eval_always` so we won't miss its result changing;
// - this write will have happened before that query is called.
let def_id = self.untracked.definitions.write().create_def(parent, data);
let def_id = self.untracked.definitions.write().create_def(parent, data, disambiguator);
// This function modifies `self.definitions` using a side-effect.
// We need to ensure that these side effects are re-run by the incr. comp. engine.

View file

@ -38,6 +38,7 @@ use rustc_errors::{Diag, ErrorGuaranteed};
use rustc_hir::LangItem;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
use rustc_hir::definitions::DisambiguatorState;
use rustc_index::IndexVec;
use rustc_macros::{
Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable,
@ -207,6 +208,8 @@ pub struct ResolverAstLowering {
pub node_id_to_def_id: NodeMap<LocalDefId>,
pub disambiguator: DisambiguatorState,
pub trait_map: NodeMap<Vec<hir::TraitCandidate>>,
/// List functions and methods for which lifetime elision was successful.
pub lifetime_elision_allowed: FxHashSet<ast::NodeId>,

View file

@ -391,6 +391,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
let visible_parent_map = self.tcx().visible_parent_map(());
let kind = self.tcx().def_kind(def_id);
if let DefPathData::AnonAssocTy(..) = key.disambiguated_data.data {
return Ok(false);
}
let get_local_name = |this: &Self, name, def_id, key: DefKey| {
if let Some(visible_parent) = visible_parent_map.get(&def_id)
&& let actual_parent = this.tcx().opt_parent(def_id)

View file

@ -73,6 +73,7 @@ use rustc_data_structures::unord::UnordMap;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::definitions::DisambiguatorState;
use rustc_middle::bug;
use rustc_middle::hir::place::{Projection, ProjectionKind};
use rustc_middle::mir::visit::MutVisitor;
@ -213,8 +214,13 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
let mut by_move_body = body.clone();
MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body);
// This will always be `{closure#1}`, since the original coroutine is `{closure#0}`.
let body_def = tcx.create_def(parent_def_id, None, DefKind::SyntheticCoroutineBody);
let body_def = tcx.create_def(
parent_def_id,
None,
DefKind::SyntheticCoroutineBody,
None,
&mut DisambiguatorState::new(),
);
by_move_body.source =
mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id()));
dump_mir(tcx, false, "built", &"after", &by_move_body, |_, _| Ok(()));

View file

@ -55,6 +55,7 @@ use rustc_hir::def::{
self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS,
};
use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
use rustc_hir::definitions::DisambiguatorState;
use rustc_hir::{PrimTy, TraitCandidate};
use rustc_metadata::creader::{CStore, CrateLoader};
use rustc_middle::metadata::ModChild;
@ -1184,6 +1185,8 @@ pub struct Resolver<'ra, 'tcx> {
node_id_to_def_id: NodeMap<Feed<'tcx, LocalDefId>>,
disambiguator: DisambiguatorState,
/// Indices of unnamed struct or variant fields with unresolved attributes.
placeholder_field_indices: FxHashMap<NodeId, usize>,
/// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
@ -1347,7 +1350,7 @@ impl<'tcx> Resolver<'_, 'tcx> {
);
// 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);
let feed = self.tcx.create_def(parent, name, def_kind, None, &mut self.disambiguator);
let def_id = feed.def_id();
// Create the definition.
@ -1561,6 +1564,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
lint_buffer: LintBuffer::default(),
next_node_id: CRATE_NODE_ID,
node_id_to_def_id,
disambiguator: DisambiguatorState::new(),
placeholder_field_indices: Default::default(),
invocation_parents,
legacy_const_generic_args: Default::default(),
@ -1690,6 +1694,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
.into_items()
.map(|(k, f)| (k, f.key()))
.collect(),
disambiguator: self.disambiguator,
trait_map: self.trait_map,
lifetime_elision_allowed: self.lifetime_elision_allowed,
lint_buffer: Steal::new(self.lint_buffer),

View file

@ -722,7 +722,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
| hir::definitions::DefPathData::GlobalAsm
| hir::definitions::DefPathData::MacroNs(..)
| hir::definitions::DefPathData::LifetimeNs(..)
| hir::definitions::DefPathData::AnonAssocTy => {
| hir::definitions::DefPathData::AnonAssocTy(..) => {
bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data);
}
});

View file

@ -859,7 +859,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
| DefPathData::Impl
| DefPathData::MacroNs(_)
| DefPathData::LifetimeNs(_)
| DefPathData::AnonAssocTy => {
| DefPathData::AnonAssocTy(..) => {
bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)
}
};

View file

@ -1,6 +1,7 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir, AmbigArg};
use rustc_middle::query::Providers;
@ -159,6 +160,22 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
container: ty::AssocItemContainer::Impl,
}
}
struct RPITVisitor {
rpits: FxIndexSet<LocalDefId>,
}
impl<'tcx> Visitor<'tcx> for RPITVisitor {
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
if let hir::TyKind::OpaqueDef(opaq) = ty.kind
&& self.rpits.insert(opaq.def_id)
{
for bound in opaq.bounds {
intravisit::walk_param_bound(self, bound);
}
}
intravisit::walk_ty(self, ty)
}
}
/// Given an `fn_def_id` of a trait or a trait implementation:
///
@ -177,23 +194,6 @@ fn associated_types_for_impl_traits_in_associated_fn(
match tcx.def_kind(parent_def_id) {
DefKind::Trait => {
struct RPITVisitor {
rpits: FxIndexSet<LocalDefId>,
}
impl<'tcx> Visitor<'tcx> for RPITVisitor {
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
if let hir::TyKind::OpaqueDef(opaq) = ty.kind
&& self.rpits.insert(opaq.def_id)
{
for bound in opaq.bounds {
intravisit::walk_param_bound(self, bound);
}
}
intravisit::walk_ty(self, ty)
}
}
let mut visitor = RPITVisitor { rpits: FxIndexSet::default() };
if let Some(output) = tcx.hir_get_fn_output(fn_def_id) {
@ -246,9 +246,23 @@ fn associated_type_for_impl_trait_in_trait(
let trait_def_id = tcx.local_parent(fn_def_id);
assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
// Collect all opaque types in return position for the method and use
// the index as the disambiguator to make an unique def path.
let mut visitor = RPITVisitor { rpits: FxIndexSet::default() };
visitor.visit_fn_ret_ty(tcx.hir_get_fn_output(fn_def_id).unwrap());
let disambiguator = visitor.rpits.get_index_of(&opaque_ty_def_id).unwrap().try_into().unwrap();
let span = tcx.def_span(opaque_ty_def_id);
// No name because this is an anonymous associated type.
let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, None, DefKind::AssocTy);
// Also use the method name to create an unique def path.
let data = DefPathData::AnonAssocTy(tcx.item_name(fn_def_id.to_def_id()));
let trait_assoc_ty = tcx.at(span).create_def(
trait_def_id,
// No name because this is an anonymous associated type.
None,
DefKind::AssocTy,
Some(data),
&mut DisambiguatorState::with(trait_def_id, data, disambiguator),
);
let local_def_id = trait_assoc_ty.def_id();
let def_id = local_def_id.to_def_id();
@ -299,8 +313,22 @@ fn associated_type_for_impl_trait_in_impl(
hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id),
hir::FnRetTy::Return(ty) => ty.span,
};
// No name because this is an anonymous associated type.
let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, None, DefKind::AssocTy);
// Use the same disambiguator and method name as the anon associated type in the trait.
let disambiguated_data = tcx.def_key(trait_assoc_def_id).disambiguated_data;
let DefPathData::AnonAssocTy(name) = disambiguated_data.data else {
bug!("expected anon associated type")
};
let data = DefPathData::AnonAssocTy(name);
let impl_assoc_ty = tcx.at(span).create_def(
impl_local_def_id,
// No name because this is an anonymous associated type.
None,
DefKind::AssocTy,
Some(data),
&mut DisambiguatorState::with(impl_local_def_id, data, disambiguated_data.disambiguator),
);
let local_def_id = impl_assoc_ty.def_id();
let def_id = local_def_id.to_def_id();

View file

@ -1,4 +1,4 @@
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{anon_assoc#0}`
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::opaque_ret::{anon_assoc#0}`
--> $DIR/unsupported.rs:22:25
|
LL | reuse to_reuse::opaque_ret;
@ -9,7 +9,7 @@ note: ...which requires comparing an impl and trait method signature, inferring
|
LL | reuse to_reuse::opaque_ret;
| ^^^^^^^^^^
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{anon_assoc#0}`, completing the cycle
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::opaque_ret::{anon_assoc#0}`, completing the cycle
note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>` is well-formed
--> $DIR/unsupported.rs:21:5
|
@ -17,7 +17,7 @@ LL | impl ToReuse for u8 {
| ^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{anon_assoc#0}`
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::opaque_ret::{anon_assoc#0}`
--> $DIR/unsupported.rs:25:24
|
LL | reuse ToReuse::opaque_ret;
@ -28,7 +28,7 @@ note: ...which requires comparing an impl and trait method signature, inferring
|
LL | reuse ToReuse::opaque_ret;
| ^^^^^^^^^^
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{anon_assoc#0}`, completing the cycle
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::opaque_ret::{anon_assoc#0}`, completing the cycle
note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>` is well-formed
--> $DIR/unsupported.rs:24:5
|

View file

@ -6,11 +6,11 @@ LL | fn bar() -> () {}
|
= help: the trait `std::fmt::Display` is not implemented for `()`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `Foo::{anon_assoc#0}`
note: required by a bound in `Foo::bar::{anon_assoc#0}`
--> $DIR/doesnt-satisfy.rs:2:22
|
LL | fn bar() -> impl std::fmt::Display;
| ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{anon_assoc#0}`
| ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::bar::{anon_assoc#0}`
error: aborting due to 1 previous error

View file

@ -8,7 +8,7 @@ trait Foo {
}
fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> {
//~^ ERROR <T as Foo>::{anon_assoc#0}<'s/#1>
//~^ ERROR <T as Foo>::hello::{anon_assoc#0}<'s/#1>
x.hello()
}

View file

@ -1,4 +1,4 @@
error: <T as Foo>::{anon_assoc#0}<'s/#1>
error: <T as Foo>::hello::{anon_assoc#0}<'s/#1>
--> $DIR/dump.rs:10:35
|
LL | fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> {

View file

@ -1,4 +1,4 @@
error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`
error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{anon_assoc#0}`
--> $DIR/method-compatability-via-leakage-cycle.rs:21:24
|
LL | fn foo(b: bool) -> impl Sized {
@ -45,7 +45,7 @@ note: ...which requires type-checking `<impl at $DIR/method-compatability-via-le
|
LL | fn foo(b: bool) -> impl Sized {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`, completing the cycle
= note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{anon_assoc#0}`, completing the cycle
note: cycle used when checking that `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>` is well-formed
--> $DIR/method-compatability-via-leakage-cycle.rs:17:1
|

View file

@ -1,4 +1,4 @@
error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`
error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{anon_assoc#0}`
--> $DIR/method-compatability-via-leakage-cycle.rs:21:24
|
LL | fn foo(b: bool) -> impl Sized {
@ -49,7 +49,7 @@ note: ...which requires type-checking `<impl at $DIR/method-compatability-via-le
|
LL | fn foo(b: bool) -> impl Sized {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`, completing the cycle
= note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{anon_assoc#0}`, completing the cycle
note: cycle used when checking that `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>` is well-formed
--> $DIR/method-compatability-via-leakage-cycle.rs:17:1
|
@ -57,7 +57,7 @@ LL | impl Trait for u32 {
| ^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`
error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{anon_assoc#0}`
--> $DIR/method-compatability-via-leakage-cycle.rs:21:24
|
LL | fn foo(b: bool) -> impl Sized {
@ -108,7 +108,7 @@ note: ...which requires type-checking `<impl at $DIR/method-compatability-via-le
|
LL | fn foo(b: bool) -> impl Sized {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`, completing the cycle
= note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{anon_assoc#0}`, completing the cycle
note: cycle used when checking that `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>` is well-formed
--> $DIR/method-compatability-via-leakage-cycle.rs:17:1
|

View file

@ -14,11 +14,11 @@ LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
| ^^^^^^^^^^^^ the trait `Foo<char>` is not implemented for `impl Foo<u8>`
|
= help: the trait `Foo<char>` is implemented for `Bar`
note: required by a bound in `Foo::{anon_assoc#0}`
note: required by a bound in `Foo::foo::{anon_assoc#0}`
--> $DIR/return-dont-satisfy-bounds.rs:2:30
|
LL | fn foo<F2>(self) -> impl Foo<T>;
| ^^^^^^ required by this bound in `Foo::{anon_assoc#0}`
| ^^^^^^ required by this bound in `Foo::foo::{anon_assoc#0}`
error[E0277]: the trait bound `Bar: Foo<u8>` is not satisfied
--> $DIR/return-dont-satisfy-bounds.rs:8:34

View file

@ -4,11 +4,11 @@ error[E0277]: the trait bound `Something: Termination` is not satisfied
LL | fn main() -> Something {
| ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
|
note: required by a bound in `Main::{anon_assoc#0}`
note: required by a bound in `Main::main::{anon_assoc#0}`
--> $DIR/issue-103052-2.rs:3:27
|
LL | fn main() -> impl std::process::Termination;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{anon_assoc#0}`
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::main::{anon_assoc#0}`
error: aborting due to 1 previous error