Skip to content

Commit

Permalink
Auto merge of rust-lang#76028 - aticu:improve_e0118, r=estebank,jyn51…
Browse files Browse the repository at this point in the history
…4,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 rust-lang#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.
  • Loading branch information
bors committed Sep 17, 2020
2 parents 285fc7d + 81161be commit 95386b6
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 21 deletions.
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

0 comments on commit 95386b6

Please sign in to comment.