Implement assumed_wf_types for RPITITs' implementations
This commit is contained in:
parent
349a2372ed
commit
50d21091ee
@ -246,6 +246,7 @@ provide! { tcx, def_id, other, cdata,
|
|||||||
debug_assert_eq!(tcx.def_kind(def_id), DefKind::OpaqueTy);
|
debug_assert_eq!(tcx.def_kind(def_id), DefKind::OpaqueTy);
|
||||||
cdata.root.tables.is_type_alias_impl_trait.get(cdata, def_id.index)
|
cdata.root.tables.is_type_alias_impl_trait.get(cdata, def_id.index)
|
||||||
}
|
}
|
||||||
|
assumed_wf_types_for_rpitit => { table }
|
||||||
collect_return_position_impl_trait_in_trait_tys => {
|
collect_return_position_impl_trait_in_trait_tys => {
|
||||||
Ok(cdata
|
Ok(cdata
|
||||||
.root
|
.root
|
||||||
|
@ -1560,6 +1560,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
if let Some(rpitit_info) = item.opt_rpitit_info {
|
if let Some(rpitit_info) = item.opt_rpitit_info {
|
||||||
record!(self.tables.opt_rpitit_info[def_id] <- rpitit_info);
|
record!(self.tables.opt_rpitit_info[def_id] <- rpitit_info);
|
||||||
|
if matches!(rpitit_info, ty::ImplTraitInTraitData::Trait { .. }) {
|
||||||
|
record_array!(
|
||||||
|
self.tables.assumed_wf_types_for_rpitit[def_id]
|
||||||
|
<- self.tcx.assumed_wf_types_for_rpitit(def_id)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,6 +457,7 @@ define_tables! {
|
|||||||
trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, ty::EarlyBinder<Ty<'static>>>>>,
|
trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, ty::EarlyBinder<Ty<'static>>>>>,
|
||||||
doc_link_resolutions: Table<DefIndex, LazyValue<DocLinkResMap>>,
|
doc_link_resolutions: Table<DefIndex, LazyValue<DocLinkResMap>>,
|
||||||
doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>,
|
doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>,
|
||||||
|
assumed_wf_types_for_rpitit: Table<DefIndex, LazyArray<(Ty<'static>, Span)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(TyEncodable, TyDecodable)]
|
#[derive(TyEncodable, TyDecodable)]
|
||||||
|
@ -885,6 +885,13 @@ rustc_queries! {
|
|||||||
desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) }
|
desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// We need to store the assumed_wf_types for an RPITIT so that impls of foreign
|
||||||
|
/// traits with return-position impl trait in traits can inherit the right wf types.
|
||||||
|
query assumed_wf_types_for_rpitit(key: DefId) -> &'tcx [(Ty<'tcx>, Span)] {
|
||||||
|
desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) }
|
||||||
|
separate_provide_extern
|
||||||
|
}
|
||||||
|
|
||||||
/// Computes the signature of the function.
|
/// Computes the signature of the function.
|
||||||
query fn_sig(key: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
|
query fn_sig(key: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
|
||||||
desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) }
|
desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) }
|
||||||
|
@ -9,7 +9,11 @@ use rustc_span::Span;
|
|||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
*providers = Providers { assumed_wf_types, ..*providers };
|
*providers = Providers {
|
||||||
|
assumed_wf_types,
|
||||||
|
assumed_wf_types_for_rpitit: |tcx, def_id| tcx.assumed_wf_types(def_id),
|
||||||
|
..*providers
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
|
fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
|
||||||
@ -44,41 +48,62 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
|
|||||||
let mut impl_spans = impl_spans(tcx, def_id);
|
let mut impl_spans = impl_spans(tcx, def_id);
|
||||||
tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap())))
|
tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap())))
|
||||||
}
|
}
|
||||||
DefKind::AssocTy if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id }) = tcx.opt_rpitit_info(def_id.to_def_id()) => {
|
DefKind::AssocTy if let Some(data) = tcx.opt_rpitit_info(def_id.to_def_id()) => match data {
|
||||||
let hir::OpaqueTy { lifetime_mapping, .. } =
|
ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id } => {
|
||||||
*tcx.hir().expect_item(opaque_def_id.expect_local()).expect_opaque_ty();
|
let hir::OpaqueTy { lifetime_mapping, .. } =
|
||||||
let mut mapping = FxHashMap::default();
|
*tcx.hir().expect_item(opaque_def_id.expect_local()).expect_opaque_ty();
|
||||||
let generics = tcx.generics_of(def_id);
|
let mut mapping = FxHashMap::default();
|
||||||
for &(lifetime, new_early_bound_def_id) in lifetime_mapping {
|
let generics = tcx.generics_of(def_id);
|
||||||
if let Some(rbv::ResolvedArg::LateBound(_, _, def_id)) =
|
for &(lifetime, new_early_bound_def_id) in
|
||||||
tcx.named_bound_var(lifetime.hir_id)
|
lifetime_mapping.expect("expected lifetime mapping for RPITIT")
|
||||||
{
|
{
|
||||||
let name = tcx.hir().name(lifetime.hir_id);
|
if let Some(rbv::ResolvedArg::LateBound(_, _, def_id)) =
|
||||||
let index = generics
|
tcx.named_bound_var(lifetime.hir_id)
|
||||||
.param_def_id_to_index(tcx, new_early_bound_def_id.to_def_id())
|
{
|
||||||
.unwrap();
|
let name = tcx.hir().name(lifetime.hir_id);
|
||||||
mapping.insert(
|
let index = generics
|
||||||
ty::Region::new_free(
|
.param_def_id_to_index(tcx, new_early_bound_def_id.to_def_id())
|
||||||
tcx,
|
.unwrap();
|
||||||
fn_def_id,
|
mapping.insert(
|
||||||
ty::BoundRegionKind::BrNamed(def_id, name),
|
ty::Region::new_free(
|
||||||
),
|
tcx,
|
||||||
ty::Region::new_early_bound(
|
fn_def_id,
|
||||||
tcx,
|
ty::BoundRegionKind::BrNamed(def_id, name),
|
||||||
ty::EarlyBoundRegion {
|
),
|
||||||
def_id: new_early_bound_def_id.to_def_id(),
|
ty::Region::new_early_bound(
|
||||||
index,
|
tcx,
|
||||||
name,
|
ty::EarlyBoundRegion {
|
||||||
},
|
def_id: new_early_bound_def_id.to_def_id(),
|
||||||
),
|
index,
|
||||||
);
|
name,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
let a = tcx.fold_regions(
|
||||||
|
tcx.assumed_wf_types(fn_def_id.expect_local()).to_vec(),
|
||||||
|
|re, _| {
|
||||||
|
if let Some(re) = mapping.get(&re) { *re } else { re }
|
||||||
|
},
|
||||||
|
);
|
||||||
|
tcx.arena.alloc_from_iter(a)
|
||||||
}
|
}
|
||||||
let a = tcx.fold_regions(tcx.assumed_wf_types(fn_def_id.expect_local()).to_vec(), |re, _| {
|
ty::ImplTraitInTraitData::Impl { .. } => {
|
||||||
if let Some(re) = mapping.get(&re) { *re } else { re }
|
let impl_def_id = tcx.local_parent(def_id);
|
||||||
});
|
let rpitit_def_id = tcx.associated_item(def_id).trait_item_def_id.unwrap();
|
||||||
tcx.arena.alloc_from_iter(a)
|
let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto(
|
||||||
}
|
tcx,
|
||||||
|
impl_def_id.to_def_id(),
|
||||||
|
tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity().args,
|
||||||
|
);
|
||||||
|
tcx.arena.alloc_from_iter(
|
||||||
|
ty::EarlyBinder::bind(tcx.assumed_wf_types_for_rpitit(rpitit_def_id))
|
||||||
|
.iter_instantiated_copied(tcx, args)
|
||||||
|
.chain(tcx.assumed_wf_types(impl_def_id).into_iter().copied()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
|
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
|
||||||
DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) {
|
DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) {
|
||||||
DefKind::TyAlias => ty::List::empty(),
|
DefKind::TyAlias => ty::List::empty(),
|
||||||
|
29
tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs
Normal file
29
tests/ui/impl-trait/in-trait/assumed-wf-bounds-in-impl.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// check-pass
|
||||||
|
// edition: 2021
|
||||||
|
// issue: 113796
|
||||||
|
|
||||||
|
#![feature(async_fn_in_trait)]
|
||||||
|
|
||||||
|
trait AsyncLendingIterator {
|
||||||
|
type Item<'a>
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
|
async fn next(&mut self) -> Option<Self::Item<'_>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Lend<I>(I);
|
||||||
|
impl<I> AsyncLendingIterator for Lend<I> {
|
||||||
|
type Item<'a> = &'a I
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
|
// Checking that the synthetic `<Self as AsyncLendingIterator>::next()` GAT
|
||||||
|
// is well-formed requires being able to assume the WF types of `next`.
|
||||||
|
|
||||||
|
async fn next(&mut self) -> Option<Self::Item<'_>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
x
Reference in New Issue
Block a user