Skip to content

Commit

Permalink
Suggest to set lint level on whole match
Browse files Browse the repository at this point in the history
  • Loading branch information
Nadrieril committed Nov 2, 2023
1 parent 8b9653f commit 64577dc
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 49 deletions.
6 changes: 4 additions & 2 deletions compiler/rustc_mir_build/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,10 @@ mir_build_non_exhaustive_omitted_pattern = some variants are not matched explici
.help = ensure that all variants are matched explicitly by adding the suggested match arms
.note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found
mir_build_non_exhaustive_omitted_pattern_lint_on_arm = the `non_exhaustive_omitted_pattern` lint level must be set on the whole match
.help = it used to make sense to set the lint level on an individual match arm, but that is no longer the case
mir_build_non_exhaustive_omitted_pattern_lint_on_arm = the lint level must be set on the whole match
.help = it no longer has any effect to set the lint level on an individual match arm
.label = remove this attribute
.suggestion = set the lint level on the whole match
mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
.def_note = `{$peeled_ty}` defined here
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_mir_build/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,14 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
#[derive(LintDiagnostic)]
#[diag(mir_build_non_exhaustive_omitted_pattern_lint_on_arm)]
#[help]
pub(crate) struct NonExhaustiveOmittedPatternLintOnArm;
pub(crate) struct NonExhaustiveOmittedPatternLintOnArm {
#[label]
pub lint_span: Span,
#[suggestion(code = "#[{lint_level}({lint_name})]\n", applicability = "maybe-incorrect")]
pub suggest_lint_on_match: Option<Span>,
pub lint_level: &'static str,
pub lint_name: &'static str,
}

#[derive(Subdiagnostic)]
#[label(mir_build_uncovered)]
Expand Down
16 changes: 11 additions & 5 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,18 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern))
}

fn new_cx(&self, hir_id: HirId, refutable: bool) -> MatchCheckCtxt<'p, 'tcx> {
fn new_cx(
&self,
hir_id: HirId,
refutable: bool,
match_span: Option<Span>,
) -> MatchCheckCtxt<'p, 'tcx> {
MatchCheckCtxt {
tcx: self.tcx,
param_env: self.param_env,
module: self.tcx.parent_module(hir_id).to_def_id(),
pattern_arena: &self.pattern_arena,
match_span,
refutable,
}
}
Expand All @@ -238,7 +244,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
return;
}
self.check_patterns(pat, Refutable);
let mut cx = self.new_cx(self.lint_level, true);
let mut cx = self.new_cx(self.lint_level, true, None);
let tpat = self.lower_pattern(&mut cx, pat);
self.check_let_reachability(&mut cx, self.lint_level, source, tpat, span);
}
Expand All @@ -250,7 +256,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
source: hir::MatchSource,
expr_span: Span,
) {
let mut cx = self.new_cx(self.lint_level, true);
let mut cx = self.new_cx(self.lint_level, true, Some(expr_span));

for &arm in arms {
// Check the arm for some things unrelated to exhaustiveness.
Expand Down Expand Up @@ -363,7 +369,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
error = Err(err);
return None;
}
let mut ncx = self.new_cx(local_lint_level, true);
let mut ncx = self.new_cx(local_lint_level, true, None);
let tpat = self.lower_pattern(&mut ncx, pat);
let refutable = !is_let_irrefutable(&mut ncx, local_lint_level, tpat);
Some((expr.span, refutable))
Expand Down Expand Up @@ -468,7 +474,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
return;
}

let mut cx = self.new_cx(self.lint_level, false);
let mut cx = self.new_cx(self.lint_level, false, None);

