70 lines
1.5 KiB
Rust
70 lines
1.5 KiB
Rust
// check-pass
|
|
|
|
// This test checks that we're correctly dealing with inductive cycles
|
|
// with canonical inference variables.
|
|
|
|
trait Trait<T, U> {}
|
|
|
|
trait IsNotU32 {}
|
|
impl IsNotU32 for i32 {}
|
|
impl<T: IsNotU32, U> Trait<T, U> for () // impl 1
|
|
where
|
|
(): Trait<U, T>
|
|
{}
|
|
|
|
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:
|
|
|
|
// (): 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>,
|
|
{
|
|
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() {
|
|
let (x, y) = implements_trait::<_, _>();
|
|
|
|
constrain::<i32, _>(x);
|
|
constrain::<u32, _>(y);
|
|
}
|