]> git.proxmox.com Git - rustc.git/blame - src/test/ui/layout/unsafe-cell-hides-niche.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / src / test / ui / layout / unsafe-cell-hides-niche.rs
CommitLineData
74b04a01
XL
1// For rust-lang/rust#68303: the contents of `UnsafeCell<T>` cannot
2// participate in the niche-optimization for enum discriminants. This
3// test checks that an `Option<UnsafeCell<NonZeroU32>>` has the same
4// size in memory as an `Option<UnsafeCell<u32>>` (namely, 8 bytes).
5
064997fb
FG
6// check-pass
7// compile-flags: --crate-type=lib
8// only-x86
74b04a01 9
064997fb 10#![feature(repr_simd)]
74b04a01 11
064997fb 12use std::cell::{UnsafeCell, RefCell, Cell};
74b04a01
XL
13use std::mem::size_of;
14use std::num::NonZeroU32 as N32;
064997fb 15use std::sync::{Mutex, RwLock};
74b04a01 16
064997fb 17struct Wrapper<T>(#[allow(unused_tuple_struct_fields)] T);
74b04a01
XL
18
19#[repr(transparent)]
064997fb 20struct Transparent<T>(#[allow(unused_tuple_struct_fields)] T);
74b04a01 21
064997fb 22struct NoNiche<T>(UnsafeCell<T>);
74b04a01 23
064997fb 24struct Size<const S: usize>;
74b04a01 25
064997fb
FG
26macro_rules! check_sizes {
27 (check_one_specific_size: $ty:ty, $size:expr) => {
28 const _: Size::<{$size}> = Size::<{size_of::<$ty>()}>;
29 };
30 // Any tests run on `UnsafeCell` must be the same for `Cell`
31 (UnsafeCell<$ty:ty>: $size:expr => $optioned_size:expr) => {
32 check_sizes!(Cell<$ty>: $size => $optioned_size);
33 check_sizes!(@actual_check: UnsafeCell<$ty>: $size => $optioned_size);
34 };
35 ($ty:ty: $size:expr => $optioned_size:expr) => {
36 check_sizes!(@actual_check: $ty: $size => $optioned_size);
37 };
38 // This branch does the actual checking logic, the `@actual_check` prefix is here to distinguish
39 // it from other branches and not accidentally match any.
40 (@actual_check: $ty:ty: $size:expr => $optioned_size:expr) => {
41 check_sizes!(check_one_specific_size: $ty, $size);
42 check_sizes!(check_one_specific_size: Option<$ty>, $optioned_size);
43 check_sizes!(check_no_niche_opt: $size != $optioned_size, $ty);
44 };
45 // only check that there is no niche (size goes up when wrapped in an option),
46 // don't check actual sizes
47 ($ty:ty) => {
48 check_sizes!(check_no_niche_opt: true, $ty);
49 };
50 (check_no_niche_opt: $no_niche_opt:expr, $ty:ty) => {
51 const _: () = if $no_niche_opt { assert!(size_of::<$ty>() < size_of::<Option<$ty>>()); };
52 };
74b04a01 53}
064997fb
FG
54
55const PTR_SIZE: usize = std::mem::size_of::<*const ()>();
56
57check_sizes!(Wrapper<u32>: 4 => 8);
58check_sizes!(Wrapper<N32>: 4 => 4); // (✓ niche opt)
59check_sizes!(Transparent<u32>: 4 => 8);
60check_sizes!(Transparent<N32>: 4 => 4); // (✓ niche opt)
61check_sizes!(NoNiche<u32>: 4 => 8);
62check_sizes!(NoNiche<N32>: 4 => 8);
63
64check_sizes!(UnsafeCell<u32>: 4 => 8);
65check_sizes!(UnsafeCell<N32>: 4 => 8);
66
67check_sizes!(UnsafeCell<&()>: PTR_SIZE => PTR_SIZE * 2);
68check_sizes!( RefCell<&()>: PTR_SIZE * 2 => PTR_SIZE * 3);
69
70check_sizes!(RwLock<&()>);
71check_sizes!(Mutex<&()>);
72
73check_sizes!(UnsafeCell<&[i32]>: PTR_SIZE * 2 => PTR_SIZE * 3);
74check_sizes!(UnsafeCell<(&(), &())>: PTR_SIZE * 2 => PTR_SIZE * 3);
75
76trait Trait {}
77check_sizes!(UnsafeCell<&dyn Trait>: PTR_SIZE * 2 => PTR_SIZE * 3);
78
79#[repr(simd)]
80pub struct Vec4<T>([T; 4]);
81
82check_sizes!(UnsafeCell<Vec4<N32>>: 16 => 32);