Skip to content

Commit

Permalink
update comment for RPITIT projections
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr authored and oli-obk committed Mar 11, 2024
1 parent 7348dd1 commit b0328c2
Showing 1 changed file with 22 additions and 15 deletions.
37 changes: 22 additions & 15 deletions compiler/rustc_ty_utils/src/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
self.span = old;
}

fn parent_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> {
fn parent_impl_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> {
let parent = self.parent()?;
if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) {
Some(self.tcx.impl_trait_ref(parent)?.instantiate_identity())
Expand Down Expand Up @@ -217,26 +217,15 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
.instantiate(self.tcx, alias_ty.args)
.visit_with(self);
}
// RPITIT are encoded as projections, not opaque types, make sure to handle these special
// projections independently of the projection handling below.
ty::Alias(ty::Projection, alias_ty)
if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) =
self.tcx.opt_rpitit_info(alias_ty.def_id)
&& fn_def_id == self.item.into() =>
{
let ty = self.tcx.type_of(alias_ty.def_id).instantiate(self.tcx, alias_ty.args);
let ty::Alias(ty::Opaque, alias_ty) = ty.kind() else { bug!("{ty:?}") };
self.visit_opaque_ty(alias_ty);
}
ty::Alias(ty::Projection, alias_ty) => {
// This avoids having to do normalization of `Self::AssocTy` by only
// supporting the case of a method defining opaque types from assoc types
// in the same impl block.
if let Some(parent_trait_ref) = self.parent_trait_ref() {
if let Some(impl_trait_ref) = self.parent_impl_trait_ref() {
// If the trait ref of the associated item and the impl differs,
// then we can't use the impl's identity args below, so
// just skip.
if alias_ty.trait_ref(self.tcx) == parent_trait_ref {
if alias_ty.trait_ref(self.tcx) == impl_trait_ref {
let parent = self.parent().expect("we should have a parent here");

for &assoc in self.tcx.associated_items(parent).in_definition_order() {
Expand All @@ -253,7 +242,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {

let impl_args = alias_ty.args.rebase_onto(
self.tcx,
parent_trait_ref.def_id,
impl_trait_ref.def_id,
ty::GenericArgs::identity_for_item(self.tcx, parent),
);

Expand All @@ -271,6 +260,24 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
}
}
}
} else if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) =
self.tcx.opt_rpitit_info(alias_ty.def_id)
&& fn_def_id == self.item.into()
{
// RPITIT in trait definitions get desugared to an associated type. For
// default methods we also create an opaque type this associated type
// normalizes to. The associated type is only known to normalize to the
// opaque if it is fully concrete. There could otherwise be an impl
// overwriting the default method.
//
// However, we have to be able to normalize the associated type while inside
// of the default method. This is normally handled by adding an unchecked
// `Projection(<Self as Trait>::synthetic_assoc_ty, trait_def::opaque)`
// assumption to the `param_env` of the default method. We also separately
// rely on that assumption here.
let ty = self.tcx.type_of(alias_ty.def_id).instantiate(self.tcx, alias_ty.args);
let ty::Alias(ty::Opaque, alias_ty) = ty.kind() else { bug!("{ty:?}") };
self.visit_opaque_ty(alias_ty);
}
}
ty::Adt(def, _) if def.did().is_local() => {
Expand Down

0 comments on commit b0328c2

Please sign in to comment.