1
Fork 0

Auto merge of #112988 - spastorino:new-rpitit-24, r=compiler-errors

Replace RPITIT current impl with new strategy that lowers as a GAT

This PR replaces the current implementation of RPITITs with the new implementation that we had under -Zlower-impl-trait-in-trait-to-assoc-ty flag that lowers the RPIT as a GAT on the trait and on the impls that implement that trait.

Opening this PR as a draft because this goes after #112682, ~#112981~ and ~#112983~.
As soon as those are merged, I can rebase and we should run perf, crater and test a lot.

r? `@compiler-errors`
This commit is contained in:
bors 2023-07-10 19:01:30 +00:00
commit 8ca44ef9ca
146 changed files with 1106 additions and 586 deletions

View file

@ -109,8 +109,6 @@ pub enum DefKind {
InlineConst,
/// Opaque type, aka `impl Trait`.
OpaqueTy,
/// A return-position `impl Trait` in a trait definition
ImplTraitPlaceholder,
Field,
/// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }`
LifetimeParam,
@ -143,7 +141,6 @@ impl DefKind {
DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",
DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",
DefKind::OpaqueTy => "opaque type",
DefKind::ImplTraitPlaceholder => "opaque type in trait",
DefKind::TyAlias => "type alias",
DefKind::TraitAlias => "trait alias",
DefKind::AssocTy => "associated type",
@ -227,8 +224,7 @@ impl DefKind {
| DefKind::Use
| DefKind::ForeignMod
| DefKind::GlobalAsm
| DefKind::Impl { .. }
| DefKind::ImplTraitPlaceholder => None,
| DefKind::Impl { .. } => None,
}
}
@ -262,7 +258,6 @@ impl DefKind {
| DefKind::Use
| DefKind::ForeignMod
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::Impl { .. }
| DefKind::Field
| DefKind::TyParam

View file

@ -36,7 +36,6 @@ pub enum Target {
GlobalAsm,
TyAlias,
OpaqueTy,
ImplTraitPlaceholder,
Enum,
Variant,
Struct,
@ -80,13 +79,7 @@ impl Target {
ItemKind::ForeignMod { .. } => Target::ForeignMod,
ItemKind::GlobalAsm(..) => Target::GlobalAsm,
ItemKind::TyAlias(..) => Target::TyAlias,
ItemKind::OpaqueTy(ref opaque) => {
if opaque.in_trait {
Target::ImplTraitPlaceholder
} else {
Target::OpaqueTy
}
}
ItemKind::OpaqueTy(..) => Target::OpaqueTy,
ItemKind::Enum(..) => Target::Enum,
ItemKind::Struct(..) => Target::Struct,
ItemKind::Union(..) => Target::Union,
@ -110,7 +103,6 @@ impl Target {
DefKind::GlobalAsm => Target::GlobalAsm,
DefKind::TyAlias => Target::TyAlias,
DefKind::OpaqueTy => Target::OpaqueTy,
DefKind::ImplTraitPlaceholder => Target::ImplTraitPlaceholder,
DefKind::Enum => Target::Enum,
DefKind::Struct => Target::Struct,
DefKind::Union => Target::Union,
@ -165,7 +157,6 @@ impl Target {
Target::GlobalAsm => "global asm",
Target::TyAlias => "type alias",
Target::OpaqueTy => "opaque type",
Target::ImplTraitPlaceholder => "opaque type in trait",
Target::Enum => "enum",
Target::Variant => "enum variant",
Target::Struct => "struct",

View file

@ -2128,7 +2128,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let span = path.span;
match path.res {
Res::Def(DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder, did) => {
Res::Def(DefKind::OpaqueTy, did) => {
// Check for desugared `impl Trait`.
assert!(tcx.is_type_alias_impl_trait(did));
let item_segment = path.segments.split_last().unwrap();
@ -2439,7 +2439,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// If this is an RPITIT and we are using the new RPITIT lowering scheme, we
// generate the def_id of an associated type for the trait and return as
// type a projection.
let def_id = if in_trait && tcx.lower_impl_trait_in_trait_to_assoc_ty() {
let def_id = if in_trait {
tcx.associated_type_for_impl_trait_in_trait(local_def_id).to_def_id()
} else {
local_def_id.to_def_id()

View file

@ -302,16 +302,11 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
if let ItemKind::OpaqueTy(&hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
in_trait,
..
}) = item.kind
{
let substs = InternalSubsts::identity_for_item(tcx, def_id);
let opaque_identity_ty = if in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
Ty::new_projection(tcx, def_id.to_def_id(), substs)
} else {
Ty::new_opaque(tcx, def_id.to_def_id(), substs)
};
let opaque_identity_ty = Ty::new_opaque(tcx, def_id.to_def_id(), substs);
let mut visitor = ProhibitOpaqueVisitor {
opaque_identity_ty,
parent_count: tcx.generics_of(def_id).parent_count as u32,
@ -576,17 +571,6 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
check_opaque(tcx, id);
}
}
DefKind::ImplTraitPlaceholder => {
let parent = tcx.impl_trait_in_trait_parent_fn(id.owner_id.to_def_id());
// Only check the validity of this opaque type if the function has a default body
if let hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
..
}) = tcx.hir().get_by_def_id(parent.expect_local())
{
check_opaque(tcx, id);
}
}
DefKind::TyAlias => {
let pty_ty = tcx.type_of(id.owner_id).subst_identity();
let generics = tcx.generics_of(id.owner_id);

View file

@ -113,16 +113,12 @@ pub(super) fn explicit_item_bounds(
..
}) => associated_type_bounds(tcx, def_id, bounds, *span),
hir::Node::Item(hir::Item {
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }),
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }),
span,
..
}) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
Ty::new_projection(tcx, def_id.to_def_id(), substs)
} else {
Ty::new_opaque(tcx, def_id.to_def_id(), substs)
};
let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), substs);
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
}
hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],

