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