summaryrefslogtreecommitdiffstats
path: root/library/core/tests/mem.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /library/core/tests/mem.rs
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/core/tests/mem.rs')
-rw-r--r--library/core/tests/mem.rs210
1 files changed, 210 insertions, 0 deletions
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index f7740a114..aee9c89b5 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -364,3 +364,213 @@ fn const_maybe_uninit() {
assert_eq!(FIELD_BY_FIELD, Foo { x: 1, y: 2 });
}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of() {
+ #[repr(C)]
+ struct Foo {
+ x: u8,
+ y: u16,
+ z: Bar,
+ }
+
+ #[repr(C)]
+ struct Bar(u8, u8);
+
+ assert_eq!(offset_of!(Foo, x), 0);
+ assert_eq!(offset_of!(Foo, y), 2);
+ assert_eq!(offset_of!(Foo, z.0), 4);
+ assert_eq!(offset_of!(Foo, z.1), 5);
+
+ // Layout of tuples is unstable
+ assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1);
+ assert!(offset_of!((u8, u16), 1) <= size_of::<(u8, u16)>() - 2);
+
+ #[repr(C)]
+ struct Generic<T> {
+ x: u8,
+ y: u32,
+ z: T
+ }
+
+ trait Trait {}
+
+ // Ensure that this type of generics works
+ fn offs_of_z<T>() -> usize {
+ offset_of!(Generic<T>, z)
+ }
+
+ assert_eq!(offset_of!(Generic<u8>, z), 8);
+ assert_eq!(offs_of_z::<u8>(), 8);
+
+ // Ensure that it works with the implicit lifetime in `Box<dyn Trait + '_>`.
+ assert_eq!(offset_of!(Generic<Box<dyn Trait>>, z), 8);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_union() {
+ #[repr(C)]
+ union Foo {
+ x: u8,
+ y: u16,
+ z: Bar,
+ }
+
+ #[repr(C)]
+ #[derive(Copy, Clone)]
+ struct Bar(u8, u8);
+
+ assert_eq!(offset_of!(Foo, x), 0);
+ assert_eq!(offset_of!(Foo, y), 0);
+ assert_eq!(offset_of!(Foo, z.0), 0);
+ assert_eq!(offset_of!(Foo, z.1), 1);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_dst() {
+ #[repr(C)]
+ struct Alpha {
+ x: u8,
+ y: u16,
+ z: [u8],
+ }
+
+ trait Trait {}
+
+ #[repr(C)]
+ struct Beta {
+ x: u8,
+ y: u16,
+ z: dyn Trait,
+ }
+
+ extern "C" {
+ type Extern;
+ }
+
+ #[repr(C)]
+ struct Gamma {
+ x: u8,
+ y: u16,
+ z: Extern,
+ }
+
+ assert_eq!(offset_of!(Alpha, x), 0);
+ assert_eq!(offset_of!(Alpha, y), 2);
+
+ assert_eq!(offset_of!(Beta, x), 0);
+ assert_eq!(offset_of!(Beta, y), 2);
+
+ assert_eq!(offset_of!(Gamma, x), 0);
+ assert_eq!(offset_of!(Gamma, y), 2);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_packed() {
+ #[repr(C, packed)]
+ struct Foo {
+ x: u8,
+ y: u16,
+ }
+
+ assert_eq!(offset_of!(Foo, x), 0);
+ assert_eq!(offset_of!(Foo, y), 1);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_projection() {
+ #[repr(C)]
+ struct Foo {
+ x: u8,
+ y: u16,
+ }
+
+ trait Projector {
+ type Type;
+ }
+
+ impl Projector for () {
+ type Type = Foo;
+ }
+
+ assert_eq!(offset_of!(<() as Projector>::Type, x), 0);
+ assert_eq!(offset_of!(<() as Projector>::Type, y), 2);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_alias() {
+ #[repr(C)]
+ struct Foo {
+ x: u8,
+ y: u16,
+ }
+
+ type Bar = Foo;
+
+ assert_eq!(offset_of!(Bar, x), 0);
+ assert_eq!(offset_of!(Bar, y), 2);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn const_offset_of() {
+ #[repr(C)]
+ struct Foo {
+ x: u8,
+ y: u16,
+ }
+
+ const X_OFFSET: usize = offset_of!(Foo, x);
+ const Y_OFFSET: usize = offset_of!(Foo, y);
+
+ assert_eq!(X_OFFSET, 0);
+ assert_eq!(Y_OFFSET, 2);
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_without_const_promotion() {
+ #[repr(C)]
+ struct Foo<SuppressConstPromotion> {
+ x: u8,
+ y: u16,
+ _scp: SuppressConstPromotion,
+ }
+
+ // Normally, offset_of is always const promoted.
+ // The generic parameter prevents this from happening.
+ // This is needed to test the codegen impl of offset_of
+ fn inner<SuppressConstPromotion>() {
+ assert_eq!(offset_of!(Foo<SuppressConstPromotion>, x), 0);
+ assert_eq!(offset_of!(Foo<SuppressConstPromotion>, y), 2);
+ }
+
+ inner::<()>();
+}
+
+#[test]
+#[cfg(not(bootstrap))]
+fn offset_of_addr() {
+ #[repr(C)]
+ struct Foo {
+ x: u8,
+ y: u16,
+ z: Bar,
+ }
+
+ #[repr(C)]
+ struct Bar(u8, u8);
+
+ let base = Foo { x: 0, y: 0, z: Bar(0, 0) };
+
+ assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, x), ptr::addr_of!(base.x).addr());
+ assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, y), ptr::addr_of!(base.y).addr());
+ assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.0), ptr::addr_of!(base.z.0).addr());
+ assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.1), ptr::addr_of!(base.z.1).addr());
+}