]> git.lizzy.rs Git - rust.git/blob - src/test/ui/methods/method-probe-no-guessing-dyn-trait.rs
Override rustc version in ui and mir-opt tests to get stable hashes
[rust.git] / src / test / ui / methods / method-probe-no-guessing-dyn-trait.rs
1 // run-pass
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
18 struct Foo<T>(T);
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 {}
36 struct Bar<T>(T, u32);
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 }