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 < ' _ > ) {
@@ -199,61 +202,42 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &m
199202 }
200203}
201204
202- struct StaticMutVisitor < ' a , ' tcx > {
203- cx : & ' a LateContext < ' tcx > ,
204- mutates_static : bool ,
205+ fn is_mutated_static ( e : & hir:: Expr < ' _ > ) -> bool {
206+ use hir:: ExprKind :: { Field , Index , Path } ;
207+
208+ match e. kind {
209+ Path ( QPath :: Resolved ( _, path) ) => !matches ! ( path. res, Res :: Local ( _) ) ,
210+ Path ( _) => true ,
211+ Field ( inner, _) | Index ( inner, _) => is_mutated_static ( inner) ,
212+ _ => false ,
213+ }
205214}
206215
207- impl < ' a , ' tcx > intravisit :: Visitor < ' tcx > for StaticMutVisitor < ' a , ' tcx > {
208- fn visit_expr ( & mut self , expr : & ' tcx hir :: Expr < ' _ > ) {
216+ fn mutates_static < ' tcx > ( cx : & LateContext < ' tcx > , body : & ' tcx hir :: Body < ' _ > ) -> bool {
217+ for_each_expr ( & body . value , |e| {
209218 use hir:: ExprKind :: { AddrOf , Assign , AssignOp , Call , MethodCall } ;
210219
211- if self . mutates_static {
212- return ;
213- }
214- match expr. kind {
220+ match e. kind {
215221 Call ( _, args) | MethodCall ( _, args, _) => {
216222 let mut tys = DefIdSet :: default ( ) ;
217223 for arg in args {
218- if self . cx . tcx . has_typeck_results ( arg. hir_id . owner . to_def_id ( ) )
219- && is_mutable_ty (
220- self . cx ,
221- self . cx . tcx . typeck ( arg. hir_id . owner ) . expr_ty ( arg) ,
222- arg. span ,
223- & mut tys,
224- )
224+ if cx. tcx . has_typeck_results ( arg. hir_id . owner . to_def_id ( ) )
225+ && is_mutable_ty ( cx, cx. tcx . typeck ( arg. hir_id . owner ) . expr_ty ( arg) , arg. span , & mut tys)
225226 && is_mutated_static ( arg)
226227 {
227- self . mutates_static = true ;
228- return ;
228+ return ControlFlow :: Break ( ( ) ) ;
229229 }
230230 tys. clear ( ) ;
231231 }
232+ ControlFlow :: Continue ( ( ) )
232233 } ,
233- Assign ( target, ..) | AssignOp ( _, target, _) | AddrOf ( _, hir:: Mutability :: Mut , target) => {
234- self . mutates_static |= is_mutated_static ( target) ;
234+ Assign ( target, ..) | AssignOp ( _, target, _) | AddrOf ( _, hir:: Mutability :: Mut , target)
235+ if is_mutated_static ( target) =>
236+ {
237+ ControlFlow :: Break ( ( ) )
235238 } ,
236- _ => { } ,
239+ _ => ControlFlow :: Continue ( ( ) ) ,
237240 }
238- }
239- }
240-
241- fn is_mutated_static ( e : & hir:: Expr < ' _ > ) -> bool {
242- use hir:: ExprKind :: { Field , Index , Path } ;
243-
244- match e. kind {
245- Path ( QPath :: Resolved ( _, path) ) => !matches ! ( path. res, Res :: Local ( _) ) ,
246- Path ( _) => true ,
247- Field ( inner, _) | Index ( inner, _) => is_mutated_static ( inner) ,
248- _ => false ,
249- }
250- }
251-
252- fn mutates_static < ' tcx > ( cx : & LateContext < ' tcx > , body : & ' tcx hir:: Body < ' _ > ) -> bool {
253- let mut v = StaticMutVisitor {
254- cx,
255- mutates_static : false ,
256- } ;
257- intravisit:: walk_expr ( & mut v, & body. value ) ;
258- v. mutates_static
241+ } )
242+ . is_some ( )
259243}
0 commit comments