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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -110,7 +110,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 +115 to +117
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
18 changes: 17 additions & 1 deletion compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1223,11 +1223,27 @@ pub(crate) struct InherentTyOutsideRelevant {

#[derive(Diagnostic)]
#[diag("cannot define inherent `impl` for a type outside of the crate where the type is defined", code = E0116)]
#[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 the orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>"
)]
pub(crate) struct InherentTyOutsideNew {
#[primary_span]
#[label("impl for type defined outside of crate")]
pub span: Span,
#[subdiagnostic]
pub note: Option<InherentTyOutsideNewAliasNote>,
}

#[derive(Subdiagnostic)]
#[note("`{$ty_name}` does not define a new type, only an alias of `{$alias_ty_name}` defined here")]
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 the 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 the orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>
note: `Function` does not define a new type, only an 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 the 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 the 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 the 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 the 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 the 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 the 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