diff --git a/compiler/rustc_error_codes/src/error_codes/E0118.md b/compiler/rustc_error_codes/src/error_codes/E0118.md index 5cb5f506e0a4b..345ec341c3f40 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 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 ::AssocAlias { //~ ERROR no base type found for inherent implementation + impl ::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 ::AssocAlias { //~ ERROR no base type found for inherent implementation + impl ::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 ::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 ::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