diff options
Diffstat (limited to 'tests/ui/coherence')
-rw-r--r-- | tests/ui/coherence/coherence-overlap-negative-impls.rs | 41 | ||||
-rw-r--r-- | tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs | 25 |
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() {} |