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]) - }); + 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 => {} } - 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]); - }); - } - 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`.