Warn when lint level is set on a match arm
This commit is contained in:
parent
7b19fb88be
commit
61d0fc7cf5
7 changed files with 107 additions and 27 deletions
|
@ -221,6 +221,9 @@ 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
|
.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
|
.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_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
|
mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type `{$ty}` is non-empty
|
||||||
.def_note = `{$peeled_ty}` defined here
|
.def_note = `{$peeled_ty}` defined here
|
||||||
.type_note = the matched value is of type `{$ty}`
|
.type_note = the matched value is of type `{$ty}`
|
||||||
|
|
|
@ -789,6 +789,11 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
|
||||||
pub uncovered: Uncovered<'tcx>,
|
pub uncovered: Uncovered<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(LintDiagnostic)]
|
||||||
|
#[diag(mir_build_non_exhaustive_omitted_pattern_lint_on_arm)]
|
||||||
|
#[help]
|
||||||
|
pub(crate) struct NonExhaustiveOmittedPatternLintOnArm;
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic)]
|
||||||
#[label(mir_build_uncovered)]
|
#[label(mir_build_uncovered)]
|
||||||
pub(crate) struct Uncovered<'tcx> {
|
pub(crate) struct Uncovered<'tcx> {
|
||||||
|
|
|
@ -311,7 +311,10 @@ use super::deconstruct_pat::{
|
||||||
Constructor, ConstructorSet, DeconstructedPat, IntRange, MaybeInfiniteInt, SplitConstructorSet,
|
Constructor, ConstructorSet, DeconstructedPat, IntRange, MaybeInfiniteInt, SplitConstructorSet,
|
||||||
WitnessPat,
|
WitnessPat,
|
||||||
};
|
};
|
||||||
use crate::errors::{NonExhaustiveOmittedPattern, Overlap, OverlappingRangeEndpoints, Uncovered};
|
use crate::errors::{
|
||||||
|
NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Overlap,
|
||||||
|
OverlappingRangeEndpoints, Uncovered,
|
||||||
|
};
|
||||||
|
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
|
|
||||||
|
@ -1149,28 +1152,45 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
|
||||||
|
|
||||||
// Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
|
// Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
|
||||||
// `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
|
// `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
|
||||||
if cx.refutable
|
if cx.refutable && non_exhaustiveness_witnesses.is_empty() {
|
||||||
&& non_exhaustiveness_witnesses.is_empty()
|
if !matches!(
|
||||||
&& !matches!(
|
|
||||||
cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, lint_root).0,
|
cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, lint_root).0,
|
||||||
rustc_session::lint::Level::Allow
|
rustc_session::lint::Level::Allow
|
||||||
)
|
) {
|
||||||
{
|
let witnesses = collect_nonexhaustive_missing_variants(cx, &pat_column);
|
||||||
let witnesses = collect_nonexhaustive_missing_variants(cx, &pat_column);
|
|
||||||
if !witnesses.is_empty() {
|
if !witnesses.is_empty() {
|
||||||
// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
|
// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
|
||||||
// is not exhaustive enough.
|
// is not exhaustive enough.
|
||||||
//
|
//
|
||||||
// NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
|
// NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
|
||||||
cx.tcx.emit_spanned_lint(
|
cx.tcx.emit_spanned_lint(
|
||||||
NON_EXHAUSTIVE_OMITTED_PATTERNS,
|
NON_EXHAUSTIVE_OMITTED_PATTERNS,
|
||||||
lint_root,
|
lint_root,
|
||||||
scrut_span,
|
scrut_span,
|
||||||
NonExhaustiveOmittedPattern {
|
NonExhaustiveOmittedPattern {
|
||||||
scrut_ty,
|
scrut_ty,
|
||||||
uncovered: Uncovered::new(scrut_span, cx, witnesses),
|
uncovered: Uncovered::new(scrut_span, cx, witnesses),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We used to allow putting the `#[allow(non_exhaustive_omitted_patterns)]` on a match
|
||||||
|
// 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,12 @@ fn repeat() -> ! {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn f(x: Ordering) {
|
pub fn f(x: Ordering) {
|
||||||
|
#[deny(non_exhaustive_omitted_patterns)]
|
||||||
match x {
|
match x {
|
||||||
Ordering::Relaxed => println!("relaxed"),
|
Ordering::Relaxed => println!("relaxed"),
|
||||||
Ordering::Release => println!("release"),
|
Ordering::Release => println!("release"),
|
||||||
Ordering::Acquire => println!("acquire"),
|
Ordering::Acquire => println!("acquire"),
|
||||||
Ordering::AcqRel | Ordering::SeqCst => repeat(),
|
Ordering::AcqRel | Ordering::SeqCst => repeat(),
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
|
||||||
_ => repeat(),
|
_ => repeat(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,5 +26,44 @@ note: the lint level is defined here
|
||||||
LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
|
LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: the `non_exhaustive_omitted_pattern` 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
|
||||||
|
|
|
||||||
|
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
|
||||||
|
|
|
||||||
|
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
|
||||||
|
|
|
||||||
|
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
|
||||||
|
|
|
||||||
|
LL | #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
|
|
@ -12,5 +12,18 @@ note: the lint level is defined here
|
||||||
LL | #[deny(non_exhaustive_omitted_patterns)]
|
LL | #[deny(non_exhaustive_omitted_patterns)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: the `non_exhaustive_omitted_pattern` 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: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -31,20 +31,20 @@ fn main() {
|
||||||
NonExhaustiveEnum::Unit => {}
|
NonExhaustiveEnum::Unit => {}
|
||||||
NonExhaustiveEnum::Tuple(_) => {}
|
NonExhaustiveEnum::Tuple(_) => {}
|
||||||
#[deny(non_exhaustive_omitted_patterns)]
|
#[deny(non_exhaustive_omitted_patterns)]
|
||||||
_ => {}
|
_ => {} //~ ERROR lint level must be set on the whole match
|
||||||
}
|
}
|
||||||
|
|
||||||
match val {
|
match val {
|
||||||
NonExhaustiveEnum::Unit => {}
|
NonExhaustiveEnum::Unit => {}
|
||||||
NonExhaustiveEnum::Tuple(_) => {}
|
NonExhaustiveEnum::Tuple(_) => {}
|
||||||
#[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
|
#[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))]
|
||||||
_ => {}
|
_ => {} //[lint]~ ERROR lint level must be set on the whole match
|
||||||
}
|
}
|
||||||
|
|
||||||
match val {
|
match val {
|
||||||
NonExhaustiveEnum::Unit => {}
|
NonExhaustiveEnum::Unit => {}
|
||||||
NonExhaustiveEnum::Tuple(_) => {}
|
NonExhaustiveEnum::Tuple(_) => {}
|
||||||
#[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
|
#[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))]
|
||||||
_ => {}
|
_ => {} //[lint]~ WARN lint level must be set on the whole match
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue