]> git.lizzy.rs Git - rust.git/blob - src/tools/miri/tests/pass/packed_struct.rs
Auto merge of #104915 - weihanglo:update-cargo, r=ehuss
[rust.git] / src / tools / miri / tests / pass / packed_struct.rs
1 #![feature(unsize, coerce_unsized)]
2
3 use std::collections::hash_map::DefaultHasher;
4 use std::hash::Hash;
5 use std::ptr;
6
7 fn test_basic() {
8     #[repr(packed)]
9     struct S {
10         fill: u8,
11         a: i32,
12         b: i64,
13     }
14
15     #[repr(packed)]
16     #[allow(dead_code)]
17     struct Test1<'a> {
18         x: u8,
19         other: &'a u32,
20     }
21
22     #[repr(packed)]
23     #[allow(dead_code)]
24     struct Test2<'a> {
25         x: u8,
26         other: &'a Test1<'a>,
27     }
28
29     fn test(t: Test2) {
30         let x = *t.other.other;
31         assert_eq!(x, 42);
32     }
33
34     let mut x = S { fill: 0, a: 42, b: 99 };
35     let a = x.a;
36     let b = x.b;
37     assert_eq!(a, 42);
38     assert_eq!(b, 99);
39     assert_eq!(&x.fill, &0); // `fill` just requirs 1-byte-align, so this is fine
40     // can't do `assert_eq!(x.a, 42)`, because `assert_eq!` takes a reference
41     assert_eq!({ x.a }, 42);
42     assert_eq!({ x.b }, 99);
43     // but we *can* take a raw pointer!
44     assert_eq!(unsafe { ptr::addr_of!(x.a).read_unaligned() }, 42);
45     assert_eq!(unsafe { ptr::addr_of!(x.b).read_unaligned() }, 99);
46
47     x.b = 77;
48     assert_eq!({ x.b }, 77);
49
50     test(Test2 { x: 0, other: &Test1 { x: 0, other: &42 } });
51 }
52
53 fn test_unsizing() {
54     #[repr(packed)]
55     #[allow(dead_code)]
56     struct UnalignedPtr<'a, T: ?Sized>
57     where
58         T: 'a,
59     {
60         data: &'a T,
61     }
62
63     impl<'a, T, U> std::ops::CoerceUnsized<UnalignedPtr<'a, U>> for UnalignedPtr<'a, T>
64     where
65         T: std::marker::Unsize<U> + ?Sized,
66         U: ?Sized,
67     {
68     }
69
70     let arr = [1, 2, 3];
71     let arr_unaligned: UnalignedPtr<[i32; 3]> = UnalignedPtr { data: &arr };
72     let arr_unaligned: UnalignedPtr<[i32]> = arr_unaligned;
73     let _unused = &arr_unaligned; // forcing an allocation, which could also yield "unaligned write"-errors
74 }
75
76 fn test_drop() {
77     struct Wrap(u32);
78     impl Drop for Wrap {
79         fn drop(&mut self) {
80             // Do an (aligned) load
81             let _test = self.0;
82             // For the fun of it, test alignment
83             assert_eq!(&self.0 as *const _ as usize % std::mem::align_of::<u32>(), 0);
84         }
85     }
86
87     #[repr(packed, C)]
88     struct Packed<T> {
89         f1: u8, // this should move the second field to something not very aligned
90         f2: T,
91     }
92
93     let p = Packed { f1: 42, f2: Wrap(23) };
94     drop(p);
95 }
96
97 fn test_inner_packed() {
98     // Even if just the inner struct is packed, accesses to the outer field can get unaligned.
99     // Make sure that works.
100     #[repr(packed)]
101     #[derive(Clone, Copy)]
102     struct Inner(u32);
103
104     #[derive(Clone, Copy)]
105     struct Outer(u8, Inner);
106
107     let o = Outer(0, Inner(42));
108     let _x = o.1;
109     let _y = (o.1).0;
110     let _o2 = o.clone();
111 }
112
113 fn test_static() {
114     #[repr(packed)]
115     struct Foo {
116         i: i32,
117     }
118
119     static FOO: Foo = Foo { i: 42 };
120
121     assert_eq!({ FOO.i }, 42);
122 }
123
124 fn test_derive() {
125     #[repr(packed)]
126     #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
127     struct P {
128         a: usize,
129         b: u8,
130         c: usize,
131     }
132
133     let x = P { a: 1usize, b: 2u8, c: 3usize };
134     let y = P { a: 1usize, b: 2u8, c: 4usize };
135
136     let _clone = x.clone();
137     assert!(x != y);
138     assert_eq!(x.partial_cmp(&y).unwrap(), x.cmp(&y));
139     x.hash(&mut DefaultHasher::new());
140     P::default();
141     format!("{:?}", x);
142 }
143
144 fn main() {
145     test_basic();
146     test_unsizing();
147     test_drop();
148     test_inner_packed();
149     test_static();
150     test_derive();
151 }