@@ -4,9 +4,8 @@ use clippy_utils::{fn_def_id, path_to_local_id, paths, peel_ref_operators};
44use rustc_ast:: Mutability ;
55use rustc_hir:: intravisit:: { walk_expr, Visitor } ;
66use 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 } ;
88use rustc_lint:: { LateContext , LateLintPass } ;
9- use rustc_middle:: ty:: Ty ;
109use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
1110
1211declare_clippy_lint ! {
@@ -117,6 +116,10 @@ impl<'a, 'tcx> PeekableVisitor<'a, 'tcx> {
117116
118117impl < ' tcx > Visitor < ' _ > for PeekableVisitor < ' _ , ' tcx > {
119118 fn visit_expr ( & mut self , ex : & ' _ Expr < ' _ > ) {
119+ if self . found_peek_call {
120+ return ;
121+ }
122+
120123 if path_to_local_id ( ex, self . expected_hir_id ) {
121124 for ( _, node) in self . cx . tcx . hir ( ) . parent_iter ( ex. hir_id ) {
122125 match node {
@@ -138,50 +141,35 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
138141 return ;
139142 }
140143
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| {
145+ matches ! ( arg. kind, ExprKind :: Path ( _) ) && arg_is_mut_peekable ( self . cx , arg)
146+ } ) {
147+ self . found_peek_call = true ;
148+ return ;
153149 }
154150 } ,
155- // Peekable::peek()
156- ExprKind :: MethodCall ( PathSegment { ident : method_name , .. } , [ arg, ..] , _) => {
151+ // Catch anything taking a Peekable mutably
152+ ExprKind :: MethodCall ( _ , [ arg, ..] , _) => {
157153 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 )
154+
155+ if let ExprKind :: Path ( _) = arg. kind
156+ && arg_is_mut_peekable ( self . cx , arg)
167157 {
168158 self . found_peek_call = true ;
169159 return ;
170160 }
171161 } ,
172- // Don't bother if moved into a struct
173- ExprKind :: Struct ( ..) => {
162+ ExprKind :: AddrOf ( _, Mutability :: Mut , _) | ExprKind :: Unary ( ..) | ExprKind :: DropTemps ( _) => {
163+ } ,
164+ ExprKind :: AddrOf ( _, Mutability :: Not , _) => return ,
165+ _ => {
174166 self . found_peek_call = true ;
175167 return ;
176168 } ,
177- _ => { } ,
178169 }
179170 } ,
180171 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- {
172+ if arg_is_mut_peekable ( self . cx , init) {
185173 self . found_peek_call = true ;
186174 return ;
187175 }
@@ -206,3 +194,14 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
206194 walk_expr ( self , ex) ;
207195 }
208196}
197+
198+ fn arg_is_mut_peekable ( cx : & LateContext < ' _ > , arg : & Expr < ' _ > ) -> bool {
199+ if let Some ( ty) = cx. typeck_results ( ) . expr_ty_opt ( arg)
200+ && let ( ty, _, Mutability :: Mut ) = peel_mid_ty_refs_is_mutable ( ty)
201+ && match_type ( cx, ty, & paths:: PEEKABLE )
202+ {
203+ true
204+ } else {
205+ false
206+ }
207+ }
0 commit comments