@@ -4,7 +4,8 @@ use clippy_utils::source::snippet;
44use clippy_utils:: visitors:: for_each_expr_without_closures;
55use rustc_ast:: LitKind ;
66use rustc_errors:: Applicability ;
7- use rustc_hir:: { ExprKind , Node } ;
7+ use rustc_hir:: def:: { DefKind , Res } ;
8+ use rustc_hir:: { ArrayLen , ExprKind , ItemKind , Node , QPath } ;
89use rustc_lint:: { LateContext , LateLintPass } ;
910use rustc_middle:: ty:: { self , ConstKind , Ty } ;
1011use rustc_session:: declare_lint_pass;
@@ -45,20 +46,44 @@ declare_clippy_lint! {
4546declare_lint_pass ! ( ZeroRepeatSideEffects => [ ZERO_REPEAT_SIDE_EFFECTS ] ) ;
4647
4748impl LateLintPass < ' _ > for ZeroRepeatSideEffects {
48- fn check_expr ( & mut self , cx : & LateContext < ' _ > , expr : & ' _ rustc_hir:: Expr < ' _ > ) {
49+ fn check_expr ( & mut self , cx : & LateContext < ' _ > , expr : & rustc_hir:: Expr < ' _ > ) {
50+ let hir_map = cx. tcx . hir ( ) ;
4951 if let Some ( args) = VecArgs :: hir ( cx, expr)
5052 && let VecArgs :: Repeat ( inner_expr, len) = args
5153 && let ExprKind :: Lit ( l) = len. kind
5254 && let LitKind :: Int ( i, _) = l. node
5355 && i. 0 == 0
5456 {
5557 inner_check ( cx, expr, inner_expr, true ) ;
56- } else if let ExprKind :: Repeat ( inner_expr, _) = expr. kind
57- && let ty:: Array ( _, cst) = cx. typeck_results ( ) . expr_ty ( expr) . kind ( )
58- && let ConstKind :: Value ( _, ty:: ValTree :: Leaf ( element_count) ) = cst. kind ( )
59- && element_count. to_target_usize ( cx. tcx ) == 0
60- {
61- inner_check ( cx, expr, inner_expr, false ) ;
58+ } else {
59+ let ExprKind :: Repeat ( inner_expr, length) = expr. kind else {
60+ return ;
61+ } ;
62+ // Skip if the length is from a macro.
63+ if let ArrayLen :: Body ( anon_const) = length {
64+ let length_expr = hir_map. body ( anon_const. body ) . value ;
65+ if !length_expr. span . eq_ctxt ( expr. span ) {
66+ return ;
67+ }
68+
69+ // Get the initialization span of a const item and compare it with the span at use-site.
70+ if let ExprKind :: Path ( QPath :: Resolved ( None , path) ) = length_expr. kind
71+ && let Res :: Def ( DefKind :: Const , def_id) = path. res
72+ && let Some ( def_id) = def_id. as_local ( )
73+ && let Node :: Item ( item) = cx. tcx . hir_node_by_def_id ( def_id)
74+ && let ItemKind :: Const ( _ty, _, body_id) = item. kind
75+ && let init_span = hir_map. span_with_body ( body_id. hir_id )
76+ && !init_span. eq_ctxt ( length_expr. span )
77+ {
78+ return ;
79+ }
80+ }
81+ if let ty:: Array ( _, cst) = cx. typeck_results ( ) . expr_ty ( expr) . kind ( )
82+ && let ConstKind :: Value ( _, ty:: ValTree :: Leaf ( element_count) ) = cst. kind ( )
83+ && element_count. to_target_usize ( cx. tcx ) == 0
84+ {
85+ inner_check ( cx, expr, inner_expr, false ) ;
86+ }
6287 }
6388 }
6489}
0 commit comments