New lint: detect unnecessary struct building

This commit is contained in:
Samuel "Sam" Tardieu 2023-03-11 12:44:18 +01:00
parent d3c8442d4d
commit d7d3dbf060
13 changed files with 355 additions and 54 deletions

View file

@ -4987,6 +4987,7 @@ Released 2018-09-13
[`unnecessary_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc [`unnecessary_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc
[`unnecessary_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_self_imports [`unnecessary_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_self_imports
[`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by [`unnecessary_sort_by`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_sort_by
[`unnecessary_struct_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_struct_initialization
[`unnecessary_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned [`unnecessary_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
[`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap [`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
[`unnecessary_wraps`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps [`unnecessary_wraps`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps

View file

@ -618,6 +618,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::unnamed_address::VTABLE_ADDRESS_COMPARISONS_INFO, crate::unnamed_address::VTABLE_ADDRESS_COMPARISONS_INFO,
crate::unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS_INFO, crate::unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS_INFO,
crate::unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS_INFO, crate::unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS_INFO,
crate::unnecessary_struct_initialization::UNNECESSARY_STRUCT_INITIALIZATION_INFO,
crate::unnecessary_wraps::UNNECESSARY_WRAPS_INFO, crate::unnecessary_wraps::UNNECESSARY_WRAPS_INFO,
crate::unnested_or_patterns::UNNESTED_OR_PATTERNS_INFO, crate::unnested_or_patterns::UNNESTED_OR_PATTERNS_INFO,
crate::unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME_INFO, crate::unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME_INFO,

View file

@ -302,6 +302,7 @@ mod unit_types;
mod unnamed_address; mod unnamed_address;
mod unnecessary_owned_empty_strings; mod unnecessary_owned_empty_strings;
mod unnecessary_self_imports; mod unnecessary_self_imports;
mod unnecessary_struct_initialization;
mod unnecessary_wraps; mod unnecessary_wraps;
mod unnested_or_patterns; mod unnested_or_patterns;
mod unsafe_removed_from_name; mod unsafe_removed_from_name;
@ -938,6 +939,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped)); store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped));
store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute)); store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute));
store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv()))); store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv())));
store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct));
// add lints here, do not remove this comment, it's used in `new_lint` // add lints here, do not remove this comment, it's used in `new_lint`
} }

View file

@ -0,0 +1,84 @@
use clippy_utils::{diagnostics::span_lint_and_sugg, get_parent_expr, path_to_local, source::snippet, ty::is_copy};
use rustc_hir::{BindingAnnotation, Expr, ExprKind, Node, PatKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! {
/// ### What it does
/// Checks for initialization of a `struct` by copying a base without setting
/// any field.
///
/// ### Why is this bad?
/// Readibility suffers from unnecessary struct building.
///
/// ### Example
/// ```rust
/// struct S { s: String }
///
/// let a = S { s: String::from("Hello, world!") };
/// let b = S { ..a };
/// ```
/// Use instead:
/// ```rust
/// struct S { s: String }
///
/// let a = S { s: String::from("Hello, world!") };
/// let b = a;
/// ```
#[clippy::version = "1.70.0"]
pub UNNECESSARY_STRUCT_INITIALIZATION,
complexity,
"struct built from a base that can be written mode concisely"
}
declare_lint_pass!(UnnecessaryStruct => [UNNECESSARY_STRUCT_INITIALIZATION]);
impl LateLintPass<'_> for UnnecessaryStruct {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
if let ExprKind::Struct(_, &[], Some(base)) = expr.kind {
if let Some(parent) = get_parent_expr(cx, expr) &&
let parent_ty = cx.typeck_results().expr_ty_adjusted(parent) &&
parent_ty.is_any_ptr()
{
if is_copy(cx, cx.typeck_results().expr_ty(expr)) && path_to_local(base).is_some() {
// When the type implements `Copy`, a reference to the new struct works on the
// copy. Using the original would borrow it.
return;
}
if parent_ty.is_mutable_ptr() && !is_mutable(cx, base) {
// The original can be used in a mutable reference context only if it is mutable.
return;
}
}
// TODO: do not propose to replace *XX if XX is not Copy
if let ExprKind::Unary(UnOp::Deref, target) = base.kind &&
matches!(target.kind, ExprKind::Path(..)) &&
!is_copy(cx, cx.typeck_results().expr_ty(expr))
{
// `*base` cannot be used instead of the struct in the general case if it is not Copy.
return;
}
span_lint_and_sugg(
cx,
UNNECESSARY_STRUCT_INITIALIZATION,
expr.span,
"unnecessary struct building",
"replace with",
snippet(cx, base.span, "..").into_owned(),
rustc_errors::Applicability::MachineApplicable,
);
}
}
}
fn is_mutable(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
if let Some(hir_id) = path_to_local(expr) &&
let Node::Pat(pat) = cx.tcx.hir().get(hir_id)
{
matches!(pat.kind, PatKind::Binding(BindingAnnotation::MUT, ..))
} else {
true
}
}

