Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,10 @@ hir_analysis_inherent_ty_outside = cannot define inherent `impl` for a type outs

hir_analysis_inherent_ty_outside_new = cannot define inherent `impl` for a type outside of the crate where the type is defined
.label = impl for type defined outside of crate
.note = define and implement a trait or new type instead
.help = consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
.note = For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>

hir_analysis_inherent_ty_outside_new_alias_note = `{$ty_name}` does not define a new type, just alias of `{$alias_ty_name}` defined here
Comment on lines -244 to +247
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems difficult to apply structured suggestions here, because not only do we have to implement a new type, we also need to implement it with impl. Maybe we can use a clearer explanation:

help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it. Note: For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules> 

hir_analysis_inherent_ty_outside_primitive = cannot define inherent `impl` for primitive types outside of `core`
.help = consider moving this inherent impl into `core` if possible
Expand Down
17 changes: 16 additions & 1 deletion compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,22 @@ impl<'tcx> InherentCollect<'tcx> {
Ok(())
} else {
let impl_span = self.tcx.def_span(impl_def_id);
Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideNew { span: impl_span }))
let mut err = errors::InherentTyOutsideNew { span: impl_span, note: None };

if let hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)) =
self.tcx.hir_node_by_def_id(impl_def_id).expect_item().expect_impl().self_ty.kind
&& let rustc_hir::def::Res::Def(DefKind::TyAlias, def_id) = path.res
Comment on lines +112 to +114
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I merged the two ifs.

{
let ty_name = self.tcx.def_path_str(def_id);
let alias_ty_name = self.tcx.type_of(def_id).skip_binder().to_string();
err.note = Some(errors::InherentTyOutsideNewAliasNote {
span: self.tcx.def_span(def_id),
ty_name,
alias_ty_name,
});
}

Err(self.tcx.dcx().emit_err(err))
}
}

Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1178,11 +1178,23 @@ pub(crate) struct InherentTyOutsideRelevant {

#[derive(Diagnostic)]
#[diag(hir_analysis_inherent_ty_outside_new, code = E0116)]
#[help]
#[note]
pub(crate) struct InherentTyOutsideNew {
#[primary_span]
#[label]
pub span: Span,
#[subdiagnostic]
pub note: Option<InherentTyOutsideNewAliasNote>,
}

#[derive(Subdiagnostic)]
#[note(hir_analysis_inherent_ty_outside_new_alias_note)]
pub(crate) struct InherentTyOutsideNewAliasNote {
#[primary_span]
pub span: Span,
pub ty_name: String,
pub alias_ty_name: String,
}

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

error: aborting due to 1 previous error

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use std::rc::Rc;
pub struct Foo;

pub type Function = Rc<Foo>;

impl Function {}
//~^ ERROR cannot define inherent `impl` for a type outside of the crate where the type is defined [E0116]
fn main(){}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined
--> $DIR/insufficient-suggestion-issue-141679.rs:6:1
|
LL | impl Function {}
| ^^^^^^^^^^^^^ impl for type defined outside of crate
|
= help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
= note: For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>
note: `Function` does not define a new type, just alias of `Rc<Foo>` defined here
--> $DIR/insufficient-suggestion-issue-141679.rs:4:1
|
LL | pub type Function = Rc<Foo>;
| ^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0116`.
12 changes: 8 additions & 4 deletions tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,35 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher
LL | impl extern_crate::StructWithAttr {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate
|
= note: define and implement a trait or new type instead
= help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
= note: For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>

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

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

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

error[E0390]: cannot define inherent `impl` for primitive types
--> $DIR/no-attr-empty-impl.rs:16:1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher
LL | impl Vec<usize> {}
| ^^^^^^^^^^^^^^^ impl for type defined outside of crate
|
= note: define and implement a trait or new type instead
= help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
= note: For more details about orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>

error: aborting due to 1 previous error

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

error: aborting due to 1 previous error

Expand Down
Loading