View file

@ -109,20 +109,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
vec![]
}
}
ty::AssocKind::Fn => {
if !tcx.lower_impl_trait_in_trait_to_assoc_ty()
&& item.defaultness(tcx).has_value()
&& tcx.impl_method_has_trait_impl_trait_tys(item.def_id)
&& let Ok(table) = tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
{
table.values().copied().flat_map(|ty| {
cgp::parameters_for(&ty.subst_identity(), true)
}).collect()
} else {
vec![]
}
}
ty::AssocKind::Const => vec![],
ty::AssocKind::Fn | ty::AssocKind::Const => vec![],
}
})
.collect();

View file

@ -56,7 +56,7 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
let crate_map = tcx.crate_variances(());
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
}
DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => {
DefKind::OpaqueTy => {
return variance_of_opaque(tcx, item_def_id);
}
_ => {}
@ -115,14 +115,6 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
{
self.visit_opaque(*def_id, substs)
}
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary
// at all for RPITITs.
ty::Alias(_, ty::AliasTy { def_id, substs, .. })
if self.tcx.is_impl_trait_in_trait(*def_id)
&& !self.tcx.lower_impl_trait_in_trait_to_assoc_ty() =>
{
self.visit_opaque(*def_id, substs)
}
_ => t.super_visit_with(self),
}
}

View file

