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).
7 // compile-flags: --crate-type=lib
10 #![feature(repr_simd)]
12 use std
::cell
::{UnsafeCell, RefCell, Cell}
;
13 use std
::mem
::size_of
;
14 use std
::num
::NonZeroU32
as N32
;
15 use std
::sync
::{Mutex, RwLock}
;
17 struct Wrapper
<T
>(#[allow(unused_tuple_struct_fields)] T);
20 struct Transparent
<T
>(#[allow(unused_tuple_struct_fields)] T);
22 struct NoNiche
<T
>(UnsafeCell
<T
>);
24 struct Size
<const S
: usize>;
26 macro_rules
! check_sizes
{
27 (check_one_specific_size
: $ty
:ty
, $size
:expr
) => {
28 const _
: Size
::<{$size}
> = Size
::<{size_of::<$ty>()}
>;
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
);
35 ($ty
:ty
: $size
:expr
=> $optioned_size
:expr
) => {
36 check_sizes
!(@actual_check
: $ty
: $size
=> $optioned_size
);
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
);
45 // only check that there is no niche (size goes up when wrapped in an option),
46 // don't check actual sizes
48 check_sizes
!(check_no_niche_opt
: true, $ty
);
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>>()); }
;
55 const PTR_SIZE
: usize = std
::mem
::size_of
::<*const ()>();
57 check_sizes
!(Wrapper
<u32>: 4 => 8);
58 check_sizes
!(Wrapper
<N32
>: 4 => 4); // (✓ niche opt)
59 check_sizes
!(Transparent
<u32>: 4 => 8);
60 check_sizes
!(Transparent
<N32
>: 4 => 4); // (✓ niche opt)
61 check_sizes
!(NoNiche
<u32>: 4 => 8);
62 check_sizes
!(NoNiche
<N32
>: 4 => 8);
64 check_sizes
!(UnsafeCell
<u32>: 4 => 8);
65 check_sizes
!(UnsafeCell
<N32
>: 4 => 8);
67 check_sizes
!(UnsafeCell
<&()>: PTR_SIZE
=> PTR_SIZE
* 2);
68 check_sizes
!( RefCell
<&()>: PTR_SIZE
* 2 => PTR_SIZE
* 3);
70 check_sizes
!(RwLock
<&()>);
71 check_sizes
!(Mutex
<&()>);
73 check_sizes
!(UnsafeCell
<&[i32]>: PTR_SIZE
* 2 => PTR_SIZE
* 3);
74 check_sizes
!(UnsafeCell
<(&(), &())>: PTR_SIZE
* 2 => PTR_SIZE
* 3);
77 check_sizes
!(UnsafeCell
<&dyn Trait
>: PTR_SIZE
* 2 => PTR_SIZE
* 3);
80 pub struct Vec4
<T
>([T
; 4]);
82 check_sizes
!(UnsafeCell
<Vec4
<N32
>>: 16 => 32);