// compile-flags: -Zmir-emit-validate=0 #![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 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(); }