@@ -3,6 +3,7 @@ use clippy_utils::eager_or_lazy::switch_to_eager_eval;
3
3
use clippy_utils:: path_to_local_id;
4
4
use clippy_utils:: source:: snippet;
5
5
use clippy_utils:: ty:: is_type_diagnostic_item;
6
+ use clippy_utils:: visitors:: is_local_used;
6
7
use rustc_ast:: LitKind :: Bool ;
7
8
use rustc_errors:: Applicability ;
8
9
use rustc_hir:: { BinOpKind , Expr , ExprKind , PatKind } ;
@@ -14,20 +15,13 @@ use super::UNNECESSARY_PATTERN_MATCHING;
14
15
// Only checking map_or for now
15
16
pub ( super ) fn check ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , recv : & Expr < ' _ > , def : & Expr < ' _ > , map : & Expr < ' _ > ) {
16
17
if let ExprKind :: Lit ( def_kind) = def. kind
17
- // only works on Result and Option
18
18
&& let recv_ty = cx. typeck_results ( ) . expr_ty ( recv)
19
19
&& ( is_type_diagnostic_item ( cx, recv_ty, sym:: Option )
20
20
|| is_type_diagnostic_item ( cx, recv_ty, sym:: Result ) )
21
- // check we are dealing with boolean map_or
22
21
&& let Bool ( def_bool) = def_kind. node
23
22
&& let ExprKind :: Closure ( map_closure) = map. kind
24
23
&& let closure_body = cx. tcx . hir ( ) . body ( map_closure. body )
25
24
&& 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)
31
25
&& let ExprKind :: Binary ( op, l, r) = closure_body_value. kind
32
26
&& let Some ( param) = closure_body. params . first ( )
33
27
&& let PatKind :: Binding ( _, hir_id, _, _) = param. pat . kind
@@ -45,17 +39,21 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def:
45
39
} else {
46
40
"Result"
47
41
} ;
48
-
49
42
let comparator = if BinOpKind :: Eq == op. node { "==" } else { "!=" } ;
50
-
51
43
// we already checked either l or r is the local id earlier
52
44
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
+ } ;
54
52
span_lint_and_sugg (
55
53
cx,
56
54
UNNECESSARY_PATTERN_MATCHING ,
57
55
expr. span ,
58
- "`map_or` here is redundant, use standard comparison instead" ,
56
+ "`map_or` is redundant, use standard comparison instead" ,
59
57
"try" ,
60
58
format ! (
61
59
"{} {} {}({})" ,
0 commit comments