about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2020-09-13 20:21:05 +0200
committerGitHub <noreply@github.com>2020-09-13 20:21:05 +0200
commit409eb89b3beaab3d962752ee6b024c36dd6cfd31 (patch)
tree39fd568bf6e38e7982d5273d996dc54e8ced1030
parent7402a394471a6738a40fea7d4f1891666e5a80c5 (diff)
parent5dfe015ba51238e686945d8ce19caf7dee8bc78c (diff)
downloadrust-409eb89b3beaab3d962752ee6b024c36dd6cfd31.tar.gz
rust-409eb89b3beaab3d962752ee6b024c36dd6cfd31.zip
Rollup merge of #75559 - RalfJung:union-test-move, r=joshtriplett
unions: test move behavior of non-Copy fields

This test ensures the behaviors suggested by @petrochenkov [here](https://github.com/rust-lang/rust/issues/32836#issuecomment-242511491).
-rw-r--r--src/test/ui/union/union-drop.rs7
-rw-r--r--src/test/ui/union/union-move.rs53
-rw-r--r--src/test/ui/union/union-move.stderr35
3 files changed, 94 insertions, 1 deletions
diff --git a/src/test/ui/union/union-drop.rs b/src/test/ui/union/union-drop.rs
index daa03ce6b6f..4df3ed50282 100644
--- a/src/test/ui/union/union-drop.rs
+++ b/src/test/ui/union/union-drop.rs
@@ -48,6 +48,11 @@ fn main() {
         {
             let y = Y { a: S };
         }
-        assert_eq!(CHECK, 2); // 2, dtor of Y is called
+        assert_eq!(CHECK, 2); // 2, Y has no dtor
+        {
+            let u2 = U { a: 1 };
+            std::mem::forget(u2);
+        }
+        assert_eq!(CHECK, 2); // 2, dtor of U *not* called for u2
     }
 }
diff --git a/src/test/ui/union/union-move.rs b/src/test/ui/union/union-move.rs
new file mode 100644
index 00000000000..a0a2d0d6598
--- /dev/null
+++ b/src/test/ui/union/union-move.rs
@@ -0,0 +1,53 @@
+//! Test the behavior of moving out of non-`Copy` union fields.
+//! Avoid types that `Drop`, we want to focus on moving.
+#![feature(untagged_unions)]
+
+use std::cell::RefCell;
+
+fn move_out<T>(x: T) {}
+
+union U1 {
+    f1_nocopy: RefCell<i32>,
+    f2_nocopy: RefCell<i32>,
+    f3_copy: i32,
+}
+
+union U2 {
+    f1_nocopy: RefCell<i32>,
+}
+impl Drop for U2 {
+    fn drop(&mut self) {}
+}
+
+fn test1(x: U1) {
+    // Moving out of a nocopy field prevents accessing other nocopy field.
+    unsafe {
+        move_out(x.f1_nocopy);
+        move_out(x.f2_nocopy); //~ ERROR use of moved value: `x`
+    }
+}
+
+fn test2(x: U1) {
+    // "Moving" out of copy field doesn't prevent later field accesses.
+    unsafe {
+        move_out(x.f3_copy);
+        move_out(x.f2_nocopy); // no error
+    }
+}
+
+fn test3(x: U1) {
+    // Moving out of a nocopy field prevents accessing other copy field.
+    unsafe {
+        move_out(x.f2_nocopy);
+        move_out(x.f3_copy); //~ ERROR use of moved value: `x`
+    }
+}
+
+fn test4(x: U2) {
+    // Cannot move out of union that implements `Drop`.
+    unsafe {
+        move_out(x.f1_nocopy); //~ ERROR cannot move out of type `U2`, which implements the `Drop`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/union/union-move.stderr b/src/test/ui/union/union-move.stderr
new file mode 100644
index 00000000000..5679192b641
--- /dev/null
+++ b/src/test/ui/union/union-move.stderr
@@ -0,0 +1,35 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/union-move.rs:26:18
+   |
+LL | fn test1(x: U1) {
+   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL |         move_out(x.f1_nocopy);
+   |                  ----------- value moved here
+LL |         move_out(x.f2_nocopy);
+   |                  ^^^^^^^^^^^ value used here after move
+
+error[E0382]: use of moved value: `x`
+  --> $DIR/union-move.rs:42:18
+   |
+LL | fn test3(x: U1) {
+   |          - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
+...
+LL |         move_out(x.f2_nocopy);
+   |                  ----------- value moved here
+LL |         move_out(x.f3_copy);
+   |                  ^^^^^^^^^ value used here after move
+
+error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
+  --> $DIR/union-move.rs:49:18
+   |
+LL |         move_out(x.f1_nocopy);
+   |                  ^^^^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  move occurs because `x.f1_nocopy` has type `RefCell<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0382, E0509.
+For more information about an error, try `rustc --explain E0382`.