]>
Commit | Line | Data |
---|---|---|
416331ca | 1 | // run-pass |
0731742a XL |
2 | // Check that method matching does not make "guesses" depending on |
3 | // Deref impls that don't eventually end up being picked. | |
4 | ||
5 | use std::ops::Deref; | |
6 | ||
7 | // An impl with less derefs will get called over an impl with more derefs, | |
8 | // so `(t: Foo<_>).my_fn()` will use `<Foo<u32> as MyTrait1>::my_fn(t)`, | |
9 | // and does *not* force the `_` to equal `()`, because the Deref impl | |
10 | // was *not* used. | |
11 | ||
12 | trait MyTrait1 { | |
13 | fn my_fn(&self) {} | |
14 | } | |
15 | ||
16 | impl MyTrait1 for Foo<u32> {} | |
17 | ||
064997fb | 18 | struct Foo<T>(#[allow(unused_tuple_struct_fields)] T); |
0731742a XL |
19 | |
20 | impl Deref for Foo<()> { | |
21 | type Target = dyn MyTrait1 + 'static; | |
22 | fn deref(&self) -> &(dyn MyTrait1 + 'static) { | |
23 | panic!() | |
24 | } | |
25 | } | |
26 | ||
27 | // ...but if there is no impl with less derefs, the "guess" will be | |
28 | // forced, so `(t: Bar<_>).my_fn2()` is `<dyn MyTrait2 as MyTrait2>::my_fn2(*t)`, | |
29 | // and because the deref impl is used, the `_` is forced to equal `u8`. | |
30 | ||
31 | trait MyTrait2 { | |
32 | fn my_fn2(&self) {} | |
33 | } | |
34 | ||
35 | impl MyTrait2 for u32 {} | |
064997fb | 36 | struct Bar<T>(#[allow(unused_tuple_struct_fields)] T, u32); |
0731742a XL |
37 | impl Deref for Bar<u8> { |
38 | type Target = dyn MyTrait2 + 'static; | |
39 | fn deref(&self) -> &(dyn MyTrait2 + 'static) { | |
40 | &self.1 | |
41 | } | |
42 | } | |
43 | ||
44 | // actually invoke things | |
45 | ||
46 | fn main() { | |
47 | let mut foo: Option<Foo<_>> = None; | |
48 | let mut bar: Option<Bar<_>> = None; | |
49 | let mut first_iter = true; | |
50 | loop { | |
51 | if !first_iter { | |
52 | foo.as_ref().unwrap().my_fn(); | |
53 | bar.as_ref().unwrap().my_fn2(); | |
54 | break; | |
55 | } | |
56 | foo = Some(Foo(0)); | |
57 | bar = Some(Bar(Default::default(), 0)); | |
58 | first_iter = false; | |
59 | } | |
60 | } |