about summary refs log tree commit diff
path: root/tests/ui/derives/deriving-with-repr-packed-move-errors.rs
diff options
context:
space:
mode:
authorGurinder Singh <frederick.the.fool@gmail.com>2023-11-03 07:32:10 +0530
committerGurinder Singh <frederick.the.fool@gmail.com>2023-11-03 07:32:10 +0530
commit4b3ece475d6e77465a30c8b53d7e1e9e861e4b79 (patch)
tree27e4c496d6eeae63e1797d63c50662f78a663125 /tests/ui/derives/deriving-with-repr-packed-move-errors.rs
parenta395214a3a88be976eec9256987d5eb6b3584bdc (diff)
downloadrust-4b3ece475d6e77465a30c8b53d7e1e9e861e4b79.tar.gz
rust-4b3ece475d6e77465a30c8b53d7e1e9e861e4b79.zip
Emit explanatory note for move errors in packed struct derives
Derive expansions for packed structs cause move errors because
they prefer copying over borrowing since borrowing the fields of a
packed struct can result in unaligned access and therefore undefined
behaviour.

This underlying cause of the errors, however, is not apparent
to the user. We add a diagnostic note here to remedy that.
Diffstat (limited to 'tests/ui/derives/deriving-with-repr-packed-move-errors.rs')
-rw-r--r--tests/ui/derives/deriving-with-repr-packed-move-errors.rs96
1 files changed, 96 insertions, 0 deletions
diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.rs b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs
new file mode 100644
index 00000000000..ffeb02d78b8
--- /dev/null
+++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.rs
@@ -0,0 +1,96 @@
+// Check that deriving builtin traits for a packed struct with
+// non-Copy fields emits move errors along with an additional
+// diagnostic note explaining the reason
+// See issue #117406
+
+use std::fmt::{Debug, Formatter, Result};
+use std::cmp::Ordering;
+
+// Packed + derives: additional diagnostic should be emitted
+// for each of Debug, PartialEq and PartialOrd
+#[repr(packed)]
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)]
+struct StructA(String);
+//~^ ERROR: cannot move out of `self` which is behind a shared reference
+//~| ERROR: cannot move out of `self` which is behind a shared reference
+//~| ERROR: cannot move out of `other` which is behind a shared reference
+//~| ERROR: cannot move out of `self` which is behind a shared reference
+//~| ERROR: cannot move out of `other` which is behind a shared reference
+//~| ERROR: cannot move out of `self` which is behind a shared reference
+//~| ERROR: cannot move out of `other` which is behind a shared reference
+//~| ERROR: cannot move out of `self` which is behind a shared reference
+//~| ERROR: cannot move out of `self` which is behind a shared reference
+
+
+// Unrelated impl: additinal diagnostic should NOT be emitted
+impl StructA {
+    fn fmt(&self) -> String {
+        self.0 //~ ERROR: cannot move out of `self` which is behind a shared reference
+    }
+}
+
+// Packed + manual impls: additional diagnostic should NOT be emitted
+#[repr(packed)]
+struct StructB(String);
+
+impl Debug for StructB {
+    fn fmt(&self, f: &mut Formatter) -> Result {
+        let x = &{ self.0 }; //~ ERROR: cannot move out of `self` which is behind a shared reference
+        write!(f, "{}", x)
+    }
+}
+
+impl PartialEq for StructB {
+    fn eq(&self, other: &StructB) -> bool {
+        ({ self.0 }) == ({ other.0 })
+        //~^ ERROR: cannot move out of `self` which is behind a shared reference
+        //~| ERROR: cannot move out of `other` which is behind a shared reference
+    }
+}
+
+impl PartialOrd for StructB {
+    fn partial_cmp(&self, other: &StructB) -> Option<Ordering> {
+        PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
+        //~^ ERROR: cannot move out of `self` which is behind a shared reference
+        //~| ERROR: cannot move out of `other` which is behind a shared reference
+    }
+}
+
+// NOT packed + derives: additinal diagnostic should NOT be emitted
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default)]
+struct StructC(String);
+
+// NOT packed + manual impls: additinal dignostic should NOT be emitted
+struct StructD(String);
+
+impl Debug for StructD {
+    fn fmt(&self, f: &mut Formatter) -> Result {
+        let x = &{ self.0 }; //~ ERROR: cannot move out of `self` which is behind a shared reference
+        write!(f, "{}", x)
+    }
+}
+
+impl PartialEq for StructD {
+    fn eq(&self, other: &StructD) -> bool {
+        ({ self.0 }) == ({ other.0 })
+        //~^ ERROR: cannot move out of `self` which is behind a shared reference
+        //~| ERROR: cannot move out of `other` which is behind a shared reference
+    }
+}
+
+impl PartialOrd for StructD {
+    fn partial_cmp(&self, other: &StructD) -> Option<Ordering> {
+        PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
+        //~^ ERROR: cannot move out of `self` which is behind a shared reference
+        //~| ERROR: cannot move out of `other` which is behind a shared reference
+    }
+}
+
+// Packed + derives but the move is outside of a derive
+// expansion: additinal diagnostic should NOT be emitted
+fn func(arg: &StructA) -> String {
+    arg.0 //~ ERROR: cannot move out of `arg` which is behind a shared reference
+}
+
+fn main(){
+}