1
1
use crate :: utils:: { match_type, paths, span_lint_and_help} ;
2
2
use if_chain:: if_chain;
3
- use rustc_hir:: { Expr , ExprKind , MatchSource , StmtKind } ;
3
+ use rustc_hir:: { Arm , Expr , ExprKind , MatchSource , Stmt , StmtKind } ;
4
4
use rustc_lint:: { LateContext , LateLintPass } ;
5
5
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
6
6
@@ -11,7 +11,7 @@ declare_clippy_lint! {
11
11
/// **Why is this bad?** The Mutex lock remains held for the whole
12
12
/// `if let ... else` block and deadlocks.
13
13
///
14
- /// **Known problems:** This lint does not generate an auto-applicable suggestion .
14
+ /// **Known problems:** None .
15
15
///
16
16
/// **Example:**
17
17
///
@@ -49,47 +49,7 @@ impl LateLintPass<'_, '_> for IfLetMutex {
49
49
if match_type( cx, ty, & paths:: MUTEX ) ; // make sure receiver is Mutex
50
50
if method_chain_names( op, 10 ) . iter( ) . any( |s| s == "lock" ) ; // and lock is called
51
51
52
- if arms. iter( ) . any( |arm| if_chain! {
53
- if let ExprKind :: Block ( ref block, _l) = arm. body. kind;
54
- if block. stmts. iter( ) . any( |stmt| match stmt. kind {
55
- StmtKind :: Local ( l) => if_chain! {
56
- if let Some ( ex) = l. init;
57
- if let ExprKind :: MethodCall ( _, _, _) = op. kind;
58
- if method_chain_names( ex, 10 ) . iter( ) . any( |s| s == "lock" ) ; // and lock is called
59
- then {
60
- match_type_method_chain( cx, ex, 5 )
61
- } else {
62
- false
63
- }
64
- } ,
65
- StmtKind :: Expr ( e) => if_chain! {
66
- if let ExprKind :: MethodCall ( _, _, _) = e. kind;
67
- if method_chain_names( e, 10 ) . iter( ) . any( |s| s == "lock" ) ; // and lock is called
68
- then {
69
- match_type_method_chain( cx, ex, 5 )
70
- } else {
71
- false
72
- }
73
- } ,
74
- StmtKind :: Semi ( e) => if_chain! {
75
- if let ExprKind :: MethodCall ( _, _, _) = e. kind;
76
- if method_chain_names( e, 10 ) . iter( ) . any( |s| s == "lock" ) ; // and lock is called
77
- then {
78
- match_type_method_chain( cx, ex, 5 )
79
- } else {
80
- false
81
- }
82
- } ,
83
- _ => {
84
- false
85
- } ,
86
- } ) ;
87
- then {
88
- true
89
- } else {
90
- false
91
- }
92
- } ) ;
52
+ if arms. iter( ) . any( |arm| matching_arm( arm, op, ex, cx) ) ;
93
53
then {
94
54
span_lint_and_help(
95
55
cx,
@@ -103,6 +63,52 @@ impl LateLintPass<'_, '_> for IfLetMutex {
103
63
}
104
64
}
105
65
66
+ fn matching_arm ( arm : & Arm < ' _ > , op : & Expr < ' _ > , ex : & Expr < ' _ > , cx : & LateContext < ' _ , ' _ > ) -> bool {
67
+ if_chain ! {
68
+ if let ExprKind :: Block ( ref block, _l) = arm. body. kind;
69
+ if block. stmts. iter( ) . any( |stmt| matching_stmt( stmt, op, ex, cx) ) ;
70
+ then {
71
+ true
72
+ } else {
73
+ false
74
+ }
75
+ }
76
+ }
77
+
78
+ fn matching_stmt ( stmt : & Stmt < ' _ > , op : & Expr < ' _ > , ex : & Expr < ' _ > , cx : & LateContext < ' _ , ' _ > ) -> bool {
79
+ match stmt. kind {
80
+ StmtKind :: Local ( l) => if_chain ! {
81
+ if let Some ( ex) = l. init;
82
+ if let ExprKind :: MethodCall ( _, _, _) = op. kind;
83
+ if method_chain_names( ex, 10 ) . iter( ) . any( |s| s == "lock" ) ; // and lock is called
84
+ then {
85
+ match_type_method_chain( cx, ex, 5 )
86
+ } else {
87
+ false
88
+ }
89
+ } ,
90
+ StmtKind :: Expr ( e) => if_chain ! {
91
+ if let ExprKind :: MethodCall ( _, _, _) = e. kind;
92
+ if method_chain_names( e, 10 ) . iter( ) . any( |s| s == "lock" ) ; // and lock is called
93
+ then {
94
+ match_type_method_chain( cx, ex, 5 )
95
+ } else {
96
+ false
97
+ }
98
+ } ,
99
+ StmtKind :: Semi ( e) => if_chain ! {
100
+ if let ExprKind :: MethodCall ( _, _, _) = e. kind;
101
+ if method_chain_names( e, 10 ) . iter( ) . any( |s| s == "lock" ) ; // and lock is called
102
+ then {
103
+ match_type_method_chain( cx, ex, 5 )
104
+ } else {
105
+ false
106
+ }
107
+ } ,
108
+ _ => false ,
109
+ }
110
+ }
111
+
106
112
/// Return the names of `max_depth` number of methods called in the chain.
107
113
fn method_chain_names < ' tcx > ( expr : & ' tcx Expr < ' tcx > , max_depth : usize ) -> Vec < String > {
108
114
let mut method_names = Vec :: with_capacity ( max_depth) ;
0 commit comments