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