Skip to content

Commit 073f9d9

Browse files
committed
Auto merge of rust-lang#13116 - tesuji:fix_zero_repeat_side_effects, r=y21
Lint `zero_repeat_side_effects` only if array length is a literal zero changelog: [`zero_repeat_side_effects` ] Lint only if array length is a literal zero Fixes rust-lang#13110 . r? y21
2 parents acc41f4 + 3c50e7a commit 073f9d9

File tree

4 files changed

+57
-42
lines changed

4 files changed

+57
-42
lines changed

clippy_lints/src/zero_repeat_side_effects.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ use clippy_utils::higher::VecArgs;
33
use clippy_utils::source::snippet;
44
use clippy_utils::visitors::for_each_expr_without_closures;
55
use rustc_ast::LitKind;
6+
use rustc_data_structures::packed::Pu128;
67
use rustc_errors::Applicability;
7-
use rustc_hir::{ExprKind, Node};
8+
use rustc_hir::{ArrayLen, ExprKind, Node};
89
use rustc_lint::{LateContext, LateLintPass};
9-
use rustc_middle::ty::{self, ConstKind, Ty};
10+
use rustc_middle::ty::Ty;
1011
use rustc_session::declare_lint_pass;
1112
use rustc_span::Span;
1213

@@ -45,18 +46,26 @@ 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
52-
&& let LitKind::Int(i, _) = l.node
53-
&& i.0 == 0
54+
&& let LitKind::Int(Pu128(0), _) = l.node
5455
{
5556
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
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
6069
{
6170
inner_check(cx, expr, inner_expr, false);
6271
}

tests/ui/zero_repeat_side_effects.fixed

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@ fn main() {
1616

1717
// on arrays
1818
f(); let a: [i32; 0] = [];
19-
f(); let a: [i32; 0] = [];
2019
let mut b;
2120
f(); b = [] as [i32; 0];
22-
f(); b = [] as [i32; 0];
2321

2422
// on vecs
2523
// vecs dont support infering value of consts
@@ -39,9 +37,11 @@ fn main() {
3937
// when singled out/not part of assignment/local
4038
{ f(); vec![] as std::vec::Vec<i32> };
4139
{ f(); [] as [i32; 0] };
42-
{ f(); [] as [i32; 0] };
4340

4441
// should not trigger
42+
let a = [f(); N];
43+
b = [f(); N];
44+
[f(); N];
4545

4646
// on arrays with > 0 repeat
4747
let a = [f(); 1];
@@ -58,3 +58,15 @@ fn main() {
5858
// as function param
5959
drop(vec![f(); 1]);
6060
}
61+
62+
macro_rules! LEN {
63+
() => {
64+
0
65+
};
66+
}
67+
68+
fn issue_13110() {
69+
let _data = [f(); LEN!()];
70+
const LENGTH: usize = LEN!();
71+
let _data = [f(); LENGTH];
72+
}

tests/ui/zero_repeat_side_effects.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@ fn main() {
1616

1717
// on arrays
1818
let a = [f(); 0];
19-
let a = [f(); N];
2019
let mut b;
2120
b = [f(); 0];
22-
b = [f(); N];
2321

2422
// on vecs
2523
// vecs dont support infering value of consts
@@ -39,9 +37,11 @@ fn main() {
3937
// when singled out/not part of assignment/local
4038
vec![f(); 0];
4139
[f(); 0];
42-
[f(); N];
4340

4441
// should not trigger
42+
let a = [f(); N];
43+
b = [f(); N];
44+
[f(); N];
4545

4646
// on arrays with > 0 repeat
4747
let a = [f(); 1];
@@ -58,3 +58,15 @@ fn main() {
5858
// as function param
5959
drop(vec![f(); 1]);
6060
}
61+
62+
macro_rules! LEN {
63+
() => {
64+
0
65+
};
66+
}
67+
68+
fn issue_13110() {
69+
let _data = [f(); LEN!()];
70+
const LENGTH: usize = LEN!();
71+
let _data = [f(); LENGTH];
72+
}

tests/ui/zero_repeat_side_effects.stderr

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,70 +8,52 @@ LL | let a = [f(); 0];
88
= help: to override `-D warnings` add `#[allow(clippy::zero_repeat_side_effects)]`
99

1010
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
11-
--> tests/ui/zero_repeat_side_effects.rs:19:5
12-
|
13-
LL | let a = [f(); N];
14-
| ^^^^^^^^^^^^^^^^^ help: consider using: `f(); let a: [i32; 0] = [];`
15-
16-
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
17-
--> tests/ui/zero_repeat_side_effects.rs:21:5
11+
--> tests/ui/zero_repeat_side_effects.rs:20:5
1812
|
1913
LL | b = [f(); 0];
2014
| ^^^^^^^^^^^^ help: consider using: `f(); b = [] as [i32; 0]`
2115

2216
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
23-
--> tests/ui/zero_repeat_side_effects.rs:22:5
24-
|
25-
LL | b = [f(); N];
26-
| ^^^^^^^^^^^^ help: consider using: `f(); b = [] as [i32; 0]`
27-
28-
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
29-
--> tests/ui/zero_repeat_side_effects.rs:26:5
17+
--> tests/ui/zero_repeat_side_effects.rs:24:5
3018
|
3119
LL | let c = vec![f(); 0];
3220
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f(); let c: std::vec::Vec<i32> = vec![];`
3321

3422
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
35-
--> tests/ui/zero_repeat_side_effects.rs:28:5
23+
--> tests/ui/zero_repeat_side_effects.rs:26:5
3624
|
3725
LL | d = vec![f(); 0];
3826
| ^^^^^^^^^^^^^^^^ help: consider using: `f(); d = vec![] as std::vec::Vec<i32>`
3927

4028
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
41-
--> tests/ui/zero_repeat_side_effects.rs:31:5
29+
--> tests/ui/zero_repeat_side_effects.rs:29:5
4230
|
4331
LL | let e = [println!("side effect"); 0];
4432
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `println!("side effect"); let e: [(); 0] = [];`
4533

4634
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
47-
--> tests/ui/zero_repeat_side_effects.rs:34:5
35+
--> tests/ui/zero_repeat_side_effects.rs:32:5
4836
|
4937
LL | let g = [{ f() }; 0];
5038
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `{ f() }; let g: [i32; 0] = [];`
5139

5240
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
53-
--> tests/ui/zero_repeat_side_effects.rs:37:10
41+
--> tests/ui/zero_repeat_side_effects.rs:35:10
5442
|
5543
LL | drop(vec![f(); 0]);
5644
| ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec<i32> }`
5745

5846
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
59-
--> tests/ui/zero_repeat_side_effects.rs:40:5
47+
--> tests/ui/zero_repeat_side_effects.rs:38:5
6048
|
6149
LL | vec![f(); 0];
6250
| ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec<i32> }`
6351

6452
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
65-
--> tests/ui/zero_repeat_side_effects.rs:41:5
53+
--> tests/ui/zero_repeat_side_effects.rs:39:5
6654
|
6755
LL | [f(); 0];
6856
| ^^^^^^^^ help: consider using: `{ f(); [] as [i32; 0] }`
6957

70-
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
71-
--> tests/ui/zero_repeat_side_effects.rs:42:5
72-
|
73-
LL | [f(); N];
74-
| ^^^^^^^^ help: consider using: `{ f(); [] as [i32; 0] }`
75-
76-
error: aborting due to 12 previous errors
58+
error: aborting due to 9 previous errors
7759

0 commit comments

Comments
 (0)