1
Fork 0

Use Binder<Vec<T>> instead of Vec<Binder<T>> in new solver

This commit is contained in:
Michael Goulet 2025-02-26 17:32:26 +00:00
parent 4ecd70ddd1
commit 8282181e42
8 changed files with 70 additions and 75 deletions

View file

@ -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();

View file

@ -327,7 +327,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
fn bound_coroutine_hidden_types( fn bound_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.bound_coroutine_hidden_types(def_id)
} }

View file

@ -748,14 +748,15 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn bound_coroutine_hidden_types( pub fn bound_coroutine_hidden_types(
self, self,
def_id: DefId, def_id: DefId,
) -> impl Iterator<Item = ty::EarlyBinder<'tcx, ty::Binder<'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);
let mut vars = vec![];
let bound_tys = self.mk_type_list_from_iter(
coroutine_layout coroutine_layout
.as_ref() .as_ref()
.map_or_else(|| [].iter(), |l| l.field_tys.iter()) .map_or_else(|| [].iter(), |l| l.field_tys.iter())
.filter(|decl| !decl.ignore_for_traits) .filter(|decl| !decl.ignore_for_traits)
.map(move |decl| { .map(|decl| {
let mut vars = vec![];
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());
@ -766,11 +767,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.

View file

@ -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) .bound_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)
} }
@ -248,9 +241,8 @@ where
ty::CoroutineWitness(def_id, args) => Ok(ecx ty::CoroutineWitness(def_id, args) => Ok(ecx
.cx() .cx()
.bound_coroutine_hidden_types(def_id) .bound_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()),
} }
} }

View file

@ -913,7 +913,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,

View file

@ -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)
}) })

View file

@ -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,

View file

@ -192,7 +192,7 @@ pub trait Interner:
fn bound_coroutine_hidden_types( fn bound_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,