View file

@ -1,5 +1,5 @@
#![warn(clippy::needless_update)] #![warn(clippy::needless_update)]
#![allow(clippy::no_effect)] #![allow(clippy::no_effect, clippy::unnecessary_struct_initialization)]
struct S { struct S {
pub a: i32, pub a: i32,

View file

@ -1,7 +1,12 @@
#![feature(box_syntax, fn_traits, unboxed_closures)] #![feature(box_syntax, fn_traits, unboxed_closures)]
#![warn(clippy::no_effect_underscore_binding)] #![warn(clippy::no_effect_underscore_binding)]
#![allow(dead_code, path_statements)] #![allow(dead_code, path_statements)]
#![allow(clippy::deref_addrof, clippy::redundant_field_names, clippy::uninlined_format_args)] #![allow(
clippy::deref_addrof,
clippy::redundant_field_names,
clippy::uninlined_format_args,
clippy::unnecessary_struct_initialization
)]
struct Unit; struct Unit;
struct Tuple(i32); struct Tuple(i32);

View file

@ -1,5 +1,5 @@
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:92:5 --> $DIR/no_effect.rs:97:5
| |
LL | 0; LL | 0;
| ^^ | ^^
@ -7,157 +7,157 @@ LL | 0;
= note: `-D clippy::no-effect` implied by `-D warnings` = note: `-D clippy::no-effect` implied by `-D warnings`
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:93:5 --> $DIR/no_effect.rs:98:5
| |
LL | s2; LL | s2;
| ^^^ | ^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:94:5 --> $DIR/no_effect.rs:99:5
| |
LL | Unit; LL | Unit;
| ^^^^^ | ^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:95:5 --> $DIR/no_effect.rs:100:5
| |
LL | Tuple(0); LL | Tuple(0);
| ^^^^^^^^^ | ^^^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:96:5 --> $DIR/no_effect.rs:101:5
| |
LL | Struct { field: 0 }; LL | Struct { field: 0 };
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:97:5 --> $DIR/no_effect.rs:102:5
| |
LL | Struct { ..s }; LL | Struct { ..s };
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:98:5 --> $DIR/no_effect.rs:103:5
| |
LL | Union { a: 0 }; LL | Union { a: 0 };
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:99:5 --> $DIR/no_effect.rs:104:5
| |
LL | Enum::Tuple(0); LL | Enum::Tuple(0);
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:100:5 --> $DIR/no_effect.rs:105:5
| |
LL | Enum::Struct { field: 0 }; LL | Enum::Struct { field: 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:101:5 --> $DIR/no_effect.rs:106:5
| |
LL | 5 + 6; LL | 5 + 6;
| ^^^^^^ | ^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:102:5 --> $DIR/no_effect.rs:107:5
| |
LL | *&42; LL | *&42;
| ^^^^^ | ^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:103:5 --> $DIR/no_effect.rs:108:5
| |
LL | &6; LL | &6;
| ^^^ | ^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:104:5 --> $DIR/no_effect.rs:109:5
| |
LL | (5, 6, 7); LL | (5, 6, 7);
| ^^^^^^^^^^ | ^^^^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:105:5 --> $DIR/no_effect.rs:110:5
| |
LL | box 42; LL | box 42;
| ^^^^^^^ | ^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:106:5 --> $DIR/no_effect.rs:111:5
| |
LL | ..; LL | ..;
| ^^^ | ^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:107:5 --> $DIR/no_effect.rs:112:5
| |
LL | 5..; LL | 5..;
| ^^^^ | ^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:108:5 --> $DIR/no_effect.rs:113:5
| |
LL | ..5; LL | ..5;
| ^^^^ | ^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:109:5 --> $DIR/no_effect.rs:114:5
| |
LL | 5..6; LL | 5..6;
| ^^^^^ | ^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:110:5 --> $DIR/no_effect.rs:115:5
| |
LL | 5..=6; LL | 5..=6;
| ^^^^^^ | ^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:111:5 --> $DIR/no_effect.rs:116:5
| |
LL | [42, 55]; LL | [42, 55];
| ^^^^^^^^^ | ^^^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:112:5 --> $DIR/no_effect.rs:117:5
| |
LL | [42, 55][1]; LL | [42, 55][1];
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:113:5 --> $DIR/no_effect.rs:118:5
| |
LL | (42, 55).1; LL | (42, 55).1;
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:114:5 --> $DIR/no_effect.rs:119:5
| |
LL | [42; 55]; LL | [42; 55];
| ^^^^^^^^^ | ^^^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:115:5 --> $DIR/no_effect.rs:120:5
| |
LL | [42; 55][13]; LL | [42; 55][13];
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:117:5 --> $DIR/no_effect.rs:122:5
| |
LL | || x += 5; LL | || x += 5;
| ^^^^^^^^^^ | ^^^^^^^^^^
error: statement with no effect error: statement with no effect
--> $DIR/no_effect.rs:119:5 --> $DIR/no_effect.rs:124:5
| |
LL | FooString { s: s }; LL | FooString { s: s };
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^
error: binding to `_` prefixed variable with no side-effect error: binding to `_` prefixed variable with no side-effect
--> $DIR/no_effect.rs:120:5 --> $DIR/no_effect.rs:125:5
| |
LL | let _unused = 1; LL | let _unused = 1;
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
@ -165,19 +165,19 @@ LL | let _unused = 1;
= note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings` = note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings`
error: binding to `_` prefixed variable with no side-effect error: binding to `_` prefixed variable with no side-effect
--> $DIR/no_effect.rs:121:5 --> $DIR/no_effect.rs:126:5
| |
LL | let _penguin = || println!("Some helpful closure"); LL | let _penguin = || println!("Some helpful closure");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: binding to `_` prefixed variable with no side-effect error: binding to `_` prefixed variable with no side-effect
--> $DIR/no_effect.rs:122:5 --> $DIR/no_effect.rs:127:5
| |
LL | let _duck = Struct { field: 0 }; LL | let _duck = Struct { field: 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: binding to `_` prefixed variable with no side-effect error: binding to `_` prefixed variable with no side-effect
--> $DIR/no_effect.rs:123:5 --> $DIR/no_effect.rs:128:5
| |
LL | let _cat = [2, 4, 6, 8][2]; LL | let _cat = [2, 4, 6, 8][2];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,7 +1,13 @@
// run-rustfix // run-rustfix
#![feature(box_syntax)] #![feature(box_syntax)]
#![allow(clippy::deref_addrof, dead_code, unused, clippy::no_effect)] #![allow(
clippy::deref_addrof,
dead_code,
unused,
clippy::no_effect,
clippy::unnecessary_struct_initialization
)]
#![warn(clippy::unnecessary_operation)] #![warn(clippy::unnecessary_operation)]
struct Tuple(i32); struct Tuple(i32);

