about summary refs log tree commit diff
path: root/clippy_lints/src/zero_repeat_side_effects.rs
diff options
context:
space:
mode:
authorPhilipp Krones <hello@philkrones.com>2024-07-25 18:09:52 +0200
committerPhilipp Krones <hello@philkrones.com>2024-07-25 18:23:27 +0200
commit9f53fc32cfb62724d95de44779259ce4e24bc085 (patch)
treedf5069c84c1a281c78b72e8935a9664b3110f66a /clippy_lints/src/zero_repeat_side_effects.rs
parent6d674685ae4e9156dbb6ecd3aa38d87864ecab3e (diff)
parentdf0cb6c51ee798264586ee9144466cf003d68181 (diff)
Merge remote-tracking branch 'upstream/master' into rustup
Diffstat (limited to 'clippy_lints/src/zero_repeat_side_effects.rs')
-rw-r--r--clippy_lints/src/zero_repeat_side_effects.rs28
1 files changed, 19 insertions, 9 deletions
diff --git a/clippy_lints/src/zero_repeat_side_effects.rs b/clippy_lints/src/zero_repeat_side_effects.rs
index ad041e55bda..fdc1d06e67a 100644
--- a/clippy_lints/src/zero_repeat_side_effects.rs
+++ b/clippy_lints/src/zero_repeat_side_effects.rs
@@ -3,10 +3,11 @@ use clippy_utils::higher::VecArgs;
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::for_each_expr_without_closures;
 use rustc_ast::LitKind;
+use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
-use rustc_hir::{ExprKind, Node};
+use rustc_hir::{ArrayLen, ConstArgKind, ExprKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, ConstKind, Ty};
+use rustc_middle::ty::Ty;
 use rustc_session::declare_lint_pass;
 use rustc_span::Span;
 
@@ -45,18 +46,27 @@ declare_clippy_lint! {
 declare_lint_pass!(ZeroRepeatSideEffects => [ZERO_REPEAT_SIDE_EFFECTS]);
 
 impl LateLintPass<'_> for ZeroRepeatSideEffects {
-    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>) {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &rustc_hir::Expr<'_>) {
+        let hir_map = cx.tcx.hir();
         if let Some(args) = VecArgs::hir(cx, expr)
             && let VecArgs::Repeat(inner_expr, len) = args
             && let ExprKind::Lit(l) = len.kind
-            && let LitKind::Int(i, _) = l.node
-            && i.0 == 0
+            && let LitKind::Int(Pu128(0), _) = l.node
         {
             inner_check(cx, expr, inner_expr, true);
-        } else if let ExprKind::Repeat(inner_expr, _) = expr.kind
-            && let ty::Array(_, cst) = cx.typeck_results().expr_ty(expr).kind()
-            && let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind()
-            && element_count.to_target_usize(cx.tcx) == 0
+        }
+        // Lint only if the length is a literal zero, and not a path to any constants.
+        // NOTE(@y21): When reading `[f(); LEN]`, I intuitively expect that the function is called and it
+        // doesn't seem as confusing as `[f(); 0]`. It would also have false positives when eg.
+        // the const item depends on `#[cfg]s` and has different values in different compilation
+        // sessions).
+        else if let ExprKind::Repeat(inner_expr, length) = expr.kind
+            && let ArrayLen::Body(const_arg) = length
+            && let ConstArgKind::Anon(anon_const) = const_arg.kind
+            && let length_expr = hir_map.body(anon_const.body).value
+            && !length_expr.span.from_expansion()
+            && let ExprKind::Lit(literal) = length_expr.kind
+            && let LitKind::Int(Pu128(0), _) = literal.node
         {
             inner_check(cx, expr, inner_expr, false);
         }