296dcf09fb
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.
142 lines
3.1 KiB
Rust
142 lines
3.1 KiB
Rust
#![allow(clippy::non_canonical_clone_impl, 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,
|
|
}
|
|
|
|
struct W {
|
|
f1: u32,
|
|
f2: 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 });
|
|
|
|
// 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 };
|
|
}
|