]> git.lizzy.rs Git - rust.git/blob - tests/ui/methods/method-lookup-order.rs
Merge commit '7f27e2e74ef957baa382dc05cf08df6368165c74' into clippyup
[rust.git] / tests / ui / methods / method-lookup-order.rs
1 // ignore-tidy-linelength
2
3 // run-pass
4
5 // There are five cfg's below. I explored the set of all non-empty combinations
6 // of the below five cfg's, which is 2^5 - 1 = 31 combinations.
7 //
8 // Of the 31, 11 resulted in ambiguous method resolutions; while it may be good
9 // to have a test for all of the eleven variations of that error, I am not sure
10 // this particular test is the best way to encode it. So they are skipped in
11 // this revisions list (but not in the expansion mapping the binary encoding to
12 // the corresponding cfg flags).
13 //
14 // Notable, here are the cases that will be incompatible if something does not override them first:
15 // {bar_for_foo, valbar_for_et_foo}: these are higher precedent than the `&mut self` method on `Foo`, and so no case matching bx1x1x is included.
16 // {mutbar_for_foo, valbar_for_etmut_foo} (which are lower precedent than the inherent `&mut self` method on `Foo`; e.g. b10101 *is* included.
17
18 // revisions: b00001 b00010 b00011 b00100 b00101 b00110 b00111 b01000 b01001 b01100 b01101 b10000 b10001 b10010 b10011 b10101 b10111 b11000 b11001 b11101
19
20 //[b00001]compile-flags:  --cfg inherent_mut
21 //[b00010]compile-flags:                     --cfg bar_for_foo
22 //[b00011]compile-flags:  --cfg inherent_mut --cfg bar_for_foo
23 //[b00100]compile-flags:                                       --cfg mutbar_for_foo
24 //[b00101]compile-flags:  --cfg inherent_mut                   --cfg mutbar_for_foo
25 //[b00110]compile-flags:                     --cfg bar_for_foo --cfg mutbar_for_foo
26 //[b00111]compile-flags:  --cfg inherent_mut --cfg bar_for_foo --cfg mutbar_for_foo
27 //[b01000]compile-flags:                                                            --cfg valbar_for_et_foo
28 //[b01001]compile-flags:  --cfg inherent_mut                                        --cfg valbar_for_et_foo
29 //[b01010]compile-flags:                     --cfg bar_for_foo                      --cfg valbar_for_et_foo
30 //[b01011]compile-flags:  --cfg inherent_mut --cfg bar_for_foo                      --cfg valbar_for_et_foo
31 //[b01100]compile-flags:                                       --cfg mutbar_for_foo --cfg valbar_for_et_foo
32 //[b01101]compile-flags:  --cfg inherent_mut                   --cfg mutbar_for_foo --cfg valbar_for_et_foo
33 //[b01110]compile-flags:                     --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_et_foo
34 //[b01111]compile-flags:  --cfg inherent_mut --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_et_foo
35 //[b10000]compile-flags:                                                                                    --cfg valbar_for_etmut_foo
36 //[b10001]compile-flags:  --cfg inherent_mut                                                                --cfg valbar_for_etmut_foo
37 //[b10010]compile-flags:                     --cfg bar_for_foo                                              --cfg valbar_for_etmut_foo
38 //[b10011]compile-flags:  --cfg inherent_mut --cfg bar_for_foo                                              --cfg valbar_for_etmut_foo
39 //[b10100]compile-flags:                                       --cfg mutbar_for_foo                         --cfg valbar_for_etmut_foo
40 //[b10101]compile-flags:  --cfg inherent_mut                   --cfg mutbar_for_foo                         --cfg valbar_for_etmut_foo
41 //[b10110]compile-flags:                     --cfg bar_for_foo --cfg mutbar_for_foo                         --cfg valbar_for_etmut_foo
42 //[b10111]compile-flags:  --cfg inherent_mut --cfg bar_for_foo --cfg mutbar_for_foo                         --cfg valbar_for_etmut_foo
43 //[b11000]compile-flags:                                                            --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
44 //[b11001]compile-flags:  --cfg inherent_mut                                        --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
45 //[b11010]compile-flags:                     --cfg bar_for_foo                      --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
46 //[b11011]compile-flags:  --cfg inherent_mut --cfg bar_for_foo                      --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
47 //[b11100]compile-flags:                                       --cfg mutbar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
48 //[b11101]compile-flags:  --cfg inherent_mut                   --cfg mutbar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
49 //[b11110]compile-flags:                     --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
50 //[b11111]compile-flags:  --cfg inherent_mut --cfg bar_for_foo --cfg mutbar_for_foo --cfg valbar_for_et_foo --cfg valbar_for_etmut_foo
51
52 struct Foo {}
53
54 type S = &'static str;
55
56 trait Bar {
57     fn bar(&self, _: &str) -> S;
58 }
59
60 trait MutBar {
61     fn bar(&mut self, _: &str) -> S;
62 }
63
64 trait ValBar {
65     fn bar(self, _: &str) -> S;
66 }
67
68 #[cfg(inherent_mut)]
69 impl Foo {
70     fn bar(&mut self, _: &str) -> S {
71         "In struct impl!"
72     }
73 }
74
75 #[cfg(bar_for_foo)]
76 impl Bar for Foo {
77     fn bar(&self, _: &str) -> S {
78         "In trait &self impl!"
79     }
80 }
81
82 #[cfg(mutbar_for_foo)]
83 impl MutBar for Foo {
84     fn bar(&mut self, _: &str) -> S {
85         "In trait &mut self impl!"
86     }
87 }
88
89 #[cfg(valbar_for_et_foo)]
90 impl ValBar for &Foo {
91     fn bar(self, _: &str) -> S {
92         "In trait self impl for &Foo!"
93     }
94 }
95
96 #[cfg(valbar_for_etmut_foo)]
97 impl ValBar for &mut Foo {
98     fn bar(self, _: &str) -> S {
99         "In trait self impl for &mut Foo!"
100     }
101 }
102
103 fn main() {
104     #![allow(unused_mut)] // some of the impls above will want it.
105
106     #![allow(unreachable_patterns)] // the cfg-coding pattern below generates unreachable patterns.
107
108     {
109         macro_rules! all_variants_on_value {
110             ($e:expr) => {
111                 match $e {
112                     #[cfg(bar_for_foo)]
113                     x => assert_eq!(x, "In trait &self impl!"),
114
115                     #[cfg(valbar_for_et_foo)]
116                     x => assert_eq!(x, "In trait self impl for &Foo!"),
117
118                     #[cfg(inherent_mut)]
119                     x => assert_eq!(x, "In struct impl!"),
120
121                     #[cfg(mutbar_for_foo)]
122                     x => assert_eq!(x, "In trait &mut self impl!"),
123
124                     #[cfg(valbar_for_etmut_foo)]
125                     x => assert_eq!(x, "In trait self impl for &mut Foo!"),
126                 }
127             }
128         }
129
130         let mut f = Foo {};
131         all_variants_on_value!(f.bar("f.bar"));
132
133         let f_mr = &mut Foo {};
134         all_variants_on_value!((*f_mr).bar("(*f_mr).bar"));
135     }
136
137     // This is sort of interesting: `&mut Foo` ends up with a significantly
138     // different resolution order than what was devised above. Presumably this
139     // is because we can get to a `&self` method by first a deref of the given
140     // `&mut Foo` and then an autoref, and that is a longer path than a mere
141     // auto-ref of a `Foo`.
142
143     {
144         let f_mr = &mut Foo {};
145
146         match f_mr.bar("f_mr.bar") {
147             #[cfg(inherent_mut)]
148             x => assert_eq!(x, "In struct impl!"),
149
150             #[cfg(valbar_for_etmut_foo)]
151             x => assert_eq!(x, "In trait self impl for &mut Foo!"),
152
153             #[cfg(mutbar_for_foo)]
154             x => assert_eq!(x, "In trait &mut self impl!"),
155
156             #[cfg(valbar_for_et_foo)]
157             x => assert_eq!(x, "In trait self impl for &Foo!"),
158
159             #[cfg(bar_for_foo)]
160             x => assert_eq!(x, "In trait &self impl!"),
161         }
162     }
163
164
165     // Note that this isn't actually testing a resolution order; if both of these are
166     // enabled, it yields an ambiguous method resolution error. The test tries to embed
167     // that fact by testing *both* orders (and so the only way that can be right is if
168     // they are not actually compatible).
169     #[cfg(any(bar_for_foo, valbar_for_et_foo))]
170     {
171         let f_r = &Foo {};
172
173         match f_r.bar("f_r.bar") {
174             #[cfg(bar_for_foo)]
175             x => assert_eq!(x, "In trait &self impl!"),
176
177             #[cfg(valbar_for_et_foo)]
178             x => assert_eq!(x, "In trait self impl for &Foo!"),
179         }
180
181         match f_r.bar("f_r.bar") {
182             #[cfg(valbar_for_et_foo)]
183             x => assert_eq!(x, "In trait self impl for &Foo!"),
184
185             #[cfg(bar_for_foo)]
186             x => assert_eq!(x, "In trait &self impl!"),
187         }
188     }
189
190 }