diff options
Diffstat (limited to 'tests/ui/traits/new-solver/coherence')
-rw-r--r-- | tests/ui/traits/new-solver/coherence/issue-102048.rs | 44 | ||||
-rw-r--r-- | tests/ui/traits/new-solver/coherence/issue-102048.stderr | 12 |
2 files changed, 56 insertions, 0 deletions
diff --git a/tests/ui/traits/new-solver/coherence/issue-102048.rs b/tests/ui/traits/new-solver/coherence/issue-102048.rs new file mode 100644 index 000000000..11636bfeb --- /dev/null +++ b/tests/ui/traits/new-solver/coherence/issue-102048.rs @@ -0,0 +1,44 @@ +// This must fail coherence. +// +// Getting this to pass was fairly difficult, so here's an explanation +// of what's happening: +// +// Normalizing projections currently tries to replace them with inference variables +// while emitting a nested `Projection` obligation. This cannot be done if the projection +// has bound variables which is the case here. +// +// So the projections stay until after normalization. When unifying two projections we +// currently treat them as if they are injective, so we **incorrectly** unify their +// substs. This means that coherence for the two impls ends up unifying `?T` and `?U` +// as it tries to unify `<?T as WithAssoc1<'a>>::Assoc` with `<?U as WithAssoc1<'a>>::Assoc`. +// +// `impl1` therefore has the projection `<?T as WithAssoc2<'a>>::Assoc` and we have the +// assumption `?T: for<'a> WithAssoc2<'a, Assoc = i32>` in the `param_env`, so we normalize +// that to `i32`. We then try to unify `i32` from `impl1` with `u32` from `impl2` which fails, +// causing coherence to consider these two impls distinct. + +// compile-flags: -Ztrait-solver=next +pub trait Trait<T> {} + +pub trait WithAssoc1<'a> { + type Assoc; +} +pub trait WithAssoc2<'a> { + type Assoc; +} + +// impl 1 +impl<T, U> Trait<for<'a> fn(<T as WithAssoc1<'a>>::Assoc, <U as WithAssoc2<'a>>::Assoc)> for (T, U) +where + T: for<'a> WithAssoc1<'a> + for<'a> WithAssoc2<'a, Assoc = i32>, + U: for<'a> WithAssoc2<'a>, +{ +} + +// impl 2 +impl<T, U> Trait<for<'a> fn(<U as WithAssoc1<'a>>::Assoc, u32)> for (T, U) where + U: for<'a> WithAssoc1<'a> //~^ ERROR conflicting implementations of trait +{ +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/coherence/issue-102048.stderr b/tests/ui/traits/new-solver/coherence/issue-102048.stderr new file mode 100644 index 000000000..17a43838f --- /dev/null +++ b/tests/ui/traits/new-solver/coherence/issue-102048.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Trait<for<'a> fn(<_ as WithAssoc1<'a>>::Assoc, <_ as WithAssoc2<'a>>::Assoc)>` for type `(_, _)` + --> $DIR/issue-102048.rs:39:1 + | +LL | impl<T, U> Trait<for<'a> fn(<T as WithAssoc1<'a>>::Assoc, <U as WithAssoc2<'a>>::Assoc)> for (T, U) + | --------------------------------------------------------------------------------------------------- first implementation here +... +LL | impl<T, U> Trait<for<'a> fn(<U as WithAssoc1<'a>>::Assoc, u32)> for (T, U) where + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(_, _)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. |