1 // run-pass
2 // Test that we evaluate projection predicates to winnow out
3 // candidates during trait selection and method resolution (#20296).
4 // If we don't properly winnow out candidates based on the output type
5 // `Target=[A]`, then the impl marked with `(*)` is seen to conflict
6 // with all the others.
7 
8 // pretty-expanded FIXME #23616
9 
10 use std::marker::PhantomData;
11 use std::ops::Deref;
12 
13 pub trait MyEq<U: ?Sized=Self> {
eq(&self, u: &U) -> bool14     fn eq(&self, u: &U) -> bool;
15 }
16 
17 impl<A, B> MyEq<[B]> for [A]
18     where A : MyEq<B>
19 {
eq(&self, other: &[B]) -> bool20     fn eq(&self, other: &[B]) -> bool {
21         self.len() == other.len() &&
22             self.iter().zip(other).all(|(a, b)| MyEq::eq(a, b))
23     }
24 }
25 
26 // (*) This impl conflicts with everything unless the `Target=[A]`
27 // constraint is considered.
28 impl<'a, A, B, Lhs> MyEq<[B; 0]> for Lhs
29     where A: MyEq<B>, Lhs: Deref<Target=[A]>
30 {
eq(&self, other: &[B; 0]) -> bool31     fn eq(&self, other: &[B; 0]) -> bool {
32         MyEq::eq(&**self, other)
33     }
34 }
35 
36 struct DerefWithHelper<H, T> {
37     pub helper: H,
38     pub marker: PhantomData<T>,
39 }
40 
41 trait Helper<T> {
helper_borrow(&self) -> &T42     fn helper_borrow(&self) -> &T;
43 }
44 
45 impl<T> Helper<T> for Option<T> {
helper_borrow(&self) -> &T46     fn helper_borrow(&self) -> &T {
47         self.as_ref().unwrap()
48     }
49 }
50 
51 impl<T, H: Helper<T>> Deref for DerefWithHelper<H, T> {
52     type Target = T;
53 
deref(&self) -> &T54     fn deref(&self) -> &T {
55         self.helper.helper_borrow()
56     }
57 }
58 
check<T: MyEq>(x: T, y: T) -> bool59 pub fn check<T: MyEq>(x: T, y: T) -> bool {
60     let d: DerefWithHelper<Option<T>, T> = DerefWithHelper { helper: Some(x),
61                                                              marker: PhantomData };
62     d.eq(&y)
63 }
64 
main()65 pub fn main() {
66 }
67