Skip to content

Commit ceec944

Browse files
committed
Add note when inherent impl for a alias type defined outside of the crate
Signed-off-by: xizheyin <[email protected]>
1 parent c0eb5f2 commit ceec944

File tree

8 files changed

+54
-10
lines changed

8 files changed

+54
-10
lines changed

compiler/rustc_hir_analysis/messages.ftl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,10 @@ hir_analysis_inherent_ty_outside = cannot define inherent `impl` for a type outs
241241
242242
hir_analysis_inherent_ty_outside_new = cannot define inherent `impl` for a type outside of the crate where the type is defined
243243
.label = impl for type defined outside of crate
244-
.note = define and implement a trait or new type instead
244+
.help = consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
245+
.note = For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>
246+
247+
hir_analysis_inherent_ty_outside_new_alias_note = `{$ty_name}` does not define a new type, just alias of `{$alias_ty_name}` defined here
245248
246249
hir_analysis_inherent_ty_outside_primitive = cannot define inherent `impl` for primitive types outside of `core`
247250
.help = consider moving this inherent impl into `core` if possible

compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,23 @@ impl<'tcx> InherentCollect<'tcx> {
107107
Ok(())
108108
} else {
109109
let impl_span = self.tcx.def_span(impl_def_id);
110-
Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span }))
110+
let mut err = errors::InherentTyOutsideNew { span: impl_span, note: None };
111+
112+
if let hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)) =
113+
self.tcx.hir_node_by_def_id(impl_def_id).expect_item().expect_impl().self_ty.kind
114+
{
115+
if let rustc_hir::def::Res::Def(DefKind::TyAlias, def_id) = path.res {
116+
let ty_name = self.tcx.def_path_str(def_id);
117+
let alias_ty_name = self.tcx.type_of(def_id).skip_binder().to_string();
118+
err.note = Some(errors::InherentTyOutsideNewAliasNote {
119+
span: self.tcx.def_span(def_id),
120+
ty_name,
121+
alias_ty_name,
122+
});
123+
}
124+
}
125+
126+
Err(self.tcx.dcx().emit_err(err))
111127
}
112128
}
113129

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,11 +1178,23 @@ pub(crate) struct InherentTyOutsideRelevant {
11781178

11791179
#[derive(Diagnostic)]
11801180
#[diag(hir_analysis_inherent_ty_outside_new, code = E0116)]
1181+
#[help]
11811182
#[note]
11821183
pub(crate) struct InherentTyOutsideNew {
11831184
#[primary_span]
11841185
#[label]
11851186
pub span: Span,
1187+
#[subdiagnostic]
1188+
pub note: Option<InherentTyOutsideNewAliasNote>,
1189+
}
1190+
1191+
#[derive(Subdiagnostic)]
1192+
#[note(hir_analysis_inherent_ty_outside_new_alias_note)]
1193+
pub(crate) struct InherentTyOutsideNewAliasNote {
1194+
#[primary_span]
1195+
pub span: Span,
1196+
pub ty_name: String,
1197+
pub alias_ty_name: String,
11861198
}
11871199

11881200
#[derive(Diagnostic)]

tests/ui/error-codes/E0116.stderr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher
44
LL | impl Vec<u8> {}
55
| ^^^^^^^^^^^^ impl for type defined outside of crate
66
|
7-
= note: define and implement a trait or new type instead
7+
= help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
8+
= note: For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>
89

910
error: aborting due to 1 previous error
1011

tests/ui/incoherent-inherent-impls/insufficient-suggestion-issue-141679.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher
44
LL | impl Function {}
55
| ^^^^^^^^^^^^^ impl for type defined outside of crate
66
|
7-
= note: define and implement a trait or new type instead
7+
= help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
8+
= note: For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>
9+
note: `Function` does not define a new type, just alias of `Rc<Foo>` defined here
10+
--> $DIR/insufficient-suggestion-issue-141679.rs:4:1
11+
|
12+
LL | pub type Function = Rc<Foo>;
13+
| ^^^^^^^^^^^^^^^^^
814

915
error: aborting due to 1 previous error
1016

tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,35 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher
44
LL | impl extern_crate::StructWithAttr {}
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate
66
|
7-
= note: define and implement a trait or new type instead
7+
= help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
8+
= note: For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>
89

910
error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined
1011
--> $DIR/no-attr-empty-impl.rs:7:1
1112
|
1213
LL | impl extern_crate::StructNoAttr {}
1314
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate
1415
|
15-
= note: define and implement a trait or new type instead
16+
= help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
17+
= note: For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>
1618

1719
error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined
1820
--> $DIR/no-attr-empty-impl.rs:10:1
1921
|
2022
LL | impl extern_crate::EnumWithAttr {}
2123
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate
2224
|
23-
= note: define and implement a trait or new type instead
25+
= help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
26+
= note: For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>
2427

2528
error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined
2629
--> $DIR/no-attr-empty-impl.rs:13:1
2730
|
2831
LL | impl extern_crate::EnumNoAttr {}
2932
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate
3033
|
31-
= note: define and implement a trait or new type instead
34+
= help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
35+
= note: For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>
3236

3337
error[E0390]: cannot define inherent `impl` for primitive types
3438
--> $DIR/no-attr-empty-impl.rs:16:1

tests/ui/incoherent-inherent-impls/no-other-unrelated-errors.stderr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher
44
LL | impl Vec<usize> {}
55
| ^^^^^^^^^^^^^^^ impl for type defined outside of crate
66
|
7-
= note: define and implement a trait or new type instead
7+
= help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
8+
= note: For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>
89

910
error: aborting due to 1 previous error
1011

tests/ui/traits/trait-or-new-type-instead.stderr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher
44
LL | impl<T> Option<T> {
55
| ^^^^^^^^^^^^^^^^^ impl for type defined outside of crate
66
|
7-
= note: define and implement a trait or new type instead
7+
= help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
8+
= note: For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>
89

910
error: aborting due to 1 previous error
1011

0 commit comments

Comments
 (0)