-
-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Fix trait method resolution on an adjusted never type #156047
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -114,6 +114,7 @@ declare_lint_pass! { | |
| TEST_UNSTABLE_LINT, | ||
| TEXT_DIRECTION_CODEPOINT_IN_COMMENT, | ||
| TEXT_DIRECTION_CODEPOINT_IN_LITERAL, | ||
| TRAIT_METHOD_ON_COERCED_NEVER_TYPE, | ||
| TRIVIAL_CASTS, | ||
| TRIVIAL_NUMERIC_CASTS, | ||
| TYVAR_BEHIND_RAW_POINTER, | ||
|
|
@@ -5709,3 +5710,35 @@ declare_lint! { | |
| report_in_deps: false, | ||
| }; | ||
| } | ||
|
|
||
| declare_lint! { | ||
| /// The `trait_method_on_coerced_never_type` lint detects situations in which a never type, which | ||
| /// was coerced to any, has a trait method on it. | ||
| /// | ||
| /// ### Example | ||
| /// | ||
| /// ```rust,no_run | ||
| /// fn main() { | ||
| /// let x = panic!(); | ||
| /// x.clone(); | ||
| /// } | ||
| /// ``` | ||
| /// | ||
| /// {{produces}} | ||
| /// | ||
| /// ### Explanation | ||
| /// | ||
| /// Calling trait methods on a coerced `!` was previously disallowed for the never type, | ||
| /// but it did work for empty enums such as `Infallible` since these don't coerce. | ||
| /// This means that changing the definition of `Infallible` to become a type alias to `!` (a long-term goal), | ||
| /// would break code that called a trait method on `Infallible`, in such a way that the `!` would coerce. | ||
| /// | ||
| /// Therefore, to aid in the transition of changing `Infallible` to a type alias, this is temporarily allowed with a FCW. | ||
|
Comment on lines
+5731
to
+5736
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please also add a note that calling a method on Also mention that if people want to support MSRVs before |
||
| pub TRAIT_METHOD_ON_COERCED_NEVER_TYPE, | ||
| Warn, | ||
| "detects trait method calls on an coerced never type", | ||
| @future_incompatible = FutureIncompatibleInfo { | ||
| reason: fcw!(FutureReleaseError #156047), | ||
| report_in_deps: true, | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I decided on a lint with level |
||
| }; | ||
| } | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that this PR allows more code to compile on stable, for example see this test.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is a problem we could delay the problem by putting this change behind the never_type feature gate |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,9 @@ | ||
| //! regression test for issue #2151 | ||
| //@ check-pass | ||
| // Regression test for https://github.com/rust-lang/rust/issues/143349 | ||
|
|
||
| fn main() { | ||
| let x = panic!(); //~ ERROR type annotations needed | ||
| let x = panic!(); | ||
| x.clone(); | ||
| //~^ WARN [trait_method_on_coerced_never_type] | ||
| //~| WARN previously accepted | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,25 @@ | ||
| error[E0282]: type annotations needed | ||
| --> $DIR/clone-never.rs:4:9 | ||
| warning: trait method call on a coerced never type | ||
| --> $DIR/clone-never.rs:6:7 | ||
| | | ||
| LL | let x = panic!(); | ||
| | ^ | ||
| LL | x.clone(); | ||
| | - type must be known at this point | ||
| | ^^^^^ | ||
| | | ||
| help: consider giving `x` an explicit type | ||
| | | ||
| LL | let x: /* Type */ = panic!(); | ||
| | ++++++++++++ | ||
| = help: consider providing a type annotation | ||
| = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | ||
| = note: for more information, see issue #156047 <https://github.com/rust-lang/rust/issues/156047> | ||
| = note: `#[warn(trait_method_on_coerced_never_type)]` (part of `#[warn(future_incompatible)]`) on by default | ||
|
|
||
| warning: 1 warning emitted | ||
|
|
||
| error: aborting due to 1 previous error | ||
| Future incompatibility report: Future breakage diagnostic: | ||
| warning: trait method call on a coerced never type | ||
| --> $DIR/clone-never.rs:6:7 | ||
| | | ||
| LL | x.clone(); | ||
| | ^^^^^ | ||
| | | ||
| = help: consider providing a type annotation | ||
| = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | ||
| = note: for more information, see issue #156047 <https://github.com/rust-lang/rust/issues/156047> | ||
| = note: `#[warn(trait_method_on_coerced_never_type)]` (part of `#[warn(future_incompatible)]`) on by default | ||
|
|
||
| For more information about this error, try `rustc --explain E0282`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| //@ check-pass | ||
| // Regression test for https://github.com/rust-lang/rust/issues/143349 | ||
|
|
||
| #![feature(never_type)] | ||
|
|
||
| trait Trait { | ||
| fn method(&self); | ||
| } | ||
| impl Trait for ! { | ||
| fn method(&self) { | ||
| todo!() | ||
| } | ||
| } | ||
|
|
||
| fn main() { | ||
| let x = loop {}; | ||
| x.method(); | ||
| //~^ WARN [trait_method_on_coerced_never_type] | ||
| //~| WARN previously accepted | ||
|
|
||
| { loop {} }.method(); | ||
| //~^ WARN [trait_method_on_coerced_never_type] | ||
| //~| WARN previously accepted | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| warning: trait method call on a coerced never type | ||
| --> $DIR/method-on-never.rs:17:7 | ||
| | | ||
| LL | x.method(); | ||
| | ^^^^^^ | ||
| | | ||
| = help: consider providing a type annotation | ||
| = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | ||
| = note: for more information, see issue #156047 <https://github.com/rust-lang/rust/issues/156047> | ||
| = note: `#[warn(trait_method_on_coerced_never_type)]` (part of `#[warn(future_incompatible)]`) on by default | ||
|
|
||
| warning: trait method call on a coerced never type | ||
| --> $DIR/method-on-never.rs:21:17 | ||
| | | ||
| LL | { loop {} }.method(); | ||
| | ^^^^^^ | ||
| | | ||
| = help: consider providing a type annotation | ||
| = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | ||
| = note: for more information, see issue #156047 <https://github.com/rust-lang/rust/issues/156047> | ||
|
|
||
| warning: 2 warnings emitted | ||
|
|
||
| Future incompatibility report: Future breakage diagnostic: | ||
| warning: trait method call on a coerced never type | ||
| --> $DIR/method-on-never.rs:17:7 | ||
| | | ||
| LL | x.method(); | ||
| | ^^^^^^ | ||
| | | ||
| = help: consider providing a type annotation | ||
| = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | ||
| = note: for more information, see issue #156047 <https://github.com/rust-lang/rust/issues/156047> | ||
| = note: `#[warn(trait_method_on_coerced_never_type)]` (part of `#[warn(future_incompatible)]`) on by default | ||
|
|
||
| Future breakage diagnostic: | ||
| warning: trait method call on a coerced never type | ||
| --> $DIR/method-on-never.rs:21:17 | ||
| | | ||
| LL | { loop {} }.method(); | ||
| | ^^^^^^ | ||
| | | ||
| = help: consider providing a type annotation | ||
| = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | ||
| = note: for more information, see issue #156047 <https://github.com/rust-lang/rust/issues/156047> | ||
| = note: `#[warn(trait_method_on_coerced_never_type)]` (part of `#[warn(future_incompatible)]`) on by default | ||
|
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm really unsure of what the correct terminology is, both for the lint definition and the diagnostic, so please give feedback on this
View changes since the review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO the proper way to say it would be "
method_call_on_diverging_infer_variable" and "detects situations in which a method is called on a value resulting from a never-to-any coercion, without necessary information to infer a type for it", but I'm not sure how much we want to surface this internal language...