#![allow(dead_code)] #![feature(unsize, coerce_unsized)] #[repr(packed)] struct S { a: i32, b: i64, } #[repr(packed)] struct Test1<'a> { x: u8, other: &'a u32, } #[repr(packed)] struct Test2<'a> { x: u8, other: &'a Test1<'a>, } fn test(t: Test2) { let x = *t.other.other; assert_eq!(x, 42); } fn test_unsizing() { #[repr(packed)] struct UnalignedPtr<'a, T: ?Sized> where T: 'a, { data: &'a T, } impl<'a, T, U> std::ops::CoerceUnsized> for UnalignedPtr<'a, T> where T: std::marker::Unsize + ?Sized, U: ?Sized, { } let arr = [1, 2, 3]; let arr_unaligned: UnalignedPtr<[i32; 3]> = UnalignedPtr { data: &arr }; let arr_unaligned: UnalignedPtr<[i32]> = arr_unaligned; let _unused = &arr_unaligned; // forcing an allocation, which could also yield "unaligned write"-errors } fn test_drop() { struct Wrap(u32); impl Drop for Wrap { fn drop(&mut self) { // Do an (aligned) load let _test = self.0; // For the fun of it, test alignment assert_eq!(&self.0 as *const _ as usize % std::mem::align_of::(), 0); } } #[repr(packed,C)] struct Packed { f1: u8, // this should move the second field to something not very aligned f2: T, } let p = Packed { f1: 42, f2: Wrap(23) }; drop(p); } fn test_inner_packed() { // Even if just the inner struct is packed, accesses to the outer field can get unaligned. // Make sure that works. #[repr(packed)] #[derive(Clone,Copy)] struct Inner(u32); #[derive(Clone,Copy)] struct Outer(u8, Inner); let o = Outer(0, Inner(42)); let _x = o.1; let _y = (o.1).0; let _o2 = o.clone(); } fn main() { let mut x = S { a: 42, b: 99, }; let a = x.a; let b = x.b; assert_eq!(a, 42); assert_eq!(b, 99); // can't do `assert_eq!(x.a, 42)`, because `assert_eq!` takes a reference assert_eq!({x.a}, 42); assert_eq!({x.b}, 99); x.b = 77; assert_eq!({x.b}, 77); test(Test2 { x: 0, other: &Test1 { x: 0, other: &42 }}); test_unsizing(); test_drop(); test_inner_packed(); }