Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions clippy_lints/src/zero_repeat_side_effects.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::VecArgs;
use clippy_utils::source::snippet;
use clippy_utils::source::{snippet, snippet_indent};
use rustc_ast::LitKind;
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
Expand Down Expand Up @@ -75,24 +75,36 @@ fn inner_check(cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>, inner_expr:
let return_type = cx.typeck_results().expr_ty(expr);

let inner_expr = snippet(cx, inner_expr.span.source_callsite(), "..");
let indent = snippet_indent(cx, expr.span).unwrap_or_default();
let vec = if is_vec { "vec!" } else { "" };

let (span, sugg) = match parent_hir_node {
Node::LetStmt(l) => (
l.span,
format!(
"{inner_expr}; let {var_name}: {return_type} = {vec}[];",
"{inner_expr};\n{indent}let {var_name}: {return_type} = {vec}[];",
var_name = snippet(cx, l.pat.span.source_callsite(), "..")
),
),
Node::Expr(x) if let ExprKind::Assign(l, _, _) = x.kind => (
x.span,
format!(
"{inner_expr}; {var_name} = {vec}[] as {return_type}",
"{inner_expr};\n{indent}{var_name} = {vec}[] as {return_type}",
var_name = snippet(cx, l.span.source_callsite(), "..")
),
),
_ => (expr.span, format!("{{ {inner_expr}; {vec}[] as {return_type} }}")),
// NOTE: don't use the stmt span to avoid touching the trailing semicolon
Node::Stmt(_) => (expr.span, format!("{inner_expr};\n{indent}{vec}[] as {return_type}")),
_ => (
expr.span,
format!(
"\
{{
{indent} {inner_expr};
{indent} {vec}[] as {return_type}
{indent}}}"
),
),
};
span_lint_and_then(
cx,
Expand Down
40 changes: 29 additions & 11 deletions tests/ui/zero_repeat_side_effects.fixed
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![warn(clippy::zero_repeat_side_effects)]
#![expect(clippy::unnecessary_operation, clippy::useless_vec, clippy::needless_late_init)]
#![allow(clippy::no_effect)] // only fires _after_ the fix

fn f() -> i32 {
println!("side effect");
Expand All @@ -13,36 +14,47 @@ fn main() {
// should trigger

// on arrays
f(); let a: [i32; 0] = [];
f();
let a: [i32; 0] = [];
//~^ zero_repeat_side_effects
let mut b;
f(); b = [] as [i32; 0];
f();
b = [] as [i32; 0];
//~^ zero_repeat_side_effects

// on vecs
// vecs dont support inferring value of consts
f(); let c: std::vec::Vec<i32> = vec![];
f();
let c: std::vec::Vec<i32> = vec![];
//~^ zero_repeat_side_effects
let d;
f(); d = vec![] as std::vec::Vec<i32>;
f();
d = vec![] as std::vec::Vec<i32>;
//~^ zero_repeat_side_effects

// for macros
println!("side effect"); let e: [(); 0] = [];
println!("side effect");
let e: [(); 0] = [];
//~^ zero_repeat_side_effects

// for nested calls
{ f() }; let g: [i32; 0] = [];
{ f() };
let g: [i32; 0] = [];
//~^ zero_repeat_side_effects

// as function param
drop({ f(); vec![] as std::vec::Vec<i32> });
drop({
f();
vec![] as std::vec::Vec<i32>
});
//~^ zero_repeat_side_effects

// when singled out/not part of assignment/local
{ f(); vec![] as std::vec::Vec<i32> };
f();
vec![] as std::vec::Vec<i32>;
//~^ zero_repeat_side_effects
{ f(); [] as [i32; 0] };
f();
[] as [i32; 0];
//~^ zero_repeat_side_effects

// should not trigger
Expand Down Expand Up @@ -96,8 +108,14 @@ fn issue_14681() {

foo(&[Some(0i64); 0]);
foo(&[Some(Some(0i64)); 0]);
foo(&{ Some(f()); [] as [std::option::Option<i32>; 0] });
foo(&{
Some(f());
[] as [std::option::Option<i32>; 0]
});
//~^ zero_repeat_side_effects
foo(&{ Some(Some(S::new())); [] as [std::option::Option<std::option::Option<S>>; 0] });
foo(&{
Some(Some(S::new()));
[] as [std::option::Option<std::option::Option<S>>; 0]
});
//~^ zero_repeat_side_effects
}
1 change: 1 addition & 0 deletions tests/ui/zero_repeat_side_effects.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![warn(clippy::zero_repeat_side_effects)]
#![expect(clippy::unnecessary_operation, clippy::useless_vec, clippy::needless_late_init)]
#![allow(clippy::no_effect)] // only fires _after_ the fix

fn f() -> i32 {
println!("side effect");
Expand Down
72 changes: 39 additions & 33 deletions tests/ui/zero_repeat_side_effects.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: expression with side effects as the initial value in a zero-sized array initializer
--> tests/ui/zero_repeat_side_effects.rs:16:5
--> tests/ui/zero_repeat_side_effects.rs:17:5
|
LL | let a = [f(); 0];
| ^^^^^^^^^^^^^^^^^
Expand All @@ -8,128 +8,134 @@ LL | let a = [f(); 0];
= help: to override `-D warnings` add `#[allow(clippy::zero_repeat_side_effects)]`
help: consider performing the side effect separately
|
LL - let a = [f(); 0];
LL + f(); let a: [i32; 0] = [];
LL ~ f();
LL + let a: [i32; 0] = [];
|

error: expression with side effects as the initial value in a zero-sized array initializer
--> tests/ui/zero_repeat_side_effects.rs:19:5
--> tests/ui/zero_repeat_side_effects.rs:20:5
|
LL | b = [f(); 0];
| ^^^^^^^^^^^^
|
help: consider performing the side effect separately
|
LL - b = [f(); 0];
LL + f(); b = [] as [i32; 0];
LL ~ f();
LL ~ b = [] as [i32; 0];
|

error: expression with side effects as the initial value in a zero-sized array initializer
--> tests/ui/zero_repeat_side_effects.rs:24:5
--> tests/ui/zero_repeat_side_effects.rs:25:5
|
LL | let c = vec![f(); 0];
| ^^^^^^^^^^^^^^^^^^^^^
|
help: consider performing the side effect separately
|
LL - let c = vec![f(); 0];
LL + f(); let c: std::vec::Vec<i32> = vec![];
LL ~ f();
LL + let c: std::vec::Vec<i32> = vec![];
|

error: expression with side effects as the initial value in a zero-sized array initializer
--> tests/ui/zero_repeat_side_effects.rs:27:5
--> tests/ui/zero_repeat_side_effects.rs:28:5
|
LL | d = vec![f(); 0];
| ^^^^^^^^^^^^^^^^
|
help: consider performing the side effect separately
|
LL - d = vec![f(); 0];
LL + f(); d = vec![] as std::vec::Vec<i32>;
LL ~ f();
LL ~ d = vec![] as std::vec::Vec<i32>;
|

error: expression with side effects as the initial value in a zero-sized array initializer
--> tests/ui/zero_repeat_side_effects.rs:31:5
--> tests/ui/zero_repeat_side_effects.rs:32:5
|
LL | let e = [println!("side effect"); 0];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider performing the side effect separately
|
LL - let e = [println!("side effect"); 0];
LL + println!("side effect"); let e: [(); 0] = [];
LL ~ println!("side effect");
LL + let e: [(); 0] = [];
|

error: expression with side effects as the initial value in a zero-sized array initializer
--> tests/ui/zero_repeat_side_effects.rs:35:5
--> tests/ui/zero_repeat_side_effects.rs:36:5
|
LL | let g = [{ f() }; 0];
| ^^^^^^^^^^^^^^^^^^^^^
|
help: consider performing the side effect separately
|
LL - let g = [{ f() }; 0];
LL + { f() }; let g: [i32; 0] = [];
LL ~ { f() };
LL + let g: [i32; 0] = [];
|

error: expression with side effects as the initial value in a zero-sized array initializer
--> tests/ui/zero_repeat_side_effects.rs:39:10
--> tests/ui/zero_repeat_side_effects.rs:40:10
|
LL | drop(vec![f(); 0]);
| ^^^^^^^^^^^^
|
help: consider performing the side effect separately
|
LL - drop(vec![f(); 0]);
LL + drop({ f(); vec![] as std::vec::Vec<i32> });
LL ~ drop({
LL + f();
LL + vec![] as std::vec::Vec<i32>
LL ~ });
|

error: expression with side effects as the initial value in a zero-sized array initializer
--> tests/ui/zero_repeat_side_effects.rs:43:5
--> tests/ui/zero_repeat_side_effects.rs:44:5
|
LL | vec![f(); 0];
| ^^^^^^^^^^^^
|
help: consider performing the side effect separately
|
LL - vec![f(); 0];
LL + { f(); vec![] as std::vec::Vec<i32> };
LL ~ f();
LL ~ vec![] as std::vec::Vec<i32>;
|

error: expression with side effects as the initial value in a zero-sized array initializer
--> tests/ui/zero_repeat_side_effects.rs:45:5
--> tests/ui/zero_repeat_side_effects.rs:46:5
|
LL | [f(); 0];
| ^^^^^^^^
|
help: consider performing the side effect separately
|
LL - [f(); 0];
LL + { f(); [] as [i32; 0] };
LL ~ f();
LL ~ [] as [i32; 0];
|

error: expression with side effects as the initial value in a zero-sized array initializer
--> tests/ui/zero_repeat_side_effects.rs:99:10
--> tests/ui/zero_repeat_side_effects.rs:100:10
|
LL | foo(&[Some(f()); 0]);
| ^^^^^^^^^^^^^^
|
help: consider performing the side effect separately
|
LL - foo(&[Some(f()); 0]);
LL + foo(&{ Some(f()); [] as [std::option::Option<i32>; 0] });
LL ~ foo(&{
LL + Some(f());
LL + [] as [std::option::Option<i32>; 0]
LL ~ });
|

error: expression with side effects as the initial value in a zero-sized array initializer
--> tests/ui/zero_repeat_side_effects.rs:101:10
--> tests/ui/zero_repeat_side_effects.rs:102:10
|
LL | foo(&[Some(Some(S::new())); 0]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider performing the side effect separately
|
LL - foo(&[Some(Some(S::new())); 0]);
LL + foo(&{ Some(Some(S::new())); [] as [std::option::Option<std::option::Option<S>>; 0] });
LL ~ foo(&{
LL + Some(Some(S::new()));
LL + [] as [std::option::Option<std::option::Option<S>>; 0]
LL ~ });
|

error: aborting due to 11 previous errors
Expand Down