From 1c1bb1309f5b2e15438711b701f6ab59f04fd633 Mon Sep 17 00:00:00 2001
From: aticu <15schnic@gmail.com>
Date: Thu, 27 Aug 2020 23:55:22 +0200
Subject: [PATCH 1/2] Improve E0118 description

---
 .../src/error_codes/E0118.md                  | 27 ++++++++++++++++---
 .../src/coherence/inherent_impls.rs           | 25 ++++++++++-------
 src/test/ui/error-codes/E0118-2.rs            |  8 ++++++
 src/test/ui/error-codes/E0118-2.stderr        | 12 +++++++++
 src/test/ui/error-codes/E0118.stderr          |  4 +--
 .../privacy/private-in-public-ill-formed.rs   |  6 +++--
 .../private-in-public-ill-formed.stderr       | 10 +++----
 7 files changed, 71 insertions(+), 21 deletions(-)
 create mode 100644 src/test/ui/error-codes/E0118-2.rs
 create mode 100644 src/test/ui/error-codes/E0118-2.stderr

diff --git a/compiler/rustc_error_codes/src/error_codes/E0118.md b/compiler/rustc_error_codes/src/error_codes/E0118.md
index 5cb5f506e0a4b..ddd4f498f0c34 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0118.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0118.md
@@ -1,10 +1,10 @@
-An inherent implementation was defined for something which isn't a struct nor
-an enum.
+An inherent implementation was defined for something which isn't a struct, an
+enum, a union or a trait object.
 
 Erroneous code example:
 
 ```compile_fail,E0118
-impl (u8, u8) { // error: no base type found for inherent implementation
+impl (u8, u8) { // error: no nominal type found for inherent implementation
     fn get_state(&self) -> String {
         // ...
     }
@@ -41,3 +41,24 @@ impl TypeWrapper {
     }
 }
 ```
+
+Instead of defining an inherent implementation on a reference, you could also
+move the reference inside the implementation:
+
+```compile_fail,E0118
+struct Foo;
+
+impl &Foo { // error: no nominal type found for inherent implementation
+    fn bar(self, other: Self) {}
+}
+```
+
+becomes
+
+```
+struct Foo;
+
+impl Foo {
+    fn bar(&self, other: &Self) {}
+}
+```
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
index 042ecdbadc61b..373acb95c9e37 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
@@ -308,18 +308,25 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
             }
             ty::Error(_) => {}
             _ => {
-                struct_span_err!(
+                let mut err = struct_span_err!(
                     self.tcx.sess,
                     ty.span,
                     E0118,
-                    "no base type found for inherent implementation"
-                )
-                .span_label(ty.span, "impl requires a base type")
-                .note(
-                    "either implement a trait on it or create a newtype \
-                       to wrap it instead",
-                )
-                .emit();
+                    "no nominal type found for inherent implementation"
+                );
+
+                err.span_label(ty.span, "impl requires a nominal type")
+                    .note("either implement a trait on it or create a newtype to wrap it instead");
+
+                if let ty::Ref(_, subty, _) = self_ty.kind() {
+                    err.note(&format!(
+                        "you could also try moving the reference to \
+                            uses of `{}` (such as `self`) within the implementation",
+                        subty
+                    ));
+                }
+
+                err.emit();
             }
         }
     }
