mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 15:14:29 +00:00
Auto merge of #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 #13110 . r? y21
This commit is contained in:
commit
073f9d9080
4 changed files with 57 additions and 42 deletions
|
@ -3,10 +3,11 @@ use clippy_utils::higher::VecArgs;
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use clippy_utils::visitors::for_each_expr_without_closures;
|
use clippy_utils::visitors::for_each_expr_without_closures;
|
||||||
use rustc_ast::LitKind;
|
use rustc_ast::LitKind;
|
||||||
|
use rustc_data_structures::packed::Pu128;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{ExprKind, Node};
|
use rustc_hir::{ArrayLen, ExprKind, Node};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
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_session::declare_lint_pass;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
|
@ -45,18 +46,26 @@ declare_clippy_lint! {
|
||||||
declare_lint_pass!(ZeroRepeatSideEffects => [ZERO_REPEAT_SIDE_EFFECTS]);
|
declare_lint_pass!(ZeroRepeatSideEffects => [ZERO_REPEAT_SIDE_EFFECTS]);
|
||||||
|
|
||||||
impl LateLintPass<'_> for ZeroRepeatSideEffects {
|
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)
|
if let Some(args) = VecArgs::hir(cx, expr)
|
||||||
&& let VecArgs::Repeat(inner_expr, len) = args
|
&& let VecArgs::Repeat(inner_expr, len) = args
|
||||||
&& let ExprKind::Lit(l) = len.kind
|
&& let ExprKind::Lit(l) = len.kind
|
||||||
&& let LitKind::Int(i, _) = l.node
|
&& let LitKind::Int(Pu128(0), _) = l.node
|
||||||
&& i.0 == 0
|
|
||||||
{
|
{
|
||||||
inner_check(cx, expr, inner_expr, true);
|
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()
|
// Lint only if the length is a literal zero, and not a path to any constants.
|
||||||
&& let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind()
|
// NOTE(@y21): When reading `[f(); LEN]`, I intuitively expect that the function is called and it
|
||||||
&& element_count.to_target_usize(cx.tcx) == 0
|
// 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(anon_const) = length
|
||||||
|
&& 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);
|
inner_check(cx, expr, inner_expr, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,8 @@ fn main() {
|
||||||
|
|
||||||
// on arrays
|
// on arrays
|
||||||
f(); let a: [i32; 0] = [];
|
f(); let a: [i32; 0] = [];
|
||||||
f(); let a: [i32; 0] = [];
|
|
||||||
let mut b;
|
let mut b;
|
||||||
f(); b = [] as [i32; 0];
|
f(); b = [] as [i32; 0];
|
||||||
f(); b = [] as [i32; 0];
|
|
||||||
|
|
||||||
// on vecs
|
// on vecs
|
||||||
// vecs dont support infering value of consts
|
// vecs dont support infering value of consts
|
||||||
|
@ -39,9 +37,11 @@ fn main() {
|
||||||
// when singled out/not part of assignment/local
|
// when singled out/not part of assignment/local
|
||||||
{ f(); vec![] as std::vec::Vec<i32> };
|
{ f(); vec![] as std::vec::Vec<i32> };
|
||||||
{ f(); [] as [i32; 0] };
|
{ f(); [] as [i32; 0] };
|
||||||
{ f(); [] as [i32; 0] };
|
|
||||||
|
|
||||||
// should not trigger
|
// should not trigger
|
||||||
|
let a = [f(); N];
|
||||||
|
b = [f(); N];
|
||||||
|
[f(); N];
|
||||||
|
|
||||||
// on arrays with > 0 repeat
|
// on arrays with > 0 repeat
|
||||||
let a = [f(); 1];
|
let a = [f(); 1];
|
||||||
|
@ -58,3 +58,15 @@ fn main() {
|
||||||
// as function param
|
// as function param
|
||||||
drop(vec![f(); 1]);
|
drop(vec![f(); 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! LEN {
|
||||||
|
() => {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn issue_13110() {
|
||||||
|
let _data = [f(); LEN!()];
|
||||||
|
const LENGTH: usize = LEN!();
|
||||||
|
let _data = [f(); LENGTH];
|
||||||
|
}
|
||||||
|
|
|
@ -16,10 +16,8 @@ fn main() {
|
||||||
|
|
||||||
// on arrays
|
// on arrays
|
||||||
let a = [f(); 0];
|
let a = [f(); 0];
|
||||||
let a = [f(); N];
|
|
||||||
let mut b;
|
let mut b;
|
||||||
b = [f(); 0];
|
b = [f(); 0];
|
||||||
b = [f(); N];
|
|
||||||
|
|
||||||
// on vecs
|
// on vecs
|
||||||
// vecs dont support infering value of consts
|
// vecs dont support infering value of consts
|
||||||
|
@ -39,9 +37,11 @@ fn main() {
|
||||||
// when singled out/not part of assignment/local
|
// when singled out/not part of assignment/local
|
||||||
vec![f(); 0];
|
vec![f(); 0];
|
||||||
[f(); 0];
|
[f(); 0];
|
||||||
[f(); N];
|
|
||||||
|
|
||||||
// should not trigger
|
// should not trigger
|
||||||
|
let a = [f(); N];
|
||||||
|
b = [f(); N];
|
||||||
|
[f(); N];
|
||||||
|
|
||||||
// on arrays with > 0 repeat
|
// on arrays with > 0 repeat
|
||||||
let a = [f(); 1];
|
let a = [f(); 1];
|
||||||
|
@ -58,3 +58,15 @@ fn main() {
|
||||||
// as function param
|
// as function param
|
||||||
drop(vec![f(); 1]);
|
drop(vec![f(); 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! LEN {
|
||||||
|
() => {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn issue_13110() {
|
||||||
|
let _data = [f(); LEN!()];
|
||||||
|
const LENGTH: usize = LEN!();
|
||||||
|
let _data = [f(); LENGTH];
|
||||||
|
}
|
||||||
|
|
|
@ -8,70 +8,52 @@ LL | let a = [f(); 0];
|
||||||
= help: to override `-D warnings` add `#[allow(clippy::zero_repeat_side_effects)]`
|
= help: to override `-D warnings` add `#[allow(clippy::zero_repeat_side_effects)]`
|
||||||
|
|
||||||
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
||||||
--> tests/ui/zero_repeat_side_effects.rs:19:5
|
--> tests/ui/zero_repeat_side_effects.rs:20:5
|
||||||
|
|
|
||||||
LL | let a = [f(); N];
|
|
||||||
| ^^^^^^^^^^^^^^^^^ help: consider using: `f(); let a: [i32; 0] = [];`
|
|
||||||
|
|
||||||
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
|
||||||
--> tests/ui/zero_repeat_side_effects.rs:21:5
|
|
||||||
|
|
|
|
||||||
LL | b = [f(); 0];
|
LL | b = [f(); 0];
|
||||||
| ^^^^^^^^^^^^ help: consider using: `f(); b = [] as [i32; 0]`
|
| ^^^^^^^^^^^^ help: consider using: `f(); b = [] as [i32; 0]`
|
||||||
|
|
||||||
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
||||||
--> tests/ui/zero_repeat_side_effects.rs:22:5
|
--> tests/ui/zero_repeat_side_effects.rs:24:5
|
||||||
|
|
|
||||||
LL | b = [f(); N];
|
|
||||||
| ^^^^^^^^^^^^ help: consider using: `f(); b = [] as [i32; 0]`
|
|
||||||
|
|
||||||
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
|
||||||
--> tests/ui/zero_repeat_side_effects.rs:26:5
|
|
||||||
|
|
|
|
||||||
LL | let c = vec![f(); 0];
|
LL | let c = vec![f(); 0];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f(); let c: std::vec::Vec<i32> = vec![];`
|
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f(); let c: std::vec::Vec<i32> = vec![];`
|
||||||
|
|
||||||
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
||||||
--> tests/ui/zero_repeat_side_effects.rs:28:5
|
--> tests/ui/zero_repeat_side_effects.rs:26:5
|
||||||
|
|
|
|
||||||
LL | d = vec![f(); 0];
|
LL | d = vec![f(); 0];
|
||||||
| ^^^^^^^^^^^^^^^^ help: consider using: `f(); d = vec![] as std::vec::Vec<i32>`
|
| ^^^^^^^^^^^^^^^^ help: consider using: `f(); d = vec![] as std::vec::Vec<i32>`
|
||||||
|
|
||||||
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
||||||
--> tests/ui/zero_repeat_side_effects.rs:31:5
|
--> tests/ui/zero_repeat_side_effects.rs:29:5
|
||||||
|
|
|
|
||||||
LL | let e = [println!("side effect"); 0];
|
LL | let e = [println!("side effect"); 0];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `println!("side effect"); let e: [(); 0] = [];`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `println!("side effect"); let e: [(); 0] = [];`
|
||||||
|
|
||||||
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
||||||
--> tests/ui/zero_repeat_side_effects.rs:34:5
|
--> tests/ui/zero_repeat_side_effects.rs:32:5
|
||||||
|
|
|
|
||||||
LL | let g = [{ f() }; 0];
|
LL | let g = [{ f() }; 0];
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `{ f() }; let g: [i32; 0] = [];`
|
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `{ f() }; let g: [i32; 0] = [];`
|
||||||
|
|
||||||
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
||||||
--> tests/ui/zero_repeat_side_effects.rs:37:10
|
--> tests/ui/zero_repeat_side_effects.rs:35:10
|
||||||
|
|
|
|
||||||
LL | drop(vec![f(); 0]);
|
LL | drop(vec![f(); 0]);
|
||||||
| ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec<i32> }`
|
| ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec<i32> }`
|
||||||
|
|
||||||
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
||||||
--> tests/ui/zero_repeat_side_effects.rs:40:5
|
--> tests/ui/zero_repeat_side_effects.rs:38:5
|
||||||
|
|
|
|
||||||
LL | vec![f(); 0];
|
LL | vec![f(); 0];
|
||||||
| ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec<i32> }`
|
| ^^^^^^^^^^^^ help: consider using: `{ f(); vec![] as std::vec::Vec<i32> }`
|
||||||
|
|
||||||
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
||||||
--> tests/ui/zero_repeat_side_effects.rs:41:5
|
--> tests/ui/zero_repeat_side_effects.rs:39:5
|
||||||
|
|
|
|
||||||
LL | [f(); 0];
|
LL | [f(); 0];
|
||||||
| ^^^^^^^^ help: consider using: `{ f(); [] as [i32; 0] }`
|
| ^^^^^^^^ help: consider using: `{ f(); [] as [i32; 0] }`
|
||||||
|
|
||||||
error: function or method calls as the initial value in zero-sized array initializers may cause side effects
|
error: aborting due to 9 previous errors
|
||||||
--> tests/ui/zero_repeat_side_effects.rs:42:5
|
|
||||||
|
|
|
||||||
LL | [f(); N];
|
|
||||||
| ^^^^^^^^ help: consider using: `{ f(); [] as [i32; 0] }`
|
|
||||||
|
|
||||||
error: aborting due to 12 previous errors
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue