Skip to content

Commit f79c47f

Browse files
committed
Match underscore-prefixed variable also
1 parent 920cdb5 commit f79c47f

File tree

3 files changed

+113
-19
lines changed

3 files changed

+113
-19
lines changed

clippy_lints/src/matches.rs

+41-4
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,24 @@ use crate::consts::{constant, miri_to_const, Constant};
22
use crate::utils::paths;
33
use crate::utils::sugg::Sugg;
44
use crate::utils::{
5-
expr_block, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg, remove_blocks, snippet,
5+
expr_block, is_allowed, is_expn_of, match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet,
66
snippet_with_applicability, span_help_and_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint,
77
walk_ptrs_ty,
88
};
99
use if_chain::if_chain;
10-
use rustc::lint::in_external_macro;
10+
use rustc::hir::map::Map;
11+
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
1112
use rustc::ty::{self, Ty};
1213
use rustc_errors::Applicability;
1314
use rustc_hir::def::CtorKind;
15+
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
1416
use rustc_hir::*;
1517
use rustc_lint::{LateContext, LateLintPass, LintContext};
1618
use rustc_session::{declare_lint_pass, declare_tool_lint};
1719
use rustc_span::source_map::Span;
1820
use std::cmp::Ordering;
1921
use std::collections::Bound;
20-
use syntax::ast::LitKind;
22+
use syntax::ast::{self, LitKind};
2123

2224
declare_clippy_lint! {
2325
/// **What it does:** Checks for matches with a single arm where an `if let`
@@ -468,6 +470,41 @@ fn is_wild<'tcx>(pat: &impl std::ops::Deref<Target = Pat<'tcx>>) -> bool {
468470
}
469471
}
470472

