@@ -4,9 +4,8 @@ use clippy_utils::{fn_def_id, path_to_local_id, paths, peel_ref_operators};
4
4
use rustc_ast:: Mutability ;
5
5
use rustc_hir:: intravisit:: { walk_expr, Visitor } ;
6
6
use rustc_hir:: lang_items:: LangItem ;
7
- use rustc_hir:: { Block , Expr , ExprKind , HirId , Local , Node , PatKind , PathSegment , StmtKind } ;
7
+ use rustc_hir:: { Block , Expr , ExprKind , HirId , Local , Node , PatKind , StmtKind } ;
8
8
use rustc_lint:: { LateContext , LateLintPass } ;
9
- use rustc_middle:: ty:: Ty ;
10
9
use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
11
10
12
11
declare_clippy_lint ! {
@@ -117,6 +116,10 @@ impl<'a, 'tcx> PeekableVisitor<'a, 'tcx> {
117
116
118
117
impl < ' tcx > Visitor < ' _ > for PeekableVisitor < ' _ , ' tcx > {
119
118
fn visit_expr ( & mut self , ex : & ' _ Expr < ' _ > ) {
119
+ if self . found_peek_call {
120
+ return ;
121
+ }
122
+
120
123
if path_to_local_id ( ex, self . expected_hir_id ) {
121
124
for ( _, node) in self . cx . tcx . hir ( ) . parent_iter ( ex. hir_id ) {
122
125
match node {
@@ -138,50 +141,31 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
138
141
return ;
139
142
}
140
143
141
- for arg in args. iter ( ) . map ( |arg| peel_ref_operators ( self . cx , arg) ) {
142
- if let ExprKind :: Path ( _) = arg. kind
143
- && let Some ( ty) = self
144
- . cx
145
- . typeck_results ( )
146
- . expr_ty_opt ( arg)
147
- . map ( Ty :: peel_refs)
148
- && match_type ( self . cx , ty, & paths:: PEEKABLE )
149
- {
150
- self . found_peek_call = true ;
151
- return ;
152
- }
144
+ if args. iter ( ) . any ( |arg| arg_is_mut_peekable ( self . cx , arg) ) {
145
+ self . found_peek_call = true ;
146
+ return ;
153
147
}
154
148
} ,
155
- // Peekable::peek()
156
- ExprKind :: MethodCall ( PathSegment { ident : method_name , .. } , [ arg, ..] , _) => {
149
+ // Catch anything taking a Peekable mutably
150
+ ExprKind :: MethodCall ( _ , [ arg, ..] , _) => {
157
151
let arg = peel_ref_operators ( self . cx , arg) ;
158
- let method_name = method_name. name . as_str ( ) ;
159
-
160
- if ( method_name == "peek"
161
- || method_name == "peek_mut"
162
- || method_name == "next_if"
163
- || method_name == "next_if_eq" )
164
- && let ExprKind :: Path ( _) = arg. kind
165
- && let Some ( ty) = self . cx . typeck_results ( ) . expr_ty_opt ( arg) . map ( Ty :: peel_refs)
166
- && match_type ( self . cx , ty, & paths:: PEEKABLE )
167
- {
152
+
153
+ if arg_is_mut_peekable ( self . cx , arg) {
168
154
self . found_peek_call = true ;
169
155
return ;
170
156
}
171
157
} ,
172
- // Don't bother if moved into a struct
173
- ExprKind :: Struct ( ..) => {
158
+ ExprKind :: AddrOf ( _, Mutability :: Mut , _) | ExprKind :: Unary ( ..) | ExprKind :: DropTemps ( _) => {
159
+ } ,
160
+ ExprKind :: AddrOf ( _, Mutability :: Not , _) => return ,
161
+ _ => {
174
162
self . found_peek_call = true ;
175
163
return ;
176
164
} ,
177
- _ => { } ,
178
165
}
179
166
} ,
180
167
Node :: Local ( Local { init : Some ( init) , .. } ) => {
181
- if let Some ( ty) = self . cx . typeck_results ( ) . expr_ty_opt ( init)
182
- && let ( ty, _, Mutability :: Mut ) = peel_mid_ty_refs_is_mutable ( ty)
183
- && match_type ( self . cx , ty, & paths:: PEEKABLE )
184
- {
168
+ if arg_is_mut_peekable ( self . cx , init) {
185
169
self . found_peek_call = true ;
186
170
return ;
187
171
}
@@ -206,3 +190,14 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
206
190
walk_expr ( self , ex) ;
207
191
}
208
192
}
193
+
194
+ fn arg_is_mut_peekable ( cx : & LateContext < ' _ > , arg : & Expr < ' _ > ) -> bool {
195
+ if let Some ( ty) = cx. typeck_results ( ) . expr_ty_opt ( arg)
196
+ && let ( ty, _, Mutability :: Mut ) = peel_mid_ty_refs_is_mutable ( ty)
197
+ && match_type ( cx, ty, & paths:: PEEKABLE )
198
+ {
199
+ true
200
+ } else {
201
+ false
202
+ }
203
+ }
0 commit comments