Rollup merge of #137689 - compiler-errors:coroutine, r=lcnr
Use `Binder<Vec<Ty>>` instead of `Vec<Binder<Ty>>` in both solvers for sized/auto traits/etc. It's more conceptually justified IMO, especially when binders get implications. r? lcnr
This commit is contained in:
commit
3cd89f2718
9 changed files with 98 additions and 157 deletions
|
@ -2,6 +2,7 @@
|
||||||
//! the end of the file for details.
|
//! the end of the file for details.
|
||||||
|
|
||||||
use rustc_middle::ty::fold::FnMutDelegate;
|
use rustc_middle::ty::fold::FnMutDelegate;
|
||||||
|
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
|
@ -26,8 +27,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
where
|
where
|
||||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||||
{
|
{
|
||||||
if let Some(inner) = binder.clone().no_bound_vars() {
|
// Inlined `no_bound_vars`.
|
||||||
return inner;
|
if !binder.as_ref().skip_binder().has_escaping_bound_vars() {
|
||||||
|
return binder.skip_binder();
|
||||||
}
|
}
|
||||||
|
|
||||||
let next_universe = self.create_next_universe();
|
let next_universe = self.create_next_universe();
|
||||||
|
|
|
@ -324,11 +324,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||||
self.features()
|
self.features()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bound_coroutine_hidden_types(
|
fn coroutine_hidden_types(
|
||||||
self,
|
self,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
) -> impl IntoIterator<Item = ty::EarlyBinder<'tcx, ty::Binder<'tcx, Ty<'tcx>>>> {
|
) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>>> {
|
||||||
self.bound_coroutine_hidden_types(def_id)
|
self.coroutine_hidden_types(def_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fn_sig(self, def_id: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> {
|
fn fn_sig(self, def_id: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> {
|
||||||
|
|
|
@ -740,36 +740,20 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the set of types that should be taken into account when checking
|
/// Return the set of types that should be taken into account when checking
|
||||||
/// trait bounds on a coroutine's internal state.
|
/// trait bounds on a coroutine's internal state. This properly replaces
|
||||||
// FIXME(compiler-errors): We should remove this when the old solver goes away;
|
/// `ReErased` with new existential bound lifetimes.
|
||||||
// and all other usages of this function should go through `bound_coroutine_hidden_types`
|
|
||||||
// instead.
|
|
||||||
pub fn coroutine_hidden_types(
|
pub fn coroutine_hidden_types(
|
||||||
self,
|
self,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
) -> impl Iterator<Item = ty::EarlyBinder<'tcx, Ty<'tcx>>> {
|
) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>>> {
|
||||||
let coroutine_layout = self.mir_coroutine_witnesses(def_id);
|
let coroutine_layout = self.mir_coroutine_witnesses(def_id);
|
||||||
coroutine_layout
|
|
||||||
.as_ref()
|
|
||||||
.map_or_else(|| [].iter(), |l| l.field_tys.iter())
|
|
||||||
.filter(|decl| !decl.ignore_for_traits)
|
|
||||||
.map(|decl| ty::EarlyBinder::bind(decl.ty))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the set of types that should be taken into account when checking
|
|
||||||
/// trait bounds on a coroutine's internal state. This properly replaces
|
|
||||||
/// `ReErased` with new existential bound lifetimes.
|
|
||||||
pub fn bound_coroutine_hidden_types(
|
|
||||||
self,
|
|
||||||
def_id: DefId,
|
|
||||||
) -> impl Iterator<Item = ty::EarlyBinder<'tcx, ty::Binder<'tcx, Ty<'tcx>>>> {
|
|
||||||
let coroutine_layout = self.mir_coroutine_witnesses(def_id);
|
|
||||||
coroutine_layout
|
|
||||||
.as_ref()
|
|
||||||
.map_or_else(|| [].iter(), |l| l.field_tys.iter())
|
|
||||||
.filter(|decl| !decl.ignore_for_traits)
|
|
||||||
.map(move |decl| {
|
|
||||||
let mut vars = vec![];
|
let mut vars = vec![];
|
||||||
|
let bound_tys = self.mk_type_list_from_iter(
|
||||||
|
coroutine_layout
|
||||||
|
.as_ref()
|
||||||
|
.map_or_else(|| [].iter(), |l| l.field_tys.iter())
|
||||||
|
.filter(|decl| !decl.ignore_for_traits)
|
||||||
|
.map(|decl| {
|
||||||
let ty = fold_regions(self, decl.ty, |re, debruijn| {
|
let ty = fold_regions(self, decl.ty, |re, debruijn| {
|
||||||
assert_eq!(re, self.lifetimes.re_erased);
|
assert_eq!(re, self.lifetimes.re_erased);
|
||||||
let var = ty::BoundVar::from_usize(vars.len());
|
let var = ty::BoundVar::from_usize(vars.len());
|
||||||
|
@ -780,11 +764,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon },
|
ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon },
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
ty
|
||||||
|
}),
|
||||||
|
);
|
||||||
ty::EarlyBinder::bind(ty::Binder::bind_with_vars(
|
ty::EarlyBinder::bind(ty::Binder::bind_with_vars(
|
||||||
ty,
|
bound_tys,
|
||||||
self.mk_bound_variable_kinds(&vars),
|
self.mk_bound_variable_kinds(&vars),
|
||||||
))
|
))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expands the given impl trait type, stopping if the type is recursive.
|
/// Expands the given impl trait type, stopping if the type is recursive.
|
||||||
|
|
|
@ -18,7 +18,7 @@ use crate::solve::{AdtDestructorKind, EvalCtxt, Goal, NoSolution};
|
||||||
pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<D, I>(
|
pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<D, I>(
|
||||||
ecx: &EvalCtxt<'_, D>,
|
ecx: &EvalCtxt<'_, D>,
|
||||||
ty: I::Ty,
|
ty: I::Ty,
|
||||||
) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution>
|
) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
|
||||||
where
|
where
|
||||||
D: SolverDelegate<Interner = I>,
|
D: SolverDelegate<Interner = I>,
|
||||||
I: Interner,
|
I: Interner,
|
||||||
|
@ -33,10 +33,10 @@ where
|
||||||
| ty::FnPtr(..)
|
| ty::FnPtr(..)
|
||||||
| ty::Error(_)
|
| ty::Error(_)
|
||||||
| ty::Never
|
| ty::Never
|
||||||
| ty::Char => Ok(vec![]),
|
| ty::Char => Ok(ty::Binder::dummy(vec![])),
|
||||||
|
|
||||||
// Treat `str` like it's defined as `struct str([u8]);`
|
// Treat `str` like it's defined as `struct str([u8]);`
|
||||||
ty::Str => Ok(vec![ty::Binder::dummy(Ty::new_slice(cx, Ty::new_u8(cx)))]),
|
ty::Str => Ok(ty::Binder::dummy(vec![Ty::new_slice(cx, Ty::new_u8(cx))])),
|
||||||
|
|
||||||
ty::Dynamic(..)
|
ty::Dynamic(..)
|
||||||
| ty::Param(..)
|
| ty::Param(..)
|
||||||
|
@ -49,53 +49,49 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::RawPtr(element_ty, _) | ty::Ref(_, element_ty, _) => {
|
ty::RawPtr(element_ty, _) | ty::Ref(_, element_ty, _) => {
|
||||||
Ok(vec![ty::Binder::dummy(element_ty)])
|
Ok(ty::Binder::dummy(vec![element_ty]))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Pat(element_ty, _) | ty::Array(element_ty, _) | ty::Slice(element_ty) => {
|
ty::Pat(element_ty, _) | ty::Array(element_ty, _) | ty::Slice(element_ty) => {
|
||||||
Ok(vec![ty::Binder::dummy(element_ty)])
|
Ok(ty::Binder::dummy(vec![element_ty]))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Tuple(tys) => {
|
ty::Tuple(tys) => {
|
||||||
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
|
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
|
||||||
Ok(tys.iter().map(ty::Binder::dummy).collect())
|
Ok(ty::Binder::dummy(tys.to_vec()))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]),
|
ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
|
||||||
|
|
||||||
ty::CoroutineClosure(_, args) => {
|
ty::CoroutineClosure(_, args) => {
|
||||||
Ok(vec![ty::Binder::dummy(args.as_coroutine_closure().tupled_upvars_ty())])
|
Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Coroutine(_, args) => {
|
ty::Coroutine(_, args) => {
|
||||||
let coroutine_args = args.as_coroutine();
|
let coroutine_args = args.as_coroutine();
|
||||||
Ok(vec![
|
Ok(ty::Binder::dummy(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()]))
|
||||||
ty::Binder::dummy(coroutine_args.tupled_upvars_ty()),
|
|
||||||
ty::Binder::dummy(coroutine_args.witness()),
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::CoroutineWitness(def_id, args) => Ok(ecx
|
ty::CoroutineWitness(def_id, args) => Ok(ecx
|
||||||
.cx()
|
.cx()
|
||||||
.bound_coroutine_hidden_types(def_id)
|
.coroutine_hidden_types(def_id)
|
||||||
.into_iter()
|
.instantiate(cx, args)
|
||||||
.map(|bty| bty.instantiate(cx, args))
|
.map_bound(|tys| tys.to_vec())),
|
||||||
.collect()),
|
|
||||||
|
|
||||||
ty::UnsafeBinder(bound_ty) => Ok(vec![bound_ty.into()]),
|
ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
|
||||||
|
|
||||||
// For `PhantomData<T>`, we pass `T`.
|
// For `PhantomData<T>`, we pass `T`.
|
||||||
ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![ty::Binder::dummy(args.type_at(0))]),
|
ty::Adt(def, args) if def.is_phantom_data() => Ok(ty::Binder::dummy(vec![args.type_at(0)])),
|
||||||
|
|
||||||
ty::Adt(def, args) => {
|
ty::Adt(def, args) => {
|
||||||
Ok(def.all_field_tys(cx).iter_instantiated(cx, args).map(ty::Binder::dummy).collect())
|
Ok(ty::Binder::dummy(def.all_field_tys(cx).iter_instantiated(cx, args).collect()))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
|
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
|
||||||
// We can resolve the `impl Trait` to its concrete type,
|
// We can resolve the `impl Trait` to its concrete type,
|
||||||
// which enforces a DAG between the functions requiring
|
// which enforces a DAG between the functions requiring
|
||||||
// the auto trait bounds in question.
|
// the auto trait bounds in question.
|
||||||
Ok(vec![ty::Binder::dummy(cx.type_of(def_id).instantiate(cx, args))])
|
Ok(ty::Binder::dummy(vec![cx.type_of(def_id).instantiate(cx, args)]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,7 +100,7 @@ where
|
||||||
pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<D, I>(
|
pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<D, I>(
|
||||||
ecx: &EvalCtxt<'_, D>,
|
ecx: &EvalCtxt<'_, D>,
|
||||||
ty: I::Ty,
|
ty: I::Ty,
|
||||||
) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution>
|
) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
|
||||||
where
|
where
|
||||||
D: SolverDelegate<Interner = I>,
|
D: SolverDelegate<Interner = I>,
|
||||||
I: Interner,
|
I: Interner,
|
||||||
|
@ -130,7 +126,7 @@ where
|
||||||
| ty::CoroutineClosure(..)
|
| ty::CoroutineClosure(..)
|
||||||
| ty::Never
|
| ty::Never
|
||||||
| ty::Dynamic(_, _, ty::DynStar)
|
| ty::Dynamic(_, _, ty::DynStar)
|
||||||
| ty::Error(_) => Ok(vec![]),
|
| ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
|
||||||
|
|
||||||
ty::Str
|
ty::Str
|
||||||
| ty::Slice(_)
|
| ty::Slice(_)
|
||||||
|
@ -145,11 +141,11 @@ where
|
||||||
panic!("unexpected type `{ty:?}`")
|
panic!("unexpected type `{ty:?}`")
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::UnsafeBinder(bound_ty) => Ok(vec![bound_ty.into()]),
|
ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
|
||||||
|
|
||||||
// impl Sized for ()
|
// impl Sized for ()
|
||||||
// impl Sized for (T1, T2, .., Tn) where Tn: Sized if n >= 1
|
// impl Sized for (T1, T2, .., Tn) where Tn: Sized if n >= 1
|
||||||
ty::Tuple(tys) => Ok(tys.last().map_or_else(Vec::new, |ty| vec![ty::Binder::dummy(ty)])),
|
ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new, |ty| vec![ty]))),
|
||||||
|
|
||||||
// impl Sized for Adt<Args...> where sized_constraint(Adt)<Args...>: Sized
|
// impl Sized for Adt<Args...> where sized_constraint(Adt)<Args...>: Sized
|
||||||
// `sized_constraint(Adt)` is the deepest struct trail that can be determined
|
// `sized_constraint(Adt)` is the deepest struct trail that can be determined
|
||||||
|
@ -162,9 +158,9 @@ where
|
||||||
// if the ADT is sized for all possible args.
|
// if the ADT is sized for all possible args.
|
||||||
ty::Adt(def, args) => {
|
ty::Adt(def, args) => {
|
||||||
if let Some(sized_crit) = def.sized_constraint(ecx.cx()) {
|
if let Some(sized_crit) = def.sized_constraint(ecx.cx()) {
|
||||||
Ok(vec![ty::Binder::dummy(sized_crit.instantiate(ecx.cx(), args))])
|
Ok(ty::Binder::dummy(vec![sized_crit.instantiate(ecx.cx(), args)]))
|
||||||
} else {
|
} else {
|
||||||
Ok(vec![])
|
Ok(ty::Binder::dummy(vec![]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,14 +170,14 @@ where
|
||||||
pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<D, I>(
|
pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<D, I>(
|
||||||
ecx: &EvalCtxt<'_, D>,
|
ecx: &EvalCtxt<'_, D>,
|
||||||
ty: I::Ty,
|
ty: I::Ty,
|
||||||
) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution>
|
) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
|
||||||
where
|
where
|
||||||
D: SolverDelegate<Interner = I>,
|
D: SolverDelegate<Interner = I>,
|
||||||
I: Interner,
|
I: Interner,
|
||||||
{
|
{
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
// impl Copy/Clone for FnDef, FnPtr
|
// impl Copy/Clone for FnDef, FnPtr
|
||||||
ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(vec![]),
|
ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
|
||||||
|
|
||||||
// Implementations are provided in core
|
// Implementations are provided in core
|
||||||
ty::Uint(_)
|
ty::Uint(_)
|
||||||
|
@ -197,7 +193,7 @@ where
|
||||||
|
|
||||||
// Cannot implement in core, as we can't be generic over patterns yet,
|
// Cannot implement in core, as we can't be generic over patterns yet,
|
||||||
// so we'd have to list all patterns and type combinations.
|
// so we'd have to list all patterns and type combinations.
|
||||||
ty::Pat(ty, ..) => Ok(vec![ty::Binder::dummy(ty)]),
|
ty::Pat(ty, ..) => Ok(ty::Binder::dummy(vec![ty])),
|
||||||
|
|
||||||
ty::Dynamic(..)
|
ty::Dynamic(..)
|
||||||
| ty::Str
|
| ty::Str
|
||||||
|
@ -215,14 +211,14 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl Copy/Clone for (T1, T2, .., Tn) where T1: Copy/Clone, T2: Copy/Clone, .. Tn: Copy/Clone
|
// impl Copy/Clone for (T1, T2, .., Tn) where T1: Copy/Clone, T2: Copy/Clone, .. Tn: Copy/Clone
|
||||||
ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()),
|
ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.to_vec())),
|
||||||
|
|
||||||
// impl Copy/Clone for Closure where Self::TupledUpvars: Copy/Clone
|
// impl Copy/Clone for Closure where Self::TupledUpvars: Copy/Clone
|
||||||
ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]),
|
ty::Closure(_, args) => Ok(ty::Binder::dummy(vec![args.as_closure().tupled_upvars_ty()])),
|
||||||
|
|
||||||
// impl Copy/Clone for CoroutineClosure where Self::TupledUpvars: Copy/Clone
|
// impl Copy/Clone for CoroutineClosure where Self::TupledUpvars: Copy/Clone
|
||||||
ty::CoroutineClosure(_, args) => {
|
ty::CoroutineClosure(_, args) => {
|
||||||
Ok(vec![ty::Binder::dummy(args.as_coroutine_closure().tupled_upvars_ty())])
|
Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// only when `coroutine_clone` is enabled and the coroutine is movable
|
// only when `coroutine_clone` is enabled and the coroutine is movable
|
||||||
|
@ -232,10 +228,7 @@ where
|
||||||
Movability::Movable => {
|
Movability::Movable => {
|
||||||
if ecx.cx().features().coroutine_clone() {
|
if ecx.cx().features().coroutine_clone() {
|
||||||
let coroutine = args.as_coroutine();
|
let coroutine = args.as_coroutine();
|
||||||
Ok(vec![
|
Ok(ty::Binder::dummy(vec![coroutine.tupled_upvars_ty(), coroutine.witness()]))
|
||||||
ty::Binder::dummy(coroutine.tupled_upvars_ty()),
|
|
||||||
ty::Binder::dummy(coroutine.witness()),
|
|
||||||
])
|
|
||||||
} else {
|
} else {
|
||||||
Err(NoSolution)
|
Err(NoSolution)
|
||||||
}
|
}
|
||||||
|
@ -247,10 +240,9 @@ where
|
||||||
// impl Copy/Clone for CoroutineWitness where T: Copy/Clone forall T in coroutine_hidden_types
|
// impl Copy/Clone for CoroutineWitness where T: Copy/Clone forall T in coroutine_hidden_types
|
||||||
ty::CoroutineWitness(def_id, args) => Ok(ecx
|
ty::CoroutineWitness(def_id, args) => Ok(ecx
|
||||||
.cx()
|
.cx()
|
||||||
.bound_coroutine_hidden_types(def_id)
|
.coroutine_hidden_types(def_id)
|
||||||
.into_iter()
|
.instantiate(ecx.cx(), args)
|
||||||
.map(|bty| bty.instantiate(ecx.cx(), args))
|
.map_bound(|tys| tys.to_vec())),
|
||||||
.collect()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -967,7 +967,7 @@ where
|
||||||
|
|
||||||
/// `enter_forall`, but takes `&mut self` and passes it back through the
|
/// `enter_forall`, but takes `&mut self` and passes it back through the
|
||||||
/// callback since it can't be aliased during the call.
|
/// callback since it can't be aliased during the call.
|
||||||
pub(super) fn enter_forall<T: TypeFoldable<I> + Copy, U>(
|
pub(super) fn enter_forall<T: TypeFoldable<I>, U>(
|
||||||
&mut self,
|
&mut self,
|
||||||
value: ty::Binder<I, T>,
|
value: ty::Binder<I, T>,
|
||||||
f: impl FnOnce(&mut Self, T) -> U,
|
f: impl FnOnce(&mut Self, T) -> U,
|
||||||
|
|
|
@ -1239,17 +1239,15 @@ where
|
||||||
constituent_tys: impl Fn(
|
constituent_tys: impl Fn(
|
||||||
&EvalCtxt<'_, D>,
|
&EvalCtxt<'_, D>,
|
||||||
I::Ty,
|
I::Ty,
|
||||||
) -> Result<Vec<ty::Binder<I, I::Ty>>, NoSolution>,
|
) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>,
|
||||||
) -> Result<Candidate<I>, NoSolution> {
|
) -> Result<Candidate<I>, NoSolution> {
|
||||||
self.probe_trait_candidate(source).enter(|ecx| {
|
self.probe_trait_candidate(source).enter(|ecx| {
|
||||||
let goals = constituent_tys(ecx, goal.predicate.self_ty())?
|
let goals =
|
||||||
.into_iter()
|
ecx.enter_forall(constituent_tys(ecx, goal.predicate.self_ty())?, |ecx, tys| {
|
||||||
.map(|ty| {
|
tys.into_iter()
|
||||||
ecx.enter_forall(ty, |ecx, ty| {
|
.map(|ty| goal.with(ecx.cx(), goal.predicate.with_self_ty(ecx.cx(), ty)))
|
||||||
goal.with(ecx.cx(), goal.predicate.with_self_ty(ecx.cx(), ty))
|
.collect::<Vec<_>>()
|
||||||
})
|
});
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
ecx.add_goals(GoalSource::ImplWhereBound, goals);
|
ecx.add_goals(GoalSource::ImplWhereBound, goals);
|
||||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::ops::ControlFlow;
|
||||||
use std::{cmp, iter};
|
use std::{cmp, iter};
|
||||||
|
|
||||||
use hir::def::DefKind;
|
use hir::def::DefKind;
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_errors::{Diag, EmissionGuarantee};
|
use rustc_errors::{Diag, EmissionGuarantee};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -25,7 +25,6 @@ use rustc_middle::dep_graph::{DepNodeIndex, dep_kinds};
|
||||||
pub use rustc_middle::traits::select::*;
|
pub use rustc_middle::traits::select::*;
|
||||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||||
use rustc_middle::ty::error::TypeErrorToStringExt;
|
use rustc_middle::ty::error::TypeErrorToStringExt;
|
||||||
use rustc_middle::ty::fold::fold_regions;
|
|
||||||
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
|
use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
|
self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
|
||||||
|
@ -2205,8 +2204,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::CoroutineWitness(def_id, args) => {
|
ty::CoroutineWitness(def_id, args) => {
|
||||||
let hidden_types = bind_coroutine_hidden_types_above(
|
let hidden_types = rebind_coroutine_witness_types(
|
||||||
self.infcx,
|
self.infcx.tcx,
|
||||||
def_id,
|
def_id,
|
||||||
args,
|
args,
|
||||||
obligation.predicate.bound_vars(),
|
obligation.predicate.bound_vars(),
|
||||||
|
@ -2354,7 +2353,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::CoroutineWitness(def_id, args) => {
|
ty::CoroutineWitness(def_id, args) => {
|
||||||
bind_coroutine_hidden_types_above(self.infcx, def_id, args, t.bound_vars())
|
rebind_coroutine_witness_types(self.infcx.tcx, def_id, args, t.bound_vars())
|
||||||
}
|
}
|
||||||
|
|
||||||
// For `PhantomData<T>`, we pass `T`.
|
// For `PhantomData<T>`, we pass `T`.
|
||||||
|
@ -2849,6 +2848,23 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rebind_coroutine_witness_types<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
|
args: ty::GenericArgsRef<'tcx>,
|
||||||
|
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||||
|
) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> {
|
||||||
|
let bound_coroutine_types = tcx.coroutine_hidden_types(def_id).skip_binder();
|
||||||
|
let shifted_coroutine_types =
|
||||||
|
tcx.shift_bound_var_indices(bound_vars.len(), bound_coroutine_types.skip_binder());
|
||||||
|
ty::Binder::bind_with_vars(
|
||||||
|
ty::EarlyBinder::bind(shifted_coroutine_types.to_vec()).instantiate(tcx, args),
|
||||||
|
tcx.mk_bound_variable_kinds_from_iter(
|
||||||
|
bound_vars.iter().chain(bound_coroutine_types.bound_vars()),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
|
impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
|
||||||
fn list(&'o self) -> TraitObligationStackList<'o, 'tcx> {
|
fn list(&'o self) -> TraitObligationStackList<'o, 'tcx> {
|
||||||
TraitObligationStackList::with(self)
|
TraitObligationStackList::with(self)
|
||||||
|
@ -3157,56 +3173,3 @@ pub(crate) enum ProjectionMatchesProjection {
|
||||||
Ambiguous,
|
Ambiguous,
|
||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replace all regions inside the coroutine interior with late bound regions.
|
|
||||||
/// Note that each region slot in the types gets a new fresh late bound region, which means that
|
|
||||||
/// none of the regions inside relate to any other, even if typeck had previously found constraints
|
|
||||||
/// that would cause them to be related.
|
|
||||||
#[instrument(level = "trace", skip(infcx), ret)]
|
|
||||||
fn bind_coroutine_hidden_types_above<'tcx>(
|
|
||||||
infcx: &InferCtxt<'tcx>,
|
|
||||||
def_id: DefId,
|
|
||||||
args: ty::GenericArgsRef<'tcx>,
|
|
||||||
bound_vars: &ty::List<ty::BoundVariableKind>,
|
|
||||||
) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> {
|
|
||||||
let tcx = infcx.tcx;
|
|
||||||
let mut seen_tys = FxHashSet::default();
|
|
||||||
|
|
||||||
let considering_regions = infcx.considering_regions;
|
|
||||||
|
|
||||||
let num_bound_variables = bound_vars.len() as u32;
|
|
||||||
let mut counter = num_bound_variables;
|
|
||||||
|
|
||||||
let hidden_types: Vec<_> = tcx
|
|
||||||
.coroutine_hidden_types(def_id)
|
|
||||||
// Deduplicate tys to avoid repeated work.
|
|
||||||
.filter(|bty| seen_tys.insert(*bty))
|
|
||||||
.map(|mut bty| {
|
|
||||||
// Only remap erased regions if we use them.
|
|
||||||
if considering_regions {
|
|
||||||
bty = bty.map_bound(|ty| {
|
|
||||||
fold_regions(tcx, ty, |r, current_depth| match r.kind() {
|
|
||||||
ty::ReErased => {
|
|
||||||
let br = ty::BoundRegion {
|
|
||||||
var: ty::BoundVar::from_u32(counter),
|
|
||||||
kind: ty::BoundRegionKind::Anon,
|
|
||||||
};
|
|
||||||
counter += 1;
|
|
||||||
ty::Region::new_bound(tcx, current_depth, br)
|
|
||||||
}
|
|
||||||
r => bug!("unexpected region: {r:?}"),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
bty.instantiate(tcx, args)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
|
|
||||||
bound_vars.iter().chain(
|
|
||||||
(num_bound_variables..counter)
|
|
||||||
.map(|_| ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon)),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
ty::Binder::bind_with_vars(hidden_types, bound_vars)
|
|
||||||
}
|
|
||||||
|
|
|
@ -151,7 +151,7 @@ pub trait InferCtxtLike: Sized {
|
||||||
value: ty::Binder<Self::Interner, T>,
|
value: ty::Binder<Self::Interner, T>,
|
||||||
) -> T;
|
) -> T;
|
||||||
|
|
||||||
fn enter_forall<T: TypeFoldable<Self::Interner> + Copy, U>(
|
fn enter_forall<T: TypeFoldable<Self::Interner>, U>(
|
||||||
&self,
|
&self,
|
||||||
value: ty::Binder<Self::Interner, T>,
|
value: ty::Binder<Self::Interner, T>,
|
||||||
f: impl FnOnce(T) -> U,
|
f: impl FnOnce(T) -> U,
|
||||||
|
|
|
@ -189,10 +189,10 @@ pub trait Interner:
|
||||||
type Features: Features<Self>;
|
type Features: Features<Self>;
|
||||||
fn features(self) -> Self::Features;
|
fn features(self) -> Self::Features;
|
||||||
|
|
||||||
fn bound_coroutine_hidden_types(
|
fn coroutine_hidden_types(
|
||||||
self,
|
self,
|
||||||
def_id: Self::DefId,
|
def_id: Self::DefId,
|
||||||
) -> impl IntoIterator<Item = ty::EarlyBinder<Self, ty::Binder<Self, Self::Ty>>>;
|
) -> ty::EarlyBinder<Self, ty::Binder<Self, Self::Tys>>;
|
||||||
|
|
||||||
fn fn_sig(
|
fn fn_sig(
|
||||||
self,
|
self,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue