1
+ use crate :: utils:: { match_type, paths, span_lint_and_help, SpanlessEq } ;
1
2
use if_chain:: if_chain;
2
- use crate :: utils:: { match_type, paths, span_lint_and_help} ;
3
3
use rustc_hir:: intravisit:: { self as visit, NestedVisitorMap , Visitor } ;
4
- use rustc_hir:: { Arm , Expr , ExprKind , MatchSource , StmtKind } ;
4
+ use rustc_hir:: { Expr , ExprKind , MatchSource } ;
5
5
use rustc_lint:: { LateContext , LateLintPass } ;
6
6
use rustc_middle:: hir:: map:: Map ;
7
7
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
@@ -44,10 +44,12 @@ impl LateLintPass<'_, '_> for IfLetMutex {
44
44
fn check_expr ( & mut self , cx : & LateContext < ' _ , ' _ > , ex : & ' _ Expr < ' _ > ) {
45
45
let mut arm_visit = ArmVisitor {
46
46
mutex_lock_called : false ,
47
+ found_mutex : None ,
47
48
cx,
48
49
} ;
49
50
let mut op_visit = OppVisitor {
50
51
mutex_lock_called : false ,
52
+ found_mutex : None ,
51
53
cx,
52
54
} ;
53
55
if let ExprKind :: Match (
@@ -64,7 +66,7 @@ impl LateLintPass<'_, '_> for IfLetMutex {
64
66
arm_visit. visit_arm ( arm) ;
65
67
}
66
68
67
- if arm_visit. mutex_lock_called {
69
+ if arm_visit. mutex_lock_called && arm_visit . same_mutex ( cx , op_visit . found_mutex . unwrap ( ) ) {
68
70
span_lint_and_help (
69
71
cx,
70
72
IF_LET_MUTEX ,
@@ -80,8 +82,9 @@ impl LateLintPass<'_, '_> for IfLetMutex {
80
82
81
83
/// Checks if `Mutex::lock` is called in the `if let _ = expr.
82
84
pub struct OppVisitor < ' tcx , ' l > {
83
- pub mutex_lock_called : bool ,
84
- pub cx : & ' tcx LateContext < ' tcx , ' l > ,
85
+ mutex_lock_called : bool ,
86
+ found_mutex : Option < & ' tcx Expr < ' tcx > > ,
87
+ cx : & ' tcx LateContext < ' tcx , ' l > ,
85
88
}
86
89
87
90
impl < ' tcx , ' l > Visitor < ' tcx > for OppVisitor < ' tcx , ' l > {
@@ -94,6 +97,7 @@ impl<'tcx, 'l> Visitor<'tcx> for OppVisitor<'tcx, 'l> {
94
97
let ty = self . cx. tables. expr_ty( & args[ 0 ] ) ;
95
98
if match_type( self . cx, ty, & paths:: MUTEX ) ;
96
99
then {
100
+ self . found_mutex = Some ( & args[ 0 ] ) ;
97
101
self . mutex_lock_called = true ;
98
102
return ;
99
103
}
@@ -108,46 +112,40 @@ impl<'tcx, 'l> Visitor<'tcx> for OppVisitor<'tcx, 'l> {
108
112
109
113
/// Checks if `Mutex::lock` is called in any of the branches.
110
114
pub struct ArmVisitor < ' tcx , ' l > {
111
- pub mutex_lock_called : bool ,
112
- pub cx : & ' tcx LateContext < ' tcx , ' l > ,
115
+ mutex_lock_called : bool ,
116
+ found_mutex : Option < & ' tcx Expr < ' tcx > > ,
117
+ cx : & ' tcx LateContext < ' tcx , ' l > ,
113
118
}
114
119
115
120
impl < ' tcx , ' l > Visitor < ' tcx > for ArmVisitor < ' tcx , ' l > {
116
121
type Map = Map < ' tcx > ;
117
122
118
- fn visit_expr ( & mut self , expr : & ' tcx Expr < ' _ > ) {
123
+ fn visit_expr ( & mut self , expr : & ' tcx Expr < ' tcx > ) {
119
124
if_chain ! {
120
125
if let ExprKind :: MethodCall ( path, _span, args) = & expr. kind;
121
126
if path. ident. to_string( ) == "lock" ;
122
127
let ty = self . cx. tables. expr_ty( & args[ 0 ] ) ;
123
128
if match_type( self . cx, ty, & paths:: MUTEX ) ;
124
129
then {
130
+ self . found_mutex = Some ( & args[ 0 ] ) ;
125
131
self . mutex_lock_called = true ;
126
132
return ;
127
133
}
128
134
}
129
135
visit:: walk_expr ( self , expr) ;
130
136
}
131
137
132
- fn visit_arm ( & mut self , arm : & ' tcx Arm < ' _ > ) {
133
- if let ExprKind :: Block ( ref block, _l) = arm. body . kind {
134
- for stmt in block. stmts {
135
- match stmt. kind {
136
- StmtKind :: Local ( loc) => {
137
- if let Some ( expr) = loc. init {
138
- self . visit_expr ( expr)
139
- }
140
- } ,
141
- StmtKind :: Expr ( expr) | StmtKind :: Semi ( expr) => self . visit_expr ( expr) ,
142
- // we don't care about `Item`
143
- _ => { } ,
144
- }
145
- }
146
- } ;
147
- visit:: walk_arm ( self , arm) ;
148
- }
149
-
150
138
fn nested_visit_map ( & mut self ) -> NestedVisitorMap < Self :: Map > {
151
139
NestedVisitorMap :: None
152
140
}
153
141
}
142
+
143
+ impl < ' tcx , ' l > ArmVisitor < ' tcx , ' l > {
144
+ fn same_mutex ( & self , cx : & LateContext < ' _ , ' _ > , op_mutex : & Expr < ' _ > ) -> bool {
145
+ if let Some ( arm_mutex) = self . found_mutex {
146
+ SpanlessEq :: new ( cx) . eq_expr ( op_mutex, arm_mutex)
147
+ } else {
148
+ false
149
+ }
150
+ }
151
+ }
0 commit comments