Skip to content

Commit

Permalink
Auto merge of #129244 - cjgillot:opaque-hir, r=<try>
Browse files Browse the repository at this point in the history
Make opaque types regular HIR nodes

Having opaque types as HIR owner introduces all sorts of complications. This PR proposes to make them regular HIR nodes instead.

I haven't gone through all the test changes yet, so there may be a few surprises.

Many thanks to `@camelid` for the first draft.
Fixes #129023

Fixes #129099
Fixes #125843
Fixes #119716
Fixes #121422
  • Loading branch information
bors committed Aug 22, 2024
2 parents 5ad98b4 + b66cc38 commit b64686e
Show file tree
Hide file tree
Showing 111 changed files with 1,024 additions and 1,050 deletions.
8 changes: 8 additions & 0 deletions compiler/rustc_ast_lowering/src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
});
}

fn visit_opaque_ty(&mut self, opaq: &'hir OpaqueTy<'hir>) {
self.insert(opaq.span, opaq.hir_id, Node::OpaqueTy(opaq));

self.with_parent(opaq.hir_id, |this| {
intravisit::walk_opaque_ty(this, opaq);
});
}

fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
// FIXME: use real span?
self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant));
Expand Down
30 changes: 10 additions & 20 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1620,13 +1620,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
) -> hir::TyKind<'hir> {
let opaque_ty_def_id = self.create_def(
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
self.current_def_id_parent,
opaque_ty_node_id,
kw::Empty,
DefKind::OpaqueTy,
opaque_ty_span,
);
debug!(?opaque_ty_def_id);
let opaque_ty_hir_id = self.lower_node_id(opaque_ty_node_id);
debug!(?opaque_ty_def_id, ?opaque_ty_hir_id);

// Map from captured (old) lifetime to synthetic (new) lifetime.
// Used to resolve lifetimes in the bounds of the opaque.
Expand Down Expand Up @@ -1699,7 +1700,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}

