summaryrefslogtreecommitdiffstats
path: root/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs69
1 files changed, 69 insertions, 0 deletions
diff --git a/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs b/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs
new file mode 100644
index 000000000..5449f5f00
--- /dev/null
+++ b/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs
@@ -0,0 +1,69 @@
+// 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);
+}