@@ -3,11 +3,11 @@ use clippy_utils::higher::VecArgs;
33use clippy_utils:: source:: snippet;
44use clippy_utils:: visitors:: for_each_expr_without_closures;
55use rustc_ast:: LitKind ;
6+ use rustc_data_structures:: packed:: Pu128 ;
67use rustc_errors:: Applicability ;
7- use rustc_hir:: def:: { DefKind , Res } ;
8- use rustc_hir:: { ArrayLen , ExprKind , ItemKind , Node , QPath } ;
8+ use rustc_hir:: { ArrayLen , ExprKind , Node } ;
99use rustc_lint:: { LateContext , LateLintPass } ;
10- use rustc_middle:: ty:: { self , ConstKind , Ty } ;
10+ use rustc_middle:: ty:: Ty ;
1111use rustc_session:: declare_lint_pass;
1212use rustc_span:: Span ;
1313
@@ -51,39 +51,23 @@ impl LateLintPass<'_> for ZeroRepeatSideEffects {
5151 if let Some ( args) = VecArgs :: hir ( cx, expr)
5252 && let VecArgs :: Repeat ( inner_expr, len) = args
5353 && let ExprKind :: Lit ( l) = len. kind
54- && let LitKind :: Int ( i, _) = l. node
55- && i. 0 == 0
54+ && let LitKind :: Int ( Pu128 ( 0 ) , _) = l. node
5655 {
5756 inner_check ( cx, expr, inner_expr, true ) ;
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- }
57+ }
58+ // Lint only if the length is a literal zero, and not a path to any constants.
59+ // NOTE(@y21): When reading `[f(); LEN]`, I intuitively expect that the function is called and it
60+ // doesn't seem as confusing as `[f(); 0]`. It would also have false positives when eg.
61+ // the const item depends on `#[cfg]s` and has different values in different compilation
62+ // sessions).
63+ else if let ExprKind :: Repeat ( inner_expr, length) = expr. kind
64+ && let ArrayLen :: Body ( anon_const) = length
65+ && let length_expr = hir_map. body ( anon_const. body ) . value
66+ && !length_expr. span . from_expansion ( )
67+ && let ExprKind :: Lit ( literal) = length_expr. kind
68+ && let LitKind :: Int ( Pu128 ( 0 ) , _) = literal. node
69+ {
70+ inner_check ( cx, expr, inner_expr, false ) ;
8771 }
8872 }
8973}
0 commit comments