summaryrefslogtreecommitdiffstats
path: root/tests/ui/methods/method-probe-no-guessing-dyn-trait.rs
blob: ec41b7117097077234baf94bfea5b108a375eeae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// run-pass
// Check that method matching does not make "guesses" depending on
// Deref impls that don't eventually end up being picked.

use std::ops::Deref;

// An impl with less derefs will get called over an impl with more derefs,
// so `(t: Foo<_>).my_fn()` will use `<Foo<u32> as MyTrait1>::my_fn(t)`,
// and does *not* force the `_` to equal `()`, because the Deref impl
// was *not* used.

trait MyTrait1 {
    fn my_fn(&self) {}
}

impl MyTrait1 for Foo<u32> {}

struct Foo<T>(#[allow(unused_tuple_struct_fields)] T);

impl Deref for Foo<()> {
    type Target = dyn MyTrait1 + 'static;
    fn deref(&self) -> &(dyn MyTrait1 + 'static) {
        panic!()
    }
}

// ...but if there is no impl with less derefs, the "guess" will be
// forced, so `(t: Bar<_>).my_fn2()` is `<dyn MyTrait2 as MyTrait2>::my_fn2(*t)`,
// and because the deref impl is used, the `_` is forced to equal `u8`.

trait MyTrait2 {
    fn my_fn2(&self) {}
}

impl MyTrait2 for u32 {}
struct Bar<T>(#[allow(unused_tuple_struct_fields)] T, u32);
impl Deref for Bar<u8> {
    type Target = dyn MyTrait2 + 'static;
    fn deref(&self) -> &(dyn MyTrait2 + 'static) {
        &self.1
    }
}

// actually invoke things

fn main() {
    let mut foo: Option<Foo<_>> = None;
    let mut bar: Option<Bar<_>> = None;
    let mut first_iter = true;
    loop {
        if !first_iter {
            foo.as_ref().unwrap().my_fn();
            bar.as_ref().unwrap().my_fn2();
            break;
        }
        foo = Some(Foo(0));
        bar = Some(Bar(Default::default(), 0));
        first_iter = false;
    }
}