473+
fn is_unused_underscored<'tcx>(patkind: &'tcx PatKind<'_>, body: &'tcx Expr<'_>) -> bool {
474+
match patkind {
475+
PatKind::Binding(.., ident, None) if ident.as_str().starts_with('_') => {
476+
let mut visitor = UsedVisitor {
477+
var: ident.name,
478+
used: false,
479+
};
480+
walk_expr(&mut visitor, body);
481+
!visitor.used
482+
},
483+
_ => false,
484+
}
485+
}
486+
487+
struct UsedVisitor {
488+
var: ast::Name, // var to look for
489+
used: bool, // has the var been used otherwise?
490+
}
491+
492+
impl<'tcx> Visitor<'tcx> for UsedVisitor {
493+
type Map = Map<'tcx>;
494+
495+
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
496+
if match_var(expr, self.var) {
497+
self.used = true;
498+
} else {
499+
walk_expr(self, expr);
500+
}
501+
}
502+
503+
fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
504+
NestedVisitorMap::None
505+
}
506+
}
507+
471508
fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
472509
let ex_ty = walk_ptrs_ty(cx.tables.expr_ty(ex));
473510
if match_type(cx, ex_ty, &paths::RESULT) {
@@ -476,7 +513,7 @@ fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>])
476513
let path_str = print::to_string(print::NO_ANN, |s| s.print_qpath(path, false));
477514
if_chain! {
478515
if path_str == "Err";
479-
if inner.iter().any(is_wild);
516+
if inner.iter().any(is_wild) || inner.iter().any(|pat| is_unused_underscored(&pat.kind, arm.body));
480517
if let ExprKind::Block(ref block, _) = arm.body.kind;
481518
if is_panic_block(block);
482519
then {

tests/ui/matches.rs

+13
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,19 @@ fn match_wild_err_arm() {
2828
},
2929
}
3030

31+
match x {
32+
Ok(3) => println!("ok"),
33+
Ok(_) => println!("ok"),
34+
Err(_e) => panic!(),
35+
}
36+
37+
// Allowed when used in `panic!`.
38+
match x {
39+
Ok(3) => println!("ok"),
40+
Ok(_) => println!("ok"),
41+
Err(_e) => panic!("{}", _e),
42+
}
43+
3144
// Allowed when not with `panic!` block.
3245
match x {
3346
Ok(3) => println!("ok"),

tests/ui/matches.stderr

+59-15
Original file line numberDiff line numberDiff line change
@@ -78,37 +78,45 @@ LL | Ok(3) => println!("ok"),
7878
| ^^^^^
7979
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
8080

81+
error: `Err(_)` will match all errors, maybe not a good idea
82+
--> $DIR/matches.rs:34:9
83+
|
84+
LL | Err(_e) => panic!(),
85+
| ^^^^^^^
86+
|
87+
= note: to remove this warning, match each error separately or use `unreachable!` macro
88+
8189
error: this `match` has identical arm bodies
82-
--> $DIR/matches.rs:34:18
90+
--> $DIR/matches.rs:33:18
8391
|
8492
LL | Ok(_) => println!("ok"),
8593
| ^^^^^^^^^^^^^^
8694
|
8795
note: same as this
88-
--> $DIR/matches.rs:33:18
96+
--> $DIR/matches.rs:32:18
8997
|
9098
LL | Ok(3) => println!("ok"),
9199
| ^^^^^^^^^^^^^^
92100
help: consider refactoring into `Ok(3) | Ok(_)`
93-
--> $DIR/matches.rs:33:9
101+
--> $DIR/matches.rs:32:9
94102
|
95103
LL | Ok(3) => println!("ok"),
96104
| ^^^^^
97105
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
98106

99107
error: this `match` has identical arm bodies
100-
--> $DIR/matches.rs:41:18
108+
--> $DIR/matches.rs:40:18
101109
|
102110
LL | Ok(_) => println!("ok"),
103111
| ^^^^^^^^^^^^^^
104112
|
105113
note: same as this
106-
--> $DIR/matches.rs:40:18
114+
--> $DIR/matches.rs:39:18
107115
|
108116
LL | Ok(3) => println!("ok"),
109117
| ^^^^^^^^^^^^^^
110118
help: consider refactoring into `Ok(3) | Ok(_)`
111-
--> $DIR/matches.rs:40:9
119+
--> $DIR/matches.rs:39:9
112120
|
113121
LL | Ok(3) => println!("ok"),
114122
| ^^^^^
@@ -133,58 +141,94 @@ LL | Ok(3) => println!("ok"),
133141
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
134142

135143
error: this `match` has identical arm bodies
144+
--> $DIR/matches.rs:54:18
145+
|
146+
LL | Ok(_) => println!("ok"),
147+
| ^^^^^^^^^^^^^^
148+
|
149+
note: same as this
136150
--> $DIR/matches.rs:53:18
137151
|
152+
LL | Ok(3) => println!("ok"),
153+
| ^^^^^^^^^^^^^^
154+
help: consider refactoring into `Ok(3) | Ok(_)`
155+
--> $DIR/matches.rs:53:9
156+
|
157+
LL | Ok(3) => println!("ok"),
158+
| ^^^^^
159+
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
160+
161+
error: this `match` has identical arm bodies
162+
--> $DIR/matches.rs:60:18
163+
|
164+
LL | Ok(_) => println!("ok"),
165+
| ^^^^^^^^^^^^^^
166+
|
167+
note: same as this
168+
--> $DIR/matches.rs:59:18
169+
|
170+
LL | Ok(3) => println!("ok"),
171+
| ^^^^^^^^^^^^^^
172+
help: consider refactoring into `Ok(3) | Ok(_)`
173+
--> $DIR/matches.rs:59:9
174+
|
175+
LL | Ok(3) => println!("ok"),
176+
| ^^^^^
177+
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
178+
179+
error: this `match` has identical arm bodies
180+
--> $DIR/matches.rs:66:18
181+
|
138182
LL | Ok(_) => println!("ok"),
139183
| ^^^^^^^^^^^^^^
140184
|
141185
note: same as this
142-
--> $DIR/matches.rs:52:18
186+
--> $DIR/matches.rs:65:18
143187
|
144188
LL | Ok(3) => println!("ok"),
145189
| ^^^^^^^^^^^^^^
146190
help: consider refactoring into `Ok(3) | Ok(_)`
147-
--> $DIR/matches.rs:52:9
191+
--> $DIR/matches.rs:65:9
148192
|
149193
LL | Ok(3) => println!("ok"),
150194
| ^^^^^
151195
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
152196

153197
error: this `match` has identical arm bodies
154-
--> $DIR/matches.rs:76:29
198+
--> $DIR/matches.rs:89:29
155199
|
156200
LL | (Ok(_), Some(x)) => println!("ok {}", x),
157201
| ^^^^^^^^^^^^^^^^^^^^
158202
|
159203
note: same as this
160-
--> $DIR/matches.rs:75:29
204+
--> $DIR/matches.rs:88:29
161205
|
162206
LL | (Ok(x), Some(_)) => println!("ok {}", x),
163207
| ^^^^^^^^^^^^^^^^^^^^
164208
help: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))`
165-
--> $DIR/matches.rs:75:9
209+
--> $DIR/matches.rs:88:9
166210
|
167211
LL | (Ok(x), Some(_)) => println!("ok {}", x),
168212
| ^^^^^^^^^^^^^^^^
169213
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
170214

171215
error: this `match` has identical arm bodies
172-
--> $DIR/matches.rs:91:18
216+
--> $DIR/matches.rs:104:18
173217
|
174218
LL | Ok(_) => println!("ok"),
175219
| ^^^^^^^^^^^^^^
176220
|
177221
note: same as this
178-
--> $DIR/matches.rs:90:18
222+
--> $DIR/matches.rs:103:18
179223
|
180224
LL | Ok(3) => println!("ok"),
181225
| ^^^^^^^^^^^^^^
182226
help: consider refactoring into `Ok(3) | Ok(_)`
183-
--> $DIR/matches.rs:90:9
227+
--> $DIR/matches.rs:103:9
184228
|
185229
LL | Ok(3) => println!("ok"),
186230
| ^^^^^
187231
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
188232

189-
error: aborting due to 12 previous errors
233+
error: aborting due to 15 previous errors
190234

0 commit comments

Comments
 (0)