11use rustc_ast:: ast:: Attribute ;
22use rustc_errors:: Applicability ;
33use rustc_hir:: def_id:: { DefIdSet , LocalDefId } ;
4- use rustc_hir:: { self as hir, def:: Res , intravisit , QPath } ;
4+ use rustc_hir:: { self as hir, def:: Res , QPath } ;
55use rustc_lint:: { LateContext , LintContext } ;
66use rustc_middle:: {
77 lint:: in_external_macro,
@@ -13,8 +13,11 @@ use clippy_utils::attrs::is_proc_macro;
1313use clippy_utils:: diagnostics:: { span_lint_and_help, span_lint_and_then} ;
1414use clippy_utils:: source:: snippet_opt;
1515use clippy_utils:: ty:: is_must_use_ty;
16+ use clippy_utils:: visitors:: for_each_expr;
1617use clippy_utils:: { match_def_path, return_ty, trait_ref_of_method} ;
1718
19+ use core:: ops:: ControlFlow ;
20+
1821use super :: { DOUBLE_MUST_USE , MUST_USE_CANDIDATE , MUST_USE_UNIT } ;
1922
2023pub ( super ) fn check_item < ' tcx > ( cx : & LateContext < ' tcx > , item : & ' tcx hir:: Item < ' _ > ) {
@@ -200,79 +203,55 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &m
200203 }
201204}
202205
203- struct StaticMutVisitor < ' a , ' tcx > {
204- cx : & ' a LateContext < ' tcx > ,
205- mutates_static : bool ,
206+ fn is_mutated_static ( e : & hir:: Expr < ' _ > ) -> bool {
207+ use hir:: ExprKind :: { Field , Index , Path } ;
208+
209+ match e. kind {
210+ Path ( QPath :: Resolved ( _, path) ) => !matches ! ( path. res, Res :: Local ( _) ) ,
211+ Path ( _) => true ,
212+ Field ( inner, _) | Index ( inner, _) => is_mutated_static ( inner) ,
213+ _ => false ,
214+ }
206215}
207216
208- impl < ' a , ' tcx > intravisit :: Visitor < ' tcx > for StaticMutVisitor < ' a , ' tcx > {
209- fn visit_expr ( & mut self , expr : & ' tcx hir :: Expr < ' _ > ) {
217+ fn mutates_static < ' tcx > ( cx : & LateContext < ' tcx > , body : & ' tcx hir :: Body < ' _ > ) -> bool {
218+ for_each_expr ( body . value , |e| {
210219 use hir:: ExprKind :: { AddrOf , Assign , AssignOp , Call , MethodCall } ;
211220
212- if self . mutates_static {
213- return ;
214- }
215- match expr. kind {
221+ match e. kind {
216222 Call ( _, args) => {
217223 let mut tys = DefIdSet :: default ( ) ;
218224 for arg in args {
219- if self . cx . tcx . has_typeck_results ( arg. hir_id . owner . to_def_id ( ) )
220- && is_mutable_ty (
221- self . cx ,
222- self . cx . tcx . typeck ( arg. hir_id . owner . def_id ) . expr_ty ( arg) ,
223- arg. span ,
224- & mut tys,
225- )
225+ if cx. tcx . has_typeck_results ( arg. hir_id . owner . to_def_id ( ) )
226+ && is_mutable_ty ( cx, cx. tcx . typeck ( arg. hir_id . owner . def_id ) . expr_ty ( arg) , arg. span , & mut tys)
226227 && is_mutated_static ( arg)
227228 {
228- self . mutates_static = true ;
229- return ;
229+ return ControlFlow :: Break ( ( ) ) ;
230230 }
231231 tys. clear ( ) ;
232232 }
233+ ControlFlow :: Continue ( ( ) )
233234 } ,
234235 MethodCall ( _, receiver, args, _) => {
235236 let mut tys = DefIdSet :: default ( ) ;
236237 for arg in std:: iter:: once ( receiver) . chain ( args. iter ( ) ) {
237- if self . cx . tcx . has_typeck_results ( arg. hir_id . owner . to_def_id ( ) )
238- && is_mutable_ty (
239- self . cx ,
240- self . cx . tcx . typeck ( arg. hir_id . owner . def_id ) . expr_ty ( arg) ,
241- arg. span ,
242- & mut tys,
243- )
238+ if cx. tcx . has_typeck_results ( arg. hir_id . owner . to_def_id ( ) )
239+ && is_mutable_ty ( cx, cx. tcx . typeck ( arg. hir_id . owner . def_id ) . expr_ty ( arg) , arg. span , & mut tys)
244240 && is_mutated_static ( arg)
245241 {
246- self . mutates_static = true ;
247- return ;
242+ return ControlFlow :: Break ( ( ) ) ;
248243 }
249244 tys. clear ( ) ;
250245 }
246+ ControlFlow :: Continue ( ( ) )
251247 } ,
252- Assign ( target, ..) | AssignOp ( _, target, _) | AddrOf ( _, hir:: Mutability :: Mut , target) => {
253- self . mutates_static |= is_mutated_static ( target) ;
248+ Assign ( target, ..) | AssignOp ( _, target, _) | AddrOf ( _, hir:: Mutability :: Mut , target)
249+ if is_mutated_static ( target) =>
250+ {
251+ ControlFlow :: Break ( ( ) )
254252 } ,
255- _ => { } ,
253+ _ => ControlFlow :: Continue ( ( ) ) ,
256254 }
257- }
258- }
259-
260- fn is_mutated_static ( e : & hir:: Expr < ' _ > ) -> bool {
261- use hir:: ExprKind :: { Field , Index , Path } ;
262-
263- match e. kind {
264- Path ( QPath :: Resolved ( _, path) ) => !matches ! ( path. res, Res :: Local ( _) ) ,
265- Path ( _) => true ,
266- Field ( inner, _) | Index ( inner, _) => is_mutated_static ( inner) ,
267- _ => false ,
268- }
269- }
270-
271- fn mutates_static < ' tcx > ( cx : & LateContext < ' tcx > , body : & ' tcx hir:: Body < ' _ > ) -> bool {
272- let mut v = StaticMutVisitor {
273- cx,
274- mutates_static : false ,
275- } ;
276- intravisit:: walk_expr ( & mut v, body. value ) ;
277- v. mutates_static
255+ } )
256+ . is_some ( )
278257}
0 commit comments