diff options
Diffstat (limited to 'src/test/ui/associated-types/associated-types-conditional-dispatch.rs')
-rw-r--r-- | src/test/ui/associated-types/associated-types-conditional-dispatch.rs | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/test/ui/associated-types/associated-types-conditional-dispatch.rs b/src/test/ui/associated-types/associated-types-conditional-dispatch.rs new file mode 100644 index 000000000..70ee60517 --- /dev/null +++ b/src/test/ui/associated-types/associated-types-conditional-dispatch.rs @@ -0,0 +1,66 @@ +// run-pass +// Test that we evaluate projection predicates to winnow out +// candidates during trait selection and method resolution (#20296). +// If we don't properly winnow out candidates based on the output type +// `Target=[A]`, then the impl marked with `(*)` is seen to conflict +// with all the others. + +// pretty-expanded FIXME #23616 + +use std::marker::PhantomData; +use std::ops::Deref; + +pub trait MyEq<U: ?Sized=Self> { + fn eq(&self, u: &U) -> bool; +} + +impl<A, B> MyEq<[B]> for [A] + where A : MyEq<B> +{ + fn eq(&self, other: &[B]) -> bool { + self.len() == other.len() && + self.iter().zip(other).all(|(a, b)| MyEq::eq(a, b)) + } +} + +// (*) This impl conflicts with everything unless the `Target=[A]` +// constraint is considered. +impl<'a, A, B, Lhs> MyEq<[B; 0]> for Lhs + where A: MyEq<B>, Lhs: Deref<Target=[A]> +{ + fn eq(&self, other: &[B; 0]) -> bool { + MyEq::eq(&**self, other) + } +} + +struct DerefWithHelper<H, T> { + pub helper: H, + pub marker: PhantomData<T>, +} + +trait Helper<T> { + fn helper_borrow(&self) -> &T; +} + +impl<T> Helper<T> for Option<T> { + fn helper_borrow(&self) -> &T { + self.as_ref().unwrap() + } +} + +impl<T, H: Helper<T>> Deref for DerefWithHelper<H, T> { + type Target = T; + + fn deref(&self) -> &T { + self.helper.helper_borrow() + } +} + +pub fn check<T: MyEq>(x: T, y: T) -> bool { + let d: DerefWithHelper<Option<T>, T> = DerefWithHelper { helper: Some(x), + marker: PhantomData }; + d.eq(&y) +} + +pub fn main() { +} |