Auto merge of #120544 - BoxyUwU:enter_forall, r=lcnr
Introduce `enter_forall` to supercede `instantiate_binder_with_placeholders`
r? `@lcnr`
Long term we'd like to experiment with decrementing the universe count after "exiting" binders so that we do not end up creating infer vars in non-root universes even when they logically reside in the root universe. The fact that we dont do this currently results in a number of issues in the new trait solver where we consider goals to be ambiguous because otherwise it would require lowering the universe of an infer var. i.e. the goal `?x.0 eq <T as Trait<?y.1>>::Assoc` where the alias is rigid would not be able to instantiate `?x` with the alias as there would be a universe error.
This PR is the first-ish sort of step towards being able to implement this as eventually we would want to decrement the universe in `enter_forall`. Unfortunately its Difficult to actually implement decrementing universes nicely so this is a separate step which moves us closer to the long term goal ✨
This commit is contained in:
commit
c29082fe7d
21 changed files with 629 additions and 549 deletions
|
@ -1032,10 +1032,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
let ty::SubtypePredicate { a_is_expected, a, b } =
|
||||
self.instantiate_binder_with_placeholders(predicate);
|
||||
|
||||
self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| {
|
||||
Ok(self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn region_outlives_predicate(
|
||||
|
@ -1043,10 +1042,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
cause: &traits::ObligationCause<'tcx>,
|
||||
predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
|
||||
) {
|
||||
let ty::OutlivesPredicate(r_a, r_b) = self.instantiate_binder_with_placeholders(predicate);
|
||||
let origin =
|
||||
SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span));
|
||||
self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| {
|
||||
let origin = SubregionOrigin::from_obligation_cause(cause, || {
|
||||
RelateRegionParamBound(cause.span)
|
||||
});
|
||||
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
|
||||
})
|
||||
}
|
||||
|
||||
/// Number of type variables created so far.
|
||||
|
@ -1455,7 +1456,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
// Use this method if you'd like to find some substitution of the binder's
|
||||
// variables (e.g. during a method call). If there isn't a [`BoundRegionConversionTime`]
|
||||
// that corresponds to your use case, consider whether or not you should
|
||||
// use [`InferCtxt::instantiate_binder_with_placeholders`] instead.
|
||||
// use [`InferCtxt::enter_forall`] instead.
|
||||
pub fn instantiate_binder_with_fresh_vars<T>(
|
||||
&self,
|
||||
span: Span,
|
||||
|
|
|
@ -38,24 +38,25 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
|
|||
// First, we instantiate each bound region in the supertype with a
|
||||
// fresh placeholder region. Note that this automatically creates
|
||||
// a new universe if needed.
|
||||
let sup_prime = self.infcx.instantiate_binder_with_placeholders(sup);
|
||||
|
||||
self.infcx.enter_forall(sup, |sup_prime| {
|
||||
// Next, we instantiate each bound region in the subtype
|
||||
// with a fresh region variable. These region variables --
|
||||
// but no other preexisting region variables -- can name
|
||||
// the placeholders.
|
||||
let sub_prime = self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub);
|
||||
|
||||
let sub_prime =
|
||||
self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub);
|
||||
debug!("a_prime={:?}", sub_prime);
|
||||
debug!("b_prime={:?}", sup_prime);
|
||||
|
||||
// Compare types now that bound regions have been replaced.
|
||||
let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime)?;
|
||||
|
||||
let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime);
|
||||
if result.is_ok() {
|
||||
debug!("OK result={result:?}");
|
||||
}
|
||||
// NOTE: returning the result here would be dangerous as it contains
|
||||
// placeholders which **must not** be named afterwards.
|
||||
Ok(())
|
||||
result.map(|_| ())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,9 +69,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
/// This is the first step of checking subtyping when higher-ranked things are involved.
|
||||
/// For more details visit the relevant sections of the [rustc dev guide].
|
||||
///
|
||||
/// `fn enter_forall` should be preferred over this method.
|
||||
///
|
||||
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
pub fn instantiate_binder_with_placeholders<T>(&self, binder: ty::Binder<'tcx, T>) -> T
|
||||
pub fn enter_forall_and_leak_universe<T>(&self, binder: ty::Binder<'tcx, T>) -> T
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>> + Copy,
|
||||
{
|
||||
|
@ -106,6 +109,31 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
self.tcx.replace_bound_vars_uncached(binder, delegate)
|
||||
}
|
||||
|
||||
/// Replaces all bound variables (lifetimes, types, and constants) bound by
|
||||
/// `binder` with placeholder variables in a new universe and then calls the
|
||||
/// closure `f` with the instantiated value. The new placeholders can only be
|
||||
/// named by inference variables created inside of the closure `f` or afterwards.
|
||||
///
|
||||
/// This is the first step of checking subtyping when higher-ranked things are involved.
|
||||
/// For more details visit the relevant sections of the [rustc dev guide].
|
||||
///
|
||||
/// This method should be preferred over `fn enter_forall_and_leak_universe`.
|
||||
///
|
||||
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
|
||||
#[instrument(level = "debug", skip(self, f))]
|
||||
pub fn enter_forall<T, U>(&self, forall: ty::Binder<'tcx, T>, f: impl FnOnce(T) -> U) -> U
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>> + Copy,
|
||||
{
|
||||
// FIXME: currently we do nothing to prevent placeholders with the new universe being
|
||||
// used after exiting `f`. For example region subtyping can result in outlives constraints
|
||||
// that name placeholders created in this function. Nested goals from type relations can
|
||||
// also contain placeholders created by this function.
|
||||
let value = self.enter_forall_and_leak_universe(forall);
|
||||
debug!("?value");
|
||||
f(value)
|
||||
}
|
||||
|
||||
/// See [RegionConstraintCollector::leak_check][1]. We only check placeholder
|
||||
/// leaking into `outer_universe`, i.e. placeholders which cannot be named by that
|
||||
/// universe.
|
||||
|
|
|
@ -261,15 +261,17 @@ where
|
|||
Ok(a)
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn instantiate_binder_with_placeholders<T>(&mut self, binder: ty::Binder<'tcx, T>) -> T
|
||||
fn enter_forall<T, U>(
|
||||
&mut self,
|
||||
binder: ty::Binder<'tcx, T>,
|
||||
f: impl FnOnce(&mut Self, T) -> U,
|
||||
) -> U
|
||||
where
|
||||
T: ty::TypeFoldable<TyCtxt<'tcx>> + Copy,
|
||||
{
|
||||
if let Some(inner) = binder.no_bound_vars() {
|
||||
return inner;
|
||||
}
|
||||
|
||||
let value = if let Some(inner) = binder.no_bound_vars() {
|
||||
inner
|
||||
} else {
|
||||
let mut next_region = {
|
||||
let nll_delegate = &mut self.delegate;
|
||||
let mut lazy_universe = None;
|
||||
|
@ -303,10 +305,11 @@ where
|
|||
},
|
||||
};
|
||||
|
||||
let replaced = self.infcx.tcx.replace_bound_vars_uncached(binder, delegate);
|
||||
debug!(?replaced);
|
||||
self.infcx.tcx.replace_bound_vars_uncached(binder, delegate)
|
||||
};
|
||||
|
||||
replaced
|
||||
debug!(?value);
|
||||
f(self, value)
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
|
@ -630,10 +633,10 @@ where
|
|||
|
||||
// Note: the order here is important. Create the placeholders first, otherwise
|
||||
// we assign the wrong universe to the existential!
|
||||
let b_replaced = self.instantiate_binder_with_placeholders(b);
|
||||
let a_replaced = self.instantiate_binder_with_existentials(a);
|
||||
|
||||
self.relate(a_replaced, b_replaced)?;
|
||||
self.enter_forall(b, |this, b| {
|
||||
let a = this.instantiate_binder_with_existentials(a);
|
||||
this.relate(a, b)
|
||||
})?;
|
||||
|
||||
self.ambient_variance = variance;
|
||||
}
|
||||
|
@ -650,10 +653,10 @@ where
|
|||
let variance =
|
||||
std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant);
|
||||
|
||||
let a_replaced = self.instantiate_binder_with_placeholders(a);
|
||||
let b_replaced = self.instantiate_binder_with_existentials(b);
|
||||
|
||||
self.relate(a_replaced, b_replaced)?;
|
||||
self.enter_forall(a, |this, a| {
|
||||
let b = this.instantiate_binder_with_existentials(b);
|
||||
this.relate(a, b)
|
||||
})?;
|
||||
|
||||
self.ambient_variance = variance;
|
||||
}
|
||||
|
|
|
@ -77,13 +77,13 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
|||
for (pred, pred_span) in
|
||||
cx.tcx.explicit_item_bounds(def_id).instantiate_identity_iter_copied()
|
||||
{
|
||||
let predicate = infcx.instantiate_binder_with_placeholders(pred.kind());
|
||||
infcx.enter_forall(pred.kind(), |predicate| {
|
||||
let ty::ClauseKind::Projection(proj) = predicate else {
|
||||
continue;
|
||||
return;
|
||||
};
|
||||
// Only check types, since those are the only things that may
|
||||
// have opaques in them anyways.
|
||||
let Some(proj_term) = proj.term.ty() else { continue };
|
||||
let Some(proj_term) = proj.term.ty() else { return };
|
||||
|
||||
// HACK: `impl Trait<Assoc = impl Trait2>` from an RPIT is "ok"...
|
||||
if let ty::Alias(ty::Opaque, opaque_ty) = *proj_term.kind()
|
||||
|
@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
|||
hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_)
|
||||
)
|
||||
{
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
// HACK: `async fn() -> Self` in traits is "ok"...
|
||||
|
@ -104,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
|||
&& matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(_))
|
||||
&& opaque.in_trait
|
||||
{
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
let proj_ty =
|
||||
|
@ -135,6 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
|||
) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// If that predicate doesn't hold modulo regions (but passed during type-check),
|
||||
// then we must've taken advantage of the hack in `project_and_unify_types` where
|
||||
// we replace opaques with inference vars. Emit a warning!
|
||||
|
@ -156,6 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
|||
}),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
cx.emit_span_lint(
|
||||
OPAQUE_HIDDEN_INFERRED_BOUND,
|
||||
pred_span,
|
||||
|
@ -172,6 +174,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
|
|||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1052,6 +1052,7 @@ impl<'tcx, T> Binder<'tcx, T> {
|
|||
where
|
||||
T: TypeVisitable<TyCtxt<'tcx>>,
|
||||
{
|
||||
// `self.value` is equivalent to `self.skip_binder()`
|
||||
if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ use crate::solve::EvalCtxt;
|
|||
pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
|
||||
ecx: &EvalCtxt<'_, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
|
||||
) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution> {
|
||||
let tcx = ecx.tcx();
|
||||
match *ty.kind() {
|
||||
ty::Uint(_)
|
||||
|
@ -34,7 +34,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
|
|||
| ty::Char => Ok(vec![]),
|
||||
|
||||
// Treat `str` like it's defined as `struct str([u8]);`
|
||||
ty::Str => Ok(vec![Ty::new_slice(tcx, tcx.types.u8)]),
|
||||
ty::Str => Ok(vec![ty::Binder::dummy(Ty::new_slice(tcx, tcx.types.u8))]),
|
||||
|
||||
ty::Dynamic(..)
|
||||
| ty::Param(..)
|
||||
|
@ -47,46 +47,48 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
|
|||
}
|
||||
|
||||
ty::RawPtr(ty::TypeAndMut { ty: element_ty, .. }) | ty::Ref(_, element_ty, _) => {
|
||||
Ok(vec![element_ty])
|
||||
Ok(vec![ty::Binder::dummy(element_ty)])
|
||||
}
|
||||
|
||||
ty::Array(element_ty, _) | ty::Slice(element_ty) => Ok(vec![element_ty]),
|
||||
ty::Array(element_ty, _) | ty::Slice(element_ty) => Ok(vec![ty::Binder::dummy(element_ty)]),
|
||||
|
||||
ty::Tuple(tys) => {
|
||||
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
|
||||
Ok(tys.iter().collect())
|
||||
Ok(tys.iter().map(ty::Binder::dummy).collect())
|
||||
}
|
||||
|
||||
ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
|
||||
ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]),
|
||||
|
||||
ty::CoroutineClosure(_, args) => Ok(vec![args.as_coroutine_closure().tupled_upvars_ty()]),
|
||||
ty::CoroutineClosure(_, args) => {
|
||||
Ok(vec![ty::Binder::dummy(args.as_coroutine_closure().tupled_upvars_ty())])
|
||||
}
|
||||
|
||||
ty::Coroutine(_, args) => {
|
||||
let coroutine_args = args.as_coroutine();
|
||||
Ok(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()])
|
||||
Ok(vec![
|
||||
ty::Binder::dummy(coroutine_args.tupled_upvars_ty()),
|
||||
ty::Binder::dummy(coroutine_args.witness()),
|
||||
])
|
||||
}
|
||||
|
||||
ty::CoroutineWitness(def_id, args) => Ok(ecx
|
||||
.tcx()
|
||||
.coroutine_hidden_types(def_id)
|
||||
.map(|bty| {
|
||||
ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
|
||||
tcx,
|
||||
bty.instantiate(tcx, args),
|
||||
))
|
||||
})
|
||||
.map(|bty| replace_erased_lifetimes_with_bound_vars(tcx, bty.instantiate(tcx, args)))
|
||||
.collect()),
|
||||
|
||||
// For `PhantomData<T>`, we pass `T`.
|
||||
ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![args.type_at(0)]),
|
||||
ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![ty::Binder::dummy(args.type_at(0))]),
|
||||
|
||||
ty::Adt(def, args) => Ok(def.all_fields().map(|f| f.ty(tcx, args)).collect()),
|
||||
ty::Adt(def, args) => {
|
||||
Ok(def.all_fields().map(|f| ty::Binder::dummy(f.ty(tcx, args))).collect())
|
||||
}
|
||||
|
||||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
|
||||
// We can resolve the `impl Trait` to its concrete type,
|
||||
// which enforces a DAG between the functions requiring
|
||||
// the auto trait bounds in question.
|
||||
Ok(vec![tcx.type_of(def_id).instantiate(tcx, args)])
|
||||
Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, args))])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +118,7 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
|
|||
pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
|
||||
ecx: &EvalCtxt<'_, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
|
||||
) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution> {
|
||||
match *ty.kind() {
|
||||
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||
| ty::Uint(_)
|
||||
|
@ -150,11 +152,11 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
|
|||
bug!("unexpected type `{ty}`")
|
||||
}
|
||||
|
||||
ty::Tuple(tys) => Ok(tys.to_vec()),
|
||||
ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()),
|
||||
|
||||
ty::Adt(def, args) => {
|
||||
let sized_crit = def.sized_constraint(ecx.tcx());
|
||||
Ok(sized_crit.iter_instantiated(ecx.tcx(), args).collect())
|
||||
Ok(sized_crit.iter_instantiated(ecx.tcx(), args).map(ty::Binder::dummy).collect())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,7 +165,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
|
|||
pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
|
||||
ecx: &EvalCtxt<'_, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
|
||||
) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution> {
|
||||
match *ty.kind() {
|
||||
ty::FnDef(..) | ty::FnPtr(_) | ty::Error(_) => Ok(vec![]),
|
||||
|
||||
|
@ -194,9 +196,9 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
|
|||
bug!("unexpected type `{ty}`")
|
||||
}
|
||||
|
||||
ty::Tuple(tys) => Ok(tys.to_vec()),
|
||||
ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()),
|
||||
|
||||
ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
|
||||
ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]),
|
||||
|
||||
ty::CoroutineClosure(..) => Err(NoSolution),
|
||||
|
||||
|
@ -205,7 +207,10 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
|
|||
Movability::Movable => {
|
||||
if ecx.tcx().features().coroutine_clone {
|
||||
let coroutine = args.as_coroutine();
|
||||
Ok(vec![coroutine.tupled_upvars_ty(), coroutine.witness()])
|
||||
Ok(vec![
|
||||
ty::Binder::dummy(coroutine.tupled_upvars_ty()),
|
||||
ty::Binder::dummy(coroutine.witness()),
|
||||
])
|
||||
} else {
|
||||
Err(NoSolution)
|
||||
}
|
||||
|
@ -216,10 +221,10 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
|
|||
.tcx()
|
||||
.coroutine_hidden_types(def_id)
|
||||
.map(|bty| {
|
||||
ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
|
||||
replace_erased_lifetimes_with_bound_vars(
|
||||
ecx.tcx(),
|
||||
bty.instantiate(ecx.tcx(), args),
|
||||
))
|
||||
)
|
||||
})
|
||||
.collect()),
|
||||
}
|
||||
|
|
|
@ -477,10 +477,11 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
let kind = self.infcx.instantiate_binder_with_placeholders(kind);
|
||||
self.infcx.enter_forall(kind, |kind| {
|
||||
let goal = goal.with(self.tcx(), ty::Binder::dummy(kind));
|
||||
self.add_goal(GoalSource::Misc, goal);
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -801,13 +802,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
pub(super) fn instantiate_binder_with_placeholders<T: TypeFoldable<TyCtxt<'tcx>> + Copy>(
|
||||
pub(super) fn enter_forall<T: TypeFoldable<TyCtxt<'tcx>> + Copy, U>(
|
||||
&self,
|
||||
value: ty::Binder<'tcx, T>,
|
||||
) -> T {
|
||||
self.infcx.instantiate_binder_with_placeholders(value)
|
||||
f: impl FnOnce(T) -> U,
|
||||
) -> U {
|
||||
self.infcx.enter_forall(value, f)
|
||||
}
|
||||
|
||||
pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
|
|
|
@ -31,11 +31,8 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
|
|||
) -> SelectionResult<'tcx, Selection<'tcx>> {
|
||||
assert!(self.next_trait_solver());
|
||||
|
||||
let trait_goal = Goal::new(
|
||||
self.tcx,
|
||||
obligation.param_env,
|
||||
self.instantiate_binder_with_placeholders(obligation.predicate),
|
||||
);
|
||||
self.enter_forall(obligation.predicate, |pred| {
|
||||
let trait_goal = Goal::new(self.tcx, obligation.param_env, pred);
|
||||
|
||||
let (result, _) = EvalCtxt::enter_root(self, GenerateProofTree::Never, |ecx| {
|
||||
let goal = Goal::new(ecx.tcx(), trait_goal.param_env, trait_goal.predicate);
|
||||
|
@ -79,7 +76,9 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
|
|||
});
|
||||
|
||||
let (candidate, certainty, nested_goals) = match result {
|
||||
Ok(Some((candidate, certainty, nested_goals))) => (candidate, certainty, nested_goals),
|
||||
Ok(Some((candidate, certainty, nested_goals))) => {
|
||||
(candidate, certainty, nested_goals)
|
||||
}
|
||||
Ok(None) => return Ok(None),
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
|
@ -87,7 +86,12 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
|
|||
let nested_obligations: Vec<_> = nested_goals
|
||||
.into_iter()
|
||||
.map(|goal| {
|
||||
Obligation::new(self.tcx, ObligationCause::dummy(), goal.param_env, goal.predicate)
|
||||
Obligation::new(
|
||||
self.tcx,
|
||||
ObligationCause::dummy(),
|
||||
goal.param_env,
|
||||
goal.predicate,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -128,6 +132,7 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
|
|||
|
||||
(Certainty::Maybe(_), _) => Ok(None),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
|
|||
)
|
||||
}
|
||||
ty::PredicateKind::Subtype(pred) => {
|
||||
let (a, b) = infcx.instantiate_binder_with_placeholders(
|
||||
let (a, b) = infcx.enter_forall_and_leak_universe(
|
||||
goal.predicate.kind().rebind((pred.a, pred.b)),
|
||||
);
|
||||
let expected_found = ExpectedFound::new(true, a, b);
|
||||
|
@ -150,7 +150,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
|
|||
)
|
||||
}
|
||||
ty::PredicateKind::Coerce(pred) => {
|
||||
let (a, b) = infcx.instantiate_binder_with_placeholders(
|
||||
let (a, b) = infcx.enter_forall_and_leak_universe(
|
||||
goal.predicate.kind().rebind((pred.a, pred.b)),
|
||||
);
|
||||
let expected_found = ExpectedFound::new(false, a, b);
|
||||
|
|
|
@ -1049,14 +1049,21 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
fn probe_and_evaluate_goal_for_constituent_tys(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, TraitPredicate<'tcx>>,
|
||||
constituent_tys: impl Fn(&EvalCtxt<'_, 'tcx>, Ty<'tcx>) -> Result<Vec<Ty<'tcx>>, NoSolution>,
|
||||
constituent_tys: impl Fn(
|
||||
&EvalCtxt<'_, 'tcx>,
|
||||
Ty<'tcx>,
|
||||
) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution>,
|
||||
) -> QueryResult<'tcx> {
|
||||
self.probe_misc_candidate("constituent tys").enter(|ecx| {
|
||||
ecx.add_goals(
|
||||
GoalSource::ImplWhereBound,
|
||||
constituent_tys(ecx, goal.predicate.self_ty())?
|
||||
.into_iter()
|
||||
.map(|ty| goal.with(ecx.tcx(), goal.predicate.with_self_ty(ecx.tcx(), ty)))
|
||||
.map(|ty| {
|
||||
ecx.enter_forall(ty, |ty| {
|
||||
goal.with(ecx.tcx(), goal.predicate.with_self_ty(ecx.tcx(), ty))
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
|
|
|
@ -971,7 +971,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
|
|||
|
||||
let Goal { param_env, predicate } = goal.goal();
|
||||
|
||||
// For bound predicates we simply call `infcx.instantiate_binder_with_placeholders`
|
||||
// For bound predicates we simply call `infcx.enter_forall`
|
||||
// and then prove the resulting predicate as a nested goal.
|
||||
let trait_ref = match predicate.kind().no_bound_vars() {
|
||||
Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref,
|
||||
|
|
|
@ -21,14 +21,18 @@ pub fn recompute_applicable_impls<'tcx>(
|
|||
|
||||
let impl_may_apply = |impl_def_id| {
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let placeholder_obligation =
|
||||
infcx.instantiate_binder_with_placeholders(obligation.predicate);
|
||||
let obligation_trait_ref =
|
||||
ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
|
||||
infcx.enter_forall(obligation.predicate, |placeholder_obligation| {
|
||||
let obligation_trait_ref = ocx.normalize(
|
||||
&ObligationCause::dummy(),
|
||||
param_env,
|
||||
placeholder_obligation.trait_ref,
|
||||
);
|
||||
|
||||
let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
|
||||
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args);
|
||||
let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
|
||||
let impl_trait_ref =
|
||||
tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args);
|
||||
let impl_trait_ref =
|
||||
ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
|
||||
|
||||
if let Err(_) =
|
||||
ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref)
|
||||
|
@ -42,14 +46,17 @@ pub fn recompute_applicable_impls<'tcx>(
|
|||
}));
|
||||
|
||||
ocx.select_where_possible().is_empty()
|
||||
})
|
||||
};
|
||||
|
||||
let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let placeholder_obligation =
|
||||
infcx.instantiate_binder_with_placeholders(obligation.predicate);
|
||||
let obligation_trait_ref =
|
||||
ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
|
||||
infcx.enter_forall(obligation.predicate, |placeholder_obligation| {
|
||||
let obligation_trait_ref = ocx.normalize(
|
||||
&ObligationCause::dummy(),
|
||||
param_env,
|
||||
placeholder_obligation.trait_ref,
|
||||
);
|
||||
|
||||
let param_env_predicate = infcx.instantiate_binder_with_fresh_vars(
|
||||
DUMMY_SP,
|
||||
|
@ -59,13 +66,17 @@ pub fn recompute_applicable_impls<'tcx>(
|
|||
let param_env_trait_ref =
|
||||
ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref);
|
||||
|
||||
if let Err(_) =
|
||||
ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, param_env_trait_ref)
|
||||
{
|
||||
if let Err(_) = ocx.eq(
|
||||
&ObligationCause::dummy(),
|
||||
param_env,
|
||||
obligation_trait_ref,
|
||||
param_env_trait_ref,
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ocx.select_where_possible().is_empty()
|
||||
})
|
||||
};
|
||||
|
||||
let mut ambiguities = Vec::new();
|
||||
|
|
|
@ -64,7 +64,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
) -> Option<(DefId, GenericArgsRef<'tcx>)> {
|
||||
let tcx = self.tcx;
|
||||
let param_env = obligation.param_env;
|
||||
let trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
|
||||
self.enter_forall(trait_ref, |trait_ref| {
|
||||
let trait_self_ty = trait_ref.self_ty();
|
||||
|
||||
let mut self_match_impls = vec![];
|
||||
|
@ -72,14 +72,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
|
||||
let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id);
|
||||
let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args);
|
||||
let impl_trait_ref =
|
||||
tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args);
|
||||
|
||||
let impl_self_ty = impl_trait_ref.self_ty();
|
||||
|
||||
if self.can_eq(param_env, trait_self_ty, impl_self_ty) {
|
||||
self_match_impls.push((def_id, impl_args));
|
||||
|
||||
if iter::zip(trait_ref.args.types().skip(1), impl_trait_ref.args.types().skip(1))
|
||||
if iter::zip(
|
||||
trait_ref.args.types().skip(1),
|
||||
impl_trait_ref.args.types().skip(1),
|
||||
)
|
||||
.all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some())
|
||||
{
|
||||
fuzzy_match_impls.push((def_id, impl_args));
|
||||
|
@ -97,6 +101,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
|
||||
tcx.has_attr(impl_def_id_and_args.0, sym::rustc_on_unimplemented)
|
||||
.then_some(impl_def_id_and_args)
|
||||
})
|
||||
}
|
||||
|
||||
/// Used to set on_unimplemented's `ItemContext`
|
||||
|
|
|
@ -1248,7 +1248,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) -> bool {
|
||||
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
|
||||
let ty = self.instantiate_binder_with_placeholders(self_ty);
|
||||
self.enter_forall(self_ty, |ty: Ty<'_>| {
|
||||
let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else {
|
||||
return false;
|
||||
};
|
||||
|
@ -1260,7 +1260,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
return false;
|
||||
};
|
||||
let arg_node = self.tcx.hir_node(*arg_hir_id);
|
||||
let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else { return false };
|
||||
let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None);
|
||||
let has_clone = |ty| {
|
||||
|
@ -1288,12 +1290,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
err.span_suggestion_verbose(
|
||||
obligation.cause.span.shrink_to_hi(),
|
||||
"consider using clone here",
|
||||
".clone()",
|
||||
".clone()".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
/// Extracts information about a callable type for diagnostics. This is a
|
||||
|
@ -4038,26 +4041,27 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
if let Some(where_pred) = where_pred.as_trait_clause()
|
||||
&& let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred()
|
||||
{
|
||||
let where_pred = self.instantiate_binder_with_placeholders(where_pred);
|
||||
self.enter_forall(where_pred, |where_pred| {
|
||||
let failed_pred = self.instantiate_binder_with_fresh_vars(
|
||||
expr.span,
|
||||
BoundRegionConversionTime::FnCall,
|
||||
failed_pred,
|
||||
);
|
||||
|
||||
let zipped = iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args);
|
||||
let zipped =
|
||||
iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args);
|
||||
for (expected, actual) in zipped {
|
||||
self.probe(|_| {
|
||||
match self.at(&ObligationCause::misc(expr.span, body_id), param_env).eq(
|
||||
DefineOpaqueTypes::No,
|
||||
expected,
|
||||
actual,
|
||||
) {
|
||||
match self
|
||||
.at(&ObligationCause::misc(expr.span, body_id), param_env)
|
||||
.eq(DefineOpaqueTypes::No, expected, actual)
|
||||
{
|
||||
Ok(_) => (), // We ignore nested obligations here for now.
|
||||
Err(err) => type_diffs.push(err),
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
} else if let Some(where_pred) = where_pred.as_projection_clause()
|
||||
&& let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred()
|
||||
&& let Some(found) = failed_pred.skip_binder().term.ty()
|
||||
|
@ -4614,7 +4618,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
{
|
||||
self.probe(|_| {
|
||||
let ocx = ObligationCtxt::new(self);
|
||||
let pred = self.instantiate_binder_with_placeholders(pred);
|
||||
self.enter_forall(pred, |pred| {
|
||||
let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred);
|
||||
ocx.register_obligation(Obligation::new(
|
||||
self.tcx,
|
||||
|
@ -4622,6 +4626,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
param_env,
|
||||
pred,
|
||||
));
|
||||
});
|
||||
if !ocx.select_where_possible().is_empty() {
|
||||
// encountered errors.
|
||||
return;
|
||||
|
@ -4768,13 +4773,13 @@ fn hint_missing_borrow<'tcx>(
|
|||
}
|
||||
|
||||
let found_args = match found.kind() {
|
||||
ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(),
|
||||
ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()),
|
||||
kind => {
|
||||
span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
|
||||
}
|
||||
};
|
||||
let expected_args = match expected.kind() {
|
||||
ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(),
|
||||
ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()),
|
||||
kind => {
|
||||
span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
|
||||
}
|
||||
|
|
|
@ -1305,12 +1305,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
let mut pred = obligation.predicate.to_opt_poly_trait_pred();
|
||||
while let Some((next_code, next_pred)) = code.parent() {
|
||||
if let Some(pred) = pred {
|
||||
let pred = self.instantiate_binder_with_placeholders(pred);
|
||||
self.enter_forall(pred, |pred| {
|
||||
diag.note(format!(
|
||||
"`{}` must implement `{}`, but it does not",
|
||||
pred.self_ty(),
|
||||
pred.print_modifiers_and_trait_path()
|
||||
));
|
||||
})
|
||||
}
|
||||
code = next_code;
|
||||
pred = next_pred;
|
||||
|
@ -2015,7 +2016,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
if let [single] = &impl_candidates {
|
||||
if self.probe(|_| {
|
||||
let ocx = ObligationCtxt::new(self);
|
||||
let obligation_trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
|
||||
|
||||
self.enter_forall(trait_ref, |obligation_trait_ref| {
|
||||
let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id);
|
||||
let impl_trait_ref = ocx.normalize(
|
||||
&ObligationCause::dummy(),
|
||||
|
@ -2029,7 +2031,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
.instantiate(self.tcx, impl_args)
|
||||
.into_iter()
|
||||
.map(|(clause, _)| {
|
||||
Obligation::new(self.tcx, ObligationCause::dummy(), param_env, clause)
|
||||
Obligation::new(
|
||||
self.tcx,
|
||||
ObligationCause::dummy(),
|
||||
param_env,
|
||||
clause,
|
||||
)
|
||||
}),
|
||||
);
|
||||
if !ocx.select_where_possible().is_empty() {
|
||||
|
@ -2055,13 +2062,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
return false;
|
||||
}
|
||||
|
||||
let cand =
|
||||
self.resolve_vars_if_possible(impl_trait_ref).fold_with(&mut BottomUpFolder {
|
||||
let cand = self.resolve_vars_if_possible(impl_trait_ref).fold_with(
|
||||
&mut BottomUpFolder {
|
||||
tcx: self.tcx,
|
||||
ty_op: |ty| ty,
|
||||
lt_op: |lt| lt,
|
||||
ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()),
|
||||
});
|
||||
},
|
||||
);
|
||||
err.highlighted_help(vec![
|
||||
StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())),
|
||||
StringPart::highlighted("is"),
|
||||
|
@ -2079,6 +2087,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
|
||||
true
|
||||
})
|
||||
}) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -358,8 +358,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
|||
| ty::PredicateKind::Coerce(_)
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
|
||||
| ty::PredicateKind::ConstEquate(..) => {
|
||||
let pred =
|
||||
ty::Binder::dummy(infcx.instantiate_binder_with_placeholders(binder));
|
||||
let pred = ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder));
|
||||
ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)]))
|
||||
}
|
||||
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
|
||||
|
|
|
@ -250,8 +250,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
|
|||
let infcx = selcx.infcx;
|
||||
let r = infcx.commit_if_ok(|_snapshot| {
|
||||
let old_universe = infcx.universe();
|
||||
let placeholder_predicate =
|
||||
infcx.instantiate_binder_with_placeholders(obligation.predicate);
|
||||
let placeholder_predicate = infcx.enter_forall_and_leak_universe(obligation.predicate);
|
||||
let new_universe = infcx.universe();
|
||||
|
||||
let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate);
|
||||
|
|
|
@ -728,9 +728,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
self.infcx.probe(|_snapshot| {
|
||||
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
|
||||
let placeholder_trait_predicate =
|
||||
self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate);
|
||||
|
||||
self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| {
|
||||
let self_ty = placeholder_trait_predicate.self_ty();
|
||||
let principal_trait_ref = match self_ty.kind() {
|
||||
ty::Dynamic(data, ..) => {
|
||||
|
@ -787,6 +785,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
candidates.vec.extend(candidate_supertraits);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Temporary migration for #89190
|
||||
|
|
|
@ -159,7 +159,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
|
||||
let placeholder_trait_predicate =
|
||||
self.infcx.instantiate_binder_with_placeholders(trait_predicate).trait_ref;
|
||||
self.infcx.enter_forall_and_leak_universe(trait_predicate).trait_ref;
|
||||
let placeholder_self_ty = placeholder_trait_predicate.self_ty();
|
||||
let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
|
||||
let (def_id, args) = match *placeholder_self_ty.kind() {
|
||||
|
@ -402,7 +402,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let cause = obligation.derived_cause(BuiltinDerivedObligation);
|
||||
|
||||
let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
|
||||
let trait_ref = self.infcx.instantiate_binder_with_placeholders(poly_trait_ref);
|
||||
let trait_ref = self.infcx.enter_forall_and_leak_universe(poly_trait_ref);
|
||||
let trait_obligations: Vec<PredicateObligation<'_>> = self.impl_or_trait_obligations(
|
||||
&cause,
|
||||
obligation.recursion_depth + 1,
|
||||
|
@ -493,7 +493,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let tcx = self.tcx();
|
||||
debug!(?obligation, ?index, "confirm_object_candidate");
|
||||
|
||||
let trait_predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
|
||||
let trait_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
|
||||
let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty());
|
||||
let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref);
|
||||
let ty::Dynamic(data, ..) = *self_ty.kind() else {
|
||||
|
@ -691,7 +691,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let cause = obligation.derived_cause(BuiltinDerivedObligation);
|
||||
|
||||
// Confirm the `type Output: Sized;` bound that is present on `FnOnce`
|
||||
let output_ty = self.infcx.instantiate_binder_with_placeholders(sig.output());
|
||||
let output_ty = self.infcx.enter_forall_and_leak_universe(sig.output());
|
||||
let output_ty = normalize_with_depth_to(
|
||||
self,
|
||||
obligation.param_env,
|
||||
|
@ -712,7 +712,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
) -> Vec<PredicateObligation<'tcx>> {
|
||||
debug!(?obligation, "confirm_trait_alias_candidate");
|
||||
|
||||
let predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
|
||||
let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
|
||||
let trait_ref = predicate.trait_ref;
|
||||
let trait_def_id = trait_ref.def_id;
|
||||
let args = trait_ref.args;
|
||||
|
|
|
@ -1606,7 +1606,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
) -> smallvec::SmallVec<[usize; 2]> {
|
||||
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
|
||||
let placeholder_trait_predicate =
|
||||
self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate);
|
||||
self.infcx.enter_forall_and_leak_universe(poly_trait_predicate);
|
||||
debug!(?placeholder_trait_predicate);
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
|
@ -2386,7 +2386,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
.flat_map(|ty| {
|
||||
let ty: ty::Binder<'tcx, Ty<'tcx>> = types.rebind(*ty); // <----/
|
||||
|
||||
let placeholder_ty = self.infcx.instantiate_binder_with_placeholders(ty);
|
||||
let placeholder_ty = self.infcx.enter_forall_and_leak_universe(ty);
|
||||
let Normalized { value: normalized_ty, mut obligations } =
|
||||
ensure_sufficient_stack(|| {
|
||||
project::normalize_with_depth(
|
||||
|
@ -2472,7 +2472,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
obligation: &PolyTraitObligation<'tcx>,
|
||||
) -> Result<Normalized<'tcx, GenericArgsRef<'tcx>>, ()> {
|
||||
let placeholder_obligation =
|
||||
self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
|
||||
self.infcx.enter_forall_and_leak_universe(obligation.predicate);
|
||||
let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;
|
||||
|
||||
let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
|
||||
|
|
|
@ -163,8 +163,7 @@ pub enum RegionKind<I: Interner> {
|
|||
/// A placeholder region -- the higher-ranked version of `ReLateParam`.
|
||||
/// Should not exist outside of type inference.
|
||||
///
|
||||
/// Used when instantiating a `forall` binder via
|
||||
/// `infcx.instantiate_binder_with_placeholders`.
|
||||
/// Used when instantiating a `forall` binder via `infcx.enter_forall`.
|
||||
RePlaceholder(I::PlaceholderRegion),
|
||||
|
||||
/// Erased region, used by trait selection, in MIR and during codegen.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue