Consider lint check attributes on match arms in match checks
This commit is contained in:
parent
ddafe23401
commit
3a03587836
3 changed files with 88 additions and 23 deletions
|
@ -90,35 +90,34 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> {
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
fn visit_arm(&mut self, arm: &Arm<'tcx>) {
|
fn visit_arm(&mut self, arm: &Arm<'tcx>) {
|
||||||
match arm.guard {
|
self.with_lint_level(arm.lint_level, |this| {
|
||||||
Some(Guard::If(expr)) => {
|
match arm.guard {
|
||||||
self.with_let_source(LetSource::IfLetGuard, |this| {
|
Some(Guard::If(expr)) => {
|
||||||
this.visit_expr(&this.thir[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)) => {
|
this.visit_pat(&arm.pattern);
|
||||||
self.with_let_source(LetSource::IfLetGuard, |this| {
|
this.visit_expr(&self.thir[arm.body]);
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
fn visit_expr(&mut self, ex: &Expr<'tcx>) {
|
fn visit_expr(&mut self, ex: &Expr<'tcx>) {
|
||||||
match ex.kind {
|
match ex.kind {
|
||||||
ExprKind::Scope { value, lint_level, .. } => {
|
ExprKind::Scope { value, lint_level, .. } => {
|
||||||
let old_lint_level = self.lint_level;
|
self.with_lint_level(lint_level, |this| {
|
||||||
if let LintLevel::Explicit(hir_id) = lint_level {
|
this.visit_expr(&this.thir[value]);
|
||||||
self.lint_level = hir_id;
|
});
|
||||||
}
|
|
||||||
self.visit_expr(&self.thir[value]);
|
|
||||||
self.lint_level = old_lint_level;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ExprKind::If { cond, then, else_opt, if_then_scope: _ } => {
|
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;
|
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) {
|
fn check_patterns(&self, pat: &Pat<'tcx>, rf: RefutableFlag) {
|
||||||
pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
|
pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
|
||||||
check_for_bindings_named_same_as_variants(self, pat, rf);
|
check_for_bindings_named_same_as_variants(self, pat, rf);
|
||||||
|
@ -236,7 +246,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
||||||
for &arm in arms {
|
for &arm in arms {
|
||||||
// Check the arm for some things unrelated to exhaustiveness.
|
// Check the arm for some things unrelated to exhaustiveness.
|
||||||
let arm = &self.thir.arms[arm];
|
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
|
let tarms: Vec<_> = arms
|
||||||
|
|
24
tests/ui/lint/lint-match-arms-2.rs
Normal file
24
tests/ui/lint/lint-match-arms-2.rs
Normal file
|
@ -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() { }
|
29
tests/ui/lint/lint-match-arms-2.stderr
Normal file
29
tests/ui/lint/lint-match-arms-2.stderr
Normal file
|
@ -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`.
|
Loading…
Add table
Reference in a new issue