Skip to content

Commit

Permalink
Rollup merge of rust-lang#106640 - lcnr:update-test, r=jackh726
Browse files Browse the repository at this point in the history
update test for inductive canonical cycles

the previous test always resulted in a cycle 😅 cc rust-lang/chalk#787.

I checked with rust-lang#102713 and this is the only test which fails with that PR.

r? ``@jackh726``
  • Loading branch information
Yuki Okushi authored Jan 9, 2023
2 parents 0ba27de + 31099ee commit 9bed3d9
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 43 deletions.
75 changes: 58 additions & 17 deletions src/test/ui/traits/solver-cycles/inductive-canonical-cycle.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,69 @@
// known-bug
// check-pass

// This test checks that we're correctly dealing with inductive cycles
// with canonical inference variables.

// This should compile but fails with the current solver.
//
// This checks that the new solver uses `Ambiguous` when hitting the
// inductive cycle here when proving `exists<^0, ^1> (): Trait<^0, ^1>`
// which requires proving `Trait<?1, ?0>` but that has the same
// canonical representation.
trait Trait<T, U> {}

impl<T, U> Trait<T, U> for ()
trait IsNotU32 {}
impl IsNotU32 for i32 {}
impl<T: IsNotU32, U> Trait<T, U> for () // impl 1
where
(): Trait<U, T>,
T: OtherTrait,
(): Trait<U, T>
{}

trait OtherTrait {}
impl OtherTrait for u32 {}
impl<T> Trait<u32, T> for () {} // impl 2

// If we now check whether `(): Trait<?0, ?1>` holds this has to
// result in ambiguity as both `for<T> (): Trait<u32, T>` and `(): Trait<i32, u32>`
// applies. The remainder of this test asserts that.

// If we were to error on inductive cycles with canonical inference variables
// this would be wrong:

fn require_trait<T, U>()
// (): Trait<?0, ?1>
// - impl 1
// - ?0: IsNotU32 // ambig
// - (): Trait<?1, ?0> // canonical cycle -> err
// - ERR
// - impl 2
// - OK ?0 == u32
//
// Result: OK ?0 == u32.

// (): Trait<i32, u32>
// - impl 1
// - i32: IsNotU32 // ok
// - (): Trait<u32, i32>
// - impl 1
// - u32: IsNotU32 // err
// - ERR
// - impl 2
// - OK
// - OK
// - impl 2 (trivial ERR)
//
// Result OK

// This would mean that `(): Trait<?0, ?1>` is not complete,
// which is unsound if we're in coherence.

fn implements_trait<T, U>() -> (T, U)
where
(): Trait<T, U>
{}
(): Trait<T, U>,
{
todo!()
}

// A hack to only constrain the infer vars after first checking
// the `(): Trait<_, _>`.
trait Constrain<T> {}
impl<T> Constrain<T> for T {}
fn constrain<T: Constrain<U>, U>(_: U) {}

fn main() {
require_trait::<_, _>();
//~^ ERROR overflow evaluating
let (x, y) = implements_trait::<_, _>();

constrain::<i32, _>(x);
constrain::<u32, _>(y);
}
26 changes: 0 additions & 26 deletions src/test/ui/traits/solver-cycles/inductive-canonical-cycle.stderr

This file was deleted.

0 comments on commit 9bed3d9

Please sign in to comment.