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