Skip to content

Commit 485b566

Browse files
committed
Warn when lint level is set on a match arm
1 parent c5aab79 commit 485b566

File tree

7 files changed

+107
-27
lines changed

7 files changed

+107
-27
lines changed

compiler/rustc_mir_build/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ mir_build_non_exhaustive_omitted_pattern = some variants are not matched explici
221221
.help = ensure that all variants are matched explicitly by adding the suggested match arms
222222
.note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found
223223
224+
mir_build_non_exhaustive_omitted_pattern_lint_on_arm = the `non_exhaustive_omitted_pattern` lint level must be set on the whole match
225+
.help = it used to make sense to set the lint level on an individual match arm, but that is no longer the case
226+
224227
mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
225228
.def_note = `{$peeled_ty}` defined here
226229
.type_note = the matched value is of type `{$ty}`

compiler/rustc_mir_build/src/errors.rs

+5
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,11 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
789789
pub uncovered: Uncovered<'tcx>,
790790
}
791791

792+
#[derive(LintDiagnostic)]
793+
#[diag(mir_build_non_exhaustive_omitted_pattern_lint_on_arm)]
794+
#[help]
795+
pub(crate) struct NonExhaustiveOmittedPatternLintOnArm;
796+
792797
#[derive(Subdiagnostic)]
793798
#[label(mir_build_uncovered)]
794799
pub(crate) struct Uncovered<'tcx> {

compiler/rustc_mir_build/src/thir/pattern/usefulness.rs

+41-21
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,10 @@ use self::Usefulness::*;
310310
use super::deconstruct_pat::{
311311
Constructor, ConstructorSet, DeconstructedPat, IntRange, SplitConstructorSet, WitnessPat,
312312
};
313-
use crate::errors::{NonExhaustiveOmittedPattern, Overlap, OverlappingRangeEndpoints, Uncovered};
313+
use crate::errors::{
314+
NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Overlap,
315+
OverlappingRangeEndpoints, Uncovered,
316+
};
314317

315318
use rustc_data_structures::captures::Captures;
316319

@@ -1148,28 +1151,45 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
11481151

11491152
// Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
11501153
// `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
1151-
if cx.refutable
1152-
&& non_exhaustiveness_witnesses.is_empty()
1153-
&& !matches!(
1154+
if cx.refutable && non_exhaustiveness_witnesses.is_empty() {
1155+
if !matches!(
11541156
cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, lint_root).0,
11551157
rustc_session::lint::Level::Allow
1156-
)
1157-
{
1158-
let witnesses = collect_nonexhaustive_missing_variants(cx, &pat_column);
1159-
if !witnesses.is_empty() {
1160-
// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
1161-
// is not exhaustive enough.
1162-
//
1163-
// NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
1164-
cx.tcx.emit_spanned_lint(
1165-
NON_EXHAUSTIVE_OMITTED_PATTERNS,
1166-
lint_root,
1167-
scrut_span,
1168-
NonExhaustiveOmittedPattern {
1169-
scrut_ty,
1170-
uncovered: Uncovered::new(scrut_span, cx, witnesses),
1171-
},
1172-
);
1158+
) {
1159+
let witnesses = collect_nonexhaustive_missing_variants(cx, &pat_column);
1160+
1161+
if !witnesses.is_empty() {
1162+
// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
1163+
// is not exhaustive enough.
1164+
//
1165+
// NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
1166+
cx.tcx.emit_spanned_lint(
1167+
NON_EXHAUSTIVE_OMITTED_PATTERNS,
1168+
lint_root,
1169+
scrut_span,
1170+
NonExhaustiveOmittedPattern {
1171+
scrut_ty,
1172+
uncovered: Uncovered::new(scrut_span, cx, witnesses),
1173+
},
1174+
);
1175+
}
1176+
} else {
1177+
// We used to allow putting the `#[allow(non_exhaustive_omitted_patterns)]` on a match
1178+
// arm. This no longer makes sense so we warn users, to avoid silently breaking their
1179+
// usage of the lint.
1180+
for arm in arms {
1181+
if !matches!(
1182+
cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.hir_id).0,
1183+
rustc_session::lint::Level::Allow
1184+
) {
1185+
cx.tcx.emit_spanned_lint(
1186+
NON_EXHAUSTIVE_OMITTED_PATTERNS,
1187+
arm.hir_id,
1188+
arm.pat.span(),
1189+
NonExhaustiveOmittedPatternLintOnArm,
1190+
);
1191+
}
1192+
}
11731193
}
11741194
}
11751195

src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ fn repeat() -> ! {
99
}
1010

1111
pub fn f(x: Ordering) {
12+
#[deny(non_exhaustive_omitted_patterns)]
1213
match x {
1314
Ordering::Relaxed => println!("relaxed"),
1415
Ordering::Release => println!("release"),
1516
Ordering::Acquire => println!("acquire"),
1617
Ordering::AcqRel | Ordering::SeqCst => repeat(),
17-
#[deny(non_exhaustive_omitted_patterns)]
1818
_ => repeat(),
1919
}
2020
}

tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr

+40-1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,44 @@ note: the lint level is defined here
2626
LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
2727
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2828

29-
error: aborting due to 2 previous errors
29+
error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match
30+
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9
31+
|
32+
LL | _ => {}
33+
| ^
34+
|
35+
= help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case
36+
note: the lint level is defined here
37+
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:33:16
38+
|
39+
LL | #[deny(non_exhaustive_omitted_patterns)]
40+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
41+
42+
error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match
43+
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:41:9
44+
|
45+
LL | _ => {}
46+
| ^
47+
|
48+
= help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case
49+
note: the lint level is defined here
50+
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:40:31
51+
|
52+
LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
54+
55+
warning: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match
56+
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:48:9
57+
|
58+
LL | _ => {}
59+
| ^
60+
|
61+
= help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case
62+
note: the lint level is defined here
63+
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:47:31
64+
|
65+
LL | #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
66+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
67+
68+
error: aborting due to 4 previous errors; 1 warning emitted
3069

tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr

+14-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,18 @@ note: the lint level is defined here
1212
LL | #[deny(non_exhaustive_omitted_patterns)]
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1414

15-
error: aborting due to previous error
15+
error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match
16+
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9
17+
|
18+
LL | _ => {}
19+
| ^
20+
|
21+
= help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case
22+
note: the lint level is defined here
23+
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:33:16
24+
|
25+
LL | #[deny(non_exhaustive_omitted_patterns)]
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27+
28+
error: aborting due to 2 previous errors
1629

tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,20 @@ fn main() {
3131
NonExhaustiveEnum::Unit => {}
3232
NonExhaustiveEnum::Tuple(_) => {}
3333
#[deny(non_exhaustive_omitted_patterns)]
34-
_ => {}
34+
_ => {} //~ ERROR lint level must be set on the whole match
3535
}
3636

3737
match val {
3838
NonExhaustiveEnum::Unit => {}
3939
NonExhaustiveEnum::Tuple(_) => {}
4040
#[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
41-
_ => {}
41+
_ => {} //[lint]~ ERROR lint level must be set on the whole match
4242
}
4343

4444
match val {
4545
NonExhaustiveEnum::Unit => {}
4646
NonExhaustiveEnum::Tuple(_) => {}
4747
#[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
48-
_ => {}
48+
_ => {} //[lint]~ WARN lint level must be set on the whole match
4949
}
5050
}

0 commit comments

Comments
 (0)