unnecessary_struct_initialization: extend to assignments moving all fields
This lint makes Clippy warn about situations where an owned struct is essentially recreated by moving all its fields into a new instance of the struct. Until now this lint only triggered for structs recreated from a base struct. NB: The new functionality too will cause false positives for the situation where a non-copy struct consisting of all copy members is touched again in subsequent code.
This commit is contained in:
parent
87f8a5b374
commit
296dcf09fb
4 changed files with 329 additions and 44 deletions
|
|
@ -26,6 +26,11 @@ struct V {
|
|||
f: u32,
|
||||
}
|
||||
|
||||
struct W {
|
||||
f1: u32,
|
||||
f2: u32,
|
||||
}
|
||||
|
||||
impl Clone for V {
|
||||
fn clone(&self) -> Self {
|
||||
// Lint: `Self` implements `Copy`
|
||||
|
|
@ -68,4 +73,69 @@ fn main() {
|
|||
|
||||
// Should lint: the result of an expression is mutable and temporary
|
||||
let p = &mut *Box::new(T { f: 5 });
|
||||
|
||||
// Should lint: all fields of `q` would be consumed anyway
|
||||
let q = W { f1: 42, f2: 1337 };
|
||||
let r = q;
|
||||
|
||||
// Should not lint: not all fields of `t` from same source
|
||||
let s = W { f1: 1337, f2: 42 };
|
||||
let t = W { f1: s.f1, f2: r.f2 };
|
||||
|
||||
// Should not lint: different fields of `s` assigned
|
||||
let u = W { f1: s.f2, f2: s.f1 };
|
||||
|
||||
// Should lint: all fields of `v` would be consumed anyway
|
||||
let v = W { f1: 42, f2: 1337 };
|
||||
let w = v;
|
||||
|
||||
// Should not lint: source differs between fields and base
|
||||
let x = W { f1: 42, f2: 1337 };
|
||||
let y = W { f1: w.f1, ..x };
|
||||
|
||||
// Should lint: range desugars to struct
|
||||
let r1 = 0..5;
|
||||
let r2 = r1;
|
||||
|
||||
references();
|
||||
shorthand();
|
||||
}
|
||||
|
||||
fn references() {
|
||||
// Should not lint as `a` is not mutable
|
||||
let a = W { f1: 42, f2: 1337 };
|
||||
let b = &mut W { f1: a.f1, f2: a.f2 };
|
||||
|
||||
// Should lint as `d` is a shared reference
|
||||
let c = W { f1: 42, f2: 1337 };
|
||||
let d = &c;
|
||||
|
||||
// Should not lint as `e` is not mutable
|
||||
let e = W { f1: 42, f2: 1337 };
|
||||
let f = &mut W { f1: e.f1, ..e };
|
||||
|
||||
// Should lint as `h` is a shared reference
|
||||
let g = W { f1: 42, f2: 1337 };
|
||||
let h = &g;
|
||||
|
||||
// Should not lint as `j` is copy
|
||||
let i = V { f: 0x1701d };
|
||||
let j = &V { ..i };
|
||||
|
||||
// Should not lint as `k` is copy
|
||||
let k = V { f: 0x1701d };
|
||||
let l = &V { f: k.f };
|
||||
}
|
||||
|
||||
fn shorthand() {
|
||||
struct S1 {
|
||||
a: i32,
|
||||
b: i32,
|
||||
}
|
||||
|
||||
let a = 42;
|
||||
let s = S1 { a: 3, b: 4 };
|
||||
|
||||
// Should not lint: `a` is not from `s`
|
||||
let s = S1 { a, b: s.b };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,11 @@ struct V {
|
|||
f: u32,
|
||||
}
|
||||
|
||||
struct W {
|
||||
f1: u32,
|
||||
f2: u32,
|
||||
}
|
||||
|
||||
impl Clone for V {
|
||||
fn clone(&self) -> Self {
|
||||
// Lint: `Self` implements `Copy`
|
||||
|
|
@ -72,4 +77,69 @@ fn main() {
|
|||
let p = &mut T {
|
||||
..*Box::new(T { f: 5 })
|
||||
};
|
||||
|
||||
// Should lint: all fields of `q` would be consumed anyway
|
||||
let q = W { f1: 42, f2: 1337 };
|
||||
let r = W { f1: q.f1, f2: q.f2 };
|
||||
|
||||
// Should not lint: not all fields of `t` from same source
|
||||
let s = W { f1: 1337, f2: 42 };
|
||||
let t = W { f1: s.f1, f2: r.f2 };
|
||||
|
||||
// Should not lint: different fields of `s` assigned
|
||||
let u = W { f1: s.f2, f2: s.f1 };
|
||||
|
||||
// Should lint: all fields of `v` would be consumed anyway
|
||||
let v = W { f1: 42, f2: 1337 };
|
||||
let w = W { f1: v.f1, ..v };
|
||||
|
||||
// Should not lint: source differs between fields and base
|
||||
let x = W { f1: 42, f2: 1337 };
|
||||
let y = W { f1: w.f1, ..x };
|
||||
|
||||
// Should lint: range desugars to struct
|
||||
let r1 = 0..5;
|
||||
let r2 = r1.start..r1.end;
|
||||
|
||||
references();
|
||||
shorthand();
|
||||
}
|
||||
|
||||
fn references() {
|
||||
// Should not lint as `a` is not mutable
|
||||
let a = W { f1: 42, f2: 1337 };
|
||||
let b = &mut W { f1: a.f1, f2: a.f2 };
|
||||
|
||||
// Should lint as `d` is a shared reference
|
||||
let c = W { f1: 42, f2: 1337 };
|
||||
let d = &W { f1: c.f1, f2: c.f2 };
|
||||
|
||||
// Should not lint as `e` is not mutable
|
||||
let e = W { f1: 42, f2: 1337 };
|
||||
let f = &mut W { f1: e.f1, ..e };
|
||||
|
||||
// Should lint as `h` is a shared reference
|
||||
let g = W { f1: 42, f2: 1337 };
|
||||
let h = &W { f1: g.f1, ..g };
|
||||
|
||||
// Should not lint as `j` is copy
|
||||
let i = V { f: 0x1701d };
|
||||
let j = &V { ..i };
|
||||
|
||||
// Should not lint as `k` is copy
|
||||
let k = V { f: 0x1701d };
|
||||
let l = &V { f: k.f };
|
||||
}
|
||||
|
||||
fn shorthand() {
|
||||
struct S1 {
|
||||
a: i32,
|
||||
b: i32,
|
||||
}
|
||||
|
||||
let a = 42;
|
||||
let s = S1 { a: 3, b: 4 };
|
||||
|
||||
// Should not lint: `a` is not from `s`
|
||||
let s = S1 { a, b: s.b };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: unnecessary struct building
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:32:9
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:37:9
|
||||
|
|
||||
LL | Self { ..*self }
|
||||
| ^^^^^^^^^^^^^^^^ help: replace with: `*self`
|
||||
|
|
@ -8,25 +8,25 @@ LL | Self { ..*self }
|
|||
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_struct_initialization)]`
|
||||
|
||||
error: unnecessary struct building
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:39:17
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:44:17
|
||||
|
|
||||
LL | let mut b = S { ..a };
|
||||
| ^^^^^^^^^ help: replace with: `a`
|
||||
|
||||
error: unnecessary struct building
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:42:18
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:47:18
|
||||
|
|
||||
LL | let c = &mut S { ..b };
|
||||
| ^^^^^^^^^ help: replace with: `b`
|
||||
|
||||
error: unnecessary struct building
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:50:14
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:55:14
|
||||
|
|
||||
LL | let g = &S { ..f };
|
||||
| ^^^^^^^^^ help: replace with: `f`
|
||||
|
||||
error: unnecessary struct building
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:53:18
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:58:18
|
||||
|
|
||||
LL | let h = &mut S {
|
||||
| __________________^
|
||||
|
|
@ -35,7 +35,7 @@ LL | | };
|
|||
| |_____^ help: replace with: `*Box::new(S { f: String::from("foo") })`
|
||||
|
||||
error: unnecessary struct building
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:72:18
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:77:18
|
||||
|
|
||||
LL | let p = &mut T {
|
||||
| __________________^
|
||||
|
|
@ -43,5 +43,35 @@ LL | | ..*Box::new(T { f: 5 })
|
|||
LL | | };
|
||||
| |_____^ help: replace with: `*Box::new(T { f: 5 })`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: unnecessary struct building
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:83:13
|
||||
|
|
||||
LL | let r = W { f1: q.f1, f2: q.f2 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `q`
|
||||
|
||||
error: unnecessary struct building
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:94:13
|
||||
|
|
||||
LL | let w = W { f1: v.f1, ..v };
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: replace with: `v`
|
||||
|
||||
error: unnecessary struct building
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:102:14
|
||||
|
|
||||
LL | let r2 = r1.start..r1.end;
|
||||
| ^^^^^^^^^^^^^^^^ help: replace with: `r1`
|
||||
|
||||
error: unnecessary struct building
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:115:14
|
||||
|
|
||||
LL | let d = &W { f1: c.f1, f2: c.f2 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `c`
|
||||
|
||||
error: unnecessary struct building
|
||||
--> tests/ui/unnecessary_struct_initialization.rs:123:14
|
||||
|
|
||||
LL | let h = &W { f1: g.f1, ..g };
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: replace with: `g`
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue