From 03a6ef67fe72c58d976c3e83ffab2296179ae8a4 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 3 Apr 2023 16:13:06 +0000 Subject: [PATCH] Only emit lint on refutable patterns. --- .../rustc_mir_build/src/thir/pattern/check_match.rs | 11 ++++++----- .../rustc_mir_build/src/thir/pattern/usefulness.rs | 7 ++++--- 2 files changed, 10 insertions(+), 8 deletions(-) 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 de63e07b7d5..0882b473f10 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -199,12 +199,13 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern)) } - fn new_cx(&self, hir_id: HirId) -> MatchCheckCtxt<'p, 'tcx> { + fn new_cx(&self, hir_id: HirId, refutable: bool) -> 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, + refutable, } } @@ -214,7 +215,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { return; } self.check_patterns(pat, Refutable); - let mut cx = self.new_cx(self.lint_level); + let mut cx = self.new_cx(self.lint_level, true); let tpat = self.lower_pattern(&mut cx, pat); self.check_let_reachability(&mut cx, self.lint_level, source, tpat, span); } @@ -226,7 +227,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { source: hir::MatchSource, expr_span: Span, ) { - let mut cx = self.new_cx(self.lint_level); + let mut cx = self.new_cx(self.lint_level, true); for &arm in arms { // Check the arm for some things unrelated to exhaustiveness. @@ -328,7 +329,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { debug!(?expr, ?local_lint_level, "after scopes"); match expr.kind { ExprKind::Let { box ref pat, expr: _ } => { - let mut ncx = self.new_cx(local_lint_level); + let mut ncx = self.new_cx(local_lint_level, true); let tpat = self.lower_pattern(&mut ncx, pat); let refutable = !is_let_irrefutable(&mut ncx, local_lint_level, tpat); Some((expr.span, refutable)) @@ -409,7 +410,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { #[instrument(level = "trace", skip(self))] fn check_irrefutable(&self, pat: &Pat<'tcx>, origin: &str, sp: Option) { - let mut cx = self.new_cx(self.lint_level); + let mut cx = self.new_cx(self.lint_level, false); 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 9edd7967e7a..8c89bcb8cec 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -300,7 +300,6 @@ use rustc_arena::TypedArena; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; use rustc_hir::HirId; -use rustc_hir::Node; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::{Span, DUMMY_SP}; @@ -319,6 +318,8 @@ pub(crate) struct MatchCheckCtxt<'p, 'tcx> { pub(crate) module: DefId, pub(crate) param_env: ty::ParamEnv<'tcx>, pub(crate) pattern_arena: &'p TypedArena>, + /// Only produce `NON_EXHAUSTIVE_OMITTED_PATTERNS` lint on refutable patterns. + pub(crate) refutable: bool, } impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { @@ -860,6 +861,8 @@ fn is_useful<'p, 'tcx>( // that has the potential to trigger the `non_exhaustive_omitted_patterns` lint. // To understand the workings checkout `Constructor::split` and `SplitWildcard::new/into_ctors` if is_non_exhaustive_and_wild + // Only emit a lint on refutable patterns. + && cx.refutable // We check that the match has a wildcard pattern and that wildcard is useful, // meaning there are variants that are covered by the wildcard. Without the check // for `witness_preference` the lint would trigger on `if let NonExhaustiveEnum::A = foo {}` @@ -868,8 +871,6 @@ fn is_useful<'p, 'tcx>( &ctor, Constructor::Missing { nonexhaustive_enum_missing_real_variants: true } ) - // We don't want to lint patterns which are function arguments or locals - && !matches!(cx.tcx.hir().find_parent(hir_id), Some(Node::Param(_)|Node::Local(_))) { let patterns = { let mut split_wildcard = SplitWildcard::new(pcx);