2020-01-23 19:33:55 +00:00
|
|
|
// For rust-lang/rust#68303: the contents of `UnsafeCell<T>` cannot
|
|
|
|
// participate in the niche-optimization for enum discriminants. This
|
|
|
|
// test checks that an `Option<UnsafeCell<NonZeroU32>>` has the same
|
|
|
|
// size in memory as an `Option<UnsafeCell<u32>>` (namely, 8 bytes).
|
|
|
|
|
2022-07-11 10:29:02 +00:00
|
|
|
// check-pass
|
2022-07-11 14:16:14 +00:00
|
|
|
// compile-flags: --crate-type=lib
|
2022-07-13 10:11:35 +00:00
|
|
|
// only-x86
|
2020-01-23 19:33:55 +00:00
|
|
|
|
2022-07-11 10:25:41 +00:00
|
|
|
#![feature(repr_simd)]
|
|
|
|
|
2022-07-08 14:28:19 +00:00
|
|
|
use std::cell::{UnsafeCell, RefCell, Cell};
|
2022-07-11 10:43:47 +00:00
|
|
|
use std::mem::size_of;
|
2020-01-23 19:33:55 +00:00
|
|
|
use std::num::NonZeroU32 as N32;
|
2022-07-08 14:28:19 +00:00
|
|
|
use std::sync::{Mutex, RwLock};
|
2020-01-23 19:33:55 +00:00
|
|
|
|
2022-07-25 20:36:03 +00:00
|
|
|
struct Wrapper<T>(#[allow(unused_tuple_struct_fields)] T);
|
2020-01-23 19:33:55 +00:00
|
|
|
|
|
|
|
#[repr(transparent)]
|
2022-07-25 20:36:03 +00:00
|
|
|
struct Transparent<T>(#[allow(unused_tuple_struct_fields)] T);
|
2020-01-23 19:33:55 +00:00
|
|
|
|
2022-07-07 10:46:22 +00:00
|
|
|
struct NoNiche<T>(UnsafeCell<T>);
|
2020-01-23 19:33:55 +00:00
|
|
|
|
2022-07-11 10:34:01 +00:00
|
|
|
struct Size<const S: usize>;
|
|
|
|
|
2022-07-11 15:41:38 +00:00
|
|
|
macro_rules! check_sizes {
|
|
|
|
(check_one_specific_size: $ty:ty, $size:expr) => {
|
2022-07-11 14:23:32 +00:00
|
|
|
const _: Size::<{$size}> = Size::<{size_of::<$ty>()}>;
|
|
|
|
};
|
2022-07-12 07:29:36 +00:00
|
|
|
// Any tests run on `UnsafeCell` must be the same for `Cell`
|
|
|
|
(UnsafeCell<$ty:ty>: $size:expr => $optioned_size:expr) => {
|
|
|
|
check_sizes!(Cell<$ty>: $size => $optioned_size);
|
|
|
|
check_sizes!(@actual_check: UnsafeCell<$ty>: $size => $optioned_size);
|
|
|
|
};
|
2022-07-12 07:22:52 +00:00
|
|
|
($ty:ty: $size:expr => $optioned_size:expr) => {
|
2022-07-12 07:29:36 +00:00
|
|
|
check_sizes!(@actual_check: $ty: $size => $optioned_size);
|
|
|
|
};
|
|
|
|
// This branch does the actual checking logic, the `@actual_check` prefix is here to distinguish
|
|
|
|
// it from other branches and not accidentally match any.
|
|
|
|
(@actual_check: $ty:ty: $size:expr => $optioned_size:expr) => {
|
2022-07-11 15:41:38 +00:00
|
|
|
check_sizes!(check_one_specific_size: $ty, $size);
|
|
|
|
check_sizes!(check_one_specific_size: Option<$ty>, $optioned_size);
|
|
|
|
check_sizes!(check_no_niche_opt: $size != $optioned_size, $ty);
|
|
|
|
};
|
2022-07-12 07:29:36 +00:00
|
|
|
// only check that there is no niche (size goes up when wrapped in an option),
|
|
|
|
// don't check actual sizes
|
2022-07-11 15:41:38 +00:00
|
|
|
($ty:ty) => {
|
|
|
|
check_sizes!(check_no_niche_opt: true, $ty);
|
|
|
|
};
|
|
|
|
(check_no_niche_opt: $no_niche_opt:expr, $ty:ty) => {
|
|
|
|
const _: () = if $no_niche_opt { assert!(size_of::<$ty>() < size_of::<Option<$ty>>()); };
|
2022-07-11 14:16:14 +00:00
|
|
|
};
|
2022-07-11 10:29:02 +00:00
|
|
|
}
|
|
|
|
|
2022-07-11 10:43:47 +00:00
|
|
|
const PTR_SIZE: usize = std::mem::size_of::<*const ()>();
|
|
|
|
|
2022-07-12 07:22:52 +00:00
|
|
|
check_sizes!(Wrapper<u32>: 4 => 8);
|
|
|
|
check_sizes!(Wrapper<N32>: 4 => 4); // (✓ niche opt)
|
|
|
|
check_sizes!(Transparent<u32>: 4 => 8);
|
|
|
|
check_sizes!(Transparent<N32>: 4 => 4); // (✓ niche opt)
|
|
|
|
check_sizes!(NoNiche<u32>: 4 => 8);
|
|
|
|
check_sizes!(NoNiche<N32>: 4 => 8);
|
2022-07-11 15:41:38 +00:00
|
|
|
|
2022-07-12 07:22:52 +00:00
|
|
|
check_sizes!(UnsafeCell<u32>: 4 => 8);
|
|
|
|
check_sizes!(UnsafeCell<N32>: 4 => 8);
|
2022-07-11 15:41:38 +00:00
|
|
|
|
2022-07-12 07:22:52 +00:00
|
|
|
check_sizes!(UnsafeCell<&()>: PTR_SIZE => PTR_SIZE * 2);
|
|
|
|
check_sizes!( RefCell<&()>: PTR_SIZE * 2 => PTR_SIZE * 3);
|
2022-07-11 15:41:38 +00:00
|
|
|
|
|
|
|
check_sizes!(RwLock<&()>);
|
|
|
|
check_sizes!(Mutex<&()>);
|
|
|
|
|
2022-07-12 07:22:52 +00:00
|
|
|
check_sizes!(UnsafeCell<&[i32]>: PTR_SIZE * 2 => PTR_SIZE * 3);
|
|
|
|
check_sizes!(UnsafeCell<(&(), &())>: PTR_SIZE * 2 => PTR_SIZE * 3);
|
2022-07-11 14:16:14 +00:00
|
|
|
|
|
|
|
trait Trait {}
|
2022-07-12 07:22:52 +00:00
|
|
|
check_sizes!(UnsafeCell<&dyn Trait>: PTR_SIZE * 2 => PTR_SIZE * 3);
|
2022-07-11 14:16:14 +00:00
|
|
|
|
|
|
|
#[repr(simd)]
|
|
|
|
pub struct Vec4<T>([T; 4]);
|
|
|
|
|
2022-07-12 07:22:52 +00:00
|
|
|
check_sizes!(UnsafeCell<Vec4<N32>>: 16 => 32);
|