]> git.lizzy.rs Git - rust.git/blobdiff - tests/ui/swap.rs
Move MSRV tests into the lint specific test files
[rust.git] / tests / ui / swap.rs
index 377319e8faa27fb40a72ff1017d8397b6d297141..a318c27919c8a4fbdb972f59d48496c695f9e590 100644 (file)
@@ -1,11 +1,36 @@
-#![feature(tool_lints)]
-
+// run-rustfix
 
 #![warn(clippy::all)]
-#![allow(clippy::blacklisted_name, unused_assignments)]
+#![allow(
+    clippy::disallowed_names,
+    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];
@@ -24,6 +49,16 @@ fn slice() {
     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];
@@ -33,10 +68,62 @@ fn vec() {
     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() {
-    array();
-    slice();
-    vec();
 
     let mut a = 42;
     let mut b = 1337;
@@ -57,3 +144,38 @@ fn main() {
     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;
+}