@@ -4,7 +4,8 @@ use clippy_utils::source::snippet;
4
4
use clippy_utils:: visitors:: for_each_expr_without_closures;
5
5
use rustc_ast:: LitKind ;
6
6
use 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 } ;
8
9
use rustc_lint:: { LateContext , LateLintPass } ;
9
10
use rustc_middle:: ty:: { self , ConstKind , Ty } ;
10
11
use rustc_session:: declare_lint_pass;
@@ -45,20 +46,44 @@ declare_clippy_lint! {
45
46
declare_lint_pass ! ( ZeroRepeatSideEffects => [ ZERO_REPEAT_SIDE_EFFECTS ] ) ;
46
47
47
48
impl 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 ( ) ;
49
51
if let Some ( args) = VecArgs :: hir ( cx, expr)
50
52
&& let VecArgs :: Repeat ( inner_expr, len) = args
51
53
&& let ExprKind :: Lit ( l) = len. kind
52
54
&& let LitKind :: Int ( i, _) = l. node
53
55
&& i. 0 == 0
54
56
{
55
57
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
+ }
62
87
}
63
88
}
64
89
}
0 commit comments