summaryrefslogtreecommitdiffstats
path: root/tests/ui/traits/solver-cycles
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
commit218caa410aa38c29984be31a5229b9fa717560ee (patch)
treec54bd55eeb6e4c508940a30e94c0032fbd45d677 /tests/ui/traits/solver-cycles
parentReleasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz
rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/traits/solver-cycles')
-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);
+}