From 7b19fb88bedccb58dfcce15d1c1c604f3635babf Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 23 Oct 2023 18:27:33 +0200 Subject: [PATCH 1/3] Add tests --- ...tted-patterns-dont-lint-on-arm.lint.stderr | 30 +++++++++++ ...ed-patterns-dont-lint-on-arm.normal.stderr | 16 ++++++ .../omitted-patterns-dont-lint-on-arm.rs | 50 +++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr create mode 100644 tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr create mode 100644 tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr new file mode 100644 index 0000000000000..c58b07d1aef2f --- /dev/null +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr @@ -0,0 +1,30 @@ +error: some variants are not matched explicitly + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:15:11 + | +LL | match val { + | ^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:14:12 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:23:11 + | +LL | match val { + | ^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:22:27 + | +LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr new file mode 100644 index 0000000000000..2d94a09de6344 --- /dev/null +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr @@ -0,0 +1,16 @@ +error: some variants are not matched explicitly + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:15:11 + | +LL | match val { + | ^^^ pattern `NonExhaustiveEnum::Struct { .. }` not covered + | + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found +note: the lint level is defined here + --> $DIR/omitted-patterns-dont-lint-on-arm.rs:14:12 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs new file mode 100644 index 0000000000000..9411d8f085bbf --- /dev/null +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs @@ -0,0 +1,50 @@ +// revisions: normal lint +// Test that putting the lint level on a match arm emits a warning, as this was previously +// meaningful and is no longer. +#![feature(non_exhaustive_omitted_patterns_lint)] + +// aux-build:enums.rs +extern crate enums; + +use enums::NonExhaustiveEnum; + +fn main() { + let val = NonExhaustiveEnum::Unit; + + #[deny(non_exhaustive_omitted_patterns)] + match val { + //~^ ERROR some variants are not matched explicitly + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + _ => {} + } + + #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] + match val { + //[lint]~^ ERROR some variants are not matched explicitly + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + _ => {} + } + + match val { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + + match val { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] + _ => {} + } + + match val { + NonExhaustiveEnum::Unit => {} + NonExhaustiveEnum::Tuple(_) => {} + #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))] + _ => {} + } +} From 61d0fc7cf5f1ae6c9b7f1321376f251ce8139ef7 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 23 Oct 2023 18:55:04 +0200 Subject: [PATCH 2/3] Warn when lint level is set on a match arm --- compiler/rustc_mir_build/messages.ftl | 3 + compiler/rustc_mir_build/src/errors.rs | 5 ++ .../src/thir/pattern/usefulness.rs | 62 ++++++++++++------- .../ui/match_same_arms_non_exhaustive.rs | 2 +- ...tted-patterns-dont-lint-on-arm.lint.stderr | 41 +++++++++++- ...ed-patterns-dont-lint-on-arm.normal.stderr | 15 ++++- .../omitted-patterns-dont-lint-on-arm.rs | 6 +- 7 files changed, 107 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 32711c23dc4e4..ed16d41a74334 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -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 .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 .def_note = `{$peeled_ty}` defined here .type_note = the matched value is of type `{$ty}` diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 5bfce3ab51008..378a957df0fb9 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -789,6 +789,11 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> { pub uncovered: Uncovered<'tcx>, } +#[derive(LintDiagnostic)] +#[diag(mir_build_non_exhaustive_omitted_pattern_lint_on_arm)] +#[help] +pub(crate) struct NonExhaustiveOmittedPatternLintOnArm; + #[derive(Subdiagnostic)] #[label(mir_build_uncovered)] pub(crate) struct Uncovered<'tcx> { diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 1eb1dd72a61d5..233b911bfee11 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -311,7 +311,10 @@ use super::deconstruct_pat::{ Constructor, ConstructorSet, DeconstructedPat, IntRange, MaybeInfiniteInt, SplitConstructorSet, WitnessPat, }; -use crate::errors::{NonExhaustiveOmittedPattern, Overlap, OverlappingRangeEndpoints, Uncovered}; +use crate::errors::{ + NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Overlap, + OverlappingRangeEndpoints, Uncovered, +}; 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 // `if let`s. Only run if the match is exhaustive otherwise the error is redundant. - if cx.refutable - && non_exhaustiveness_witnesses.is_empty() - && !matches!( + if cx.refutable && non_exhaustiveness_witnesses.is_empty() { + if !matches!( cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, lint_root).0, rustc_session::lint::Level::Allow - ) - { - let witnesses = collect_nonexhaustive_missing_variants(cx, &pat_column); - if !witnesses.is_empty() { - // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns` - // is not exhaustive enough. - // - // NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`. - cx.tcx.emit_spanned_lint( - NON_EXHAUSTIVE_OMITTED_PATTERNS, - lint_root, - scrut_span, - NonExhaustiveOmittedPattern { - scrut_ty, - uncovered: Uncovered::new(scrut_span, cx, witnesses), - }, - ); + ) { + let witnesses = collect_nonexhaustive_missing_variants(cx, &pat_column); + + if !witnesses.is_empty() { + // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns` + // is not exhaustive enough. + // + // NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`. + cx.tcx.emit_spanned_lint( + NON_EXHAUSTIVE_OMITTED_PATTERNS, + lint_root, + scrut_span, + NonExhaustiveOmittedPattern { + scrut_ty, + 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, + ); + } + } } } diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs index e1b95aa577604..5c277f925a8f1 100644 --- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs +++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs @@ -9,12 +9,12 @@ fn repeat() -> ! { } pub fn f(x: Ordering) { + #[deny(non_exhaustive_omitted_patterns)] match x { Ordering::Relaxed => println!("relaxed"), Ordering::Release => println!("release"), Ordering::Acquire => println!("acquire"), Ordering::AcqRel | Ordering::SeqCst => repeat(), - #[deny(non_exhaustive_omitted_patterns)] _ => repeat(), } } diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr index c58b07d1aef2f..b0629c6de1a48 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr @@ -26,5 +26,44 @@ note: the lint level is defined here 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 diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr index 2d94a09de6344..a7a2ad3a5f0d3 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr @@ -12,5 +12,18 @@ note: the lint level is defined here 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 diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs index 9411d8f085bbf..ac7b7cd93fd1f 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs @@ -31,20 +31,20 @@ fn main() { NonExhaustiveEnum::Unit => {} NonExhaustiveEnum::Tuple(_) => {} #[deny(non_exhaustive_omitted_patterns)] - _ => {} + _ => {} //~ ERROR 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 } 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 } } From f0e83308791698b47a738c8fe0a762624c88a2e0 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 2 Nov 2023 06:21:08 +0100 Subject: [PATCH 3/3] Suggest to set lint level on whole match --- compiler/rustc_mir_build/messages.ftl | 6 ++- compiler/rustc_mir_build/src/errors.rs | 9 +++- .../src/thir/pattern/check_match.rs | 11 +++-- .../src/thir/pattern/usefulness.rs | 27 +++++++---- ...tted-patterns-dont-lint-on-arm.lint.stderr | 48 +++++++++++-------- ...ed-patterns-dont-lint-on-arm.normal.stderr | 16 ++++--- .../omitted-patterns-dont-lint-on-arm.rs | 9 ++-- 7 files changed, 79 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index ed16d41a74334..563851f712c66 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -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 diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 378a957df0fb9..c4eed5532ee63 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -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, + pub lint_level: &'static str, + pub lint_name: &'static str, +} #[derive(Subdiagnostic)] #[label(mir_build_uncovered)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 165d3f37111e9..8c3d09c19a15a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -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, + ) -> 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()); diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 233b911bfee11..da7b6587a7220 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -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>, + /// The span of the whole match, if applicable. + pub(crate) match_span: Option, /// 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(); } } } diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr index b0629c6de1a48..9192c66143cc4 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.lint.stderr @@ -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 diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr index a7a2ad3a5f0d3..46093eb9fb35f 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.normal.stderr @@ -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 diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs index ac7b7cd93fd1f..33f9f56a5bbc8 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns-dont-lint-on-arm.rs @@ -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 }