View file

@ -1,7 +1,13 @@
// run-rustfix // run-rustfix
#![feature(box_syntax)] #![feature(box_syntax)]
#![allow(clippy::deref_addrof, dead_code, unused, clippy::no_effect)] #![allow(
clippy::deref_addrof,
dead_code,
unused,
clippy::no_effect,
clippy::unnecessary_struct_initialization
)]
#![warn(clippy::unnecessary_operation)] #![warn(clippy::unnecessary_operation)]
struct Tuple(i32); struct Tuple(i32);

View file

@ -1,5 +1,5 @@
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:51:5 --> $DIR/unnecessary_operation.rs:57:5
| |
LL | Tuple(get_number()); LL | Tuple(get_number());
| ^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` | ^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
@ -7,109 +7,109 @@ LL | Tuple(get_number());
= note: `-D clippy::unnecessary-operation` implied by `-D warnings` = note: `-D clippy::unnecessary-operation` implied by `-D warnings`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:52:5 --> $DIR/unnecessary_operation.rs:58:5
| |
LL | Struct { field: get_number() }; LL | Struct { field: get_number() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:53:5 --> $DIR/unnecessary_operation.rs:59:5
| |
LL | Struct { ..get_struct() }; LL | Struct { ..get_struct() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_struct();` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_struct();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:54:5 --> $DIR/unnecessary_operation.rs:60:5
| |
LL | Enum::Tuple(get_number()); LL | Enum::Tuple(get_number());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:55:5 --> $DIR/unnecessary_operation.rs:61:5
| |
LL | Enum::Struct { field: get_number() }; LL | Enum::Struct { field: get_number() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:56:5 --> $DIR/unnecessary_operation.rs:62:5
| |
LL | 5 + get_number(); LL | 5 + get_number();
| ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();` | ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:57:5 --> $DIR/unnecessary_operation.rs:63:5
| |
LL | *&get_number(); LL | *&get_number();
| ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` | ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:58:5 --> $DIR/unnecessary_operation.rs:64:5
| |
LL | &get_number(); LL | &get_number();
| ^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` | ^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:59:5 --> $DIR/unnecessary_operation.rs:65:5
| |
LL | (5, 6, get_number()); LL | (5, 6, get_number());
| ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;6;get_number();` | ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;6;get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:60:5 --> $DIR/unnecessary_operation.rs:66:5
| |
LL | box get_number(); LL | box get_number();
| ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` | ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:61:5 --> $DIR/unnecessary_operation.rs:67:5
| |
LL | get_number()..; LL | get_number()..;
| ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` | ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:62:5 --> $DIR/unnecessary_operation.rs:68:5
| |
LL | ..get_number(); LL | ..get_number();
| ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` | ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:63:5 --> $DIR/unnecessary_operation.rs:69:5
| |
LL | 5..get_number(); LL | 5..get_number();
| ^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();` | ^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:64:5 --> $DIR/unnecessary_operation.rs:70:5
| |
LL | [42, get_number()]; LL | [42, get_number()];
| ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();` | ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:65:5 --> $DIR/unnecessary_operation.rs:71:5
| |
LL | [42, 55][get_usize()]; LL | [42, 55][get_usize()];
| ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42, 55].len() > get_usize());` | ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42, 55].len() > get_usize());`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:66:5 --> $DIR/unnecessary_operation.rs:72:5
| |
LL | (42, get_number()).1; LL | (42, get_number()).1;
| ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();` | ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:67:5 --> $DIR/unnecessary_operation.rs:73:5
| |
LL | [get_number(); 55]; LL | [get_number(); 55];
| ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();` | ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:68:5 --> $DIR/unnecessary_operation.rs:74:5
| |
LL | [42; 55][get_usize()]; LL | [42; 55][get_usize()];
| ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42; 55].len() > get_usize());` | ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42; 55].len() > get_usize());`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:69:5 --> $DIR/unnecessary_operation.rs:75:5
| |
LL | / { LL | / {
LL | | get_number() LL | | get_number()
@ -117,7 +117,7 @@ LL | | };
| |______^ help: statement can be reduced to: `get_number();` | |______^ help: statement can be reduced to: `get_number();`
error: unnecessary operation error: unnecessary operation
--> $DIR/unnecessary_operation.rs:72:5 --> $DIR/unnecessary_operation.rs:78:5
| |
LL | / FooString { LL | / FooString {
LL | | s: String::from("blah"), LL | | s: String::from("blah"),

View file

@ -0,0 +1,73 @@
// run-rustfix
#![allow(unused)]
#![warn(clippy::unnecessary_struct_initialization)]
struct S {
f: String,
}
#[derive(Clone, Copy)]
struct T {
f: u32,
}
struct U {
f: u32,
}
impl Clone for U {
fn clone(&self) -> Self {
// Do not lint: `Self` does not implement `Copy`
Self { ..*self }
}
}
#[derive(Copy)]
struct V {
f: u32,
}
impl Clone for V {
fn clone(&self) -> Self {
// Lint: `Self` implements `Copy`
*self
}
}
fn main() {
// Should lint: `a` would be consumed anyway
let a = S { f: String::from("foo") };
let mut b = a;
// Should lint: `b` would be consumed, and is mutable
let c = &mut b;
// Should not lint as `d` is not mutable
let d = S { f: String::from("foo") };
let e = &mut S { ..d };
// Should lint as `f` would be consumed anyway
let f = S { f: String::from("foo") };
let g = &f;
// Should lint: the result of an expression is mutable
let h = &mut *Box::new(S { f: String::from("foo") });
// Should not lint: `m` would be both alive and borrowed
let m = T { f: 17 };
let n = &T { ..m };
// Should not lint: `m` should not be modified
let o = &mut T { ..m };
o.f = 32;
assert_eq!(m.f, 17);
// Should not lint: `m` should not be modified
let o = &mut T { ..m } as *mut T;
unsafe { &mut *o }.f = 32;
assert_eq!(m.f, 17);
// Should lint: the result of an expression is mutable and temporary
let p = &mut *Box::new(T { f: 5 });
}

View file

@ -0,0 +1,77 @@
// run-rustfix
#![allow(unused)]
#![warn(clippy::unnecessary_struct_initialization)]
struct S {
f: String,
}
#[derive(Clone, Copy)]
struct T {
f: u32,
}
struct U {
f: u32,
}
impl Clone for U {
fn clone(&self) -> Self {
// Do not lint: `Self` does not implement `Copy`
Self { ..*self }
}
}
#[derive(Copy)]
struct V {
f: u32,
}
impl Clone for V {
fn clone(&self) -> Self {
// Lint: `Self` implements `Copy`
Self { ..*self }
}
}
fn main() {
// Should lint: `a` would be consumed anyway
let a = S { f: String::from("foo") };
let mut b = S { ..a };
// Should lint: `b` would be consumed, and is mutable
let c = &mut S { ..b };
// Should not lint as `d` is not mutable
let d = S { f: String::from("foo") };
let e = &mut S { ..d };
// Should lint as `f` would be consumed anyway
let f = S { f: String::from("foo") };
let g = &S { ..f };
// Should lint: the result of an expression is mutable
let h = &mut S {
..*Box::new(S { f: String::from("foo") })
};
// Should not lint: `m` would be both alive and borrowed
let m = T { f: 17 };
let n = &T { ..m };
// Should not lint: `m` should not be modified
let o = &mut T { ..m };
o.f = 32;
assert_eq!(m.f, 17);
// Should not lint: `m` should not be modified
let o = &mut T { ..m } as *mut T;
unsafe { &mut *o }.f = 32;
assert_eq!(m.f, 17);
// Should lint: the result of an expression is mutable and temporary
let p = &mut T {
..*Box::new(T { f: 5 })
};
}

View file

@ -0,0 +1,46 @@
error: unnecessary struct building
--> $DIR/unnecessary_struct_initialization.rs:34:9
|
LL | Self { ..*self }
| ^^^^^^^^^^^^^^^^ help: replace with: `*self`
|
= note: `-D clippy::unnecessary-struct-initialization` implied by `-D warnings`
error: unnecessary struct building
--> $DIR/unnecessary_struct_initialization.rs:41:17
|
LL | let mut b = S { ..a };
| ^^^^^^^^^ help: replace with: `a`
error: unnecessary struct building
--> $DIR/unnecessary_struct_initialization.rs:44:18
|
LL | let c = &mut S { ..b };
| ^^^^^^^^^ help: replace with: `b`
error: unnecessary struct building
--> $DIR/unnecessary_struct_initialization.rs:52:14
|
LL | let g = &S { ..f };
| ^^^^^^^^^ help: replace with: `f`
error: unnecessary struct building
--> $DIR/unnecessary_struct_initialization.rs:55:18
|
LL | let h = &mut S {
| __________________^
LL | | ..*Box::new(S { f: String::from("foo") })
LL | | };
| |_____^ help: replace with: `*Box::new(S { f: String::from("foo") })`
error: unnecessary struct building
--> $DIR/unnecessary_struct_initialization.rs:74:18
|
LL | let p = &mut T {
| __________________^
LL | | ..*Box::new(T { f: 5 })
LL | | };
| |_____^ help: replace with: `*Box::new(T { f: 5 })`
error: aborting due to 6 previous errors