]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | use core::mem::*; |
1a4d82fc | 2 | |
fc512014 XL |
3 | #[cfg(panic = "unwind")] |
4 | use std::rc::Rc; | |
5 | ||
1a4d82fc JJ |
6 | #[test] |
7 | fn size_of_basic() { | |
85aaf69f SL |
8 | assert_eq!(size_of::<u8>(), 1); |
9 | assert_eq!(size_of::<u16>(), 2); | |
10 | assert_eq!(size_of::<u32>(), 4); | |
11 | assert_eq!(size_of::<u64>(), 8); | |
1a4d82fc JJ |
12 | } |
13 | ||
3157f602 XL |
14 | #[test] |
15 | #[cfg(target_pointer_width = "16")] | |
16 | fn size_of_16() { | |
17 | assert_eq!(size_of::<usize>(), 2); | |
18 | assert_eq!(size_of::<*const usize>(), 2); | |
19 | } | |
20 | ||
1a4d82fc | 21 | #[test] |
85aaf69f | 22 | #[cfg(target_pointer_width = "32")] |
1a4d82fc | 23 | fn size_of_32() { |
c34b1796 AL |
24 | assert_eq!(size_of::<usize>(), 4); |
25 | assert_eq!(size_of::<*const usize>(), 4); | |
1a4d82fc JJ |
26 | } |
27 | ||
28 | #[test] | |
85aaf69f | 29 | #[cfg(target_pointer_width = "64")] |
1a4d82fc | 30 | fn size_of_64() { |
c34b1796 AL |
31 | assert_eq!(size_of::<usize>(), 8); |
32 | assert_eq!(size_of::<*const usize>(), 8); | |
1a4d82fc JJ |
33 | } |
34 | ||
35 | #[test] | |
36 | fn size_of_val_basic() { | |
37 | assert_eq!(size_of_val(&1u8), 1); | |
38 | assert_eq!(size_of_val(&1u16), 2); | |
39 | assert_eq!(size_of_val(&1u32), 4); | |
40 | assert_eq!(size_of_val(&1u64), 8); | |
41 | } | |
42 | ||
43 | #[test] | |
44 | fn align_of_basic() { | |
85aaf69f SL |
45 | assert_eq!(align_of::<u8>(), 1); |
46 | assert_eq!(align_of::<u16>(), 2); | |
47 | assert_eq!(align_of::<u32>(), 4); | |
1a4d82fc JJ |
48 | } |
49 | ||
3157f602 XL |
50 | #[test] |
51 | #[cfg(target_pointer_width = "16")] | |
52 | fn align_of_16() { | |
53 | assert_eq!(align_of::<usize>(), 2); | |
54 | assert_eq!(align_of::<*const usize>(), 2); | |
55 | } | |
56 | ||
1a4d82fc | 57 | #[test] |
85aaf69f | 58 | #[cfg(target_pointer_width = "32")] |
1a4d82fc | 59 | fn align_of_32() { |
c34b1796 AL |
60 | assert_eq!(align_of::<usize>(), 4); |
61 | assert_eq!(align_of::<*const usize>(), 4); | |
1a4d82fc JJ |
62 | } |
63 | ||
64 | #[test] | |
85aaf69f | 65 | #[cfg(target_pointer_width = "64")] |
1a4d82fc | 66 | fn align_of_64() { |
c34b1796 AL |
67 | assert_eq!(align_of::<usize>(), 8); |
68 | assert_eq!(align_of::<*const usize>(), 8); | |
1a4d82fc JJ |
69 | } |
70 | ||
71 | #[test] | |
72 | fn align_of_val_basic() { | |
85aaf69f SL |
73 | assert_eq!(align_of_val(&1u8), 1); |
74 | assert_eq!(align_of_val(&1u16), 2); | |
75 | assert_eq!(align_of_val(&1u32), 4); | |
1a4d82fc JJ |
76 | } |
77 | ||
78 | #[test] | |
79 | fn test_swap() { | |
85aaf69f SL |
80 | let mut x = 31337; |
81 | let mut y = 42; | |
1a4d82fc JJ |
82 | swap(&mut x, &mut y); |
83 | assert_eq!(x, 42); | |
84 | assert_eq!(y, 31337); | |
85 | } | |
86 | ||
87 | #[test] | |
88 | fn test_replace() { | |
89 | let mut x = Some("test".to_string()); | |
90 | let y = replace(&mut x, None); | |
91 | assert!(x.is_none()); | |
92 | assert!(y.is_some()); | |
93 | } | |
94 | ||
95 | #[test] | |
96 | fn test_transmute_copy() { | |
85aaf69f | 97 | assert_eq!(1, unsafe { transmute_copy(&1) }); |
1a4d82fc JJ |
98 | } |
99 | ||
064997fb FG |
100 | #[test] |
101 | fn test_transmute_copy_shrink() { | |
102 | assert_eq!(0_u8, unsafe { transmute_copy(&0_u64) }); | |
103 | } | |
104 | ||
105 | #[test] | |
106 | fn test_transmute_copy_unaligned() { | |
107 | #[repr(C)] | |
108 | #[derive(Default)] | |
109 | struct Unaligned { | |
110 | a: u8, | |
111 | b: [u8; 8], | |
112 | } | |
113 | ||
114 | let u = Unaligned::default(); | |
115 | assert_eq!(0_u64, unsafe { transmute_copy(&u.b) }); | |
116 | } | |
117 | ||
118 | #[test] | |
119 | #[cfg(panic = "unwind")] | |
120 | fn test_transmute_copy_grow_panics() { | |
121 | use std::panic; | |
122 | ||
123 | let err = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe { | |
124 | let _unused: u64 = transmute_copy(&1_u8); | |
125 | })); | |
126 | ||
127 | match err { | |
128 | Ok(_) => unreachable!(), | |
129 | Err(payload) => { | |
130 | payload | |
131 | .downcast::<&'static str>() | |
132 | .and_then(|s| { | |
133 | if *s == "cannot transmute_copy if U is larger than T" { Ok(s) } else { Err(s) } | |
134 | }) | |
135 | .unwrap_or_else(|p| panic::resume_unwind(p)); | |
136 | } | |
137 | } | |
138 | } | |
139 | ||
abe05a73 XL |
140 | #[test] |
141 | #[allow(dead_code)] | |
142 | fn test_discriminant_send_sync() { | |
143 | enum Regular { | |
144 | A, | |
60c5eb7d | 145 | B(i32), |
abe05a73 XL |
146 | } |
147 | enum NotSendSync { | |
60c5eb7d | 148 | A(*const i32), |
abe05a73 XL |
149 | } |
150 | ||
60c5eb7d | 151 | fn is_send_sync<T: Send + Sync>() {} |
abe05a73 XL |
152 | |
153 | is_send_sync::<Discriminant<Regular>>(); | |
154 | is_send_sync::<Discriminant<NotSendSync>>(); | |
155 | } | |
fc512014 XL |
156 | |
157 | #[test] | |
fc512014 XL |
158 | fn assume_init_good() { |
159 | const TRUE: bool = unsafe { MaybeUninit::<bool>::new(true).assume_init() }; | |
160 | ||
161 | assert!(TRUE); | |
162 | } | |
163 | ||
5869c6ff XL |
164 | #[test] |
165 | fn uninit_array_assume_init() { | |
166 | let mut array: [MaybeUninit<i16>; 5] = MaybeUninit::uninit_array(); | |
167 | array[0].write(3); | |
168 | array[1].write(1); | |
169 | array[2].write(4); | |
170 | array[3].write(1); | |
171 | array[4].write(5); | |
172 | ||
173 | let array = unsafe { MaybeUninit::array_assume_init(array) }; | |
174 | ||
175 | assert_eq!(array, [3, 1, 4, 1, 5]); | |
176 | ||
177 | let [] = unsafe { MaybeUninit::<!>::array_assume_init([]) }; | |
178 | } | |
179 | ||
fc512014 XL |
180 | #[test] |
181 | fn uninit_write_slice() { | |
182 | let mut dst = [MaybeUninit::new(255); 64]; | |
183 | let src = [0; 64]; | |
184 | ||
185 | assert_eq!(MaybeUninit::write_slice(&mut dst, &src), &src); | |
186 | } | |
187 | ||
188 | #[test] | |
189 | #[should_panic(expected = "source slice length (32) does not match destination slice length (64)")] | |
190 | fn uninit_write_slice_panic_lt() { | |
191 | let mut dst = [MaybeUninit::uninit(); 64]; | |
192 | let src = [0; 32]; | |
193 | ||
194 | MaybeUninit::write_slice(&mut dst, &src); | |
195 | } | |
196 | ||
197 | #[test] | |
198 | #[should_panic(expected = "source slice length (128) does not match destination slice length (64)")] | |
199 | fn uninit_write_slice_panic_gt() { | |
200 | let mut dst = [MaybeUninit::uninit(); 64]; | |
201 | let src = [0; 128]; | |
202 | ||
203 | MaybeUninit::write_slice(&mut dst, &src); | |
204 | } | |
205 | ||
206 | #[test] | |
207 | fn uninit_clone_from_slice() { | |
208 | let mut dst = [MaybeUninit::new(255); 64]; | |
209 | let src = [0; 64]; | |
210 | ||
211 | assert_eq!(MaybeUninit::write_slice_cloned(&mut dst, &src), &src); | |
212 | } | |
213 | ||
214 | #[test] | |
215 | #[should_panic(expected = "destination and source slices have different lengths")] | |
216 | fn uninit_write_slice_cloned_panic_lt() { | |
217 | let mut dst = [MaybeUninit::uninit(); 64]; | |
218 | let src = [0; 32]; | |
219 | ||
220 | MaybeUninit::write_slice_cloned(&mut dst, &src); | |
221 | } | |
222 | ||
223 | #[test] | |
224 | #[should_panic(expected = "destination and source slices have different lengths")] | |
225 | fn uninit_write_slice_cloned_panic_gt() { | |
226 | let mut dst = [MaybeUninit::uninit(); 64]; | |
227 | let src = [0; 128]; | |
228 | ||
229 | MaybeUninit::write_slice_cloned(&mut dst, &src); | |
230 | } | |
231 | ||
232 | #[test] | |
233 | #[cfg(panic = "unwind")] | |
234 | fn uninit_write_slice_cloned_mid_panic() { | |
235 | use std::panic; | |
236 | ||
237 | enum IncrementOrPanic { | |
238 | Increment(Rc<()>), | |
239 | ExpectedPanic, | |
240 | UnexpectedPanic, | |
241 | } | |
242 | ||
243 | impl Clone for IncrementOrPanic { | |
244 | fn clone(&self) -> Self { | |
245 | match self { | |
246 | Self::Increment(rc) => Self::Increment(rc.clone()), | |
247 | Self::ExpectedPanic => panic!("expected panic on clone"), | |
248 | Self::UnexpectedPanic => panic!("unexpected panic on clone"), | |
249 | } | |
250 | } | |
251 | } | |
252 | ||
253 | let rc = Rc::new(()); | |
254 | ||
255 | let mut dst = [ | |
256 | MaybeUninit::uninit(), | |
257 | MaybeUninit::uninit(), | |
258 | MaybeUninit::uninit(), | |
259 | MaybeUninit::uninit(), | |
260 | ]; | |
261 | ||
262 | let src = [ | |
263 | IncrementOrPanic::Increment(rc.clone()), | |
264 | IncrementOrPanic::Increment(rc.clone()), | |
265 | IncrementOrPanic::ExpectedPanic, | |
266 | IncrementOrPanic::UnexpectedPanic, | |
267 | ]; | |
268 | ||
269 | let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { | |
270 | MaybeUninit::write_slice_cloned(&mut dst, &src); | |
271 | })); | |
272 | ||
273 | drop(src); | |
274 | ||
275 | match err { | |
276 | Ok(_) => unreachable!(), | |
277 | Err(payload) => { | |
278 | payload | |
279 | .downcast::<&'static str>() | |
280 | .and_then(|s| if *s == "expected panic on clone" { Ok(s) } else { Err(s) }) | |
281 | .unwrap_or_else(|p| panic::resume_unwind(p)); | |
282 | ||
283 | assert_eq!(Rc::strong_count(&rc), 1) | |
284 | } | |
285 | } | |
286 | } | |
287 | ||
288 | #[test] | |
289 | fn uninit_write_slice_cloned_no_drop() { | |
290 | #[derive(Clone)] | |
291 | struct Bomb; | |
292 | ||
293 | impl Drop for Bomb { | |
294 | fn drop(&mut self) { | |
295 | panic!("dropped a bomb! kaboom") | |
296 | } | |
297 | } | |
298 | ||
299 | let mut dst = [MaybeUninit::uninit()]; | |
300 | let src = [Bomb]; | |
301 | ||
302 | MaybeUninit::write_slice_cloned(&mut dst, &src); | |
303 | ||
304 | forget(src); | |
305 | } | |
5869c6ff XL |
306 | |
307 | #[test] | |
5869c6ff XL |
308 | fn uninit_const_assume_init_read() { |
309 | const FOO: u32 = unsafe { MaybeUninit::new(42).assume_init_read() }; | |
310 | assert_eq!(FOO, 42); | |
311 | } | |
a2a8927a XL |
312 | |
313 | #[test] | |
314 | fn const_maybe_uninit() { | |
315 | use std::ptr; | |
316 | ||
317 | #[derive(Debug, PartialEq)] | |
318 | struct Foo { | |
319 | x: u8, | |
320 | y: u8, | |
321 | } | |
322 | ||
323 | const FIELD_BY_FIELD: Foo = unsafe { | |
324 | let mut val = MaybeUninit::uninit(); | |
325 | init_y(&mut val); // order shouldn't matter | |
326 | init_x(&mut val); | |
327 | val.assume_init() | |
328 | }; | |
329 | ||
330 | const fn init_x(foo: &mut MaybeUninit<Foo>) { | |
331 | unsafe { | |
332 | *ptr::addr_of_mut!((*foo.as_mut_ptr()).x) = 1; | |
333 | } | |
334 | } | |
335 | ||
336 | const fn init_y(foo: &mut MaybeUninit<Foo>) { | |
337 | unsafe { | |
338 | *ptr::addr_of_mut!((*foo.as_mut_ptr()).y) = 2; | |
339 | } | |
340 | } | |
341 | ||
342 | assert_eq!(FIELD_BY_FIELD, Foo { x: 1, y: 2 }); | |
343 | } |