Skip to content

Commit 00cf7af

Browse files
committed
rework error messages for incorrect inherent impls
1 parent ee62514 commit 00cf7af

File tree

9 files changed

+89
-50
lines changed

9 files changed

+89
-50
lines changed

compiler/rustc_error_codes/src/error_codes/E0118.md

+4-25
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ enum, union, or trait object.
44
Erroneous code example:
55

66
```compile_fail,E0118
7-
impl (u8, u8) { // error: no nominal type found for inherent implementation
7+
impl fn(u8) { // error: no nominal type found for inherent implementation
88
fn get_state(&self) -> String {
99
// ...
1010
}
@@ -20,8 +20,8 @@ trait LiveLongAndProsper {
2020
fn get_state(&self) -> String;
2121
}
2222
23-
// and now you can implement it on (u8, u8)
24-
impl LiveLongAndProsper for (u8, u8) {
23+
// and now you can implement it on fn(u8)
24+
impl LiveLongAndProsper for fn(u8) {
2525
fn get_state(&self) -> String {
2626
"He's dead, Jim!".to_owned()
2727
}
@@ -33,32 +33,11 @@ For example, `NewType` is a newtype over `Foo` in `struct NewType(Foo)`.
3333
Example:
3434

3535
```
36-
struct TypeWrapper((u8, u8));
36+
struct TypeWrapper(fn(u8));
3737
3838
impl TypeWrapper {
3939
fn get_state(&self) -> String {
4040
"Fascinating!".to_owned()
4141
}
4242
}
4343
```
44-
45-
Instead of defining an inherent implementation on a reference, you could also
46-
move the reference inside the implementation:
47-
48-
```compile_fail,E0118
49-
struct Foo;
50-
51-
impl &Foo { // error: no nominal type found for inherent implementation
52-
fn bar(self, other: Self) {}
53-
}
54-
```
55-
56-
becomes
57-
58-
```
59-
struct Foo;
60-
61-
impl Foo {
62-
fn bar(&self, other: &Self) {}
63-
}
64-
```

compiler/rustc_error_codes/src/error_codes/E0390.md

+22-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ struct Foo {
88
}
99
1010
impl *mut Foo {}
11-
// error: only a single inherent implementation marked with
12-
// `#[lang = "mut_ptr"]` is allowed for the `*mut T` primitive
11+
// error: cannot define inherent `impl` for primitive types
1312
```
1413

1514
This isn't allowed, but using a trait to implement a method or constant
@@ -29,3 +28,24 @@ impl Bar for *mut Foo {
2928
fn bar() {} // ok!
3029
}
3130
```
31+
32+
Instead of defining an inherent implementation on a reference, you could also
33+
move the reference inside the implementation:
34+
35+
```compile_fail,E0390
36+
struct Foo;
37+
38+
impl &Foo { // error: no nominal type found for inherent implementation
39+
fn bar(self, other: Self) {}
40+
}
41+
```
42+
43+
becomes
44+
45+
```
46+
struct Foo;
47+
48+
impl Foo {
49+
fn bar(&self, other: &Self) {}
50+
}
51+
```

compiler/rustc_typeck/src/coherence/inherent_impls.rs

+27-18
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> {
8686
| ty::Ref(..)
8787
| ty::Never
8888
| ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span),
89-
ty::Error(_) => {}
90-
_ => {
89+
ty::FnPtr(_) | ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
9190
let mut err = struct_span_err!(
9291
self.tcx.sess,
9392
ty.span,
@@ -98,16 +97,18 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> {
9897
err.span_label(ty.span, "impl requires a nominal type")
9998
.note("either implement a trait on it or create a newtype to wrap it instead");
10099

101-
if let ty::Ref(_, subty, _) = self_ty.kind() {
102-
err.note(&format!(
103-
"you could also try moving the reference to \
104-
uses of `{}` (such as `self`) within the implementation",
105-
subty
106-
));
107-
}
108-
109100
err.emit();
110101
}
102+
ty::FnDef(..)
103+
| ty::Closure(..)
104+
| ty::Generator(..)
105+
| ty::GeneratorWitness(..)
106+
| ty::Bound(..)
107+
| ty::Placeholder(_)
108+
| ty::Infer(_) => {
109+
bug!("unexpected impl self type of impl: {:?} {:?}", item.def_id, self_ty);
110+
}
111+
ty::Error(_) => {}
111112
}
112113
}
113114

@@ -170,21 +171,29 @@ impl<'tcx> InherentCollect<'tcx> {
170171
}
171172
}
172173
} else {
173-
struct_span_err!(
174+
let mut err = struct_span_err!(
174175
self.tcx.sess,
175176
span,
176177
E0390,
177178
"cannot define inherent `impl` for primitive types",
178-
)
179-
.help("consider using an extension trait instead")
180-
.emit();
179+
);
180+
err.help("consider using an extension trait instead");
181+
if let ty::Ref(_, subty, _) = ty.kind() {
182+
err.note(&format!(
183+
"you could also try moving the reference to \
184+
uses of `{}` (such as `self`) within the implementation",
185+
subty
186+
));
187+
}
188+
err.emit();
189+
return;
181190
}
182191
}
183192

184-
let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsPlaceholders) else {
193+
if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsPlaceholders) {
194+
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
195+
} else {
185196
bug!("unexpected primitive type: {:?}", ty);
186-
};
187-
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
188-
return;
197+
}
189198
}
190199
}

src/test/ui/error-codes/E0117.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
impl Drop for u32 {} //~ ERROR E0117
22
//~| ERROR the `Drop` trait may only be implemented for structs, enums, and unions
33

4-
fn main() {
5-
}
4+
fn main() {}

src/test/ui/error-codes/E0118.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
impl fn(u8) { //~ ERROR E0118
2+
fn get_state(&self) -> String {
3+
String::new()
4+
}
5+
}
6+
7+
fn main() {}

src/test/ui/error-codes/E0118.stderr

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0118]: no nominal type found for inherent implementation
2+
--> $DIR/E0118.rs:1:6
3+
|
4+
LL | impl fn(u8) {
5+
| ^^^^^^ impl requires a nominal type
6+
|
7+
= note: either implement a trait on it or create a newtype to wrap it instead
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0118`.

src/test/ui/error-codes/E0120.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,4 @@ impl Drop for dyn MyTrait {
55
fn drop(&mut self) {}
66
}
77

8-
fn main() {
9-
}
8+
fn main() {}

src/test/ui/kinds-of-primitive-impl.rs

+6
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,10 @@ impl char {
1717
fn bar(self) {}
1818
}
1919

20+
struct MyType;
21+
impl &MyType {
22+
//~^ error: cannot define inherent `impl` for primitive types
23+
pub fn for_ref(self) {}
24+
}
25+
2026
fn main() {}

src/test/ui/kinds-of-primitive-impl.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ LL | impl char {
2222
|
2323
= help: consider using an extension trait instead
2424

25-
error: aborting due to 3 previous errors
25+
error[E0390]: cannot define inherent `impl` for primitive types
26+
--> $DIR/kinds-of-primitive-impl.rs:21:6
27+
|
28+
LL | impl &MyType {
29+
| ^^^^^^^
30+
|
31+
= help: consider using an extension trait instead
32+
= note: you could also try moving the reference to uses of `MyType` (such as `self`) within the implementation
33+
34+
error: aborting due to 4 previous errors
2635

2736
For more information about this error, try `rustc --explain E0390`.

0 commit comments

Comments
 (0)