Skip to content
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 @@ -226,6 +226,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
27 changes: 9 additions & 18 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1603,7 +1603,8 @@ 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.local_def_id(opaque_ty_node_id);
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 @@ -1676,7 +1677,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 @@ -1714,7 +1715,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 @@ -1725,19 +1729,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
bounds,
origin,
lifetime_mapping,
};

// 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 @@ -1750,10 +1744,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,
)
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 @@ -830,20 +830,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 @@ -329,8 +329,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
15 changes: 8 additions & 7 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2749,6 +2749,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 @@ -2762,6 +2764,7 @@ pub struct OpaqueTy<'hir> {
/// This mapping associated a captured lifetime (first parameter) with the new
/// early-bound lifetime that was generated for the opaque.
pub lifetime_mapping: &'hir [(&'hir Lifetime, LocalDefId)],
pub span: Span,
}

#[derive(Debug, Clone, Copy, HashStable_Generic)]
Expand Down Expand Up @@ -2868,7 +2871,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>]),
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 @@ -3337,8 +3340,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 @@ -3451,8 +3452,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 @@ -3496,7 +3495,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 @@ -3519,7 +3517,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 @@ -3806,6 +3803,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 @@ -3871,6 +3869,7 @@ impl<'hir> Node<'hir> {
| Node::Crate(..)
| Node::Ty(..)
| Node::TraitRef(..)
| Node::OpaqueTy(..)
| Node::Infer(..)
| Node::WhereBoundPredicate(..)
| Node::ArrayLenInfer(..)
Expand Down Expand Up @@ -3996,6 +3995,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 @@ -4055,6 +4055,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
25 changes: 18 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) => {
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,15 @@ 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: _, 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 @@ -252,10 +252,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 @@ -265,16 +262,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 @@ -481,8 +478,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 @@ -93,7 +93,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 { parent, .. } | hir::OpaqueTyOrigin::FnReturn { parent, .. }
if parent == impl_m.def_id.expect_local()
)
Expand Down
Loading
Loading