Skip to content

Commit 64577dc

Browse files
committed
Suggest to set lint level on whole match
1 parent 8b9653f commit 64577dc

File tree

7 files changed

+82
-49
lines changed

7 files changed

+82
-49
lines changed

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

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)]

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

+11-5
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,18 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
218218
cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern))
219219
}
220220

221-
fn new_cx(&self, hir_id: HirId, refutable: bool) -> MatchCheckCtxt<'p, 'tcx> {
221+
fn new_cx(
222+
&self,
223+
hir_id: HirId,
224+
refutable: bool,
225+
match_span: Option<Span>,
226+
) -> MatchCheckCtxt<'p, 'tcx> {
222227
MatchCheckCtxt {
223228
tcx: self.tcx,
224229
param_env: self.param_env,
225230
module: self.tcx.parent_module(hir_id).to_def_id(),
226231
pattern_arena: &self.pattern_arena,
232+
match_span,
227233
refutable,
228234
}
229235
}
@@ -238,7 +244,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
238244
return;
239245
}
240246
self.check_patterns(pat, Refutable);
241-
let mut cx = self.new_cx(self.lint_level, true);
247+
let mut cx = self.new_cx(self.lint_level, true, None);
242248
let tpat = self.lower_pattern(&mut cx, pat);
243249
self.check_let_reachability(&mut cx, self.lint_level, source, tpat, span);
244250
}
@@ -250,7 +256,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
250256
source: hir::MatchSource,
251257
expr_span: Span,
252258
) {
253-
let mut cx = self.new_cx(self.lint_level, true);
259+
let mut cx = self.new_cx(self.lint_level, true, Some(expr_span));
254260

255261
for &arm in arms {
256262
// Check the arm for some things unrelated to exhaustiveness.
@@ -363,7 +369,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
363369
error = Err(err);
364370
return None;
365371
}
366-
let mut ncx = self.new_cx(local_lint_level, true);
372+
let mut ncx = self.new_cx(local_lint_level, true, None);
367373
let tpat = self.lower_pattern(&mut ncx, pat);
368374
let refutable = !is_let_irrefutable(&mut ncx, local_lint_level, tpat);
369375
Some((expr.span, refutable))
@@ -468,7 +474,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
468474
return;
469475
}
470476

471-
let mut cx = self.new_cx(self.lint_level, false);
477+
let mut cx = self.new_cx(self.lint_level, false, None);
472478

473479
let pattern = self.lower_pattern(&mut cx, pat);
474480
let pattern_ty = pattern.ty();

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
}

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

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

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)