Auto merge of #112682 - spastorino:new-rpitit-21, r=compiler-errors
Add bidirectional where clauses on RPITIT synthesized GATs Given the following: ```rust struct MyStruct<'a, T>(&'a T); trait MyTrait<'a, T> { fn my_fn<'b, 'c, 'd, V>(item: &'c String) -> impl Sized + 'a + 'b + 'c where V: 'b, V: 'd; } impl<'a, T> MyTrait<'a, T> for MyStruct<'a, T> { fn my_fn<'b, 'c, 'd, V>(_: &'c String) -> impl Sized + 'a + 'b + 'c where V: 'b, V: 'd, { unimplemented!(); } } ``` We need the desugaring to be: ```rust trait MyTrait<'a, T> { type MyFn<'bf, 'df, Vf, 'a2, 'b2, 'c2>: Sized + 'a2 + 'b2 + 'c2 where Vf: 'b2, 'a2: 'a, 'a: 'a2, 'b2: 'bf, 'bf: 'b2; fn my_fn<'b, 'c, 'd, V>(item: &'c String) -> MyStruct<'a>::MyFn<'b, 'd, V, 'a, 'b, 'c> where V: 'b, V: 'd { type opaque<'a3, 'b3, 'c3>; }; } impl<'a, T> MyIter<'a, T> for MyStruct<'a, T> { type MyFn<'bf, 'df, Vf, 'a2, 'b2, 'c2> = impl Sized + 'a2 + 'b2 + 'c2 where Vf: b2, 'a2: 'a, 'a: 'a2, 'b2: 'bf, 'bf: 'b2; fn my_fn<'b, 'c, 'd, V>(_: &'c String) -> MyStruct<'a>::MyFn<'a, 'b, 'c, V> where V: 'b, V: 'd { type opaque<'a3, 'b3, 'c3>; unimplemented!(); } } ``` This PR adds the where clauses for the `MyFn` generated GATs. This is a draft with a very ugly solution so we can make comments over concrete code. r? `@compiler-errors`
This commit is contained in:
commit
330727467b
@ -1539,9 +1539,6 @@ fn lower_opaque_impl_trait(
|
||||
);
|
||||
debug!(?opaque_ty_def_id);
|
||||
|
||||
// Contains the new lifetime definitions created for the TAIT (if any).
|
||||
let mut collected_lifetimes = Vec::new();
|
||||
|
||||
// If this came from a TAIT (as opposed to a function that returns an RPIT), we only want
|
||||
// to capture the lifetimes that appear in the bounds. So visit the bounds to find out
|
||||
// exactly which ones those are.
|
||||
@ -1558,20 +1555,31 @@ fn lower_opaque_impl_trait(
|
||||
};
|
||||
debug!(?lifetimes_to_remap);
|
||||
|
||||
let mut new_remapping = FxHashMap::default();
|
||||
|
||||
// Contains the new lifetime definitions created for the TAIT (if any).
|
||||
// If this opaque type is only capturing a subset of the lifetimes (those that appear in
|
||||
// bounds), then create the new lifetime parameters required and create a mapping from the
|
||||
// old `'a` (on the function) to the new `'a` (on the opaque type).
|
||||
let collected_lifetimes =
|
||||
self.create_lifetime_defs(opaque_ty_def_id, &lifetimes_to_remap, &mut new_remapping);
|
||||
debug!(?collected_lifetimes);
|
||||
debug!(?new_remapping);
|
||||
|
||||
// This creates HIR lifetime arguments as `hir::GenericArg`, in the given example `type
|
||||
// TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing `&['x]`.
|
||||
let collected_lifetime_mapping: Vec<_> = collected_lifetimes
|
||||
.iter()
|
||||
.map(|(node_id, lifetime)| {
|
||||
let id = self.next_node_id();
|
||||
let lifetime = self.new_named_lifetime(lifetime.id, id, lifetime.ident);
|
||||
let def_id = self.local_def_id(*node_id);
|
||||
(lifetime, def_id)
|
||||
})
|
||||
.collect();
|
||||
debug!(?collected_lifetime_mapping);
|
||||
|
||||
self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
|
||||
let mut new_remapping = FxHashMap::default();
|
||||
|
||||
// If this opaque type is only capturing a subset of the lifetimes (those that appear
|
||||
// in bounds), then create the new lifetime parameters required and create a mapping
|
||||
// from the old `'a` (on the function) to the new `'a` (on the opaque type).
|
||||
collected_lifetimes = lctx.create_lifetime_defs(
|
||||
opaque_ty_def_id,
|
||||
&lifetimes_to_remap,
|
||||
&mut new_remapping,
|
||||
);
|
||||
debug!(?collected_lifetimes);
|
||||
debug!(?new_remapping);
|
||||
|
||||
// Install the remapping from old to new (if any):
|
||||
lctx.with_remapping(new_remapping, |lctx| {
|
||||
// This creates HIR lifetime definitions as `hir::GenericParam`, in the given
|
||||
@ -1610,6 +1618,16 @@ fn lower_opaque_impl_trait(
|
||||
let hir_bounds = lctx.lower_param_bounds(bounds, itctx);
|
||||
debug!(?hir_bounds);
|
||||
|
||||
let lifetime_mapping = if in_trait {
|
||||
self.arena.alloc_from_iter(
|
||||
collected_lifetime_mapping
|
||||
.iter()
|
||||
.map(|(lifetime, def_id)| (**lifetime, *def_id)),
|
||||
)
|
||||
} else {
|
||||
&mut []
|
||||
};
|
||||
|
||||
let opaque_ty_item = hir::OpaqueTy {
|
||||
generics: self.arena.alloc(hir::Generics {
|
||||
params: lifetime_defs,
|
||||
@ -1620,6 +1638,7 @@ fn lower_opaque_impl_trait(
|
||||
}),
|
||||
bounds: hir_bounds,
|
||||
origin,
|
||||
lifetime_mapping,
|
||||
in_trait,
|
||||
};
|
||||
debug!(?opaque_ty_item);
|
||||
@ -1628,20 +1647,14 @@ fn lower_opaque_impl_trait(
|
||||
})
|
||||
});
|
||||
|
||||
// This creates HIR lifetime arguments as `hir::GenericArg`, in the given example `type
|
||||
// TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing `&['x]`.
|
||||
let lifetimes =
|
||||
self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(_, lifetime)| {
|
||||
let id = self.next_node_id();
|
||||
let l = self.new_named_lifetime(lifetime.id, id, lifetime.ident);
|
||||
hir::GenericArg::Lifetime(l)
|
||||
}));
|
||||
debug!(?lifetimes);
|
||||
|
||||
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
|
||||
hir::TyKind::OpaqueDef(
|
||||
hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
|
||||
lifetimes,
|
||||
self.arena.alloc_from_iter(
|
||||
collected_lifetime_mapping
|
||||
.iter()
|
||||
.map(|(lifetime, _)| hir::GenericArg::Lifetime(*lifetime)),
|
||||
),
|
||||
in_trait,
|
||||
)
|
||||
}
|
||||
@ -1655,7 +1668,7 @@ fn generate_opaque_type(
|
||||
span: Span,
|
||||
opaque_ty_span: Span,
|
||||
) -> hir::OwnerNode<'hir> {
|
||||
let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item);
|
||||
let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(self.arena.alloc(opaque_ty_item));
|
||||
// Generate an `type Foo = impl Trait;` declaration.
|
||||
trace!("registering opaque type with id {:#?}", opaque_ty_id);
|
||||
let opaque_ty_item = hir::Item {
|
||||
@ -1983,7 +1996,6 @@ fn lower_async_fn_ret_ty(
|
||||
let lifetime = Lifetime { id: outer_node_id, ident };
|
||||
collected_lifetimes.push((inner_node_id, lifetime, Some(inner_res)));
|
||||
}
|
||||
|
||||
debug!(?collected_lifetimes);
|
||||
|
||||
// We only want to capture the lifetimes that appear in the bounds. So visit the bounds to
|
||||
@ -1993,22 +2005,36 @@ fn lower_async_fn_ret_ty(
|
||||
let lifetimes_to_remap = lifetime_collector::lifetimes_in_ret_ty(&self.resolver, output);
|
||||
debug!(?lifetimes_to_remap);
|
||||
|
||||
self.with_hir_id_owner(opaque_ty_node_id, |this| {
|
||||
// If this opaque type is only capturing a subset of the lifetimes (those that appear
|
||||
// in bounds), then create the new lifetime parameters required and create a mapping
|
||||
// from the old `'a` (on the function) to the new `'a` (on the opaque type).
|
||||
collected_lifetimes.extend(
|
||||
this.create_lifetime_defs(
|
||||
opaque_ty_def_id,
|
||||
&lifetimes_to_remap,
|
||||
&mut new_remapping,
|
||||
)
|
||||
// If this opaque type is only capturing a subset of the lifetimes (those that appear in
|
||||
// bounds), then create the new lifetime parameters required and create a mapping from the
|
||||
// old `'a` (on the function) to the new `'a` (on the opaque type).
|
||||
collected_lifetimes.extend(
|
||||
self.create_lifetime_defs(opaque_ty_def_id, &lifetimes_to_remap, &mut new_remapping)
|
||||
.into_iter()
|
||||
.map(|(new_node_id, lifetime)| (new_node_id, lifetime, None)),
|
||||
);
|
||||
debug!(?collected_lifetimes);
|
||||
debug!(?new_remapping);
|
||||
);
|
||||
debug!(?collected_lifetimes);
|
||||
debug!(?new_remapping);
|
||||
|
||||
// This creates pairs of HIR lifetimes and def_ids. In the given example `type
|
||||
// TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing the
|
||||
// new lifetime of the RPIT 'x and the def_id of the lifetime 'x corresponding to
|
||||
// `TestReturn`.
|
||||
let collected_lifetime_mapping: Vec<_> = collected_lifetimes
|
||||
.iter()
|
||||
.map(|(node_id, lifetime, res)| {
|
||||
let id = self.next_node_id();
|
||||
let res = res.unwrap_or(
|
||||
self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
|
||||
);
|
||||
let lifetime = self.new_named_lifetime_with_res(id, lifetime.ident, res);
|
||||
let def_id = self.local_def_id(*node_id);
|
||||
(lifetime, def_id)
|
||||
})
|
||||
.collect();
|
||||
debug!(?collected_lifetime_mapping);
|
||||
|
||||
self.with_hir_id_owner(opaque_ty_node_id, |this| {
|
||||
// Install the remapping from old to new (if any):
|
||||
this.with_remapping(new_remapping, |this| {
|
||||
// We have to be careful to get elision right here. The
|
||||
@ -2063,6 +2089,16 @@ fn lower_async_fn_ret_ty(
|
||||
));
|
||||
debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params);
|
||||
|
||||
let lifetime_mapping = if in_trait {
|
||||
self.arena.alloc_from_iter(
|
||||
collected_lifetime_mapping
|
||||
.iter()
|
||||
.map(|(lifetime, def_id)| (**lifetime, *def_id)),
|
||||
)
|
||||
} else {
|
||||
&mut []
|
||||
};
|
||||
|
||||
let opaque_ty_item = hir::OpaqueTy {
|
||||
generics: this.arena.alloc(hir::Generics {
|
||||
params: generic_params,
|
||||
@ -2073,6 +2109,7 @@ fn lower_async_fn_ret_ty(
|
||||
}),
|
||||
bounds: arena_vec![this; future_bound],
|
||||
origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
|
||||
lifetime_mapping,
|
||||
in_trait,
|
||||
};
|
||||
|
||||
@ -2096,15 +2133,11 @@ fn lower_async_fn_ret_ty(
|
||||
//
|
||||
// For the "output" lifetime parameters, we just want to
|
||||
// generate `'_`.
|
||||
let generic_args = self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(
|
||||
|(_, lifetime, res)| {
|
||||
let id = self.next_node_id();
|
||||
let res = res.unwrap_or(
|
||||
self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
|
||||
);
|
||||
hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, lifetime.ident, res))
|
||||
},
|
||||
));
|
||||
let generic_args = self.arena.alloc_from_iter(
|
||||
collected_lifetime_mapping
|
||||
.iter()
|
||||
.map(|(lifetime, _)| hir::GenericArg::Lifetime(*lifetime)),
|
||||
);
|
||||
|
||||
// Create the `Foo<...>` reference itself. Note that the `type
|
||||
// Foo = impl Trait` is, internally, created as a child of the
|
||||
|
@ -2664,6 +2664,10 @@ pub struct OpaqueTy<'hir> {
|
||||
pub generics: &'hir Generics<'hir>,
|
||||
pub bounds: GenericBounds<'hir>,
|
||||
pub origin: OpaqueTyOrigin,
|
||||
// Opaques have duplicated lifetimes, this mapping connects the original lifetime with the copy
|
||||
// so we can later generate bidirectional outlives predicates to enforce that these lifetimes
|
||||
// stay in sync.
|
||||
pub lifetime_mapping: &'hir [(Lifetime, LocalDefId)],
|
||||
pub in_trait: bool,
|
||||
}
|
||||
|
||||
@ -3315,7 +3319,7 @@ pub enum ItemKind<'hir> {
|
||||
/// A type alias, e.g., `type Foo = Bar<u8>`.
|
||||
TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>),
|
||||
/// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
|
||||
OpaqueTy(OpaqueTy<'hir>),
|
||||
OpaqueTy(&'hir OpaqueTy<'hir>),
|
||||
/// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`.
|
||||
Enum(EnumDef<'hir>, &'hir Generics<'hir>),
|
||||
/// A struct definition, e.g., `struct Foo<A> {x: A}`.
|
||||
|
@ -502,7 +502,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
|
||||
visitor.visit_ty(ty);
|
||||
visitor.visit_generics(generics)
|
||||
}
|
||||
ItemKind::OpaqueTy(OpaqueTy { ref generics, bounds, .. }) => {
|
||||
ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, .. }) => {
|
||||
visitor.visit_id(item.hir_id());
|
||||
walk_generics(visitor, generics);
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
|
@ -2809,7 +2809,7 @@ fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool, in_path: bool
|
||||
let opaque_ty = tcx.hir().item(item_id);
|
||||
|
||||
match opaque_ty.kind {
|
||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
|
||||
hir::ItemKind::OpaqueTy(&hir::OpaqueTy { origin, .. }) => {
|
||||
let local_def_id = item_id.owner_id.def_id;
|
||||
// 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
|
||||
|
@ -299,7 +299,7 @@ fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
|
||||
}
|
||||
}
|
||||
|
||||
if let ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||
if let ItemKind::OpaqueTy(&hir::OpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
|
||||
in_trait,
|
||||
..
|
||||
|
@ -144,7 +144,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||
Some(tcx.typeck_root_def_id(def_id.to_def_id()))
|
||||
}
|
||||
Node::Item(item) => match item.kind {
|
||||
ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||
ItemKind::OpaqueTy(&hir::OpaqueTy {
|
||||
origin:
|
||||
hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
|
||||
in_trait,
|
||||
|
@ -2,7 +2,7 @@
|
||||
use crate::bounds::Bounds;
|
||||
use crate::collect::ItemCtxt;
|
||||
use crate::constrained_generic_params as cgp;
|
||||
use hir::{HirId, Node};
|
||||
use hir::{HirId, Lifetime, Node};
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
@ -10,9 +10,9 @@
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{GenericPredicates, ToPredicate};
|
||||
use rustc_middle::ty::{GenericPredicates, Generics, ImplTraitInTraitData, ToPredicate};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_span::{Span, Symbol, DUMMY_SP};
|
||||
|
||||
/// Returns a list of all type predicates (explicit and implicit) for the definition with
|
||||
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
|
||||
@ -62,6 +62,54 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
|
||||
fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
|
||||
use rustc_hir::*;
|
||||
|
||||
match tcx.opt_rpitit_info(def_id.to_def_id()) {
|
||||
Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
|
||||
let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local());
|
||||
let opaque_ty_node = tcx.hir().get(opaque_ty_id);
|
||||
let Node::Item(&Item { kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }), .. }) = opaque_ty_node else {
|
||||
bug!("unexpected {opaque_ty_node:?}")
|
||||
};
|
||||
|
||||
let mut predicates = Vec::new();
|
||||
compute_bidirectional_outlives_predicates(
|
||||
tcx,
|
||||
def_id,
|
||||
lifetime_mapping.iter().map(|(lifetime, def_id)| {
|
||||
(*lifetime, (*def_id, lifetime.ident.name, lifetime.ident.span))
|
||||
}),
|
||||
tcx.generics_of(def_id.to_def_id()),
|
||||
&mut predicates,
|
||||
);
|
||||
|
||||
return ty::GenericPredicates {
|
||||
parent: Some(tcx.parent(def_id.to_def_id())),
|
||||
predicates: tcx.arena.alloc_from_iter(predicates),
|
||||
};
|
||||
}
|
||||
|
||||
Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
|
||||
let assoc_item = tcx.associated_item(def_id);
|
||||
let trait_assoc_predicates = tcx.predicates_of(assoc_item.trait_item_def_id.unwrap());
|
||||
|
||||
let impl_assoc_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||
let impl_def_id = tcx.parent(fn_def_id);
|
||||
let impl_trait_ref_substs =
|
||||
tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder().substs;
|
||||
|
||||
let impl_assoc_substs =
|
||||
impl_assoc_identity_substs.rebase_onto(tcx, impl_def_id, impl_trait_ref_substs);
|
||||
|
||||
let impl_predicates = trait_assoc_predicates.instantiate_own(tcx, impl_assoc_substs);
|
||||
|
||||
return ty::GenericPredicates {
|
||||
parent: Some(impl_def_id),
|
||||
predicates: tcx.arena.alloc_from_iter(impl_predicates),
|
||||
};
|
||||
}
|
||||
|
||||
None => {}
|
||||
}
|
||||
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let node = tcx.hir().get(hir_id);
|
||||
|
||||
@ -289,38 +337,22 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
bug!("unexpected {opaque_ty_node:?}")
|
||||
};
|
||||
debug!(?lifetimes);
|
||||
for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) {
|
||||
let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
|
||||
let orig_region = icx.astconv().ast_region_to_region(&arg, None);
|
||||
if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
|
||||
// Only early-bound regions can point to the original generic parameter.
|
||||
continue;
|
||||
}
|
||||
|
||||
let hir::GenericParamKind::Lifetime { .. } = duplicate.kind else { continue };
|
||||
let dup_def = duplicate.def_id.to_def_id();
|
||||
let lifetime_mapping = std::iter::zip(lifetimes, ast_generics.params)
|
||||
.map(|(arg, dup)| {
|
||||
let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
|
||||
(**arg, dup)
|
||||
})
|
||||
.filter(|(_, dup)| matches!(dup.kind, hir::GenericParamKind::Lifetime { .. }))
|
||||
.map(|(lifetime, dup)| (lifetime, (dup.def_id, dup.name.ident().name, dup.span)));
|
||||
|
||||
let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() };
|
||||
|
||||
let dup_region = ty::Region::new_early_bound(
|
||||
tcx,
|
||||
ty::EarlyBoundRegion {
|
||||
def_id: dup_def,
|
||||
index: dup_index,
|
||||
name: duplicate.name.ident().name,
|
||||
},
|
||||
);
|
||||
predicates.push((
|
||||
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region))
|
||||
.to_predicate(icx.tcx),
|
||||
duplicate.span,
|
||||
));
|
||||
predicates.push((
|
||||
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region))
|
||||
.to_predicate(icx.tcx),
|
||||
duplicate.span,
|
||||
));
|
||||
}
|
||||
compute_bidirectional_outlives_predicates(
|
||||
tcx,
|
||||
def_id,
|
||||
lifetime_mapping,
|
||||
generics,
|
||||
&mut predicates,
|
||||
);
|
||||
debug!(?predicates);
|
||||
}
|
||||
|
||||
@ -330,6 +362,46 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
}
|
||||
}
|
||||
|
||||
/// Opaques have duplicated lifetimes and we need to compute bidirectional outlives predicates to
|
||||
/// enforce that these lifetimes stay in sync.
|
||||
fn compute_bidirectional_outlives_predicates<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item_def_id: LocalDefId,
|
||||
lifetime_mapping: impl Iterator<Item = (Lifetime, (LocalDefId, Symbol, Span))>,
|
||||
generics: &Generics,
|
||||
predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||
) {
|
||||
let icx = ItemCtxt::new(tcx, item_def_id);
|
||||
|
||||
for (arg, (dup_def, name, span)) in lifetime_mapping {
|
||||
let orig_region = icx.astconv().ast_region_to_region(&arg, None);
|
||||
if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
|
||||
// There is no late-bound lifetime to actually match up here, since the lifetime doesn't
|
||||
// show up in the opaque's parent's substs.
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(dup_index) = generics.param_def_id_to_index(icx.tcx, dup_def.to_def_id()) else { bug!() };
|
||||
|
||||
let dup_region = ty::Region::new_early_bound(
|
||||
tcx,
|
||||
ty::EarlyBoundRegion { def_id: dup_def.to_def_id(), index: dup_index, name },
|
||||
);
|
||||
|
||||
predicates.push((
|
||||
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region))
|
||||
.to_predicate(tcx),
|
||||
span,
|
||||
));
|
||||
|
||||
predicates.push((
|
||||
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region))
|
||||
.to_predicate(tcx),
|
||||
span,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn const_evaluatable_predicates_of(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: LocalDefId,
|
||||
@ -668,7 +740,7 @@ pub(super) fn type_param_predicates(
|
||||
ItemKind::Fn(.., generics, _)
|
||||
| ItemKind::Impl(&hir::Impl { generics, .. })
|
||||
| ItemKind::TyAlias(_, generics)
|
||||
| ItemKind::OpaqueTy(OpaqueTy {
|
||||
| ItemKind::OpaqueTy(&OpaqueTy {
|
||||
generics,
|
||||
origin: hir::OpaqueTyOrigin::TyAlias { .. },
|
||||
..
|
||||
|
@ -556,7 +556,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
||||
});
|
||||
}
|
||||
}
|
||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
|
||||
hir::ItemKind::OpaqueTy(&hir::OpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
|
||||
generics,
|
||||
..
|
||||
|
@ -435,7 +435,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
|
||||
..
|
||||
}) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id),
|
||||
// Opaque types desugared from `impl Trait`.
|
||||
ItemKind::OpaqueTy(OpaqueTy {
|
||||
ItemKind::OpaqueTy(&OpaqueTy {
|
||||
origin:
|
||||
hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner),
|
||||
in_trait,
|
||||
|
@ -340,12 +340,6 @@ fn associated_type_for_impl_trait_in_trait(
|
||||
}
|
||||
});
|
||||
|
||||
// There are no predicates for the synthesized associated type.
|
||||
trait_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
|
||||
parent: Some(trait_def_id.to_def_id()),
|
||||
predicates: &[],
|
||||
});
|
||||
|
||||
// There are no inferred outlives for the synthesized associated type.
|
||||
trait_assoc_ty.inferred_outlives_of(&[]);
|
||||
|
||||
@ -424,12 +418,6 @@ fn associated_type_for_impl_trait_in_impl(
|
||||
}
|
||||
});
|
||||
|
||||
// There are no predicates for the synthesized associated type.
|
||||
impl_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
|
||||
parent: Some(impl_local_def_id.to_def_id()),
|
||||
predicates: &[],
|
||||
});
|
||||
|
||||
// There are no inferred outlives for the synthesized associated type.
|
||||
impl_assoc_ty.inferred_outlives_of(&[]);
|
||||
|
||||
|
@ -131,7 +131,9 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
|
||||
if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
|
||||
| Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id)
|
||||
{
|
||||
predicates = tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates;
|
||||
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Should not need to add the predicates
|
||||
// from the parent fn to our assumptions
|
||||
predicates.extend(tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates);
|
||||
}
|
||||
|
||||
// Finally, we have to normalize the bounds in the environment, in
|
||||
|
@ -1,5 +1,7 @@
|
||||
// check-pass
|
||||
// edition: 2021
|
||||
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
|
||||
// revisions: current next
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
#![allow(incomplete_features)]
|
||||
|
@ -1,5 +1,7 @@
|
||||
// check-pass
|
||||
// edition: 2021
|
||||
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
|
||||
// revisions: current next
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
#![allow(incomplete_features)]
|
||||
|
Loading…
Reference in New Issue
Block a user