self.with_hir_id_owner(opaque_ty_node_id, |this| {
let opaque_ty_def = self.with_def_id_parent(opaque_ty_def_id, |this| {
// Install the remapping from old to new (if any). This makes sure that
// any lifetimes that would have resolved to the def-id of captured
// lifetimes are remapped to the new *synthetic* lifetimes of the opaque.
Expand Down Expand Up @@ -1737,7 +1738,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {

let lifetime_mapping = self.arena.alloc_slice(&synthesized_lifetime_args);

let opaque_ty_item = hir::OpaqueTy {
trace!("registering opaque type with id {:#?}", opaque_ty_def_id);
let opaque_ty_def = hir::OpaqueTy {
hir_id: opaque_ty_hir_id,
def_id: opaque_ty_def_id,
generics: this.arena.alloc(hir::Generics {
params: generic_params,
predicates: &[],
Expand All @@ -1749,19 +1753,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
origin,
lifetime_mapping,
in_trait,
};

// Generate an `type Foo = impl Trait;` declaration.
trace!("registering opaque type with id {:#?}", opaque_ty_def_id);
let opaque_ty_item = hir::Item {
owner_id: hir::OwnerId { def_id: opaque_ty_def_id },
ident: Ident::empty(),
kind: hir::ItemKind::OpaqueTy(this.arena.alloc(opaque_ty_item)),
vis_span: this.lower_span(span.shrink_to_lo()),
span: this.lower_span(opaque_ty_span),
};

hir::OwnerNode::Item(this.arena.alloc(opaque_ty_item))
this.arena.alloc(opaque_ty_def)
});

let generic_args = self.arena.alloc_from_iter(
Expand All @@ -1774,11 +1768,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Foo = impl Trait` is, internally, created as a child of the
// async fn, so the *type parameters* are inherited. It's
// only the lifetime parameters that we must supply.
hir::TyKind::OpaqueDef(
hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
generic_args,
in_trait,
)
hir::TyKind::OpaqueDef(opaque_ty_def, generic_args)
}

fn lower_precise_capturing_args(
Expand Down
10 changes: 2 additions & 8 deletions compiler/rustc_borrowck/src/diagnostics/region_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -829,20 +829,14 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
///
/// [`OpaqueDef`]: hir::TyKind::OpaqueDef
fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
let hir = self.infcx.tcx.hir();

let hir::TyKind::OpaqueDef(id, _, _) = hir_ty.kind else {
let hir::TyKind::OpaqueDef(opaque_ty, _) = hir_ty.kind else {
span_bug!(
hir_ty.span,
"lowered return type of async fn is not OpaqueDef: {:?}",
hir_ty
);
};
let opaque_ty = hir.item(id);
if let hir::ItemKind::OpaqueTy(hir::OpaqueTy {
bounds: [hir::GenericBound::Trait(trait_ref, _)],
..
}) = opaque_ty.kind
if let hir::OpaqueTy { bounds: [hir::GenericBound::Trait(trait_ref, _)], .. } = opaque_ty
&& let Some(segment) = trait_ref.trait_ref.path.segments.last()
&& let Some(args) = segment.args
&& let [constraint] = args.constraints
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,8 @@ fn check_opaque_type_well_formed<'tcx>(
) -> Result<Ty<'tcx>, ErrorGuaranteed> {
// Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
// on stable and we'd break that.
let opaque_ty_hir = tcx.hir().expect_item(def_id);
let OpaqueTyOrigin::TyAlias { .. } = opaque_ty_hir.expect_opaque_ty().origin else {
let opaque_ty_hir = tcx.hir().expect_opaque_ty(def_id);
let OpaqueTyOrigin::TyAlias { .. } = opaque_ty_hir.origin else {
return Ok(definition_ty);
};
let param_env = tcx.param_env(def_id);
Expand Down
17 changes: 9 additions & 8 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2610,7 +2610,7 @@ impl<'hir> Ty<'hir> {
}
TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty),
TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(),
TyKind::OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args),
TyKind::OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args),
TyKind::Path(QPath::TypeRelative(ty, segment)) => {
ty.is_suggestable_infer_ty() || are_suggestable_generic_args(segment.args().args)
}
Expand Down Expand Up @@ -2727,6 +2727,8 @@ pub struct BareFnTy<'hir> {

#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct OpaqueTy<'hir> {
pub hir_id: HirId,
pub def_id: LocalDefId,
pub generics: &'hir Generics<'hir>,
pub bounds: GenericBounds<'hir>,
pub origin: OpaqueTyOrigin,
Expand All @@ -2744,6 +2746,7 @@ pub struct OpaqueTy<'hir> {
/// originating from a trait method. This makes it so that the opaque is
/// lowered as an associated type.
pub in_trait: bool,
pub span: Span,
}

#[derive(Debug, Clone, Copy, HashStable_Generic)]
Expand Down Expand Up @@ -2834,7 +2837,7 @@ pub enum TyKind<'hir> {
/// possibly parameters) that are actually bound on the `impl Trait`.
///
/// The last parameter specifies whether this opaque appears in a trait definition.
OpaqueDef(ItemId, &'hir [GenericArg<'hir>], bool),
OpaqueDef(&'hir OpaqueTy<'hir>, &'hir [GenericArg<'hir>]),
/// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime.
TraitObject(
Expand Down Expand Up @@ -3301,8 +3304,6 @@ impl<'hir> Item<'hir> {
expect_ty_alias, (&'hir Ty<'hir>, &'hir Generics<'hir>),
ItemKind::TyAlias(ty, generics), (ty, generics);

expect_opaque_ty, &OpaqueTy<'hir>, ItemKind::OpaqueTy(ty), ty;

expect_enum, (&EnumDef<'hir>, &'hir Generics<'hir>), ItemKind::Enum(def, generics), (def, generics);

expect_struct, (&VariantData<'hir>, &'hir Generics<'hir>),
Expand Down Expand Up @@ -3415,8 +3416,6 @@ pub enum ItemKind<'hir> {
GlobalAsm(&'hir InlineAsm<'hir>),
/// A type alias, e.g., `type Foo = Bar<u8>`.
TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>),
/// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
OpaqueTy(&'hir OpaqueTy<'hir>),
/// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`.
Enum(EnumDef<'hir>, &'hir Generics<'hir>),
/// A struct definition, e.g., `struct Foo<A> {x: A}`.
Expand Down Expand Up @@ -3460,7 +3459,6 @@ impl ItemKind<'_> {
ItemKind::Fn(_, ref generics, _)
| ItemKind::TyAlias(_, ref generics)
| ItemKind::Const(_, ref generics, _)
| ItemKind::OpaqueTy(OpaqueTy { ref generics, .. })
| ItemKind::Enum(_, ref generics)
| ItemKind::Struct(_, ref generics)
| ItemKind::Union(_, ref generics)
Expand All @@ -3483,7 +3481,6 @@ impl ItemKind<'_> {
ItemKind::ForeignMod { .. } => "extern block",
ItemKind::GlobalAsm(..) => "global asm item",
ItemKind::TyAlias(..) => "type alias",
ItemKind::OpaqueTy(..) => "opaque type",
ItemKind::Enum(..) => "enum",
ItemKind::Struct(..) => "struct",
ItemKind::Union(..) => "union",
Expand Down Expand Up @@ -3770,6 +3767,7 @@ pub enum Node<'hir> {
Ty(&'hir Ty<'hir>),
AssocItemConstraint(&'hir AssocItemConstraint<'hir>),
TraitRef(&'hir TraitRef<'hir>),
OpaqueTy(&'hir OpaqueTy<'hir>),
Pat(&'hir Pat<'hir>),
PatField(&'hir PatField<'hir>),
Arm(&'hir Arm<'hir>),
Expand Down Expand Up @@ -3835,6 +3833,7 @@ impl<'hir> Node<'hir> {
| Node::Crate(..)
| Node::Ty(..)
| Node::TraitRef(..)
| Node::OpaqueTy(..)
| Node::Infer(..)
| Node::WhereBoundPredicate(..)
| Node::ArrayLenInfer(..)
Expand Down Expand Up @@ -3960,6 +3959,7 @@ impl<'hir> Node<'hir> {
| Node::TraitItem(TraitItem { generics, .. })
| Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
Node::Item(item) => item.kind.generics(),
Node::OpaqueTy(opaque) => Some(opaque.generics),
_ => None,
}
}
Expand Down Expand Up @@ -4019,6 +4019,7 @@ impl<'hir> Node<'hir> {
expect_ty, &'hir Ty<'hir>, Node::Ty(n), n;
expect_assoc_item_constraint, &'hir AssocItemConstraint<'hir>, Node::AssocItemConstraint(n), n;
expect_trait_ref, &'hir TraitRef<'hir>, Node::TraitRef(n), n;
expect_opaque_ty, &'hir OpaqueTy<'hir>, Node::OpaqueTy(n), n;
expect_pat, &'hir Pat<'hir>, Node::Pat(n), n;
expect_pat_field, &'hir PatField<'hir>, Node::PatField(n), n;
expect_arm, &'hir Arm<'hir>, Node::Arm(n), n;
Expand Down
33 changes: 26 additions & 7 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ impl<'a> FnKind<'a> {
pub trait Map<'hir> {
/// Retrieves the `Node` corresponding to `id`.
fn hir_node(&self, hir_id: HirId) -> Node<'hir>;
fn hir_node_by_def_id(&self, def_id: LocalDefId) -> Node<'hir>;
fn body(&self, id: BodyId) -> &'hir Body<'hir>;
fn item(&self, id: ItemId) -> &'hir Item<'hir>;
fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
Expand All @@ -123,6 +124,9 @@ impl<'hir> Map<'hir> for ! {
fn hir_node(&self, _: HirId) -> Node<'hir> {
*self;
}
fn hir_node_by_def_id(&self, _: LocalDefId) -> Node<'hir> {
*self;
}
fn body(&self, _: BodyId) -> &'hir Body<'hir> {
*self;
}
Expand Down Expand Up @@ -423,6 +427,9 @@ pub trait Visitor<'v>: Sized {
fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef<'v>) -> Self::Result {
walk_poly_trait_ref(self, t)
}
fn visit_opaque_ty(&mut self, opaque: &'v OpaqueTy<'v>) -> Self::Result {
walk_opaque_ty(self, opaque)
}
fn visit_variant_data(&mut self, s: &'v VariantData<'v>) -> Self::Result {
walk_struct_def(self, s)
}
Expand Down Expand Up @@ -536,11 +543,6 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
try_visit!(visitor.visit_ty(ty));
try_visit!(visitor.visit_generics(generics));
}
ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, .. }) => {
try_visit!(visitor.visit_id(item.hir_id()));
try_visit!(walk_generics(visitor, generics));
walk_list!(visitor, visit_param_bound, bounds);
}
ItemKind::Enum(ref enum_definition, ref generics) => {
try_visit!(visitor.visit_generics(generics));
// `visit_enum_def()` takes care of visiting the `Item`'s `HirId`.
Expand Down Expand Up @@ -894,8 +896,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
TyKind::Path(ref qpath) => {
try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span));
}
TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => {
try_visit!(visitor.visit_nested_item(item_id));
TyKind::OpaqueDef(opaque, lifetimes) => {
try_visit!(visitor.visit_opaque_ty(opaque));
walk_list!(visitor, visit_generic_arg, lifetimes);
}
TyKind::Array(ref ty, ref length) => {
Expand Down Expand Up @@ -1185,6 +1187,23 @@ pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
visitor.visit_trait_ref(&trait_ref.trait_ref)
}

pub fn walk_opaque_ty<'v, V: Visitor<'v>>(visitor: &mut V, opaque: &'v OpaqueTy<'v>) -> V::Result {
let &OpaqueTy {
hir_id,
def_id: _,
generics,
bounds,
origin: _,
lifetime_mapping: _,
in_trait: _,
span: _,
} = opaque;
try_visit!(visitor.visit_id(hir_id));
try_visit!(walk_generics(visitor, generics));
walk_list!(visitor, visit_param_bound, bounds);
V::Result::output()
}

pub fn walk_struct_def<'v, V: Visitor<'v>>(
visitor: &mut V,
struct_definition: &'v VariantData<'v>,
Expand Down
5 changes: 0 additions & 5 deletions compiler/rustc_hir/src/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ pub enum Target {
ForeignMod,
GlobalAsm,
TyAlias,
OpaqueTy,
Enum,
Variant,
Struct,
Expand Down Expand Up @@ -79,7 +78,6 @@ impl Target {
| Target::ForeignMod
| Target::GlobalAsm
| Target::TyAlias
| Target::OpaqueTy
| Target::Enum
| Target::Variant
| Target::Struct
Expand Down Expand Up @@ -114,7 +112,6 @@ impl Target {
ItemKind::ForeignMod { .. } => Target::ForeignMod,
ItemKind::GlobalAsm(..) => Target::GlobalAsm,
ItemKind::TyAlias(..) => Target::TyAlias,
ItemKind::OpaqueTy(..) => Target::OpaqueTy,
ItemKind::Enum(..) => Target::Enum,
ItemKind::Struct(..) => Target::Struct,
ItemKind::Union(..) => Target::Union,
Expand All @@ -137,7 +134,6 @@ impl Target {
DefKind::ForeignMod => Target::ForeignMod,
DefKind::GlobalAsm => Target::GlobalAsm,
DefKind::TyAlias => Target::TyAlias,
DefKind::OpaqueTy => Target::OpaqueTy,
DefKind::Enum => Target::Enum,
DefKind::Struct => Target::Struct,
DefKind::Union => Target::Union,
Expand Down Expand Up @@ -191,7 +187,6 @@ impl Target {
Target::ForeignMod => "foreign module",
Target::GlobalAsm => "global asm",
Target::TyAlias => "type alias",
Target::OpaqueTy => "opaque type",
Target::Enum => "enum",
Target::Variant => "enum variant",
Target::Struct => "struct",
Expand Down
16 changes: 6 additions & 10 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
/// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
/// projections that would result in "inheriting lifetimes".
fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let item = tcx.hir().expect_item(def_id);
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
tcx.dcx().span_bug(item.span, "expected opaque item");
};
let hir::OpaqueTy { origin, .. } = tcx.hir().expect_opaque_ty(def_id);

// HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
// `async-std` (and `pub async fn` in general).
Expand All @@ -264,16 +261,16 @@ fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
return;
}

let span = tcx.def_span(item.owner_id.def_id);
let span = tcx.def_span(def_id);

if tcx.type_of(item.owner_id.def_id).instantiate_identity().references_error() {
if tcx.type_of(def_id).instantiate_identity().references_error() {
return;
}
if check_opaque_for_cycles(tcx, item.owner_id.def_id, span).is_err() {
if check_opaque_for_cycles(tcx, def_id, span).is_err() {
return;
}

let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, origin);
let _ = check_opaque_meets_bounds(tcx, def_id, span, origin);
}

/// Checks that an opaque type does not contain cycles.
Expand Down Expand Up @@ -480,8 +477,7 @@ fn sanity_check_found_hidden_type<'tcx>(
/// 2. Checking that all lifetimes that are implicitly captured are mentioned.
/// 3. Asserting that all parameters mentioned in the captures list are invariant.
fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDefId) {
let hir::OpaqueTy { bounds, .. } =
*tcx.hir_node_by_def_id(opaque_def_id).expect_item().expect_opaque_ty();
let hir::OpaqueTy { bounds, .. } = *tcx.hir_node_by_def_id(opaque_def_id).expect_opaque_ty();
let Some(precise_capturing_args) = bounds.iter().find_map(|bound| match *bound {
hir::GenericBound::Use(bounds, ..) => Some(bounds),
_ => None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
// it's a refinement to a TAIT.
if !tcx.hir().get_if_local(impl_opaque.def_id).is_some_and(|node| {
matches!(
node.expect_item().expect_opaque_ty().origin,
node.expect_opaque_ty().origin,
hir::OpaqueTyOrigin::AsyncFn(def_id) | hir::OpaqueTyOrigin::FnReturn(def_id)
if def_id == impl_m.def_id.expect_local()
)
Expand Down
Loading

0 comments on commit b64686e

Please sign in to comment.