about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2023-04-03 16:13:06 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-04-03 16:13:06 +0000
commit03a6ef67fe72c58d976c3e83ffab2296179ae8a4 (patch)
tree954b61fd1f8580de2e17626aa86f6c7e2cd64530
parent03fbb3db1e3dd767caebe176a368e0e52aeb68cb (diff)
downloadrust-03a6ef67fe72c58d976c3e83ffab2296179ae8a4.tar.gz
rust-03a6ef67fe72c58d976c3e83ffab2296179ae8a4.zip
Only emit lint on refutable patterns.
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs11
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs7
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<Span>) {
-        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<DeconstructedPat<'p, 'tcx>>,
+    /// 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);