11use clippy_utils:: diagnostics:: span_lint_and_then;
22use clippy_utils:: ty:: is_type_diagnostic_item;
3+ use clippy_utils:: visitors:: for_each_expr_without_closures;
34use clippy_utils:: { higher, SpanlessEq } ;
5+ use core:: ops:: ControlFlow ;
46use rustc_errors:: Diag ;
5- use rustc_hir:: intravisit:: { self as visit, Visitor } ;
67use rustc_hir:: { Expr , ExprKind } ;
78use rustc_lint:: { LateContext , LateLintPass } ;
89use rustc_session:: declare_lint_pass;
@@ -44,21 +45,27 @@ declare_lint_pass!(IfLetMutex => [IF_LET_MUTEX]);
4445
4546impl < ' tcx > LateLintPass < ' tcx > for IfLetMutex {
4647 fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > ) {
47- let mut arm_visit = ArmVisitor { found_mutex : None , cx } ;
48- let mut op_visit = OppVisitor { found_mutex : None , cx } ;
4948 if let Some ( higher:: IfLet {
5049 let_expr,
5150 if_then,
5251 if_else : Some ( if_else) ,
5352 ..
5453 } ) = higher:: IfLet :: hir ( cx, expr)
5554 {
56- op_visit. visit_expr ( let_expr) ;
57- if let Some ( op_mutex) = op_visit. found_mutex {
58- arm_visit. visit_expr ( if_then) ;
59- arm_visit. visit_expr ( if_else) ;
55+ let is_mutex_lock = |e : & ' tcx Expr < ' tcx > | {
56+ if let Some ( mutex) = is_mutex_lock_call ( cx, e) {
57+ ControlFlow :: Break ( mutex)
58+ } else {
59+ ControlFlow :: Continue ( ( ) )
60+ }
61+ } ;
6062
61- if let Some ( arm_mutex) = arm_visit. found_mutex_if_same_as ( op_mutex) {
63+ let op_mutex = for_each_expr_without_closures ( let_expr, is_mutex_lock) ;
64+ if let Some ( op_mutex) = op_mutex {
65+ let arm_mutex = for_each_expr_without_closures ( ( if_then, if_else) , is_mutex_lock) ;
66+ if let Some ( arm_mutex) = arm_mutex
67+ && SpanlessEq :: new ( cx) . eq_expr ( op_mutex, arm_mutex)
68+ {
6269 let diag = |diag : & mut Diag < ' _ , ( ) > | {
6370 diag. span_label (
6471 op_mutex. span ,
@@ -83,48 +90,6 @@ impl<'tcx> LateLintPass<'tcx> for IfLetMutex {
8390 }
8491}
8592
86- /// Checks if `Mutex::lock` is called in the `if let` expr.
87- pub struct OppVisitor < ' a , ' tcx > {
88- found_mutex : Option < & ' tcx Expr < ' tcx > > ,
89- cx : & ' a LateContext < ' tcx > ,
90- }
91-
92- impl < ' tcx > Visitor < ' tcx > for OppVisitor < ' _ , ' tcx > {
93- fn visit_expr ( & mut self , expr : & ' tcx Expr < ' _ > ) {
94- if let Some ( mutex) = is_mutex_lock_call ( self . cx , expr) {
95- self . found_mutex = Some ( mutex) ;
96- return ;
97- }
98- visit:: walk_expr ( self , expr) ;
99- }
100- }
101-
102- /// Checks if `Mutex::lock` is called in any of the branches.
103- pub struct ArmVisitor < ' a , ' tcx > {
104- found_mutex : Option < & ' tcx Expr < ' tcx > > ,
105- cx : & ' a LateContext < ' tcx > ,
106- }
107-
108- impl < ' tcx > Visitor < ' tcx > for ArmVisitor < ' _ , ' tcx > {
109- fn visit_expr ( & mut self , expr : & ' tcx Expr < ' tcx > ) {
110- if let Some ( mutex) = is_mutex_lock_call ( self . cx , expr) {
111- self . found_mutex = Some ( mutex) ;
112- return ;
113- }
114- visit:: walk_expr ( self , expr) ;
115- }
116- }
117-
118- impl < ' tcx , ' l > ArmVisitor < ' tcx , ' l > {
119- fn found_mutex_if_same_as ( & self , op_mutex : & Expr < ' _ > ) -> Option < & Expr < ' _ > > {
120- self . found_mutex . and_then ( |arm_mutex| {
121- SpanlessEq :: new ( self . cx )
122- . eq_expr ( op_mutex, arm_mutex)
123- . then_some ( arm_mutex)
124- } )
125- }
126- }
127-
12893fn is_mutex_lock_call < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) -> Option < & ' tcx Expr < ' tcx > > {
12994 if let ExprKind :: MethodCall ( path, self_arg, ..) = & expr. kind
13095 && path. ident . as_str ( ) == "lock"
0 commit comments