Add `current_def_id_parent` to `LoweringContext`

This is needed to track anon const parents properly once we implement
`ConstArgKind::Path` (which requires moving anon const def-creation
outside of `DefCollector`):

    Why do we need this in addition to [`Self::current_hir_id_owner`]?

    Currently (as of June 2024), anonymous constants are not HIR owners;
    however, they do get their own DefIds. Some of these DefIds have to be
    created during AST lowering, rather than def collection, because we
    can't tell until after name resolution whether an anonymous constant
    will end up instead being a [`rustc_hir::ConstArgKind::Path`]. However,
    to compute which generics are available to an anonymous constant nested
    inside another, we need to make sure that the parent is recorded as the
    parent anon const, not the enclosing item. So we need to track parent
    defs differently from HIR owners, since they will be finer-grained in
    the case of anon consts.
This commit is contained in:
Noah Lev 2024-06-29 21:45:22 -07:00
parent 7d356ebde3
commit 71f8aed510
3 changed files with 30 additions and 16 deletions

View File

@ -222,10 +222,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}; };
// Wrap the expression in an AnonConst. // Wrap the expression in an AnonConst.
let parent_def_id = self.current_hir_id_owner; let parent_def_id = self.current_def_id_parent;
let node_id = self.next_node_id(); let node_id = self.next_node_id();
self.create_def( self.create_def(
parent_def_id.def_id, parent_def_id,
node_id, node_id,
kw::Empty, kw::Empty,
DefKind::AnonConst, DefKind::AnonConst,

View File

@ -377,17 +377,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let mut generic_args = ThinVec::new(); let mut generic_args = ThinVec::new();
for (idx, arg) in args.into_iter().enumerate() { for (idx, arg) in args.into_iter().enumerate() {
if legacy_args_idx.contains(&idx) { if legacy_args_idx.contains(&idx) {
let parent_def_id = self.current_hir_id_owner; let parent_def_id = self.current_def_id_parent;
let node_id = self.next_node_id(); let node_id = self.next_node_id();
// Add a definition for the in-band const def. // Add a definition for the in-band const def.
self.create_def( self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
parent_def_id.def_id,
node_id,
kw::Empty,
DefKind::AnonConst,
f.span,
);
let anon_const = AnonConst { id: node_id, value: arg }; let anon_const = AnonConst { id: node_id, value: arg };
generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));

View File

@ -120,6 +120,18 @@ struct LoweringContext<'a, 'hir> {
is_in_dyn_type: bool, is_in_dyn_type: bool,
current_hir_id_owner: hir::OwnerId, current_hir_id_owner: hir::OwnerId,
/// Why do we need this in addition to [`Self::current_hir_id_owner`]?
///
/// Currently (as of June 2024), anonymous constants are not HIR owners; however,
/// they do get their own DefIds. Some of these DefIds have to be created during
/// AST lowering, rather than def collection, because we can't tell until after
/// name resolution whether an anonymous constant will end up instead being a
/// [`rustc_hir::ConstArgKind::Path`]. However, to compute which generics are
/// available to an anonymous constant nested inside another, we need to make
/// sure that the parent is recorded as the parent anon const, not the enclosing
/// item. So we need to track parent defs differently from HIR owners, since they
/// will be finer-grained in the case of anon consts.
current_def_id_parent: LocalDefId,
item_local_id_counter: hir::ItemLocalId, item_local_id_counter: hir::ItemLocalId,
trait_map: ItemLocalMap<Box<[TraitCandidate]>>, trait_map: ItemLocalMap<Box<[TraitCandidate]>>,
@ -162,6 +174,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
attrs: SortedMap::default(), attrs: SortedMap::default(),
children: Vec::default(), children: Vec::default(),
current_hir_id_owner: hir::CRATE_OWNER_ID, current_hir_id_owner: hir::CRATE_OWNER_ID,
current_def_id_parent: CRATE_DEF_ID,
item_local_id_counter: hir::ItemLocalId::ZERO, item_local_id_counter: hir::ItemLocalId::ZERO,
node_id_to_local_id: Default::default(), node_id_to_local_id: Default::default(),
trait_map: Default::default(), trait_map: Default::default(),
@ -592,7 +605,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO); let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO);
debug_assert_eq!(_old, None); debug_assert_eq!(_old, None);
let item = f(self); let item = self.with_def_id_parent(def_id, f);
debug_assert_eq!(def_id, item.def_id().def_id); debug_assert_eq!(def_id, item.def_id().def_id);
// `f` should have consumed all the elements in these vectors when constructing `item`. // `f` should have consumed all the elements in these vectors when constructing `item`.
debug_assert!(self.impl_trait_defs.is_empty()); debug_assert!(self.impl_trait_defs.is_empty());
@ -612,6 +625,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.children.push((def_id, hir::MaybeOwner::Owner(info))); self.children.push((def_id, hir::MaybeOwner::Owner(info)));
} }
fn with_def_id_parent<T>(&mut self, parent: LocalDefId, f: impl FnOnce(&mut Self) -> T) -> T {
let current_def_id_parent = std::mem::replace(&mut self.current_def_id_parent, parent);
let result = f(self);
self.current_def_id_parent = current_def_id_parent;
result
}
/// Installs the remapping `remap` in scope while `f` is being executed. /// Installs the remapping `remap` in scope while `f` is being executed.
/// This causes references to the `LocalDefId` keys to be changed to /// This causes references to the `LocalDefId` keys to be changed to
/// refer to the values instead. /// refer to the values instead.
@ -806,7 +826,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
LifetimeRes::Fresh { param, kind, .. } => { LifetimeRes::Fresh { param, kind, .. } => {
// Late resolution delegates to us the creation of the `LocalDefId`. // Late resolution delegates to us the creation of the `LocalDefId`.
let _def_id = self.create_def( let _def_id = self.create_def(
self.current_hir_id_owner.def_id, self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
param, param,
kw::UnderscoreLifetime, kw::UnderscoreLifetime,
DefKind::LifetimeParam, DefKind::LifetimeParam,
@ -1152,13 +1172,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Construct an AnonConst where the expr is the "ty"'s path. // Construct an AnonConst where the expr is the "ty"'s path.
let parent_def_id = self.current_hir_id_owner; let parent_def_id = self.current_def_id_parent;
let node_id = self.next_node_id(); let node_id = self.next_node_id();
let span = self.lower_span(ty.span); let span = self.lower_span(ty.span);
// Add a definition for the in-band const def. // Add a definition for the in-band const def.
let def_id = self.create_def( let def_id = self.create_def(
parent_def_id.def_id, parent_def_id,
node_id, node_id,
kw::Empty, kw::Empty,
DefKind::AnonConst, DefKind::AnonConst,
@ -1429,7 +1449,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
); );
self.create_def( self.create_def(
self.current_hir_id_owner.def_id, self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
*def_node_id, *def_node_id,
ident.name, ident.name,
DefKind::TyParam, DefKind::TyParam,
@ -1637,7 +1657,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>], lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
) -> hir::TyKind<'hir> { ) -> hir::TyKind<'hir> {
let opaque_ty_def_id = self.create_def( let opaque_ty_def_id = self.create_def(
self.current_hir_id_owner.def_id, self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
opaque_ty_node_id, opaque_ty_node_id,
kw::Empty, kw::Empty,
DefKind::OpaqueTy, DefKind::OpaqueTy,