]> git.proxmox.com Git - rustc.git/blame - library/core/tests/mem.rs
New upstream version 1.75.0+dfsg1
[rustc.git] / library / core / tests / mem.rs
CommitLineData
1a4d82fc 1use core::mem::*;
487cf647 2use core::ptr;
1a4d82fc 3
fc512014
XL
4#[cfg(panic = "unwind")]
5use std::rc::Rc;
6
1a4d82fc
JJ
7#[test]
8fn size_of_basic() {
85aaf69f
SL
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);
1a4d82fc
JJ
13}
14
3157f602
XL
15#[test]
16#[cfg(target_pointer_width = "16")]
17fn size_of_16() {
18 assert_eq!(size_of::<usize>(), 2);
19 assert_eq!(size_of::<*const usize>(), 2);
20}
21
1a4d82fc 22#[test]
85aaf69f 23#[cfg(target_pointer_width = "32")]
1a4d82fc 24fn size_of_32() {
c34b1796
AL
25 assert_eq!(size_of::<usize>(), 4);
26 assert_eq!(size_of::<*const usize>(), 4);
1a4d82fc
JJ
27}
28
29#[test]
85aaf69f 30#[cfg(target_pointer_width = "64")]
1a4d82fc 31fn size_of_64() {
c34b1796
AL
32 assert_eq!(size_of::<usize>(), 8);
33 assert_eq!(size_of::<*const usize>(), 8);
1a4d82fc
JJ
34}
35
36#[test]
37fn 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]
45fn align_of_basic() {
85aaf69f
SL
46 assert_eq!(align_of::<u8>(), 1);
47 assert_eq!(align_of::<u16>(), 2);
48 assert_eq!(align_of::<u32>(), 4);
1a4d82fc
JJ
49}
50
3157f602
XL
51#[test]
52#[cfg(target_pointer_width = "16")]
53fn align_of_16() {
54 assert_eq!(align_of::<usize>(), 2);
55 assert_eq!(align_of::<*const usize>(), 2);
56}
57
1a4d82fc 58#[test]
85aaf69f 59#[cfg(target_pointer_width = "32")]
1a4d82fc 60fn align_of_32() {
c34b1796
AL
61 assert_eq!(align_of::<usize>(), 4);
62 assert_eq!(align_of::<*const usize>(), 4);
1a4d82fc
JJ
63}
64
65#[test]
85aaf69f 66#[cfg(target_pointer_width = "64")]
1a4d82fc 67fn align_of_64() {
c34b1796
AL
68 assert_eq!(align_of::<usize>(), 8);
69 assert_eq!(align_of::<*const usize>(), 8);
1a4d82fc
JJ
70}
71
72#[test]
73fn align_of_val_basic() {
85aaf69f
SL
74 assert_eq!(align_of_val(&1u8), 1);
75 assert_eq!(align_of_val(&1u16), 2);
76 assert_eq!(align_of_val(&1u32), 4);
1a4d82fc
JJ
77}
78
487cf647 79#[test]
487cf647
FG
80fn 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
1a4d82fc
JJ
97#[test]
98fn test_swap() {
85aaf69f
SL
99 let mut x = 31337;
100 let mut y = 42;
1a4d82fc
JJ
101 swap(&mut x, &mut y);
102 assert_eq!(x, 42);
103 assert_eq!(y, 31337);
104}
105
106#[test]
107fn 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]
115fn test_transmute_copy() {
85aaf69f 116 assert_eq!(1, unsafe { transmute_copy(&1) });
1a4d82fc
JJ
117}
118
064997fb
FG
119#[test]
120fn test_transmute_copy_shrink() {
121 assert_eq!(0_u8, unsafe { transmute_copy(&0_u64) });
122}
123
124#[test]
125fn 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")]
139fn 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| {
2b03887a
FG
152 if *s == "cannot transmute_copy if Dst is larger than Src" {
153 Ok(s)
154 } else {
155 Err(s)
156 }
064997fb
FG
157 })
158 .unwrap_or_else(|p| panic::resume_unwind(p));
159 }
160 }
161}
162
abe05a73
XL
163#[test]
164#[allow(dead_code)]
165fn test_discriminant_send_sync() {
166 enum Regular {
167 A,
60c5eb7d 168 B(i32),
abe05a73
XL
169 }
170 enum NotSendSync {
60c5eb7d 171 A(*const i32),
abe05a73
XL
172 }
173
60c5eb7d 174 fn is_send_sync<T: Send + Sync>() {}
abe05a73
XL
175
176 is_send_sync::<Discriminant<Regular>>();
177 is_send_sync::<Discriminant<NotSendSync>>();
178}
fc512014
XL
179
180#[test]
fc512014
XL
181fn assume_init_good() {
182 const TRUE: bool = unsafe { MaybeUninit::<bool>::new(true).assume_init() };
183
184 assert!(TRUE);
185}
186
5869c6ff
XL
187#[test]
188fn uninit_array_assume_init() {
2b03887a 189 let mut array = [MaybeUninit::<i16>::uninit(); 5];
5869c6ff
XL
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
2b03887a 196 let array = unsafe { array.transpose().assume_init() };
5869c6ff
XL
197
198 assert_eq!(array, [3, 1, 4, 1, 5]);
199
2b03887a 200 let [] = unsafe { [MaybeUninit::<!>::uninit(); 0].transpose().assume_init() };
5869c6ff
XL
201}
202
fc512014
XL
203#[test]
204fn 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)")]
213fn 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)")]
222fn 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]
230fn 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")]
239fn 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")]
248fn 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")]
257fn 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]
312fn 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}
5869c6ff
XL
329
330#[test]
5869c6ff
XL
331fn uninit_const_assume_init_read() {
332 const FOO: u32 = unsafe { MaybeUninit::new(42).assume_init_read() };
333 assert_eq!(FOO, 42);
334}
a2a8927a
XL
335
336#[test]
337fn 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}
49aad941
FG
367
368#[test]
49aad941
FG
369fn offset_of() {
370 #[repr(C)]
371 struct Foo {
372 x: u8,
373 y: u16,
374 z: Bar,
375 }
376
377 #[repr(C)]
378 struct Bar(u8, u8);
379
380 assert_eq!(offset_of!(Foo, x), 0);
381 assert_eq!(offset_of!(Foo, y), 2);
382 assert_eq!(offset_of!(Foo, z.0), 4);
383 assert_eq!(offset_of!(Foo, z.1), 5);
384
385 // Layout of tuples is unstable
386 assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1);
387 assert!(offset_of!((u8, u16), 1) <= size_of::<(u8, u16)>() - 2);
388
389 #[repr(C)]
390 struct Generic<T> {
391 x: u8,
392 y: u32,
fe692bf9 393 z: T,
49aad941
FG
394 }
395
396 trait Trait {}
397
398 // Ensure that this type of generics works
399 fn offs_of_z<T>() -> usize {
400 offset_of!(Generic<T>, z)
401 }
402
403 assert_eq!(offset_of!(Generic<u8>, z), 8);
404 assert_eq!(offs_of_z::<u8>(), 8);
405
406 // Ensure that it works with the implicit lifetime in `Box<dyn Trait + '_>`.
407 assert_eq!(offset_of!(Generic<Box<dyn Trait>>, z), 8);
408}
409
410#[test]
49aad941
FG
411fn offset_of_union() {
412 #[repr(C)]
413 union Foo {
414 x: u8,
415 y: u16,
416 z: Bar,
417 }
418
419 #[repr(C)]
420 #[derive(Copy, Clone)]
421 struct Bar(u8, u8);
422
423 assert_eq!(offset_of!(Foo, x), 0);
424 assert_eq!(offset_of!(Foo, y), 0);
425 assert_eq!(offset_of!(Foo, z.0), 0);
426 assert_eq!(offset_of!(Foo, z.1), 1);
427}
428
429#[test]
49aad941
FG
430fn offset_of_dst() {
431 #[repr(C)]
432 struct Alpha {
433 x: u8,
434 y: u16,
435 z: [u8],
436 }
437
438 trait Trait {}
439
440 #[repr(C)]
441 struct Beta {
442 x: u8,
443 y: u16,
444 z: dyn Trait,
445 }
446
447 extern "C" {
448 type Extern;
449 }
450
451 #[repr(C)]
452 struct Gamma {
453 x: u8,
454 y: u16,
455 z: Extern,
456 }
457
458 assert_eq!(offset_of!(Alpha, x), 0);
459 assert_eq!(offset_of!(Alpha, y), 2);
460
461 assert_eq!(offset_of!(Beta, x), 0);
462 assert_eq!(offset_of!(Beta, y), 2);
463
464 assert_eq!(offset_of!(Gamma, x), 0);
465 assert_eq!(offset_of!(Gamma, y), 2);
466}
467
468#[test]
49aad941
FG
469fn offset_of_packed() {
470 #[repr(C, packed)]
471 struct Foo {
472 x: u8,
473 y: u16,
474 }
475
476 assert_eq!(offset_of!(Foo, x), 0);
477 assert_eq!(offset_of!(Foo, y), 1);
478}
479
480#[test]
49aad941
FG
481fn offset_of_projection() {
482 #[repr(C)]
483 struct Foo {
484 x: u8,
485 y: u16,
486 }
487
488 trait Projector {
489 type Type;
490 }
491
492 impl Projector for () {
493 type Type = Foo;
494 }
495
496 assert_eq!(offset_of!(<() as Projector>::Type, x), 0);
497 assert_eq!(offset_of!(<() as Projector>::Type, y), 2);
498}
499
500#[test]
49aad941
FG
501fn offset_of_alias() {
502 #[repr(C)]
503 struct Foo {
504 x: u8,
505 y: u16,
506 }
507
508 type Bar = Foo;
509
510 assert_eq!(offset_of!(Bar, x), 0);
511 assert_eq!(offset_of!(Bar, y), 2);
512}
513
514#[test]
49aad941
FG
515fn const_offset_of() {
516 #[repr(C)]
517 struct Foo {
518 x: u8,
519 y: u16,
520 }
521
522 const X_OFFSET: usize = offset_of!(Foo, x);
523 const Y_OFFSET: usize = offset_of!(Foo, y);
524
525 assert_eq!(X_OFFSET, 0);
526 assert_eq!(Y_OFFSET, 2);
527}
528
529#[test]
49aad941
FG
530fn offset_of_without_const_promotion() {
531 #[repr(C)]
532 struct Foo<SuppressConstPromotion> {
533 x: u8,
534 y: u16,
535 _scp: SuppressConstPromotion,
536 }
537
538 // Normally, offset_of is always const promoted.
539 // The generic parameter prevents this from happening.
540 // This is needed to test the codegen impl of offset_of
541 fn inner<SuppressConstPromotion>() {
542 assert_eq!(offset_of!(Foo<SuppressConstPromotion>, x), 0);
543 assert_eq!(offset_of!(Foo<SuppressConstPromotion>, y), 2);
544 }
545
546 inner::<()>();
547}
548
549#[test]
49aad941
FG
550fn offset_of_addr() {
551 #[repr(C)]
552 struct Foo {
553 x: u8,
554 y: u16,
555 z: Bar,
556 }
557
558 #[repr(C)]
559 struct Bar(u8, u8);
560
561 let base = Foo { x: 0, y: 0, z: Bar(0, 0) };
562
563 assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, x), ptr::addr_of!(base.x).addr());
564 assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, y), ptr::addr_of!(base.y).addr());
565 assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.0), ptr::addr_of!(base.z.0).addr());
566 assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.1), ptr::addr_of!(base.z.1).addr());
567}
ed00b5ec
FG
568
569#[test]
570fn const_maybe_uninit_zeroed() {
571 // Sanity check for `MaybeUninit::zeroed` in a realistic const situation (plugin array term)
572 #[repr(C)]
573 struct Foo {
574 a: Option<&'static str>,
575 b: Bar,
576 c: f32,
577 d: *const u8,
578 }
579 #[repr(C)]
580 struct Bar(usize);
581 struct FooPtr(*const Foo);
582 unsafe impl Sync for FooPtr {}
583
584 static UNINIT: FooPtr = FooPtr([unsafe { MaybeUninit::zeroed().assume_init() }].as_ptr());
585 const SIZE: usize = size_of::<Foo>();
586
587 assert_eq!(unsafe { (*UNINIT.0.cast::<[[u8; SIZE]; 1]>())[0] }, [0u8; SIZE]);
588}