let pattern = self.lower_pattern(&mut cx, pat);
let pattern_ty = pattern.ty();
Expand Down
27 changes: 17 additions & 10 deletions compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,8 @@ pub(crate) struct MatchCheckCtxt<'p, 'tcx> {
pub(crate) module: DefId,
pub(crate) param_env: ty::ParamEnv<'tcx>,
pub(crate) pattern_arena: &'p TypedArena<DeconstructedPat<'p, 'tcx>>,
/// The span of the whole match, if applicable.
pub(crate) match_span: Option<Span>,
/// Only produce `NON_EXHAUSTIVE_OMITTED_PATTERNS` lint on refutable patterns.
pub(crate) refutable: bool,
}
Expand Down Expand Up @@ -1179,16 +1181,21 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
// arm. This no longer makes sense so we warn users, to avoid silently breaking their
// usage of the lint.
for arm in arms {
if !matches!(
cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.hir_id).0,
rustc_session::lint::Level::Allow
) {
cx.tcx.emit_spanned_lint(
NON_EXHAUSTIVE_OMITTED_PATTERNS,
arm.hir_id,
arm.pat.span(),
NonExhaustiveOmittedPatternLintOnArm,
);
let (lint_level, lint_level_source) =
cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.hir_id);
if !matches!(lint_level, rustc_session::lint::Level::Allow) {
let decorator = NonExhaustiveOmittedPatternLintOnArm {
lint_span: lint_level_source.span(),
suggest_lint_on_match: cx.match_span.map(|span| span.shrink_to_lo()),
lint_level: lint_level.as_str(),
lint_name: "non_exhaustive_omitted_patterns",
};

use rustc_errors::DecorateLint;
let mut err = cx.tcx.sess.struct_span_warn(arm.pat.span(), "");
err.set_primary_message(decorator.msg());
decorator.decorate_lint(&mut err);
err.emit();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,44 +26,50 @@ note: the lint level is defined here
LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match
warning: the lint level must be set on the whole match
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9
|
LL | #[deny(non_exhaustive_omitted_patterns)]
| ------------------------------- remove this attribute
LL | _ => {}
| ^
|
= help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case
note: the lint level is defined here
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:33:16
= help: it no longer has any effect to set the lint level on an individual match arm
help: set the lint level on the whole match
|
LL + #[deny(non_exhaustive_omitted_patterns)]
LL | match val {
|
LL | #[deny(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:41:9
warning: the lint level must be set on the whole match
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:42:9
|
LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
| ------------------------------- remove this attribute
LL | _ => {}
| ^
|
= help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case
note: the lint level is defined here
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:40:31
= help: it no longer has any effect to set the lint level on an individual match arm
help: set the lint level on the whole match
|
LL + #[deny(non_exhaustive_omitted_patterns)]
LL | match val {
|
LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:48:9
warning: the lint level must be set on the whole match
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:50:9
|
LL | #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
| ------------------------------- remove this attribute
LL | _ => {}
| ^
|
= help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case
note: the lint level is defined here
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:47:31
= help: it no longer has any effect to set the lint level on an individual match arm
help: set the lint level on the whole match
|
LL + #[warn(non_exhaustive_omitted_patterns)]
LL | match val {
|
LL | #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 4 previous errors; 1 warning emitted
error: aborting due to 2 previous errors; 3 warnings emitted

Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,20 @@ note: the lint level is defined here
LL | #[deny(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: the `non_exhaustive_omitted_pattern` lint level must be set on the whole match
warning: the lint level must be set on the whole match
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:34:9
|
LL | #[deny(non_exhaustive_omitted_patterns)]
| ------------------------------- remove this attribute
LL | _ => {}
| ^
|
= help: it used to make sense to set the lint level on an individual match arm, but that is no longer the case
note: the lint level is defined here
--> $DIR/omitted-patterns-dont-lint-on-arm.rs:33:16
= help: it no longer has any effect to set the lint level on an individual match arm
help: set the lint level on the whole match
|
LL + #[deny(non_exhaustive_omitted_patterns)]
LL | match val {
|
LL | #[deny(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors
error: aborting due to previous error; 1 warning emitted

Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,23 @@ fn main() {
NonExhaustiveEnum::Unit => {}
NonExhaustiveEnum::Tuple(_) => {}
#[deny(non_exhaustive_omitted_patterns)]
_ => {} //~ ERROR lint level must be set on the whole match
_ => {}
}
//~^^ WARN lint level must be set on the whole match

match val {
NonExhaustiveEnum::Unit => {}
NonExhaustiveEnum::Tuple(_) => {}
#[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
_ => {} //[lint]~ ERROR lint level must be set on the whole match
_ => {}
}
//[lint]~^^ WARN lint level must be set on the whole match

match val {
NonExhaustiveEnum::Unit => {}
NonExhaustiveEnum::Tuple(_) => {}
#[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
_ => {} //[lint]~ WARN lint level must be set on the whole match
_ => {}
}
//[lint]~^^ WARN lint level must be set on the whole match
}

0 comments on commit 64577dc

Please sign in to comment.