Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve E0118 #76028

Merged
merged 2 commits into from
Sep 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions compiler/rustc_error_codes/src/error_codes/E0118.md
Original file line number Diff line number Diff line change
@@ -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 {
// ...
}
Expand Down Expand Up @@ -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) {}
}
```
25 changes: 16 additions & 9 deletions compiler/rustc_typeck/src/coherence/inherent_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/error-codes/E0118-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
struct Foo;

impl &mut Foo {
//~^ ERROR E0118
fn bar(self) {}
}

fn main() {}
12 changes: 12 additions & 0 deletions src/test/ui/error-codes/E0118-2.stderr
Original file line number Diff line number Diff line change
@@ -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`.
4 changes: 2 additions & 2 deletions src/test/ui/error-codes/E0118.stderr
Original file line number Diff line number Diff line change
@@ -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

Expand Down
6 changes: 4 additions & 2 deletions src/test/ui/privacy/private-in-public-ill-formed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand All @@ -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
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/test/ui/privacy/private-in-public-ill-formed.stderr
Original file line number Diff line number Diff line change
@@ -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

Expand Down