Skip to content

Commit a8f68d6

Browse files
Add FCW lint trait_method_on_coerced_never_type
1 parent ff8aec4 commit a8f68d6

6 files changed

Lines changed: 123 additions & 0 deletions

File tree

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_hir_analysis::autoderef::{self, Autoderef};
1212
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
1313
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TyCtxtInferExt};
1414
use rustc_infer::traits::{ObligationCauseCode, PredicateObligation, query};
15+
use rustc_lint::builtin::TRAIT_METHOD_ON_COERCED_NEVER_TYPE;
1516
use rustc_macros::Diagnostic;
1617
use rustc_middle::middle::stability;
1718
use rustc_middle::ty::elaborate::supertrait_def_ids;
@@ -394,6 +395,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
394395
#[diag("type annotations needed")]
395396
struct MissingTypeAnnot;
396397

398+
#[derive(Diagnostic)]
399+
#[diag("trait method call on a coerced never type")]
400+
#[help("consider providing a type annotation")]
401+
struct TraitMethodOnCoercedNeverType;
402+
397403
let mut orig_values = OriginalQueryValues::default();
398404
let predefined_opaques_in_body = if self.next_trait_solver() {
399405
self.tcx.mk_predefined_opaques_in_body_from_iter(
@@ -503,6 +509,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
503509
.iter()
504510
.any(|&candidate_id| self.root_var(candidate_id) == ty_id)
505511
{
512+
self.tcx.emit_node_span_lint(
513+
TRAIT_METHOD_ON_COERCED_NEVER_TYPE,
514+
scope_expr_id,
515+
span,
516+
TraitMethodOnCoercedNeverType,
517+
);
506518
self.demand_eqtype(span, root_ty, self.tcx.types.never);
507519
} else {
508520
let guar = match *ty.kind() {

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ declare_lint_pass! {
114114
TEST_UNSTABLE_LINT,
115115
TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
116116
TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
117+
TRAIT_METHOD_ON_COERCED_NEVER_TYPE,
117118
TRIVIAL_CASTS,
118119
TRIVIAL_NUMERIC_CASTS,
119120
TYVAR_BEHIND_RAW_POINTER,
@@ -5709,3 +5710,35 @@ declare_lint! {
57095710
report_in_deps: false,
57105711
};
57115712
}
5713+
5714+
declare_lint! {
5715+
/// The `trait_method_on_coerced_never_type` lint detects situations in which a never type, which
5716+
/// was coerced to any, has a trait method on it.
5717+
///
5718+
/// ### Example
5719+
///
5720+
/// ```rust
5721+
/// fn main() {
5722+
/// let x = panic!();
5723+
/// x.clone();
5724+
/// }
5725+
/// ```
5726+
///
5727+
/// {{produces}}
5728+
///
5729+
/// ### Explanation
5730+
///
5731+
/// Calling trait methods on a coerced `!` was previously disallowed for the never type,
5732+
/// but it did work for empty enums such as `Infallible` since these don't coerce.
5733+
/// This means that changing the definition of `Infallible` to become a type alias to `!` (a long-term goal),
5734+
/// would break code that called a trait method on `Infallible`, in such a way that the `!` would coerce.
5735+
///
5736+
/// Therefore, to aid in the transition of changing `Infallible` to a type alias, this is temporarily allowed with a FCW.
5737+
pub TRAIT_METHOD_ON_COERCED_NEVER_TYPE,
5738+
Warn,
5739+
"detects trait method calls on an coerced never type",
5740+
@future_incompatible = FutureIncompatibleInfo {
5741+
reason: fcw!(FutureReleaseError #156047),
5742+
report_in_deps: true,
5743+
};
5744+
}

tests/ui/never_type/basic/clone-never.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@
44
fn main() {
55
let x = panic!();
66
x.clone();
7+
//~^ WARN [trait_method_on_coerced_never_type]
8+
//~| WARN previously accepted
79
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
warning: trait method call on a coerced never type
2+
--> $DIR/clone-never.rs:6:7
3+
|
4+
LL | x.clone();
5+
| ^^^^^
6+
|
7+
= help: consider providing a type annotation
8+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
9+
= note: for more information, see issue #156047 <https://github.com/rust-lang/rust/issues/156047>
10+
= note: `#[warn(trait_method_on_coerced_never_type)]` on by default
11+
12+
warning: 1 warning emitted
13+
14+
Future incompatibility report: Future breakage diagnostic:
15+
warning: trait method call on a coerced never type
16+
--> $DIR/clone-never.rs:6:7
17+
|
18+
LL | x.clone();
19+
| ^^^^^
20+
|
21+
= help: consider providing a type annotation
22+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
23+
= note: for more information, see issue #156047 <https://github.com/rust-lang/rust/issues/156047>
24+
= note: `#[warn(trait_method_on_coerced_never_type)]` on by default
25+

tests/ui/never_type/basic/method-on-never.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ impl Trait for ! {
1515
fn main() {
1616
let x = loop {};
1717
x.method();
18+
//~^ WARN [trait_method_on_coerced_never_type]
19+
//~| WARN previously accepted
1820

1921
{ loop {} }.method();
22+
//~^ WARN [trait_method_on_coerced_never_type]
23+
//~| WARN previously accepted
2024
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
warning: trait method call on a coerced never type
2+
--> $DIR/method-on-never.rs:17:7
3+
|
4+
LL | x.method();
5+
| ^^^^^^
6+
|
7+
= help: consider providing a type annotation
8+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
9+
= note: for more information, see issue #156047 <https://github.com/rust-lang/rust/issues/156047>
10+
= note: `#[warn(trait_method_on_coerced_never_type)]` on by default
11+
12+
warning: trait method call on a coerced never type
13+
--> $DIR/method-on-never.rs:21:17
14+
|
15+
LL | { loop {} }.method();
16+
| ^^^^^^
17+
|
18+
= help: consider providing a type annotation
19+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
20+
= note: for more information, see issue #156047 <https://github.com/rust-lang/rust/issues/156047>
21+
22+
warning: 2 warnings emitted
23+
24+
Future incompatibility report: Future breakage diagnostic:
25+
warning: trait method call on a coerced never type
26+
--> $DIR/method-on-never.rs:17:7
27+
|
28+
LL | x.method();
29+
| ^^^^^^
30+
|
31+
= help: consider providing a type annotation
32+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
33+
= note: for more information, see issue #156047 <https://github.com/rust-lang/rust/issues/156047>
34+
= note: `#[warn(trait_method_on_coerced_never_type)]` on by default
35+
36+
Future breakage diagnostic:
37+
warning: trait method call on a coerced never type
38+
--> $DIR/method-on-never.rs:21:17
39+
|
40+
LL | { loop {} }.method();
41+
| ^^^^^^
42+
|
43+
= help: consider providing a type annotation
44+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
45+
= note: for more information, see issue #156047 <https://github.com/rust-lang/rust/issues/156047>
46+
= note: `#[warn(trait_method_on_coerced_never_type)]` on by default
47+

0 commit comments

Comments
 (0)