@ -824,7 +824,6 @@ fn should_encode_span(def_kind: DefKind) -> bool {
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::Field
| DefKind::Impl { .. }
| DefKind::Closure
@ -867,7 +866,6 @@ fn should_encode_attrs(def_kind: DefKind) -> bool {
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::LifetimeParam
| DefKind::GlobalAsm
| DefKind::Generator => false,
@ -902,7 +900,6 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool {
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm
@ -939,7 +936,6 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::GlobalAsm
| DefKind::Impl { .. }
| DefKind::Closure
@ -966,7 +962,6 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
| DefKind::ForeignMod
| DefKind::TyAlias
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::Enum
| DefKind::Union
| DefKind::Impl { .. }
@ -1033,7 +1028,6 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
| DefKind::Enum
| DefKind::Variant
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::Fn
| DefKind::Ctor(..)
| DefKind::AssocFn => true,
@ -1083,7 +1077,6 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::Impl { .. }
| DefKind::Field
| DefKind::TyParam
@ -1134,19 +1127,6 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
}
}
DefKind::ImplTraitPlaceholder => {
let parent_def_id = tcx.impl_trait_in_trait_parent_fn(def_id.to_def_id());
let assoc_item = tcx.associated_item(parent_def_id);
match assoc_item.container {
// Always encode an RPIT in an impl fn, since it always has a body
ty::AssocItemContainer::ImplContainer => true,
ty::AssocItemContainer::TraitContainer => {
// Encode an RPIT for a trait only if the trait has a default body
assoc_item.defaultness(tcx).has_value()
}
}
}
DefKind::AssocTy => {
let assoc_item = tcx.associated_item(def_id);
match assoc_item.container {
@ -1192,7 +1172,6 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool {
| DefKind::Ctor(..)
| DefKind::TyAlias
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::ForeignTy
| DefKind::Impl { .. }
| DefKind::AssocConst
@ -1235,7 +1214,6 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
| DefKind::TyAlias
| DefKind::OpaqueTy
| DefKind::Impl { of_trait: false }
| DefKind::ImplTraitPlaceholder
| DefKind::ForeignTy
| DefKind::Generator
| DefKind::ConstParam
@ -1268,7 +1246,6 @@ fn should_encode_const(def_kind: DefKind) -> bool {
| DefKind::Static(..)
| DefKind::TyAlias
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::ForeignTy
| DefKind::Impl { .. }
| DefKind::AssocFn
@ -1289,11 +1266,8 @@ fn should_encode_const(def_kind: DefKind) -> bool {
}
}
// We only encode impl trait in trait when using `lower-impl-trait-in-trait-to-assoc-ty` unstable
// option.
fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
if tcx.lower_impl_trait_in_trait_to_assoc_ty()
&& let Some(assoc_item) = tcx.opt_associated_item(def_id)
if let Some(assoc_item) = tcx.opt_associated_item(def_id)
&& assoc_item.container == ty::AssocItemContainer::TraitContainer
&& assoc_item.kind == ty::AssocKind::Fn
{
@ -1447,9 +1421,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
.is_type_alias_impl_trait
.set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
}
if let DefKind::ImplTraitPlaceholder = def_kind {
self.encode_explicit_item_bounds(def_id);
}
if tcx.impl_method_has_trait_impl_trait_tys(def_id)
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
{

View file

@ -142,7 +142,6 @@ fixed_size_enum! {
( AnonConst )
( InlineConst )
( OpaqueTy )
( ImplTraitPlaceholder )
( Field )
( LifetimeParam )
( GlobalAsm )

View file

@ -195,13 +195,7 @@ impl<'hir> Map<'hir> {
ItemKind::Fn(..) => DefKind::Fn,
ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind),
ItemKind::Mod(..) => DefKind::Mod,
ItemKind::OpaqueTy(ref opaque) => {
if opaque.in_trait && !self.tcx.lower_impl_trait_in_trait_to_assoc_ty() {
DefKind::ImplTraitPlaceholder
} else {
DefKind::OpaqueTy
}
}
ItemKind::OpaqueTy(..) => DefKind::OpaqueTy,
ItemKind::TyAlias(..) => DefKind::TyAlias,
ItemKind::Enum(..) => DefKind::Enum,
ItemKind::Struct(..) => DefKind::Struct,

View file

@ -1036,7 +1036,9 @@ impl<'tcx> TyCtxt<'tcx> {
scope_def_id: LocalDefId,
) -> Vec<&'tcx hir::Ty<'tcx>> {
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) else {
let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) =
self.hir().fn_decl_by_hir_id(hir_id)
else {
return vec![];
};
@ -2002,16 +2004,8 @@ impl<'tcx> TyCtxt<'tcx> {
)
}
pub fn lower_impl_trait_in_trait_to_assoc_ty(self) -> bool {
self.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
}
pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
if self.lower_impl_trait_in_trait_to_assoc_ty() {
self.opt_rpitit_info(def_id).is_some()
} else {
self.def_kind(def_id) == DefKind::ImplTraitPlaceholder
}
self.opt_rpitit_info(def_id).is_some()
}
/// Named module children from all kinds of items, including imports.

View file

@ -2688,7 +2688,6 @@ impl<'tcx> TyCtxt<'tcx> {
| Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) => fn_def_id,
None => {
while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder);
def_id = self.parent(def_id);
}
def_id
@ -2720,26 +2719,9 @@ impl<'tcx> TyCtxt<'tcx> {
let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
if self.lower_impl_trait_in_trait_to_assoc_ty() {
return !self
.associated_types_for_impl_traits_in_associated_fn(trait_item_def_id)
.is_empty();
}
// FIXME(RPITIT): This does a somewhat manual walk through the signature
// of the trait fn to look for any RPITITs, but that's kinda doing a lot
// of work. We can probably remove this when we refactor RPITITs to be
// associated types.
self.fn_sig(trait_item_def_id).subst_identity().skip_binder().output().walk().any(|arg| {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Alias(ty::Projection, data) = ty.kind()
&& self.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
{
true
} else {
false
}
})
return !self
.associated_types_for_impl_traits_in_associated_fn(trait_item_def_id)
.is_empty();
}
}

View file

@ -567,15 +567,9 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
// Alias tend to mostly already be handled downstream due to normalization.
(&ty::Alias(a_kind, a_data), &ty::Alias(b_kind, b_data)) => {
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This if can be removed
// and the assert uncommented once the new desugaring is stable.
if a_kind == b_kind {
let alias_ty = relation.relate(a_data, b_data)?;
// assert_eq!(a_kind, b_kind);
Ok(Ty::new_alias(tcx, a_kind, alias_ty))
} else {
Err(TypeError::Sorts(expected_found(relation, a, b)))
}
let alias_ty = relation.relate(a_data, b_data)?;
assert_eq!(a_kind, b_kind);
Ok(Ty::new_alias(tcx, a_kind, alias_ty))
}
_ => Err(TypeError::Sorts(expected_found(relation, a, b))),

View file

@ -1237,7 +1237,7 @@ impl<'tcx> AliasTy<'tcx> {
pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind {
match tcx.def_kind(self.def_id) {
DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent,
DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection,
DefKind::AssocTy => ty::Projection,
DefKind::OpaqueTy => ty::Opaque,
DefKind::TyAlias => ty::Weak,
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
@ -1265,9 +1265,6 @@ impl<'tcx> AliasTy<'tcx> {
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
match tcx.def_kind(self.def_id) {
DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
DefKind::ImplTraitPlaceholder => {
tcx.parent(tcx.impl_trait_in_trait_parent_fn(self.def_id))
}
kind => bug!("expected a projection AliasTy; found {kind:?}"),
}
}
@ -1970,7 +1967,6 @@ impl<'tcx> Ty<'tcx> {
(kind, tcx.def_kind(alias_ty.def_id)),
(ty::Opaque, DefKind::OpaqueTy)
| (ty::Projection | ty::Inherent, DefKind::AssocTy)
| (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder)
| (ty::Weak, DefKind::TyAlias)
);
Ty::new(tcx, Alias(kind, alias_ty))

View file

@ -163,7 +163,6 @@ fn mark_used_by_default_parameters<'tcx>(
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm

View file

@ -694,7 +694,6 @@ impl CheckAttrVisitor<'_> {
| Target::GlobalAsm
| Target::TyAlias
| Target::OpaqueTy
| Target::ImplTraitPlaceholder
| Target::Enum
| Target::Variant
| Target::Struct

View file

@ -136,19 +136,7 @@ where
fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> {
let tcx = self.def_id_visitor.tcx();
let (trait_ref, assoc_substs) = if tcx.def_kind(projection.def_id)
!= DefKind::ImplTraitPlaceholder
{
projection.trait_ref_and_own_substs(tcx)
} else {
// HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
let def_id = tcx.impl_trait_in_trait_parent_fn(projection.def_id);
let trait_generics = tcx.generics_of(def_id);
(
ty::TraitRef::new(tcx, def_id, projection.substs.truncate_to(tcx, trait_generics)),
&projection.substs[trait_generics.count()..],
)
};
let (trait_ref, assoc_substs) = projection.trait_ref_and_own_substs(tcx);
self.visit_trait(trait_ref)?;
if V::SHALLOW {
ControlFlow::Continue(())
@ -651,7 +639,6 @@ impl<'tcx> EmbargoVisitor<'tcx> {
| DefKind::ForeignTy
| DefKind::Fn
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::AssocFn
| DefKind::Trait
| DefKind::TyParam

View file

@ -949,7 +949,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::TraitAlias
| DefKind::AssocTy,
_,

View file

@ -1583,9 +1583,6 @@ options! {
"what location details should be tracked when using caller_location, either \
`none`, or a comma separated list of location details, for which \
valid options are `file`, `line`, and `column` (default: `file,line,column`)"),
lower_impl_trait_in_trait_to_assoc_ty: bool = (false, parse_bool, [TRACKED],
"modify the lowering strategy for `impl Trait` in traits so that they are lowered to \
generic associated types"),
ls: bool = (false, parse_bool, [UNTRACKED],
"list the symbols defined by a library crate (default: no)"),
macro_backtrace: bool = (false, parse_bool, [UNTRACKED],

View file

@ -131,8 +131,6 @@ enum ProjectionCandidate<'tcx> {
/// From an "impl" (or a "pseudo-impl" returned by select)
Select(Selection<'tcx>),
ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
}
enum ProjectionCandidateSet<'tcx> {
@ -1472,8 +1470,6 @@ fn project<'cx, 'tcx>(
let mut candidates = ProjectionCandidateSet::None;
assemble_candidate_for_impl_trait_in_trait(selcx, obligation, &mut candidates);
// Make sure that the following procedures are kept in order. ParamEnv
// needs to be first because it has highest priority, and Select checks
// the return value of push_candidate which assumes it's ran at last.
@ -1499,7 +1495,7 @@ fn project<'cx, 'tcx>(
ProjectionCandidateSet::None => {
let tcx = selcx.tcx();
let term = match tcx.def_kind(obligation.predicate.def_id) {
DefKind::AssocTy | DefKind::ImplTraitPlaceholder => Ty::new_projection(
DefKind::AssocTy => Ty::new_projection(
tcx,
obligation.predicate.def_id,
obligation.predicate.substs,
@ -1530,47 +1526,6 @@ fn project<'cx, 'tcx>(
}
}
/// If the predicate's item is an `ImplTraitPlaceholder`, we do a select on the
/// corresponding trait ref. If this yields an `impl`, then we're able to project
/// to a concrete type, since we have an `impl`'s method to provide the RPITIT.
fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
selcx: &mut SelectionContext<'cx, 'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
candidate_set: &mut ProjectionCandidateSet<'tcx>,
) {
let tcx = selcx.tcx();
if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
let trait_def_id = tcx.parent(trait_fn_def_id);
let trait_substs =
obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
let trait_predicate = ty::TraitRef::new(tcx, trait_def_id, trait_substs);
let _ = selcx.infcx.commit_if_ok(|_| {
match selcx.select(&obligation.with(tcx, trait_predicate)) {
Ok(Some(super::ImplSource::UserDefined(data))) => {
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
Ok(())
}
Ok(None) => {
candidate_set.mark_ambiguous();
Err(())
}
Ok(Some(_)) => {
// Don't know enough about the impl to provide a useful signature
Err(())
}
Err(e) => {
debug!(error = ?e, "selection error");
candidate_set.mark_error(e);
Err(())
}
}
});
}
}
/// The first thing we have to do is scan through the parameter
/// environment to see whether there are any projection predicates
/// there that can answer this question.
@ -1739,11 +1694,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
obligation: &ProjectionTyObligation<'tcx>,
candidate_set: &mut ProjectionCandidateSet<'tcx>,
) {
// Can't assemble candidate from impl for RPITIT
if selcx.tcx().def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
return;
}
// If we are resolving `<T as TraitRef<...>>::Item == Type`,
// start out by selecting the predicate `T as TraitRef<...>`:
let trait_ref = obligation.predicate.trait_ref(selcx.tcx());
@ -2012,9 +1962,6 @@ fn confirm_candidate<'cx, 'tcx>(
ProjectionCandidate::Select(impl_source) => {
confirm_select_candidate(selcx, obligation, impl_source)
}
ProjectionCandidate::ImplTraitInTrait(data) => {
confirm_impl_trait_in_trait_candidate(selcx, obligation, data)
}
};
// When checking for cycle during evaluation, we compare predicates with
@ -2240,8 +2187,7 @@ fn confirm_closure_candidate<'cx, 'tcx>(
obligation: &ProjectionTyObligation<'tcx>,
nested: Vec<PredicateObligation<'tcx>>,
) -> Progress<'tcx> {
let ty::Closure(_, substs) =
selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
let ty::Closure(_, substs) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
else {
unreachable!()
};
@ -2419,103 +2365,6 @@ fn confirm_impl_candidate<'cx, 'tcx>(
}
}
fn confirm_impl_trait_in_trait_candidate<'tcx>(
selcx: &mut SelectionContext<'_, 'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
data: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>,
) -> Progress<'tcx> {
let tcx = selcx.tcx();
let mut obligations = data.nested;
let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
let leaf_def = match specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) {
Ok(assoc_ty) => assoc_ty,
Err(guar) => return Progress::error(tcx, guar),
};
// We don't support specialization for RPITITs anyways... yet.
// Also don't try to project to an RPITIT that has no value
if !leaf_def.is_final() || !leaf_def.item.defaultness(tcx).has_value() {
return Progress { term: Ty::new_misc_error(tcx).into(), obligations };
}
// Use the default `impl Trait` for the trait, e.g., for a default trait body
if leaf_def.item.container == ty::AssocItemContainer::TraitContainer {
return Progress {
term: Ty::new_opaque(tcx, obligation.predicate.def_id, obligation.predicate.substs)
.into(),
obligations,
};
}
// Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque},
// since `data.substs` are the impl substs.
let impl_fn_substs =
obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs);
let impl_fn_substs = translate_substs(
selcx.infcx,
obligation.param_env,
data.impl_def_id,
impl_fn_substs,
leaf_def.defining_node,
);
if !check_substs_compatible(tcx, leaf_def.item, impl_fn_substs) {
let err = Ty::new_error_with_message(
tcx,
obligation.cause.span,
"impl method and trait method have different parameters",
);
return Progress { term: err.into(), obligations };
}
let impl_fn_def_id = leaf_def.item.def_id;
let cause = ObligationCause::new(
obligation.cause.span,
obligation.cause.body_id,
super::ItemObligation(impl_fn_def_id),
);
let predicates = normalize_with_depth_to(
selcx,
obligation.param_env,
cause.clone(),
obligation.recursion_depth + 1,
tcx.predicates_of(impl_fn_def_id).instantiate(tcx, impl_fn_substs),
&mut obligations,
);
obligations.extend(predicates.into_iter().map(|(pred, span)| {
Obligation::with_depth(
tcx,
ObligationCause::new(
obligation.cause.span,
obligation.cause.body_id,
if span.is_dummy() {
super::ItemObligation(impl_fn_def_id)
} else {
super::BindingObligation(impl_fn_def_id, span)
},
),
obligation.recursion_depth + 1,
obligation.param_env,
pred,
)
}));
let ty = normalize_with_depth_to(
selcx,
obligation.param_env,
cause.clone(),
obligation.recursion_depth + 1,
tcx.collect_return_position_impl_trait_in_trait_tys(impl_fn_def_id).map_or_else(
|guar| Ty::new_error(tcx, guar),
|tys| tys[&obligation.predicate.def_id].subst(tcx, impl_fn_substs),
),
&mut obligations,
);
Progress { term: ty.into(), obligations }
}
// Get obligations corresponding to the predicates from the where-clause of the
// associated type itself.
fn assoc_ty_own_obligations<'cx, 'tcx>(

View file

@ -24,70 +24,54 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
let item = tcx.hir().expect_item(def_id);
match item.kind {
hir::ItemKind::Trait(.., ref trait_item_refs) => {
if tcx.lower_impl_trait_in_trait_to_assoc_ty() {
// We collect RPITITs for each trait method's return type and create a
// corresponding associated item using associated_types_for_impl_traits_in_associated_fn
// query.
tcx.arena.alloc_from_iter(
trait_item_refs
.iter()
.map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id())
.chain(
trait_item_refs
.iter()
.filter(|trait_item_ref| {
matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. })
})
.flat_map(|trait_item_ref| {
let trait_fn_def_id =
trait_item_ref.id.owner_id.def_id.to_def_id();
tcx.associated_types_for_impl_traits_in_associated_fn(
trait_fn_def_id,
)
})
.map(|def_id| *def_id),
),
)
} else {
tcx.arena.alloc_from_iter(
trait_item_refs
.iter()
.map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()),
)
}
// We collect RPITITs for each trait method's return type and create a
// corresponding associated item using associated_types_for_impl_traits_in_associated_fn
// query.
tcx.arena.alloc_from_iter(
trait_item_refs
.iter()
.map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id())
.chain(
trait_item_refs
.iter()
.filter(|trait_item_ref| {
matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. })
})
.flat_map(|trait_item_ref| {
let trait_fn_def_id = trait_item_ref.id.owner_id.def_id.to_def_id();
tcx.associated_types_for_impl_traits_in_associated_fn(
trait_fn_def_id,
)
})
.map(|def_id| *def_id),
),
)
}
hir::ItemKind::Impl(ref impl_) => {
if tcx.lower_impl_trait_in_trait_to_assoc_ty() {
// We collect RPITITs for each trait method's return type, on the impl side too and
// create a corresponding associated item using
// associated_types_for_impl_traits_in_associated_fn query.
tcx.arena.alloc_from_iter(
impl_
.items
.iter()
.map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id())
.chain(impl_.of_trait.iter().flat_map(|_| {
impl_
.items
.iter()
.filter(|impl_item_ref| {
matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. })
})
.flat_map(|impl_item_ref| {
let impl_fn_def_id =
impl_item_ref.id.owner_id.def_id.to_def_id();
tcx.associated_types_for_impl_traits_in_associated_fn(
impl_fn_def_id,
)
})
.map(|def_id| *def_id)
})),
)
} else {
tcx.arena.alloc_from_iter(
impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()),
)
}
// We collect RPITITs for each trait method's return type, on the impl side too and
// create a corresponding associated item using
// associated_types_for_impl_traits_in_associated_fn query.
tcx.arena.alloc_from_iter(
impl_
.items
.iter()
.map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id())
.chain(impl_.of_trait.iter().flat_map(|_| {
impl_
.items
.iter()
.filter(|impl_item_ref| {
matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. })
})
.flat_map(|impl_item_ref| {
let impl_fn_def_id = impl_item_ref.id.owner_id.def_id.to_def_id();
tcx.associated_types_for_impl_traits_in_associated_fn(
impl_fn_def_id,
)
})
.map(|def_id| *def_id)
})),
)
}
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
}

View file

@ -75,7 +75,6 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
| DefKind::ForeignMod
| DefKind::AnonConst
| DefKind::InlineConst
| DefKind::ImplTraitPlaceholder
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm

View file

@ -318,7 +318,6 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
| DefKind::ExternCrate
| DefKind::Use
| DefKind::ForeignMod
| DefKind::ImplTraitPlaceholder
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm

View file

@ -282,11 +282,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
// 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(shifted_alias_ty.def_id).subst(self.tcx, shifted_alias_ty.substs)
} else {
Ty::new_alias(self.tcx,ty::Opaque, shifted_alias_ty)
};
let default_ty = self.tcx.type_of(shifted_alias_ty.def_id).subst(self.tcx, shifted_alias_ty.substs);
self.predicates.push(
ty::Binder::bind_with_vars(
@ -408,9 +404,7 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32
};
// The last field of the structure has to exist and contain type/const parameters.
let Some((tail_field, prefix_fields)) =
def.non_enum_variant().fields.raw.split_last() else
{
let Some((tail_field, prefix_fields)) = def.non_enum_variant().fields.raw.split_last() else {
return BitSet::new_empty(num_params);
};