update comment for RPITIT projections
This commit is contained in:
parent
7348dd1950
commit
b0328c20ce
1 changed files with 22 additions and 15 deletions
|
@ -54,7 +54,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
|
||||||
self.span = old;
|
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()?;
|
let parent = self.parent()?;
|
||||||
if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) {
|
if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) {
|
||||||
Some(self.tcx.impl_trait_ref(parent)?.instantiate_identity())
|
Some(self.tcx.impl_trait_ref(parent)?.instantiate_identity())
|
||||||
|
@ -217,26 +217,15 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
|
||||||
.instantiate(self.tcx, alias_ty.args)
|
.instantiate(self.tcx, alias_ty.args)
|
||||||
.visit_with(self);
|
.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) => {
|
ty::Alias(ty::Projection, alias_ty) => {
|
||||||
// This avoids having to do normalization of `Self::AssocTy` by only
|
// This avoids having to do normalization of `Self::AssocTy` by only
|
||||||
// supporting the case of a method defining opaque types from assoc types
|
// supporting the case of a method defining opaque types from assoc types
|
||||||
// in the same impl block.
|
// 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,
|
// If the trait ref of the associated item and the impl differs,
|
||||||
// then we can't use the impl's identity args below, so
|
// then we can't use the impl's identity args below, so
|
||||||
// just skip.
|
// 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");
|
let parent = self.parent().expect("we should have a parent here");
|
||||||
|
|
||||||
for &assoc in self.tcx.associated_items(parent).in_definition_order() {
|
for &assoc in self.tcx.associated_items(parent).in_definition_order() {
|
||||||
|
@ -253,7 +242,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
|
||||||
|
|
||||||
let impl_args = alias_ty.args.rebase_onto(
|
let impl_args = alias_ty.args.rebase_onto(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
parent_trait_ref.def_id,
|
impl_trait_ref.def_id,
|
||||||
ty::GenericArgs::identity_for_item(self.tcx, parent),
|
ty::GenericArgs::identity_for_item(self.tcx, parent),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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() => {
|
ty::Adt(def, _) if def.did().is_local() => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue