aboutsummaryrefslogtreecommitdiff
path: root/tests/repr_packed.rs
diff options
context:
space:
mode:
authorChih-Hung Hsieh <chh@google.com>2020-05-13 16:08:03 -0700
committerChih-Hung Hsieh <chh@google.com>2020-05-13 16:08:03 -0700
commit6f3e9271b123f94f158b1f000c996a558351320f (patch)
treec0d427205c0f0002d86155721cc4f8de67c4fbe5 /tests/repr_packed.rs
parent2e1ed433d835e9f8409237243b8c03b0be6a1310 (diff)
downloadpin-project-6f3e9271b123f94f158b1f000c996a558351320f.tar.gz
Import 'pin-project' package version 0.4.16
* Add OWNERS and Android.bp Bug: 156165390 Test: make Change-Id: I8ace68f978b2725ad91e0f64282003fa453674ca
Diffstat (limited to 'tests/repr_packed.rs')
-rw-r--r--tests/repr_packed.rs50
1 files changed, 50 insertions, 0 deletions
diff --git a/tests/repr_packed.rs b/tests/repr_packed.rs
new file mode 100644
index 0000000..ca56959
--- /dev/null
+++ b/tests/repr_packed.rs
@@ -0,0 +1,50 @@
+#![warn(rust_2018_idioms, single_use_lifetimes)]
+#![allow(dead_code)]
+#![deny(safe_packed_borrows)]
+
+use std::cell::Cell;
+
+// Ensure that the compiler doesn't copy the fields
+// of #[repr(packed)] types during drop, if the field has alignment 1
+// (that is, any reference to the field is guaranteed to have proper alignment)
+// We are currently unable to statically prevent the usage of #[pin_project]
+// on #[repr(packed)] types composed entirely of fields of alignment 1.
+// This shouldn't lead to undefined behavior, as long as the compiler doesn't
+// try to move the field anyway during drop.
+//
+// This tests validates that the compiler is doing what we expect.
+#[test]
+fn weird_repr_packed() {
+ // We keep track of the field address during
+ // drop using a thread local, to avoid changing
+ // the layout of our #[repr(packed)] type.
+ thread_local! {
+ static FIELD_ADDR: Cell<usize> = Cell::new(0);
+ }
+
+ #[repr(packed)]
+ struct Foo {
+ field: u8,
+ }
+
+ impl Drop for Foo {
+ fn drop(&mut self) {
+ FIELD_ADDR.with(|f| {
+ f.set(&self.field as *const u8 as usize);
+ })
+ }
+ }
+
+ #[allow(clippy::let_and_return)]
+ let field_addr = {
+ // We let this field drop by going out of scope,
+ // rather than explicitly calling drop(foo).
+ // Calling drop(foo) causes 'foo' to be moved
+ // into the 'drop' function, resulting in a different
+ // address.
+ let x = Foo { field: 27 };
+ let field_addr = &x.field as *const u8 as usize;
+ field_addr
+ };
+ assert_eq!(field_addr, FIELD_ADDR.with(|f| f.get()));
+}