From feac3b9823338a5b3f04c77a39c2def21e218e20 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 31 Oct 2023 21:48:26 +0100 Subject: [PATCH] Suggest to set lint level on whole match --- compiler/rustc_mir_build/messages.ftl | 1 + compiler/rustc_mir_build/src/errors.rs | 9 ++++++++- .../src/thir/pattern/check_match.rs | 16 +++++++++++----- .../src/thir/pattern/usefulness.rs | 14 +++++++++----- ...omitted-patterns-dont-lint-on-arm.lint.stderr | 15 +++++++++++++++ ...itted-patterns-dont-lint-on-arm.normal.stderr | 5 +++++ 6 files changed, 49 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index ed16d41a74334..25f2bcf59c2c6 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -223,6 +223,7 @@ mir_build_non_exhaustive_omitted_pattern = some variants are not matched explici 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 + .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 c305bbb457019..95f157639cb2f 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 { + #[suggestion( + code = "#[{lint_level}(non_exhaustive_omitted_patterns)]\n", + applicability = "maybe-incorrect" + )] + pub suggest_lint_on_match: Option, + pub lint_level: &'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 9156af3425aea..ac1c73e82fdf0 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -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, + ) -> 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, } } @@ -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); } @@ -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. @@ -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)) @@ -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(); diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index a69da949cf8ef..a3ca7f3a2f875 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -339,6 +339,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, } @@ -1178,15 +1180,17 @@ 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 - ) { + let lint_level = + cx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.hir_id).0; + if !matches!(lint_level, rustc_session::lint::Level::Allow) { cx.tcx.emit_spanned_lint( NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.hir_id, arm.pat.span(), - NonExhaustiveOmittedPatternLintOnArm, + NonExhaustiveOmittedPatternLintOnArm { + suggest_lint_on_match: cx.match_span, + lint_level: lint_level.as_str(), + }, ); } } 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..6da0290df421d 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 @@ -38,6 +38,11 @@ note: the lint level is defined here | LL | #[deny(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: set the lint level on the whole match + | +LL + #[deny(non_exhaustive_omitted_patterns)] +LL | match val { + | 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 @@ -51,6 +56,11 @@ note: the lint level is defined here | LL | #[cfg_attr(lint, deny(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: set the lint level on the whole match + | +LL + #[deny(non_exhaustive_omitted_patterns)] +LL | match val { + | 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 @@ -64,6 +74,11 @@ note: the lint level is defined here | LL | #[cfg_attr(lint, warn(non_exhaustive_omitted_patterns))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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 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..9997d9bb52cf5 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 @@ -24,6 +24,11 @@ note: the lint level is defined here | LL | #[deny(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: set the lint level on the whole match + | +LL + #[deny(non_exhaustive_omitted_patterns)] +LL | match val { + | error: aborting due to 2 previous errors