about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-02-03 15:12:19 +0000
committerbors <bors@rust-lang.org>2021-02-03 15:12:19 +0000
commit186f7ae5b04d31d8ccd1746ac63cdf1ab4bc2354 (patch)
treea8c3d451b31ddc271ae52cbf2426e31e424bc840
parent6ad11e2e25919b75ebbc36d7910f2a1126a7e873 (diff)
parent1783c476fac1bfe475157be3817e051811e90897 (diff)
downloadrust-186f7ae5b04d31d8ccd1746ac63cdf1ab4bc2354.tar.gz
rust-186f7ae5b04d31d8ccd1746ac63cdf1ab4bc2354.zip
Auto merge of #81294 - pnkfelix:issue-81211-use-ufcs-in-derive-debug, r=oli-obk
Use ufcs in derive(Debug)

Cc #81211.

(Arguably this *is* the fix for it.)
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/debug.rs38
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#7}-fmt.-------.InstrumentCoverage.0.html56
-rw-r--r--src/test/ui/derives/derive-Debug-use-ufcs-struct.rs40
-rw-r--r--src/test/ui/derives/derive-Debug-use-ufcs-tuple.rs32
-rw-r--r--src/test/ui/methods/method-lookup-order.rs190
6 files changed, 315 insertions, 43 deletions
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index 5c21329069b..ba43be6ae9a 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -8,6 +8,10 @@ use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, DUMMY_SP};
 
+fn make_mut_borrow(cx: &mut ExtCtxt<'_>, sp: Span, expr: P<Expr>) -> P<Expr> {
+    cx.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Mut, expr))
+}
+
 pub fn expand_deriving_debug(
     cx: &mut ExtCtxt<'_>,
     span: Span,
@@ -67,11 +71,12 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
     let fmt = substr.nonself_args[0].clone();
 
     let mut stmts = Vec::with_capacity(fields.len() + 2);
+    let fn_path_finish;
     match vdata {
         ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
             // tuple struct/"normal" variant
-            let expr =
-                cx.expr_method_call(span, fmt, Ident::new(sym::debug_tuple, span), vec![name]);
+            let fn_path_debug_tuple = cx.std_path(&[sym::fmt, sym::Formatter, sym::debug_tuple]);
+            let expr = cx.expr_call_global(span, fn_path_debug_tuple, vec![fmt, name]);
             stmts.push(cx.stmt_let(span, true, builder, expr));
 
             for field in fields {
@@ -79,22 +84,21 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
                 let field = cx.expr_addr_of(field.span, field.self_.clone());
                 let field = cx.expr_addr_of(field.span, field);
 
-                let expr = cx.expr_method_call(
-                    span,
-                    builder_expr.clone(),
-                    Ident::new(sym::field, span),
-                    vec![field],
-                );
+                let fn_path_field = cx.std_path(&[sym::fmt, sym::DebugTuple, sym::field]);
+                let builder_recv = make_mut_borrow(cx, span, builder_expr.clone());
+                let expr = cx.expr_call_global(span, fn_path_field, vec![builder_recv, field]);
 
                 // Use `let _ = expr;` to avoid triggering the
                 // unused_results lint.
                 stmts.push(stmt_let_underscore(cx, span, expr));
             }
+
+            fn_path_finish = cx.std_path(&[sym::fmt, sym::DebugTuple, sym::finish]);
         }
         ast::VariantData::Struct(..) => {
             // normal struct/struct variant
-            let expr =
-                cx.expr_method_call(span, fmt, Ident::new(sym::debug_struct, span), vec![name]);
+            let fn_path_debug_struct = cx.std_path(&[sym::fmt, sym::Formatter, sym::debug_struct]);
+            let expr = cx.expr_call_global(span, fn_path_debug_struct, vec![fmt, name]);
             stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
 
             for field in fields {
@@ -104,20 +108,20 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
                 );
 
                 // Use double indirection to make sure this works for unsized types
+                let fn_path_field = cx.std_path(&[sym::fmt, sym::DebugStruct, sym::field]);
                 let field = cx.expr_addr_of(field.span, field.self_.clone());
                 let field = cx.expr_addr_of(field.span, field);
-                let expr = cx.expr_method_call(
-                    span,
-                    builder_expr.clone(),
-                    Ident::new(sym::field, span),
-                    vec![name, field],
-                );
+                let builder_recv = make_mut_borrow(cx, span, builder_expr.clone());
+                let expr =
+                    cx.expr_call_global(span, fn_path_field, vec![builder_recv, name, field]);
                 stmts.push(stmt_let_underscore(cx, span, expr));
             }
+            fn_path_finish = cx.std_path(&[sym::fmt, sym::DebugStruct, sym::finish]);
         }
     }
 