diff --git a/src/test/ui/error-codes/E0118-2.rs b/src/test/ui/error-codes/E0118-2.rs
new file mode 100644
index 0000000000000..fe04190162af4
--- /dev/null
+++ b/src/test/ui/error-codes/E0118-2.rs
@@ -0,0 +1,8 @@
+struct Foo;
+
+impl &mut Foo {
+    //~^ ERROR E0118
+    fn bar(self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0118-2.stderr b/src/test/ui/error-codes/E0118-2.stderr
new file mode 100644
index 0000000000000..2a1fe23111687
--- /dev/null
+++ b/src/test/ui/error-codes/E0118-2.stderr
@@ -0,0 +1,12 @@
+error[E0118]: no nominal type found for inherent implementation
+  --> $DIR/E0118-2.rs:3:6
+   |
+LL | impl &mut Foo {
+   |      ^^^^^^^^ impl requires a nominal type
+   |
+   = note: either implement a trait on it or create a newtype to wrap it instead
+   = note: you could also try moving the reference to uses of `Foo` (such as `self`) within the implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0118`.
diff --git a/src/test/ui/error-codes/E0118.stderr b/src/test/ui/error-codes/E0118.stderr
index b0afaeb5c1fa9..2693a93213a3b 100644
--- a/src/test/ui/error-codes/E0118.stderr
+++ b/src/test/ui/error-codes/E0118.stderr
@@ -1,8 +1,8 @@
-error[E0118]: no base type found for inherent implementation
+error[E0118]: no nominal type found for inherent implementation
   --> $DIR/E0118.rs:1:6
    |
 LL | impl (u8, u8) {
-   |      ^^^^^^^^ impl requires a base type
+   |      ^^^^^^^^ impl requires a nominal type
    |
    = note: either implement a trait on it or create a newtype to wrap it instead
 
diff --git a/src/test/ui/privacy/private-in-public-ill-formed.rs b/src/test/ui/privacy/private-in-public-ill-formed.rs
index 0ef5d89002e49..031e2874a2ba8 100644
--- a/src/test/ui/privacy/private-in-public-ill-formed.rs
+++ b/src/test/ui/privacy/private-in-public-ill-formed.rs
@@ -11,7 +11,8 @@ mod aliases_pub {
         type AssocAlias = m::Pub3;
     }
 
-    impl <Priv as PrivTr>::AssocAlias { //~ ERROR no base type found for inherent implementation
+    impl <Priv as PrivTr>::AssocAlias {
+        //~^ ERROR no nominal type found for inherent implementation
         pub fn f(arg: Priv) {} // private type `aliases_pub::Priv` in public interface
     }
 }
@@ -27,7 +28,8 @@ mod aliases_priv {
         type AssocAlias = Priv3;
     }
 
-    impl <Priv as PrivTr>::AssocAlias { //~ ERROR no base type found for inherent implementation
+    impl <Priv as PrivTr>::AssocAlias {
+        //~^ ERROR no nominal type found for inherent implementation
         pub fn f(arg: Priv) {} // OK
     }
 }
diff --git a/src/test/ui/privacy/private-in-public-ill-formed.stderr b/src/test/ui/privacy/private-in-public-ill-formed.stderr
index a1a326f2873e1..e7c94bc301bdf 100644
--- a/src/test/ui/privacy/private-in-public-ill-formed.stderr
+++ b/src/test/ui/privacy/private-in-public-ill-formed.stderr
@@ -1,16 +1,16 @@
-error[E0118]: no base type found for inherent implementation
+error[E0118]: no nominal type found for inherent implementation
   --> $DIR/private-in-public-ill-formed.rs:14:10
    |
 LL |     impl <Priv as PrivTr>::AssocAlias {
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a base type
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
    |
    = note: either implement a trait on it or create a newtype to wrap it instead
 
-error[E0118]: no base type found for inherent implementation
-  --> $DIR/private-in-public-ill-formed.rs:30:10
+error[E0118]: no nominal type found for inherent implementation
+  --> $DIR/private-in-public-ill-formed.rs:31:10
    |
 LL |     impl <Priv as PrivTr>::AssocAlias {
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a base type
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
    |
    = note: either implement a trait on it or create a newtype to wrap it instead
 

From 81161bed41124a7a62bdaf5a349df0e8f2ff09bf Mon Sep 17 00:00:00 2001
From: Niclas Schwarzlose <15schnic@gmail.com>
Date: Tue, 15 Sep 2020 18:10:41 +0200
Subject: [PATCH 2/2] Adjust spelling

Co-authored-by: Joshua Nelson <joshua@yottadb.com>
---
 compiler/rustc_error_codes/src/error_codes/E0118.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_error_codes/src/error_codes/E0118.md b/compiler/rustc_error_codes/src/error_codes/E0118.md
index ddd4f498f0c34..345ec341c3f40 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0118.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0118.md
@@ -1,5 +1,5 @@
-An inherent implementation was defined for something which isn't a struct, an
-enum, a union or a trait object.
+An inherent implementation was defined for something which isn't a struct,
+enum, union, or trait object.
 
 Erroneous code example: