Skip to content

Commit f0e8330

Browse files
committed
Suggest to set lint level on whole match
1 parent 61d0fc7 commit f0e8330

File tree

7 files changed

+79
-47
lines changed

7 files changed

+79
-47
lines changed

Diff for: compiler/rustc_mir_build/messages.ftl

+4-2
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,10 @@ 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
224+
mir_build_non_exhaustive_omitted_pattern_lint_on_arm = the lint level must be set on the whole match
225+
.help = it no longer has any effect to set the lint level on an individual match arm
226+
.label = remove this attribute
227+
.suggestion = set the lint level on the whole match
226228
227229
mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
228230
.def_note = `{$peeled_ty}` defined here

Diff for: compiler/rustc_mir_build/src/errors.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,14 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
792792
#[derive(LintDiagnostic)]
793793
#[diag(mir_build_non_exhaustive_omitted_pattern_lint_on_arm)]
794794
#[help]
795-
pub(crate) struct NonExhaustiveOmittedPatternLintOnArm;
795+
pub(crate) struct NonExhaustiveOmittedPatternLintOnArm {
796+
#[label]
797+
pub lint_span: Span,
798+
#[suggestion(code = "#[{lint_level}({lint_name})]\n", applicability = "maybe-incorrect")]
799+
pub suggest_lint_on_match: Option<Span>,
800+
pub lint_level: &'static str,
801+
pub lint_name: &'static str,
802+
}
796803

797804
#[derive(Subdiagnostic)]
798805
#[label(mir_build_uncovered)]

Diff for: compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,11 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
285285
}
286286
}
287287

288-
fn new_cx(&self, refutability: RefutableFlag) -> MatchCheckCtxt<'p, 'tcx> {
288+
fn new_cx(
289+
&self,
290+
refutability: RefutableFlag,
291+
match_span: Option<Span>,
292+
) -> MatchCheckCtxt<'p, 'tcx> {
289293
let refutable = match refutability {
290294
Irrefutable => false,
291295
Refutable => true,
@@ -295,6 +299,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
295299
param_env: self.param_env,
296300
module: self.tcx.parent_module(self.lint_level).to_def_id(),
297301
pattern_arena: &self.pattern_arena,
302+
match_span,
298303
refutable,
299304
}
300305
}
@@ -325,7 +330,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
325330
source: hir::MatchSource,
326331
expr_span: Span,
327332
) {
328-
let cx = self.new_cx(Refutable);
333+
let cx = self.new_cx(Refutable, Some(expr_span));
329334

330335
let mut tarms = Vec::with_capacity(arms.len());
331336
for &arm in arms {
@@ -448,7 +453,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
448453
pat: &Pat<'tcx>,
449454
refutability: RefutableFlag,
450455
) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> {
451-
let cx = self.new_cx(refutability);
456+
let cx = self.new_cx(refutability, None);
452457
let pat = self.lower_pattern(&cx, pat)?;
453458
let arms = [MatchArm { pat, hir_id: self.lint_level, has_guard: false }];
454459
let report = compute_match_usefulness(&cx, &arms, self.lint_level, pat.ty(), pat.span());

Diff for: compiler/rustc_mir_build/src/thir/pattern/usefulness.rs

+17-10
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ pub(crate) struct MatchCheckCtxt<'p, 'tcx> {
340340
pub(crate) module: DefId,
341341
pub(crate) param_env: ty::ParamEnv<'tcx>,
342342
pub(crate) pattern_arena: &'p TypedArena<DeconstructedPat<'p, 'tcx>>,
343+
/// The span of the whole match, if applicable.
344+
pub(crate) match_span: Option<Span>,
343345
/// Only produce `NON_EXHAUSTIVE_OMITTED_PATTERNS` lint on refutable patterns.
344346
pub(crate) refutable: bool,
345347
}
@@ -1179,16 +1181,21 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
11791181
// arm. This no longer makes sense so we warn users, to avoid silently breaking their
11801182
// usage of the lint.
11811183
for arm in arms {
1182-
if !matches!(
1183-
cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.hir_id).0,
1184-
rustc_session::lint::Level::Allow
1185-
) {
1186-
cx.tcx.emit_spanned_lint(
1187-
NON_EXHAUSTIVE_OMITTED_PATTERNS,
1188-
arm.hir_id,
1189-
arm.pat.span(),
1190-
NonExhaustiveOmittedPatternLintOnArm,
1191-
);
1184+
let (lint_level, lint_level_source) =
1185+
cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.hir_id);
1186+
if !matches!(lint_level, rustc_session::lint::Level::Allow) {
1187+
let decorator = NonExhaustiveOmittedPatternLintOnArm {
1188+
lint_span: lint_level_source.span(),
1189+
suggest_lint_on_match: cx.match_span.map(|span| span.shrink_to_lo()),
1190+
lint_level: lint_level.as_str(),
1191+
lint_name: "non_exhaustive_omitted_patterns",
1192+
};
1193+
1194+
use rustc_errors::DecorateLint;
1195+
let mut err = cx.tcx.sess.struct_span_warn(arm.pat.span(), "");
1196+
err.set_primary_message(decorator.msg());
1197+
decorator.decorate_lint(&mut err);
1198+
err.emit();
11921199
}
11931200
}
11941201
}

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

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