-    let expr = cx.expr_method_call(span, builder_expr, Ident::new(sym::finish, span), vec![]);
+    let builder_recv = make_mut_borrow(cx, span, builder_expr);
+    let expr = cx.expr_call_global(span, fn_path_finish, vec![builder_recv]);
 
     stmts.push(cx.stmt_expr(expr));
     let block = cx.block(span, stmts);
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9b6a41b2067..df23b4006b3 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -133,6 +133,8 @@ symbols! {
         Copy,
         Count,
         Debug,
+        DebugStruct,
+        DebugTuple,
         Decodable,
         Decoder,
         Default,
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#7}-fmt.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#7}-fmt.-------.InstrumentCoverage.0.html
index 195ef4da7b4..94c77025ecf 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#7}-fmt.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.partial_eq/partial_eq.{impl#7}-fmt.-------.InstrumentCoverage.0.html
@@ -78,32 +78,36 @@ For revisions in Pull Requests (PR):
 4:17-4:22: @0[13]: _8 = &amp;(*_9)
 4:17-4:22: @0.Call: _6 = Formatter::debug_struct(move _7, move _8) -&gt; [return: bb1, unwind: bb6]
 4:17-4:22: @1[2]: FakeRead(ForLet, _6)
-4:17-4:22: @1[6]: _11 = &amp;mut _6
-4:17-4:22: @1[9]: _13 = const &quot;major&quot;
-4:17-4:22: @1[10]: _12 = &amp;(*_13)
-4:17-4:22: @1[15]: _17 = &amp;(*_3)
-4:17-4:22: @1[16]: _16 = &amp;_17
-4:17-4:22: @1[17]: _15 = &amp;(*_16)
-4:17-4:22: @1[18]: _14 = move _15 as &amp;dyn std::fmt::Debug (Pointer(Unsize))
-4:17-4:22: @1.Call: _10 = DebugStruct::field(move _11, move _12, move _14) -&gt; [return: bb2, unwind: bb6]
-4:17-4:22: @2[9]: _19 = &amp;mut _6
-4:17-4:22: @2[12]: _21 = const &quot;minor&quot;
-4:17-4:22: @2[13]: _20 = &amp;(*_21)
-4:17-4:22: @2[18]: _25 = &amp;(*_4)
-4:17-4:22: @2[19]: _24 = &amp;_25
-4:17-4:22: @2[20]: _23 = &amp;(*_24)
-4:17-4:22: @2[21]: _22 = move _23 as &amp;dyn std::fmt::Debug (Pointer(Unsize))
-4:17-4:22: @2.Call: _18 = DebugStruct::field(move _19, move _20, move _22) -&gt; [return: bb3, unwind: bb6]
-4:17-4:22: @3[9]: _27 = &amp;mut _6
-4:17-4:22: @3[12]: _29 = const &quot;patch&quot;
-4:17-4:22: @3[13]: _28 = &amp;(*_29)
-4:17-4:22: @3[18]: _33 = &amp;(*_5)
-4:17-4:22: @3[19]: _32 = &amp;_33
-4:17-4:22: @3[20]: _31 = &amp;(*_32)
-4:17-4:22: @3[21]: _30 = move _31 as &amp;dyn std::fmt::Debug (Pointer(Unsize))
-4:17-4:22: @3.Call: _26 = DebugStruct::field(move _27, move _28, move _30) -&gt; [return: bb4, unwind: bb6]
-4:17-4:22: @4[8]: _34 = &amp;mut _6
-4:17-4:22: @4.Call: _0 = DebugStruct::finish(move _34) -&gt; [return: bb5, unwind: bb6]
+4:17-4:22: @1[7]: _12 = &amp;mut _6
+4:17-4:22: @1[8]: _11 = &amp;mut (*_12)
+4:17-4:22: @1[11]: _14 = const &quot;major&quot;
+4:17-4:22: @1[12]: _13 = &amp;(*_14)
+4:17-4:22: @1[17]: _18 = &amp;(*_3)
+4:17-4:22: @1[18]: _17 = &amp;_18
+4:17-4:22: @1[19]: _16 = &amp;(*_17)
+4:17-4:22: @1[20]: _15 = move _16 as &amp;dyn std::fmt::Debug (Pointer(Unsize))
+4:17-4:22: @1.Call: _10 = DebugStruct::field(move _11, move _13, move _15) -&gt; [return: bb2, unwind: bb6]
+4:17-4:22: @2[11]: _21 = &amp;mut _6
+4:17-4:22: @2[12]: _20 = &amp;mut (*_21)
+4:17-4:22: @2[15]: _23 = const &quot;minor&quot;
+4:17-4:22: @2[16]: _22 = &amp;(*_23)
+4:17-4:22: @2[21]: _27 = &amp;(*_4)
+4:17-4:22: @2[22]: _26 = &amp;_27
+4:17-4:22: @2[23]: _25 = &amp;(*_26)
+4:17-4:22: @2[24]: _24 = move _25 as &amp;dyn std::fmt::Debug (Pointer(Unsize))
+4:17-4:22: @2.Call: _19 = DebugStruct::field(move _20, move _22, move _24) -&gt; [return: bb3, unwind: bb6]
+4:17-4:22: @3[11]: _30 = &amp;mut _6
+4:17-4:22: @3[12]: _29 = &amp;mut (*_30)
+4:17-4:22: @3[15]: _32 = const &quot;patch&quot;
+4:17-4:22: @3[16]: _31 = &amp;(*_32)
+4:17-4:22: @3[21]: _36 = &amp;(*_5)
+4:17-4:22: @3[22]: _35 = &amp;_36
+4:17-4:22: @3[23]: _34 = &amp;(*_35)
+4:17-4:22: @3[24]: _33 = move _34 as &amp;dyn std::fmt::Debug (Pointer(Unsize))
+4:17-4:22: @3.Call: _28 = DebugStruct::field(move _29, move _31, move _33) -&gt; [return: bb4, unwind: bb6]
+4:17-4:22: @4[10]: _38 = &amp;mut _6
+4:17-4:22: @4[11]: _37 = &amp;mut (*_38)
+4:17-4:22: @4.Call: _0 = DebugStruct::finish(move _37) -&gt; [return: bb5, unwind: bb6]
 4:22-4:22: @5.Return: return"><span class="annotation">@0,1,2,3,4,5⦊</span>Debug<span class="annotation">⦉@0,1,2,3,4,5</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/ui/derives/derive-Debug-use-ufcs-struct.rs b/src/test/ui/derives/derive-Debug-use-ufcs-struct.rs
new file mode 100644
index 00000000000..cb9dda84159
--- /dev/null
+++ b/src/test/ui/derives/derive-Debug-use-ufcs-struct.rs
@@ -0,0 +1,40 @@
+// run-pass
+#![allow(warnings)]
+
+#[derive(Debug)]
+pub struct Bar { pub t: () }
+
+impl<T> Access for T {}
+pub trait Access {
+    fn field(&self, _: impl Sized, _: impl Sized) {
+        panic!("got into Access::field");
+    }
+
+    fn finish(&self) -> Result<(), std::fmt::Error> {
+        panic!("got into Access::finish");
+    }
+
+    fn debug_struct(&self, _: impl Sized, _: impl Sized) {
+        panic!("got into Access::debug_struct");
+    }
+}
+
+impl<T> MutAccess for T {}
+pub trait MutAccess {
+    fn field(&mut self, _: impl Sized, _: impl Sized) {
+        panic!("got into MutAccess::field");
+    }
+
+    fn finish(&mut self) -> Result<(), std::fmt::Error> {
+        panic!("got into MutAccess::finish");
+    }
+
+    fn debug_struct(&mut self, _: impl Sized, _: impl Sized) {
+        panic!("got into MutAccess::debug_struct");
+    }
+}
+
+fn main() {
+    let bar = Bar { t: () };
+    assert_eq!("Bar { t: () }", format!("{:?}", bar));
+}
diff --git a/src/test/ui/derives/derive-Debug-use-ufcs-tuple.rs b/src/test/ui/derives/derive-Debug-use-ufcs-tuple.rs
new file mode 100644
index 00000000000..5f786769fe7
--- /dev/null
+++ b/src/test/ui/derives/derive-Debug-use-ufcs-tuple.rs
@@ -0,0 +1,32 @@
+// run-pass
+#![allow(warnings)]
+
+#[derive(Debug)]
+pub struct Foo<T>(pub T);
+
+use std::fmt;
+
+impl<T> Field for T {}
+impl<T> Finish for T {}
+impl Dt for &mut fmt::Formatter<'_> {}
+
+pub trait Field {
+    fn field(&self, _: impl Sized) {
+        panic!("got into field");
+    }
+}
+pub trait Finish {
+    fn finish(&self) -> Result<(), std::fmt::Error> {
+        panic!("got into finish");
+    }
+}
+pub trait Dt {
+    fn debug_tuple(&self, _: &str) {
+        panic!("got into debug_tuple");
+    }
+}
+
+fn main() {
+    let foo = Foo(());
+    assert_eq!("Foo(())", format!("{:?}", foo));
+}
diff --git a/src/test/ui/methods/method-lookup-order.rs b/src/test/ui/methods/method-lookup-order.rs
new file mode 100644
index 00000000000..986fe103cdc
--- /dev/null
+++ b/src/test/ui/methods/method-lookup-order.rs
@@ -0,0 +1,190 @@
+// ignore-tidy-linelength
+
+// run-pass
+
+// 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
+
+//[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!"),
+        }
+    }
+
+}