Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion compiler/rustc_infer/src/infer/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,14 +209,28 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
)
}

fn enter_forall<T: TypeFoldable<TyCtxt<'tcx>>, U>(
fn enter_forall_without_assumptions<T: TypeFoldable<TyCtxt<'tcx>>, U>(
&self,
value: ty::Binder<'tcx, T>,
f: impl FnOnce(T) -> U,
) -> U {
self.enter_forall(value, f)
}

fn enter_forall_with_empty_assumptions<T: TypeFoldable<TyCtxt<'tcx>>, U>(
&self,
value: ty::Binder<'tcx, T>,
f: impl FnOnce(T) -> U,
) -> U {
self.enter_forall(value, |value| {
let u = self.universe();
self.placeholder_assumptions_for_next_solver
.borrow_mut()
.insert(u, Some(rustc_type_ir::region_constraint::Assumptions::empty()));
f(value)
})
}

fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
self.inner.borrow_mut().type_variables().equate(a, b);
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1331,8 +1331,8 @@ where
self.delegate.instantiate_binder_with_infer(value)
}

/// `enter_forall`, but takes `&mut self` and passes it back through the
/// callback since it can't be aliased during the call.
/// `enter_forall_with_assumptions`, but takes `&mut self` and passes it back through
/// the callback since it can't be aliased during the call.
///
/// The `param_env` is used to *compute* the assumptions of the binder, not *as* the
/// assumptions associated with the binder.
Expand All @@ -1344,7 +1344,7 @@ where
param_env: I::ParamEnv,
f: impl FnOnce(&mut Self, T) -> U,
) -> U {
self.delegate.enter_forall(value, |value| {
self.delegate.enter_forall_without_assumptions(value, |value| {
let u = self.delegate.universe();
let assumptions = if self.cx().assumptions_on_binders() {
self.region_assumptions_for_placeholders_in_universe(value.clone(), u, param_env)
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_type_ir/src/infer_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,16 @@ pub trait InferCtxtLike: Sized {
value: ty::Binder<Self::Interner, T>,
) -> T;

fn enter_forall<T: TypeFoldable<Self::Interner>, U>(
fn enter_forall_without_assumptions<T: TypeFoldable<Self::Interner>, U>(
&self,
value: ty::Binder<Self::Interner, T>,
f: impl FnOnce(T) -> U,
) -> U;

/// FIXME(-Zassumptions-on-binders): Any usage of this method is likely wrong
/// and should be replaced in the long term by actually taking assumptions into
/// account.
fn enter_forall_with_empty_assumptions<T: TypeFoldable<Self::Interner>, U>(
&self,
value: ty::Binder<Self::Interner, T>,
f: impl FnOnce(T) -> U,
Expand Down
10 changes: 3 additions & 7 deletions compiler/rustc_type_ir/src/region_constraint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1096,11 +1096,7 @@ fn alias_outlives_candidates_from_assumptions<Infcx: InferCtxtLike<Interner = I>

let prev_universe = infcx.universe();

// FIXME(-Zassumptions-on-binders): Handle the assumptions on this binder
infcx.enter_forall(bound_outlives, |(alias, r)| {
let u = infcx.universe();
infcx.insert_placeholder_assumptions(u, Some(Assumptions::empty()));

infcx.enter_forall_with_empty_assumptions(bound_outlives, |(alias, r)| {
for bound_type_outlives in assumptions.type_outlives.iter() {
let OutlivesPredicate(alias2, r2) =
infcx.instantiate_binder_with_infer(*bound_type_outlives);
Expand Down Expand Up @@ -1187,14 +1183,14 @@ impl<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeRelation<I>
where
T: Relate<I>,
{
self.infcx.enter_forall(a, |a| {
self.infcx.enter_forall_with_empty_assumptions(a, |a| {
let u = self.infcx.universe();
self.infcx.insert_placeholder_assumptions(u, Some(Assumptions::empty()));
let b = self.infcx.instantiate_binder_with_infer(b);
self.relate(a, b)
})?;

self.infcx.enter_forall(b, |b| {
self.infcx.enter_forall_with_empty_assumptions(b, |b| {
let u = self.infcx.universe();
self.infcx.insert_placeholder_assumptions(u, Some(Assumptions::empty()));
let a = self.infcx.instantiate_binder_with_infer(a);
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_type_ir/src/relate/solver_relating.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,13 +311,13 @@ where
//
// [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html
ty::Covariant => {
self.infcx.enter_forall(b, |b| {
self.infcx.enter_forall_with_empty_assumptions(b, |b| {
let a = self.infcx.instantiate_binder_with_infer(a);
self.relate(a, b)
})?;
}
ty::Contravariant => {
self.infcx.enter_forall(a, |a| {
self.infcx.enter_forall_with_empty_assumptions(a, |a| {
let b = self.infcx.instantiate_binder_with_infer(b);
self.relate(a, b)
})?;
Expand All @@ -334,13 +334,13 @@ where
// `exists<..> A == for<..> B` and `exists<..> B == for<..> A`.
// Check if `exists<..> A == for<..> B`
ty::Invariant => {
self.infcx.enter_forall(b, |b| {
self.infcx.enter_forall_with_empty_assumptions(b, |b| {
let a = self.infcx.instantiate_binder_with_infer(a);
self.relate(a, b)
})?;

// Check if `exists<..> B == for<..> A`.
self.infcx.enter_forall(a, |a| {
self.infcx.enter_forall_with_empty_assumptions(a, |a| {
let b = self.infcx.instantiate_binder_with_infer(b);
self.relate(a, b)
})?;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//@ check-pass
//@ compile-flags: -Znext-solver -Zassumptions-on-binders

#![crate_type = "lib"]

// When entering binders if we don't insert assumptions corresponding to the
// binder then we'll ICE when later trying to eagerly handle placeholders. This
// test checks that type relations involving higher ranked types insert assumptions
// for the binders of the higher ranked types.
//
// This is specifically checking that type relations used from *inside* the trait
// solver do this. In this case the type relation occurs as part of an `AliasRelate`
// involving the rigid alias: `<T as Trait>::Assoc<for<'b> fn('b ()) -> &'?0 ()>`.

trait Trait { type Assoc<T>; }

fn foo<T: Trait, U>(_: U) -> <T as Trait>::Assoc::<U> { loop {} }

fn mk<'a>() -> for<'b> fn(&'b ()) -> &'a () { loop {} }

fn bar<T: Trait>() {
foo::<T, _>(mk());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ check-pass
//@ compile-flags: -Znext-solver -Zassumptions-on-binders

#![crate_type = "lib"]

// Slight derivative of `type_relation_binders_inside_solver-1.rs` except this time the
// rigid alias is the opaque type `(impl Sized)<for<'b> fn(&'b ()) -> &'?0 ()>` instead.

fn foo<T>(_: T) -> impl Sized + use<T> {}

fn mk<'a>() -> for<'b> fn(&'b ()) -> &'a () { loop {} }

fn bar() {
foo(mk());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//@ check-pass
//@ compile-flags: -Znext-solver -Zassumptions-on-binders

#![crate_type = "lib"]

// Same concept as `type_relation_binders_inside_solver-1.rs`, this time the type relation
// occuring when checking `for<'b> fn(&'b ()): Trait` holds and we have to equate the two
// higher ranked function pointer types.

trait Trait { }

fn req_trait<T: Trait>(_: T) { }

fn mk() -> for<'b> fn(&'b ()) { loop {} }

fn ice()
where
(for<'b> fn(&'b ())): Trait
{
req_trait(mk());
}
Loading