Skip to content

Commit fa82547

Browse files
committed
finalise implementation of match_or lint case
1 parent 80292c9 commit fa82547

File tree

4 files changed

+82
-12
lines changed

4 files changed

+82
-12
lines changed

clippy_lints/src/methods/unnecessary_pattern_matching.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use clippy_utils::eager_or_lazy::switch_to_eager_eval;
33
use clippy_utils::path_to_local_id;
44
use clippy_utils::source::snippet;
55
use clippy_utils::ty::is_type_diagnostic_item;
6+
use clippy_utils::visitors::is_local_used;
67
use rustc_ast::LitKind::Bool;
78
use rustc_errors::Applicability;
89
use rustc_hir::{BinOpKind, Expr, ExprKind, PatKind};
@@ -14,20 +15,13 @@ use super::UNNECESSARY_PATTERN_MATCHING;
1415
// Only checking map_or for now
1516
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def: &Expr<'_>, map: &Expr<'_>) {
1617
if let ExprKind::Lit(def_kind) = def.kind
17-
// only works on Result and Option
1818
&& let recv_ty = cx.typeck_results().expr_ty(recv)
1919
&& (is_type_diagnostic_item(cx, recv_ty, sym::Option)
2020
|| is_type_diagnostic_item(cx, recv_ty, sym::Result))
21-
// check we are dealing with boolean map_or
2221
&& let Bool(def_bool) = def_kind.node
2322
&& let ExprKind::Closure(map_closure) = map.kind
2423
&& let closure_body = cx.tcx.hir().body(map_closure.body)
2524
&& let closure_body_value = closure_body.value.peel_blocks()
26-
// switching from closure to direct comparison changes the comparison
27-
// from lazy (when map_or evaluates to first param) to eager, so we force eager here
28-
// this stops the lint running whenever the closure has a potentially expensive
29-
// computation inside of it
30-
&& switch_to_eager_eval(cx, closure_body_value)
3125
&& let ExprKind::Binary(op, l, r) = closure_body_value.kind
3226
&& let Some(param) = closure_body.params.first()
3327
&& let PatKind::Binding(_, hir_id, _, _) = param.pat.kind
@@ -45,17 +39,21 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def:
4539
} else {
4640
"Result"
4741
};
48-
4942
let comparator = if BinOpKind::Eq == op.node { "==" } else { "!=" };
50-
5143
// we already checked either l or r is the local id earlier
5244
let non_binding_location = if path_to_local_id(l, hir_id) { r } else { l };
53-
45+
// we switch to eager in the event that the closure has an
46+
// expensive computation inside of it
47+
if is_local_used(cx, non_binding_location, hir_id)
48+
|| !switch_to_eager_eval(cx, non_binding_location)
49+
|| l.kind {
50+
return;
51+
};
5452
span_lint_and_sugg(
5553
cx,
5654
UNNECESSARY_PATTERN_MATCHING,
5755
expr.span,
58-
"`map_or` here is redundant, use standard comparison instead",
56+
"`map_or` is redundant, use standard comparison instead",
5957
"try",
6058
format!(
6159
"{} {} {}({})",
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#![warn(clippy::unnecessary_pattern_matching)]
2+
#![allow(clippy::no_effect)]
3+
#![allow(clippy::eq_op)]
4+
5+
fn main() {
6+
// should trigger
7+
let _ = Some(5) == Some(5);
8+
let _ = Some(5) == Some(5);
9+
let _ = Some(5) != Some(5);
10+
let _ = Some(5) != Some(5);
11+
let _ = Some(vec![5]) == Some([5]);
12+
13+
// shouldnt trigger
14+
let _ = Some(5).map_or(true, |n| n == 5);
15+
let _ = Some(5).map_or(true, |n| 5 == n);
16+
let _ = Some(5).map_or(false, |n| n != 5);
17+
let _ = Some(5).map_or(false, |n| 5 != n);
18+
let _ = Some(5).map_or(false, |n| n == n);
19+
let _ = Some(vec![1]).map_or(false, |n| vec![2] == n);
20+
let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 });
21+
}
Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
#![warn(clippy::unnecessary_pattern_matching)]
2+
#![allow(clippy::no_effect)]
3+
#![allow(clippy::eq_op)]
24

35
fn main() {
4-
// test code goes here
6+
// should trigger
7+
let _ = Some(5).map_or(false, |n| n == 5);
8+
let _ = Some(5).map_or(false, |n| 5 == n);
9+
let _ = Some(5).map_or(true, |n| n != 5);
10+
let _ = Some(5).map_or(true, |n| 5 != n);
11+
let _ = Some(vec![5]).map_or(false, |n| n == [5]);
12+
13+
// shouldnt trigger
14+
let _ = Some(5).map_or(true, |n| n == 5);
15+
let _ = Some(5).map_or(true, |n| 5 == n);
16+
let _ = Some(5).map_or(false, |n| n != 5);
17+
let _ = Some(5).map_or(false, |n| 5 != n);
18+
let _ = Some(5).map_or(false, |n| n == n);
19+
let _ = Some(vec![1]).map_or(false, |n| vec![2] == n);
20+
let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 });
521
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: `map_or` is redundant, use standard comparison instead
2+
--> $DIR/unnecessary_pattern_matching.rs:7:13
3+
|
4+
LL | let _ = Some(5).map_or(false, |n| n == 5);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(5) == Some(5)`
6+
|
7+
= note: `-D clippy::unnecessary-pattern-matching` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_pattern_matching)]`
9+
10+
error: `map_or` is redundant, use standard comparison instead
11+
--> $DIR/unnecessary_pattern_matching.rs:8:13
12+
|
13+
LL | let _ = Some(5).map_or(false, |n| 5 == n);
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(5) == Some(5)`
15+
16+
error: `map_or` is redundant, use standard comparison instead
17+
--> $DIR/unnecessary_pattern_matching.rs:9:13
18+
|
19+
LL | let _ = Some(5).map_or(true, |n| n != 5);
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(5) != Some(5)`
21+
22+
error: `map_or` is redundant, use standard comparison instead
23+
--> $DIR/unnecessary_pattern_matching.rs:10:13
24+
|
25+
LL | let _ = Some(5).map_or(true, |n| 5 != n);
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(5) != Some(5)`
27+
28+
error: `map_or` is redundant, use standard comparison instead
29+
--> $DIR/unnecessary_pattern_matching.rs:11:13
30+
|
31+
LL | let _ = Some(vec![5]).map_or(false, |n| n == [5]);
32+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(vec![5]) == Some([5])`
33+
34+
error: aborting due to 5 previous errors
35+

0 commit comments

Comments
 (0)