From b0328c20ce75a56879bda08235242c21c1a451a1 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 11 Mar 2024 17:51:10 +0100 Subject: [PATCH] update comment for RPITIT projections --- compiler/rustc_ty_utils/src/opaque_types.rs | 37 ++++++++++++--------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 4b706ef955ac4..4a1064b29f6f9 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -54,7 +54,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { self.span = old; } - fn parent_trait_ref(&self) -> Option> { + fn parent_impl_trait_ref(&self) -> Option> { let parent = self.parent()?; if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) { Some(self.tcx.impl_trait_ref(parent)?.instantiate_identity()) @@ -217,26 +217,15 @@ impl<'tcx> TypeVisitor> 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() { @@ -253,7 +242,7 @@ impl<'tcx> TypeVisitor> 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), ); @@ -271,6 +260,24 @@ impl<'tcx> TypeVisitor> 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(::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() => {