Suggest to set lint level on whole match

This commit is contained in:
Nadrieril 2023-11-02 06:21:08 +01:00
parent 61d0fc7cf5
commit f0e8330879
7 changed files with 84 additions and 52 deletions

View File

@ -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

View File

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

View File

@ -285,7 +285,11 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
}
}
fn new_cx(&self, refutability: RefutableFlag) -> MatchCheckCtxt<'p, 'tcx> {
fn new_cx(
&self,
refutability: RefutableFlag,
match_span: Option<Span>,
) -> MatchCheckCtxt<'p, 'tcx> {
let refutable = match refutability {
Irrefutable => false,
Refutable => true,
@ -295,6 +299,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
param_env: self.param_env,
module: self.tcx.parent_module(self.lint_level).to_def_id(),
pattern_arena: &self.pattern_arena,
match_span,
refutable,
}
}
@ -325,7 +330,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
source: hir::MatchSource,
expr_span: Span,
) {
let cx = self.new_cx(Refutable);
let cx = self.new_cx(Refutable, Some(expr_span));
let mut tarms = Vec::with_capacity(arms.len());
for &arm in arms {
@ -448,7 +453,7 @@ impl<'thir, 'p, 'tcx> MatchVisitor<'thir, 'p, 'tcx> {
pat: &Pat<'tcx>,
refutability: RefutableFlag,
) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> {
let cx = self.new_cx(refutability);
let cx = self.new_cx(refutability, None);
let pat = self.lower_pattern(&cx, pat)?;
let arms = [MatchArm { pat, hir_id: self.lint_level, has_guard: false }];
let report = compute_match_usefulness(&cx, &arms, self.lint_level, pat.ty(), pat.span());

View File

@ -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,
}
@ -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();
}
}
}

View File

@ -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 | _ => {}
| ^
|
= 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
|
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
|
| ------------------------------- 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 {
|
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))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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
|
| ------------------------------- 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 + #[deny(non_exhaustive_omitted_patterns)]
LL | match val {
|
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 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 {
|
error: aborting due to 4 previous errors; 1 warning emitted
error: aborting due to 2 previous errors; 3 warnings emitted

View File

@ -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

View File

@ -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
}