about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-09-17 03:56:38 +0000
committerbors <bors@rust-lang.org>2020-09-17 03:56:38 +0000
commit95386b656e91168bf53e2ab63c6b992cae591fe7 (patch)
tree1f8188971f7f3a37db4a03b96941449576352c13
parent285fc7d704fcdd7b2a37d475d04d5d955490e000 (diff)
parent81161bed41124a7a62bdaf5a349df0e8f2ff09bf (diff)
downloadrust-95386b656e91168bf53e2ab63c6b992cae591fe7.tar.gz
rust-95386b656e91168bf53e2ab63c6b992cae591fe7.zip
Auto merge of #76028 - aticu:improve_e0118, r=estebank,jyn514,GuillaumeGomez
Improve E0118

- Changes the "base type" terminology to "nominal type" (according to the [reference](https://doc.rust-lang.org/stable/reference/items/implementations.html#inherent-implementations)).
- Suggests removing a reference, if one is present on the type.
- Clarify what is meant by a "nominal type".

closes #69392

This is my first not-entirely-trivial PR, so please let me know if I missed anything or if something could be improved. Though I probably won't be able to fix anything in the upcoming week.
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0118.md27
-rw-r--r--compiler/rustc_typeck/src/coherence/inherent_impls.rs25
-rw-r--r--src/test/ui/error-codes/E0118-2.rs8
-rw-r--r--src/test/ui/error-codes/E0118-2.stderr12
-rw-r--r--src/test/ui/error-codes/E0118.stderr4
-rw-r--r--src/test/ui/privacy/private-in-public-ill-formed.rs6
-rw-r--r--src/test/ui/privacy/private-in-public-ill-formed.stderr10
7 files changed, 71 insertions, 21 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes/E0118.md b/compiler/rustc_error_codes/src/error_codes/E0118.md
index 5cb5f506e0a..345ec341c3f 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,
+enum, union, or 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 042ecdbadc6..373acb95c9e 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 00000000000..fe04190162a
--- /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 00000000000..2a1fe231116
--- /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 b0afaeb5c1f..2693a93213a 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 0ef5d89002e..031e2874a2b 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 a1a326f2873..e7c94bc301b 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