diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
commit | 64d98f8ee037282c35007b64c2649055c56af1db (patch) | |
tree | 5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /tests/ui/layout/unsafe-cell-hides-niche.rs | |
parent | Adding debian version 1.67.1+dfsg1-1. (diff) | |
download | rustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz rustc-64d98f8ee037282c35007b64c2649055c56af1db.zip |
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/layout/unsafe-cell-hides-niche.rs')
-rw-r--r-- | tests/ui/layout/unsafe-cell-hides-niche.rs | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/tests/ui/layout/unsafe-cell-hides-niche.rs b/tests/ui/layout/unsafe-cell-hides-niche.rs new file mode 100644 index 000000000..68bcc3c1a --- /dev/null +++ b/tests/ui/layout/unsafe-cell-hides-niche.rs @@ -0,0 +1,82 @@ +// 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). + +// check-pass +// compile-flags: --crate-type=lib +// only-x86 + +#![feature(repr_simd)] + +use std::cell::{UnsafeCell, RefCell, Cell}; +use std::mem::size_of; +use std::num::NonZeroU32 as N32; +use std::sync::{Mutex, RwLock}; + +struct Wrapper<T>(#[allow(unused_tuple_struct_fields)] T); + +#[repr(transparent)] +struct Transparent<T>(#[allow(unused_tuple_struct_fields)] T); + +struct NoNiche<T>(UnsafeCell<T>); + +struct Size<const S: usize>; + +macro_rules! check_sizes { + (check_one_specific_size: $ty:ty, $size:expr) => { + const _: Size::<{$size}> = Size::<{size_of::<$ty>()}>; + }; + // 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); + }; + ($ty:ty: $size:expr => $optioned_size:expr) => { + 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) => { + 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); + }; + // only check that there is no niche (size goes up when wrapped in an option), + // don't check actual sizes + ($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>>()); }; + }; +} + +const PTR_SIZE: usize = std::mem::size_of::<*const ()>(); + +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); + +check_sizes!(UnsafeCell<u32>: 4 => 8); +check_sizes!(UnsafeCell<N32>: 4 => 8); + +check_sizes!(UnsafeCell<&()>: PTR_SIZE => PTR_SIZE * 2); +check_sizes!( RefCell<&()>: PTR_SIZE * 2 => PTR_SIZE * 3); + +check_sizes!(RwLock<&()>); +check_sizes!(Mutex<&()>); + +check_sizes!(UnsafeCell<&[i32]>: PTR_SIZE * 2 => PTR_SIZE * 3); +check_sizes!(UnsafeCell<(&(), &())>: PTR_SIZE * 2 => PTR_SIZE * 3); + +trait Trait {} +check_sizes!(UnsafeCell<&dyn Trait>: PTR_SIZE * 2 => PTR_SIZE * 3); + +#[repr(simd)] +pub struct Vec4<T>([T; 4]); + +check_sizes!(UnsafeCell<Vec4<N32>>: 16 => 32); |