Skip to content

Commit f74b3a7

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 00228ab commit f74b3a7

File tree

4 files changed

+35
-7
lines changed

4 files changed

+35
-7
lines changed

compiler/rustc_hir_analysis/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ hir_analysis_inherent_ty_outside_new = cannot define inherent `impl` for a type
236236
.label = impl for type defined outside of crate
237237
.note = define and implement a trait or new type instead
238238
239+
hir_analysis_inherent_ty_outside_new_alias_note = `{$ty_name}` does not define a new type, just alias of `{$alias_ty_name}`, which defined outside of crate
240+
239241
hir_analysis_inherent_ty_outside_primitive = cannot define inherent `impl` for primitive types outside of `core`
240242
.help = consider moving this inherent impl into `core` if possible
241243
.span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items

compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ impl<'tcx> InherentCollect<'tcx> {
6464
fn check_def_id(
6565
&mut self,
6666
impl_def_id: LocalDefId,
67+
hir_item_id: hir::ItemId,
6768
self_ty: Ty<'tcx>,
6869
ty_def_id: DefId,
6970
) -> Result<(), ErrorGuaranteed> {
@@ -103,7 +104,22 @@ impl<'tcx> InherentCollect<'tcx> {
103104
Ok(())
104105
} else {
105106
let impl_span = self.tcx.def_span(impl_def_id);
106-
Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span }))
107+
let mut err = errors::InherentTyOutsideNew { span: impl_span, note: None };
108+
109+
if let hir::ItemKind::Impl(impl_item) = self.tcx.hir_item(hir_item_id).kind {
110+
if let hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)) =
111+
impl_item.self_ty.kind
112+
{
113+
if let rustc_hir::def::Res::Def(DefKind::TyAlias, def_id) = path.res {
114+
let ty_name = self.tcx.def_path_str(def_id);
115+
let alias_ty_name = self.tcx.type_of(def_id).skip_binder().to_string();
116+
err.note =
117+
Some(errors::InherentTyOutsideNewAliasNote { ty_name, alias_ty_name });
118+
}
119+
}
120+
}
121+
122+
Err(self.tcx.dcx().emit_err(err))
107123
}
108124
}
109125

@@ -142,12 +158,12 @@ impl<'tcx> InherentCollect<'tcx> {
142158
Ok(())
143159
}
144160

145-
fn check_item(&mut self, id: hir::ItemId) -> Result<(), ErrorGuaranteed> {
146-
if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl { of_trait: false }) {
161+
fn check_item(&mut self, hir_item_id: hir::ItemId) -> Result<(), ErrorGuaranteed> {
162+
if !matches!(self.tcx.def_kind(hir_item_id.owner_id), DefKind::Impl { of_trait: false }) {
147163
return Ok(());
148164
}
149165

150-
let id = id.owner_id.def_id;
166+
let id = hir_item_id.owner_id.def_id;
151167
let item_span = self.tcx.def_span(id);
152168
let self_ty = self.tcx.type_of(id).instantiate_identity();
153169
let mut self_ty = self.tcx.peel_off_free_alias_tys(self_ty);
@@ -157,10 +173,10 @@ impl<'tcx> InherentCollect<'tcx> {
157173
self_ty = base;
158174
}
159175
match *self_ty.kind() {
160-
ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()),
161-
ty::Foreign(did) => self.check_def_id(id, self_ty, did),
176+
ty::Adt(def, _) => self.check_def_id(id, hir_item_id, self_ty, def.did()),
177+
ty::Foreign(did) => self.check_def_id(id, hir_item_id, self_ty, did),
162178
ty::Dynamic(data, ..) if data.principal_def_id().is_some() => {
163-
self.check_def_id(id, self_ty, data.principal_def_id().unwrap())
179+
self.check_def_id(id, hir_item_id, self_ty, data.principal_def_id().unwrap())
164180
}
165181
ty::Dynamic(..) => {
166182
Err(self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span }))

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,6 +1186,15 @@ pub(crate) struct InherentTyOutsideNew {
11861186
#[primary_span]
11871187
#[label]
11881188
pub span: Span,
1189+
#[subdiagnostic]
1190+
pub note: Option<InherentTyOutsideNewAliasNote>,
1191+
}
1192+
1193+
#[derive(Subdiagnostic)]
1194+
#[note(hir_analysis_inherent_ty_outside_new_alias_note)]
1195+
pub(crate) struct InherentTyOutsideNewAliasNote {
1196+
pub ty_name: String,
1197+
pub alias_ty_name: String,
11891198
}
11901199

11911200
#[derive(Diagnostic)]

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ LL | impl Function {}
55
| ^^^^^^^^^^^^^ impl for type defined outside of crate
66
|
77
= note: define and implement a trait or new type instead
8+
= note: `Function` does not define a new type, just alias of `Rc<Foo>`, which defined outside of crate
89

910
error: aborting due to 1 previous error
1011

0 commit comments

Comments
 (0)