about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs58
-rw-r--r--tests/ui/lint/lint-match-arms-2.rs24
-rw-r--r--tests/ui/lint/lint-match-arms-2.stderr29
3 files changed, 88 insertions, 23 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 ca25f83e643..3d4f2cad047 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -90,35 +90,34 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> {
 
     #[instrument(level = "trace", skip(self))]
     fn visit_arm(&mut self, arm: &Arm<'tcx>) {
-        match arm.guard {
-            Some(Guard::If(expr)) => {
-                self.with_let_source(LetSource::IfLetGuard, |this| {
-                    this.visit_expr(&this.thir[expr])
-                });
-            }
-            Some(Guard::IfLet(ref pat, expr)) => {
-                self.with_let_source(LetSource::IfLetGuard, |this| {
-                    this.check_let(pat, expr, LetSource::IfLetGuard, pat.span);
-                    this.visit_pat(pat);
-                    this.visit_expr(&this.thir[expr]);
-                });
+        self.with_lint_level(arm.lint_level, |this| {
+            match arm.guard {
+                Some(Guard::If(expr)) => {
+                    this.with_let_source(LetSource::IfLetGuard, |this| {
+                        this.visit_expr(&this.thir[expr])
+                    });
+                }
+                Some(Guard::IfLet(ref pat, expr)) => {
+                    this.with_let_source(LetSource::IfLetGuard, |this| {
+                        this.check_let(pat, expr, LetSource::IfLetGuard, pat.span);
+                        this.visit_pat(pat);
+                        this.visit_expr(&this.thir[expr]);
+                    });
+                }
+                None => {}
             }
-            None => {}
-        }
-        self.visit_pat(&arm.pattern);
-        self.visit_expr(&self.thir[arm.body]);
+            this.visit_pat(&arm.pattern);
+            this.visit_expr(&self.thir[arm.body]);
+        });
     }
 
     #[instrument(level = "trace", skip(self))]
     fn visit_expr(&mut self, ex: &Expr<'tcx>) {
         match ex.kind {
             ExprKind::Scope { value, lint_level, .. } => {
-                let old_lint_level = self.lint_level;
-                if let LintLevel::Explicit(hir_id) = lint_level {
-                    self.lint_level = hir_id;
-                }
-                self.visit_expr(&self.thir[value]);
-                self.lint_level = old_lint_level;
+                self.with_lint_level(lint_level, |this| {
+                    this.visit_expr(&this.thir[value]);
+                });
                 return;
             }
             ExprKind::If { cond, then, else_opt, if_then_scope: _ } => {
@@ -190,6 +189,17 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         self.let_source = old_let_source;
     }
 
+    fn with_lint_level(&mut self, new_lint_level: LintLevel, f: impl FnOnce(&mut Self)) {
+        if let LintLevel::Explicit(hir_id) = new_lint_level {
+            let old_lint_level = self.lint_level;
+            self.lint_level = hir_id;
+            f(self);
+            self.lint_level = old_lint_level;
+        } else {
+            f(self);
+        }
+    }
+
     fn check_patterns(&self, pat: &Pat<'tcx>, rf: RefutableFlag) {
         pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
         check_for_bindings_named_same_as_variants(self, pat, rf);
@@ -236,7 +246,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         for &arm in arms {
             // Check the arm for some things unrelated to exhaustiveness.
             let arm = &self.thir.arms[arm];
-            self.check_patterns(&arm.pattern, Refutable);
+            self.with_lint_level(arm.lint_level, |this| {
+                this.check_patterns(&arm.pattern, Refutable);
+            });
         }
 
         let tarms: Vec<_> = arms
diff --git a/tests/ui/lint/lint-match-arms-2.rs b/tests/ui/lint/lint-match-arms-2.rs
new file mode 100644
index 00000000000..0c1146339c4
--- /dev/null
+++ b/tests/ui/lint/lint-match-arms-2.rs
@@ -0,0 +1,24 @@
+#![feature(if_let_guard)]
+#![allow(unused, non_snake_case)]
+
+enum E {
+    A,
+}
+
+#[allow(bindings_with_variant_name, irrefutable_let_patterns)]
+fn foo() {
+    match E::A {
+        #[deny(bindings_with_variant_name)]
+        A => {}
+    //~^ ERROR pattern binding `A` is named the same as one of the variants of the type `E`
+    }
+
+    match &E::A {
+        #[deny(irrefutable_let_patterns)]
+        a if let b = a => {}
+    //~^ ERROR irrefutable `if let` guard pattern
+        _ => {}
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/lint/lint-match-arms-2.stderr b/tests/ui/lint/lint-match-arms-2.stderr
new file mode 100644
index 00000000000..062d5c12e96
--- /dev/null
+++ b/tests/ui/lint/lint-match-arms-2.stderr
@@ -0,0 +1,29 @@
+error[E0170]: pattern binding `A` is named the same as one of the variants of the type `E`
+  --> $DIR/lint-match-arms-2.rs:12:9
+   |
+LL |         A => {}
+   |         ^ help: to match on the variant, qualify the path: `E::A`
+   |
+note: the lint level is defined here
+  --> $DIR/lint-match-arms-2.rs:11:16
+   |
+LL |         #[deny(bindings_with_variant_name)]
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: irrefutable `if let` guard pattern
+  --> $DIR/lint-match-arms-2.rs:18:18
+   |
+LL |         a if let b = a => {}
+   |                  ^
+   |
+   = note: this pattern will always match, so the guard is useless
+   = help: consider removing the guard and adding a `let` inside the match arm
+note: the lint level is defined here
+  --> $DIR/lint-match-arms-2.rs:17:16
+   |
+LL |         #[deny(irrefutable_let_patterns)]
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0170`.