1
Fork 0

Install projection from RPITIT to default trait method opaque correctly

This commit is contained in:
Michael Goulet 2023-03-15 22:55:00 +00:00
parent c5c4340760
commit 0949da8f4e
8 changed files with 64 additions and 19 deletions

View file

@ -3,7 +3,7 @@ use crate::astconv::AstConv;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_infer::traits::util; use rustc_infer::traits::util;
use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, ImplTraitInTraitData, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
use rustc_span::Span; use rustc_span::Span;
@ -76,18 +76,26 @@ pub(super) fn explicit_item_bounds(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
def_id: DefId, def_id: DefId,
) -> &'_ [(ty::Predicate<'_>, Span)] { ) -> &'_ [(ty::Predicate<'_>, Span)] {
// If the def_id is about an RPITIT, delegate explicit_item_bounds to the opaque_def_id that match tcx.opt_rpitit_info(def_id) {
// generated the synthesized associate type. // RPITIT's bounds are the same as opaque type bounds, but with
let rpitit_info = if let Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) = // a projection self type.
tcx.opt_rpitit_info(def_id) Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
{ let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item();
Some(opaque_def_id) let opaque_ty = item.expect_opaque_ty();
} else { return opaque_type_bounds(
None tcx,
}; opaque_def_id,
opaque_ty.bounds,
tcx.mk_projection(def_id, ty::InternalSubsts::identity_for_item(tcx, def_id)),
item.span,
);
}
// These should have been fed!
Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(),
None => {}
}
let bounds_def_id = rpitit_info.unwrap_or(def_id); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let hir_id = tcx.hir().local_def_id_to_hir_id(bounds_def_id.expect_local());
match tcx.hir().get(hir_id) { match tcx.hir().get(hir_id) {
hir::Node::TraitItem(hir::TraitItem { hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Type(bounds, _), kind: hir::TraitItemKind::Type(bounds, _),
@ -100,12 +108,12 @@ pub(super) fn explicit_item_bounds(
.. ..
}) => { }) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id); let substs = InternalSubsts::identity_for_item(tcx, def_id);
let item_ty = if *in_trait || rpitit_info.is_some() { let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
tcx.mk_projection(def_id, substs) tcx.mk_projection(def_id, substs)
} else { } else {
tcx.mk_opaque(def_id, substs) tcx.mk_opaque(def_id, substs)
}; };
opaque_type_bounds(tcx, bounds_def_id, bounds, item_ty, *span) opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
} }
_ => bug!("item_bounds called on {:?}", def_id), _ => bug!("item_bounds called on {:?}", def_id),
} }

View file

@ -268,8 +268,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
if let ty::Alias(ty::Projection, alias_ty) = *ty.kind() if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) need to project to the opaque, could
// get it via type_of + subst.
&& self.tcx.is_impl_trait_in_trait(alias_ty.def_id) && self.tcx.is_impl_trait_in_trait(alias_ty.def_id)
&& self.tcx.impl_trait_in_trait_parent_fn(alias_ty.def_id) == self.fn_def_id && self.tcx.impl_trait_in_trait_parent_fn(alias_ty.def_id) == self.fn_def_id
&& self.seen.insert(alias_ty.def_id) && self.seen.insert(alias_ty.def_id)
@ -284,11 +282,24 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
re re
} }
}); });
// If we're lowering to associated item, install the opaque type which is just
// the `type_of` of the trait's associated item. If we're using the old lowering
// strategy, then just reinterpret the associated type like an opaque :^)
let default_ty = if self.tcx.lower_impl_trait_in_trait_to_assoc_ty() {
self
.tcx
.type_of(alias_ty.def_id)
.subst(self.tcx, alias_ty.substs)
} else {
self.tcx.mk_alias(ty::Opaque, alias_ty)
};
self.predicates.push( self.predicates.push(
ty::Binder::bind_with_vars( ty::Binder::bind_with_vars(
ty::ProjectionPredicate { ty::ProjectionPredicate {
projection_ty: alias_ty, projection_ty: alias_ty,
term: self.tcx.mk_alias(ty::Opaque, alias_ty).into(), term: default_ty.into(),
}, },
self.bound_vars, self.bound_vars,
) )

View file

@ -1,5 +1,5 @@
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/async-default-fn-overridden.rs:4:12 --> $DIR/async-default-fn-overridden.rs:6:12
| |
LL | #![feature(async_fn_in_trait)] LL | #![feature(async_fn_in_trait)]
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^

View file

@ -0,0 +1,11 @@
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/async-default-fn-overridden.rs:6:12
|
LL | #![feature(async_fn_in_trait)]
| ^^^^^^^^^^^^^^^^^
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View file

@ -1,5 +1,7 @@
// run-pass // run-pass
// edition:2021 // edition:2021
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
// revisions: current next
#![feature(async_fn_in_trait)] #![feature(async_fn_in_trait)]
//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use //~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use

View file

@ -1,5 +1,5 @@
warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/default-method-constraint.rs:5:12 --> $DIR/default-method-constraint.rs:7:12
| |
LL | #![feature(return_position_impl_trait_in_trait)] LL | #![feature(return_position_impl_trait_in_trait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -0,0 +1,11 @@
warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/default-method-constraint.rs:7:12
|
LL | #![feature(return_position_impl_trait_in_trait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View file

@ -1,4 +1,6 @@
// check-pass // check-pass
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
// revisions: current next
// This didn't work in the previous default RPITIT method hack attempt // This didn't work in the previous default RPITIT method hack attempt