about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0118.md29
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0390.md24
-rw-r--r--compiler/rustc_typeck/src/coherence/inherent_impls.rs45
-rw-r--r--src/test/ui/error-codes/E0117.rs3
-rw-r--r--src/test/ui/error-codes/E0118.rs7
-rw-r--r--src/test/ui/error-codes/E0118.stderr11
-rw-r--r--src/test/ui/error-codes/E0120.rs3
-rw-r--r--src/test/ui/kinds-of-primitive-impl.rs6
-rw-r--r--src/test/ui/kinds-of-primitive-impl.stderr11
9 files changed, 89 insertions, 50 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes/E0118.md b/compiler/rustc_error_codes/src/error_codes/E0118.md
index 345ec341c3f..8033aa8384c 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0118.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0118.md
@@ -4,7 +4,7 @@ enum, union, or trait object.
 Erroneous code example:
 
 ```compile_fail,E0118
-impl (u8, u8) { // error: no nominal type found for inherent implementation
+impl fn(u8) { // error: no nominal type found for inherent implementation
     fn get_state(&self) -> String {
         // ...
     }
@@ -20,8 +20,8 @@ trait LiveLongAndProsper {
     fn get_state(&self) -> String;
 }
 
-// and now you can implement it on (u8, u8)
-impl LiveLongAndProsper for (u8, u8) {
+// and now you can implement it on fn(u8)
+impl LiveLongAndProsper for fn(u8) {
     fn get_state(&self) -> String {
         "He's dead, Jim!".to_owned()
     }
@@ -33,7 +33,7 @@ For example, `NewType` is a newtype over `Foo` in `struct NewType(Foo)`.
 Example:
 
 ```
-struct TypeWrapper((u8, u8));
+struct TypeWrapper(fn(u8));
 
 impl TypeWrapper {
     fn get_state(&self) -> String {
@@ -41,24 +41,3 @@ 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_error_codes/src/error_codes/E0390.md b/compiler/rustc_error_codes/src/error_codes/E0390.md
index 7a13160d098..26a9dd331ce 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0390.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0390.md
@@ -8,8 +8,7 @@ struct Foo {
 }
 
 impl *mut Foo {}
-// error: only a single inherent implementation marked with
-//        `#[lang = "mut_ptr"]` is allowed for the `*mut T` primitive
+// error: cannot define inherent `impl` for primitive types
 ```
 
 This isn't allowed, but using a trait to implement a method or constant
@@ -29,3 +28,24 @@ impl Bar for *mut Foo {
     fn bar() {} // ok!
 }
 ```
+
+Instead of defining an inherent implementation on a reference, you could also
+move the reference inside the implementation:
+
+```compile_fail,E0390
+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 e7f9ad91172..e11bd9355eb 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs
@@ -86,8 +86,7 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> {
             | ty::Ref(..)
             | ty::Never
             | ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span),
-            ty::Error(_) => {}
-            _ => {
+            ty::FnPtr(_) | ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
                 let mut err = struct_span_err!(
                     self.tcx.sess,
                     ty.span,
@@ -98,16 +97,18 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> {
                 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();
             }
+            ty::FnDef(..)
+            | ty::Closure(..)
+            | ty::Generator(..)
+            | ty::GeneratorWitness(..)
+            | ty::Bound(..)
+            | ty::Placeholder(_)
+            | ty::Infer(_) => {
+                bug!("unexpected impl self type of impl: {:?} {:?}", item.def_id, self_ty);
+            }
+            ty::Error(_) => {}
         }
     }
 
@@ -170,21 +171,29 @@ impl<'tcx> InherentCollect<'tcx> {
                     }
                 }
             } else {
-                struct_span_err!(
+                let mut err = struct_span_err!(
                     self.tcx.sess,
                     span,
                     E0390,
                     "cannot define inherent `impl` for primitive types",
-                )
-                .help("consider using an extension trait instead")
-                .emit();
+                );
+                err.help("consider using an extension trait instead");
+                if let ty::Ref(_, subty, _) = ty.kind() {
+                    err.note(&format!(
+                        "you could also try moving the reference to \
+                            uses of `{}` (such as `self`) within the implementation",
+                        subty
+                    ));
+                }
+                err.emit();
+                return;
             }
         }
 
-        let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsPlaceholders) else {
+        if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsPlaceholders) {
+            self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
+        } else {
             bug!("unexpected primitive type: {:?}", ty);
-        };
-        self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
-        return;
+        }
     }
 }
diff --git a/src/test/ui/error-codes/E0117.rs b/src/test/ui/error-codes/E0117.rs
index dbbac514801..22b48657385 100644
--- a/src/test/ui/error-codes/E0117.rs
+++ b/src/test/ui/error-codes/E0117.rs
@@ -1,5 +1,4 @@
 impl Drop for u32 {} //~ ERROR E0117
 //~| ERROR the `Drop` trait may only be implemented for structs, enums, and unions
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/error-codes/E0118.rs b/src/test/ui/error-codes/E0118.rs
new file mode 100644
index 00000000000..aaef8113b8a
--- /dev/null
+++ b/src/test/ui/error-codes/E0118.rs
@@ -0,0 +1,7 @@
+impl fn(u8) { //~ ERROR E0118
+    fn get_state(&self) -> String {
+       String::new()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0118.stderr b/src/test/ui/error-codes/E0118.stderr
new file mode 100644
index 00000000000..296fb5d664a
--- /dev/null
+++ b/src/test/ui/error-codes/E0118.stderr
@@ -0,0 +1,11 @@
+error[E0118]: no nominal type found for inherent implementation
+  --> $DIR/E0118.rs:1:6
+   |
+LL | impl fn(u8) {
+   |      ^^^^^^ impl requires a nominal type
+   |
+   = note: either implement a trait on it or create a newtype to wrap it instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0118`.
diff --git a/src/test/ui/error-codes/E0120.rs b/src/test/ui/error-codes/E0120.rs
index 287a4088183..a0a301a06e2 100644
--- a/src/test/ui/error-codes/E0120.rs
+++ b/src/test/ui/error-codes/E0120.rs
@@ -5,5 +5,4 @@ impl Drop for dyn MyTrait {
     fn drop(&mut self) {}
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/kinds-of-primitive-impl.rs b/src/test/ui/kinds-of-primitive-impl.rs
index 9eba72e7627..6a067a9a360 100644
--- a/src/test/ui/kinds-of-primitive-impl.rs
+++ b/src/test/ui/kinds-of-primitive-impl.rs
@@ -17,4 +17,10 @@ impl char {
     fn bar(self) {}
 }
 
+struct MyType;
+impl &MyType {
+//~^ error: cannot define inherent `impl` for primitive types
+    pub fn for_ref(self) {}
+}
+
 fn main() {}
diff --git a/src/test/ui/kinds-of-primitive-impl.stderr b/src/test/ui/kinds-of-primitive-impl.stderr
index c788317d786..f4dbd1c40e8 100644
--- a/src/test/ui/kinds-of-primitive-impl.stderr
+++ b/src/test/ui/kinds-of-primitive-impl.stderr
@@ -22,6 +22,15 @@ LL | impl char {
    |
    = help: consider using an extension trait instead
 
-error: aborting due to 3 previous errors
+error[E0390]: cannot define inherent `impl` for primitive types
+  --> $DIR/kinds-of-primitive-impl.rs:21:6
+   |
+LL | impl &MyType {
+   |      ^^^^^^^
+   |
+   = help: consider using an extension trait instead
+   = note: you could also try moving the reference to uses of `MyType` (such as `self`) within the implementation
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0390`.