Skip to content

Commit 5540060

Browse files
committed
Skip linting if array length is from a macro.
1 parent c65ddb8 commit 5540060

File tree

4 files changed

+42
-25
lines changed

4 files changed

+42
-25
lines changed

clippy_lints/src/zero_repeat_side_effects.rs

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use clippy_utils::source::snippet;
44
use clippy_utils::visitors::for_each_expr_without_closures;
55
use rustc_ast::LitKind;
66
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};
89
use rustc_lint::{LateContext, LateLintPass};
910
use rustc_middle::ty::{self, ConstKind, Ty};
1011
use rustc_session::declare_lint_pass;
@@ -45,20 +46,44 @@ declare_clippy_lint! {
4546
declare_lint_pass!(ZeroRepeatSideEffects => [ZERO_REPEAT_SIDE_EFFECTS]);
4647

4748
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();
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
}

tests/ui/zero_repeat_side_effects.fixed

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,13 @@ fn main() {
6060
}
6161

6262
macro_rules! LEN {
63-
() => {0};
63+
() => {
64+
0
65+
};
6466
}
6567

6668
fn issue_13110() {
67-
f(); let _data: [i32; 0] = [];
69+
let _data = [f(); LEN!()];
6870
const LENGTH: usize = LEN!();
69-
f(); let _data: [i32; 0] = [];
71+
let _data = [f(); LENGTH];
7072
}

tests/ui/zero_repeat_side_effects.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ fn main() {
6060
}
6161

6262
macro_rules! LEN {
63-
() => {0};
63+
() => {
64+
0
65+
};
6466
}
6567

6668
fn issue_13110() {

tests/ui/zero_repeat_side_effects.stderr

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,5 @@ error: function or method calls as the initial value in zero-sized array initial
7373
LL | [f(); N];
7474
| ^^^^^^^^ help: consider using: `{ f(); [] as [i32; 0] }`
7575

76-
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
77-
--> tests/ui/zero_repeat_side_effects.rs:67:5
78-
|
79-
LL | let _data = [f(); LEN!()];
80-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f(); let _data: [i32; 0] = [];`
81-
82-
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
83-
--> tests/ui/zero_repeat_side_effects.rs:69:5
84-
|
85-
LL | let _data = [f(); LENGTH];
86-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f(); let _data: [i32; 0] = [];`
87-
88-
error: aborting due to 14 previous errors
76+
error: aborting due to 12 previous errors
8977

0 commit comments

Comments
 (0)