29-
error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match
29+
warning: the lint level must be set on the whole match
3030
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9
3131
|
32+
LL | #[deny(non_exhaustive_omitted_patterns)]
33+
| ------------------------------- remove this attribute
3234
LL | _ => {}
3335
| ^
3436
|
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
37+
= help: it no longer has any effect to set the lint level on an individual match arm
38+
help: set the lint level on the whole match
39+
|
40+
LL + #[deny(non_exhaustive_omitted_patterns)]
41+
LL | match val {
3842
|
39-
LL | #[deny(non_exhaustive_omitted_patterns)]
40-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4143

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+
warning: the lint level must be set on the whole match
45+
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:42:9
4446
|
47+
LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
48+
| ------------------------------- remove this attribute
4549
LL | _ => {}
4650
| ^
4751
|
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
52+
= help: it no longer has any effect to set the lint level on an individual match arm
53+
help: set the lint level on the whole match
54+
|
55+
LL + #[deny(non_exhaustive_omitted_patterns)]
56+
LL | match val {
5157
|
52-
LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
53-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5458

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
59+
warning: the lint level must be set on the whole match
60+
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:50:9
5761
|
62+
LL | #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
63+
| ------------------------------- remove this attribute
5864
LL | _ => {}
5965
| ^
6066
|
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
67+
= help: it no longer has any effect to set the lint level on an individual match arm
68+
help: set the lint level on the whole match
69+
|
70+
LL + #[warn(non_exhaustive_omitted_patterns)]
71+
LL | match val {
6472
|
65-
LL | #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
66-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6773

68-
error: aborting due to 4 previous errors; 1 warning emitted
74+
error: aborting due to 2 previous errors; 3 warnings emitted
6975

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

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

15-
error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match
15+
warning: the lint level must be set on the whole match
1616
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9
1717
|
18+
LL | #[deny(non_exhaustive_omitted_patterns)]
19+
| ------------------------------- remove this attribute
1820
LL | _ => {}
1921
| ^
2022
|
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
23+
= help: it no longer has any effect to set the lint level on an individual match arm
24+
help: set the lint level on the whole match
25+
|
26+
LL + #[deny(non_exhaustive_omitted_patterns)]
27+
LL | match val {
2428
|
25-
LL | #[deny(non_exhaustive_omitted_patterns)]
26-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2729

28-
error: aborting due to 2 previous errors
30+
error: aborting due to previous error; 1 warning emitted
2931

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

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

3738
match val {
3839
NonExhaustiveEnum::Unit => {}
3940
NonExhaustiveEnum::Tuple(_) => {}
4041
#[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
41-
_ => {} //[lint]~ ERROR lint level must be set on the whole match
42+
_ => {}
4243
}
44+
//[lint]~^^ WARN lint level must be set on the whole match
4345

4446
match val {
4547
NonExhaustiveEnum::Unit => {}
4648
NonExhaustiveEnum::Tuple(_) => {}
4749
#[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
48-
_ => {} //[lint]~ WARN lint level must be set on the whole match
50+
_ => {}
4951
}
52+
//[lint]~^^ WARN lint level must be set on the whole match
5053
}

0 commit comments

Comments
 (0)