From 3c62ddb3a750ab42363285ca4da0acb3c0227a62 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 7 Oct 2025 00:47:34 +0200 Subject: [PATCH 1/2] feat(zero_repeat_side_effects): put the suggestion on two lines --- clippy_lints/src/zero_repeat_side_effects.rs | 18 +++++-- tests/ui/zero_repeat_side_effects.fixed | 43 ++++++++++++---- tests/ui/zero_repeat_side_effects.stderr | 54 ++++++++++++-------- 3 files changed, 78 insertions(+), 37 deletions(-) diff --git a/clippy_lints/src/zero_repeat_side_effects.rs b/clippy_lints/src/zero_repeat_side_effects.rs index cd6c11b51274..7a371507f525 100644 --- a/clippy_lints/src/zero_repeat_side_effects.rs +++ b/clippy_lints/src/zero_repeat_side_effects.rs @@ -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; @@ -75,24 +75,34 @@ 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} }}")), + _ => ( + expr.span, + format!( + "\ +{{ +{indent} {inner_expr}; +{indent} {vec}[] as {return_type} +{indent}}}" + ), + ), }; span_lint_and_then( cx, diff --git a/tests/ui/zero_repeat_side_effects.fixed b/tests/ui/zero_repeat_side_effects.fixed index e6c451ce7399..231ed85ee635 100644 --- a/tests/ui/zero_repeat_side_effects.fixed +++ b/tests/ui/zero_repeat_side_effects.fixed @@ -13,36 +13,51 @@ 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 = vec![]; + f(); + let c: std::vec::Vec = vec![]; //~^ zero_repeat_side_effects let d; - f(); d = vec![] as std::vec::Vec; + f(); + d = vec![] as std::vec::Vec; //~^ 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 }); + drop({ + f(); + vec![] as std::vec::Vec + }); //~^ zero_repeat_side_effects // when singled out/not part of assignment/local - { f(); vec![] as std::vec::Vec }; + { + f(); + vec![] as std::vec::Vec + }; //~^ zero_repeat_side_effects - { f(); [] as [i32; 0] }; + { + f(); + [] as [i32; 0] + }; //~^ zero_repeat_side_effects // should not trigger @@ -96,8 +111,14 @@ fn issue_14681() { foo(&[Some(0i64); 0]); foo(&[Some(Some(0i64)); 0]); - foo(&{ Some(f()); [] as [std::option::Option; 0] }); + foo(&{ + Some(f()); + [] as [std::option::Option; 0] + }); //~^ zero_repeat_side_effects - foo(&{ Some(Some(S::new())); [] as [std::option::Option>; 0] }); + foo(&{ + Some(Some(S::new())); + [] as [std::option::Option>; 0] + }); //~^ zero_repeat_side_effects } diff --git a/tests/ui/zero_repeat_side_effects.stderr b/tests/ui/zero_repeat_side_effects.stderr index 771b71c686ae..3f43f15da4a0 100644 --- a/tests/ui/zero_repeat_side_effects.stderr +++ b/tests/ui/zero_repeat_side_effects.stderr @@ -8,8 +8,8 @@ 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 @@ -20,8 +20,8 @@ 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 @@ -32,8 +32,8 @@ 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 = vec![]; +LL ~ f(); +LL + let c: std::vec::Vec = vec![]; | error: expression with side effects as the initial value in a zero-sized array initializer @@ -44,8 +44,8 @@ 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; +LL ~ f(); +LL ~ d = vec![] as std::vec::Vec; | error: expression with side effects as the initial value in a zero-sized array initializer @@ -56,8 +56,8 @@ 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 @@ -68,8 +68,8 @@ 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 @@ -80,8 +80,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 }); +LL ~ drop({ +LL + f(); +LL + vec![] as std::vec::Vec +LL ~ }); | error: expression with side effects as the initial value in a zero-sized array initializer @@ -92,8 +94,10 @@ LL | vec![f(); 0]; | help: consider performing the side effect separately | -LL - vec![f(); 0]; -LL + { f(); vec![] as std::vec::Vec }; +LL ~ { +LL + f(); +LL + vec![] as std::vec::Vec +LL ~ }; | error: expression with side effects as the initial value in a zero-sized array initializer @@ -104,8 +108,10 @@ LL | [f(); 0]; | help: consider performing the side effect separately | -LL - [f(); 0]; -LL + { f(); [] as [i32; 0] }; +LL ~ { +LL + f(); +LL + [] as [i32; 0] +LL ~ }; | error: expression with side effects as the initial value in a zero-sized array initializer @@ -116,8 +122,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; 0] }); +LL ~ foo(&{ +LL + Some(f()); +LL + [] as [std::option::Option; 0] +LL ~ }); | error: expression with side effects as the initial value in a zero-sized array initializer @@ -128,8 +136,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>; 0] }); +LL ~ foo(&{ +LL + Some(Some(S::new())); +LL + [] as [std::option::Option>; 0] +LL ~ }); | error: aborting due to 11 previous errors From bb53f994cf15a39f5fcb9745f9508e034d0975b7 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 6 Oct 2025 18:24:57 +0200 Subject: [PATCH 2/2] feat(zero_repeat_side_effects): don't suggest unnecessary braces around stmts --- clippy_lints/src/zero_repeat_side_effects.rs | 2 ++ tests/ui/zero_repeat_side_effects.fixed | 13 +++----- tests/ui/zero_repeat_side_effects.rs | 1 + tests/ui/zero_repeat_side_effects.stderr | 34 +++++++++----------- 4 files changed, 23 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/zero_repeat_side_effects.rs b/clippy_lints/src/zero_repeat_side_effects.rs index 7a371507f525..55b2e35a3a0f 100644 --- a/clippy_lints/src/zero_repeat_side_effects.rs +++ b/clippy_lints/src/zero_repeat_side_effects.rs @@ -93,6 +93,8 @@ fn inner_check(cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>, inner_expr: var_name = snippet(cx, l.span.source_callsite(), "..") ), ), + // 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!( diff --git a/tests/ui/zero_repeat_side_effects.fixed b/tests/ui/zero_repeat_side_effects.fixed index 231ed85ee635..b5fca36f3f08 100644 --- a/tests/ui/zero_repeat_side_effects.fixed +++ b/tests/ui/zero_repeat_side_effects.fixed @@ -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"); @@ -49,15 +50,11 @@ fn main() { //~^ zero_repeat_side_effects // when singled out/not part of assignment/local - { - f(); - vec![] as std::vec::Vec - }; + f(); + vec![] as std::vec::Vec; //~^ zero_repeat_side_effects - { - f(); - [] as [i32; 0] - }; + f(); + [] as [i32; 0]; //~^ zero_repeat_side_effects // should not trigger diff --git a/tests/ui/zero_repeat_side_effects.rs b/tests/ui/zero_repeat_side_effects.rs index f8a497976aa4..ea043d21638c 100644 --- a/tests/ui/zero_repeat_side_effects.rs +++ b/tests/ui/zero_repeat_side_effects.rs @@ -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"); diff --git a/tests/ui/zero_repeat_side_effects.stderr b/tests/ui/zero_repeat_side_effects.stderr index 3f43f15da4a0..49e850d03534 100644 --- a/tests/ui/zero_repeat_side_effects.stderr +++ b/tests/ui/zero_repeat_side_effects.stderr @@ -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]; | ^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ 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]; | ^^^^^^^^^^^^ @@ -25,7 +25,7 @@ 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]; | ^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + let c: std::vec::Vec = 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]; | ^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL ~ d = vec![] as std::vec::Vec; | 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]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ 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]; | ^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ 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]); | ^^^^^^^^^^^^ @@ -87,35 +87,31 @@ 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 ~ { -LL + f(); -LL + vec![] as std::vec::Vec -LL ~ }; +LL ~ f(); +LL ~ vec![] as std::vec::Vec; | 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 ~ { -LL + f(); -LL + [] as [i32; 0] -LL ~ }; +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]); | ^^^^^^^^^^^^^^ @@ -129,7 +125,7 @@ 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]); | ^^^^^^^^^^^^^^^^^^^^^^^^^