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