Skip to content

Commit d78f0a1

Browse files
committed
Test exploring the interactions between all of the different kinds of method collisions I could imagine.
The different impls are all guarded by cfg-flags, and the revisions could be used to cover the full power-set of combinations. (I only included 20 of the possible 32 cases here; the null-set is not interesting, and the remaining 11 all yielded ambiguous method resolution errors which did not mix well with this testing strategy; I'm not trying to check UI for the resolution diagnostics; I'm trying to create checkpoint of current resolution semantics when compilation succeeds.)
1 parent 78e57d3 commit d78f0a1

File tree

1 file changed

+190
-0
lines changed

1 file changed

+190
-0
lines changed
+190
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
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+
}

0 commit comments

Comments
 (0)