Skip to content

Commit cd643ad

Browse files
committed
Add note when inherent impl for a alias type defined outside of the crate
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
1 parent b747da6 commit cd643ad

8 files changed

Lines changed: 58 additions & 10 deletions

File tree

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: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,27 @@ 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::ItemKind::Impl(impl_item) =
113+
self.tcx.hir_node_by_def_id(impl_def_id).expect_item().kind
114+
{
115+
if let hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)) =
116+
impl_item.self_ty.kind
117+
{
118+
if let rustc_hir::def::Res::Def(DefKind::TyAlias, def_id) = path.res {
119+
let ty_name = self.tcx.def_path_str(def_id);
120+
let alias_ty_name = self.tcx.type_of(def_id).skip_binder().to_string();
121+
err.note = Some(errors::InherentTyOutsideNewAliasNote {
122+
span: self.tcx.def_span(def_id),
123+
ty_name,
124+
alias_ty_name,
125+
});
126+
}
127+
}
128+
}
129+
130+
Err(self.tcx.dcx().emit_err(err))
111131
}
112132
}
113133

compiler/rustc_hir_analysis/src/errors.rs

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

11931193
#[derive(Diagnostic)]
11941194
#[diag(hir_analysis_inherent_ty_outside_new, code = E0116)]
1195+
#[help]
11951196
#[note]
11961197
pub(crate) struct InherentTyOutsideNew {
11971198
#[primary_span]
11981199
#[label]
11991200
pub span: Span,
1201+
#[subdiagnostic]
1202+
pub note: Option<InherentTyOutsideNewAliasNote>,
1203+
}
1204+
1205+
#[derive(Subdiagnostic)]
1206+
#[note(hir_analysis_inherent_ty_outside_new_alias_note)]
1207+
pub(crate) struct InherentTyOutsideNewAliasNote {
1208+
#[primary_span]
1209+
pub span: Span,
1210+
pub ty_name: String,
1211+
pub alias_ty_name: String,
12001212
}
12011213

12021214
#[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)