diff options
Diffstat (limited to '')
-rw-r--r-- | src/tools/clippy/tests/ui/swap.rs | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/tools/clippy/tests/ui/swap.rs b/src/tools/clippy/tests/ui/swap.rs new file mode 100644 index 000000000..8179ac1f2 --- /dev/null +++ b/src/tools/clippy/tests/ui/swap.rs @@ -0,0 +1,181 @@ +// run-rustfix + +#![warn(clippy::all)] +#![allow( + clippy::blacklisted_name, + clippy::no_effect, + clippy::redundant_clone, + redundant_semicolons, + dead_code, + unused_assignments +)] + +struct Foo(u32); + +#[derive(Clone)] +struct Bar { + a: u32, + b: u32, +} + +fn field() { + let mut bar = Bar { a: 1, b: 2 }; + + let temp = bar.a; + bar.a = bar.b; + bar.b = temp; + + let mut baz = vec![bar.clone(), bar.clone()]; + let temp = baz[0].a; + baz[0].a = baz[1].a; + baz[1].a = temp; +} + +fn array() { + let mut foo = [1, 2]; + let temp = foo[0]; + foo[0] = foo[1]; + foo[1] = temp; + + foo.swap(0, 1); +} + +fn slice() { + let foo = &mut [1, 2]; + let temp = foo[0]; + foo[0] = foo[1]; + foo[1] = temp; + + foo.swap(0, 1); +} + +fn unswappable_slice() { + let foo = &mut [vec![1, 2], vec![3, 4]]; + let temp = foo[0][1]; + foo[0][1] = foo[1][0]; + foo[1][0] = temp; + + // swap(foo[0][1], foo[1][0]) would fail + // this could use split_at_mut and mem::swap, but that is not much simpler. +} + +fn vec() { + let mut foo = vec![1, 2]; + let temp = foo[0]; + foo[0] = foo[1]; + foo[1] = temp; + + foo.swap(0, 1); +} + +fn xor_swap_locals() { + // This is an xor-based swap of local variables. + let mut a = 0; + let mut b = 1; + a ^= b; + b ^= a; + a ^= b; +} + +fn xor_field_swap() { + // This is an xor-based swap of fields in a struct. + let mut bar = Bar { a: 0, b: 1 }; + bar.a ^= bar.b; + bar.b ^= bar.a; + bar.a ^= bar.b; +} + +fn xor_slice_swap() { + // This is an xor-based swap of a slice + let foo = &mut [1, 2]; + foo[0] ^= foo[1]; + foo[1] ^= foo[0]; + foo[0] ^= foo[1]; +} + +fn xor_no_swap() { + // This is a sequence of xor-assignment statements that doesn't result in a swap. + let mut a = 0; + let mut b = 1; + let mut c = 2; + a ^= b; + b ^= c; + a ^= c; + c ^= a; +} + +fn xor_unswappable_slice() { + let foo = &mut [vec![1, 2], vec![3, 4]]; + foo[0][1] ^= foo[1][0]; + foo[1][0] ^= foo[0][0]; + foo[0][1] ^= foo[1][0]; + + // swap(foo[0][1], foo[1][0]) would fail + // this could use split_at_mut and mem::swap, but that is not much simpler. +} + +fn distinct_slice() { + let foo = &mut [vec![1, 2], vec![3, 4]]; + let bar = &mut [vec![1, 2], vec![3, 4]]; + let temp = foo[0][1]; + foo[0][1] = bar[1][0]; + bar[1][0] = temp; +} + +#[rustfmt::skip] +fn main() { + + let mut a = 42; + let mut b = 1337; + + a = b; + b = a; + + ; let t = a; + a = b; + b = t; + + let mut c = Foo(42); + + c.0 = a; + a = c.0; + + ; let t = c.0; + c.0 = a; + a = t; +} + +fn issue_8154() { + struct S1 { + x: i32, + y: i32, + } + struct S2(S1); + struct S3<'a, 'b>(&'a mut &'b mut S1); + + impl std::ops::Deref for S2 { + type Target = S1; + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl std::ops::DerefMut for S2 { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + // Don't lint. `s.0` is mutably borrowed by `s.x` and `s.y` via the deref impl. + let mut s = S2(S1 { x: 0, y: 0 }); + let t = s.x; + s.x = s.y; + s.y = t; + + // Accessing through a mutable reference is fine + let mut s = S1 { x: 0, y: 0 }; + let mut s = &mut s; + let s = S3(&mut s); + let t = s.0.x; + s.0.x = s.0.y; + s.0.y = t; +} |