summaryrefslogtreecommitdiffstats
path: root/tests/ui/coherence
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/coherence')
-rw-r--r--tests/ui/coherence/coherence-overlap-negative-impls.rs41
-rw-r--r--tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs25
2 files changed, 66 insertions, 0 deletions
diff --git a/tests/ui/coherence/coherence-overlap-negative-impls.rs b/tests/ui/coherence/coherence-overlap-negative-impls.rs
new file mode 100644
index 000000000..cd1df53a5
--- /dev/null
+++ b/tests/ui/coherence/coherence-overlap-negative-impls.rs
@@ -0,0 +1,41 @@
+// check-pass
+// known-bug: #74629
+
+// Should fail. The `0` and `1` impls overlap, violating coherence. Eg, with
+// `T = Test, F = ()`, all bounds are true, making both impls applicable.
+// `Test: Fold<Nil>`, `Test: Fold<()>` are true because of `2`.
+// `Is<Test>: NotNil` is true because of `auto trait` and lack of negative impl.
+
+#![feature(negative_impls)]
+#![feature(auto_traits)]
+
+struct Nil;
+struct Cons<H>(H);
+struct Test;
+
+trait Fold<F> {}
+
+impl<T, F> Fold<F> for Cons<T> // 0
+where
+ T: Fold<Nil>,
+{}
+
+impl<T, F> Fold<F> for Cons<T> // 1
+where
+ T: Fold<F>,
+ private::Is<T>: private::NotNil,
+{}
+
+impl<F> Fold<F> for Test {} // 2
+
+mod private {
+ use crate::Nil;
+
+ pub struct Is<T>(T);
+ pub auto trait NotNil {}
+
+ #[allow(suspicious_auto_trait_impls)]
+ impl !NotNil for Is<Nil> {}
+}
+
+fn main() {}
diff --git a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs
new file mode 100644
index 000000000..bb46498f9
--- /dev/null
+++ b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs
@@ -0,0 +1,25 @@
+// check-pass
+// known-bug: #57893
+
+// Should fail. Because we see an impl that uses a certain associated type, we
+// type-check assuming that impl is used. However, this conflicts with the
+// "implicit impl" that we get for trait objects, violating coherence.
+
+trait Object<U> {
+ type Output;
+}
+
+impl<T: ?Sized, U> Object<U> for T {
+ type Output = U;
+}
+
+fn foo<T: ?Sized, U>(x: <T as Object<U>>::Output) -> U {
+ x
+}
+
+#[allow(dead_code)]
+fn transmute<T, U>(x: T) -> U {
+ foo::<dyn Object<U, Output = T>, U>(x)
+}
+
+fn main() {}