From c5f7b8b620e229372b956ac66b7e63ac8171403f Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Wed, 12 Jun 2024 16:49:30 -0700 Subject: [PATCH] cpu: Make `cpu::Features` be `!Send`. We don't intend to put `cpu::Features` in any type that could be sent across threads. Enforce this in the type system. This way, we can potentially change the representation of `cpu::Features` to one that really couldn't be `Send` in the future. --- src/cpu.rs | 8 ++++++-- src/polyfill.rs | 4 +++- src/test.rs | 12 ++++++------ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/cpu.rs b/src/cpu.rs index cdeea8f475..a8d02f2eee 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -20,11 +20,13 @@ pub(crate) fn features() -> Features { } mod features { + use crate::polyfill::NotSend; + /// A witness indicating that CPU features have been detected and cached. /// /// This is a zero-sized type so that it can be "stored" wherever convenient. #[derive(Copy, Clone)] - pub(crate) struct Features(()); + pub(crate) struct Features(NotSend); cfg_if::cfg_if! { if #[cfg(any(target_arch = "aarch64", target_arch = "arm", @@ -33,7 +35,7 @@ mod features { // SAFETY: This must only be called after CPU features have been written // and synchronized. pub(super) unsafe fn new_after_feature_flags_written_and_synced_unchecked() -> Self { - Self(()) + Self(NotSend::VALUE) } } } else { @@ -46,6 +48,8 @@ mod features { } } +const _: () = assert!(core::mem::size_of::() == 0); + cfg_if::cfg_if! { if #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] { pub mod arm; diff --git a/src/polyfill.rs b/src/polyfill.rs index 42f455eb6b..4d5a0ec1f0 100644 --- a/src/polyfill.rs +++ b/src/polyfill.rs @@ -54,6 +54,7 @@ pub mod sliceutil; #[cfg(feature = "alloc")] mod leading_zeros_skipped; +mod notsend; pub mod ptr; pub mod slice; @@ -64,7 +65,8 @@ mod test; mod unwrap_const; pub use self::{ - array_flat_map::ArrayFlatMap, array_split_map::ArraySplitMap, unwrap_const::unwrap_const, + array_flat_map::ArrayFlatMap, array_split_map::ArraySplitMap, notsend::NotSend, + unwrap_const::unwrap_const, }; #[cfg(feature = "alloc")] diff --git a/src/test.rs b/src/test.rs index b416ecc957..fb62cff951 100644 --- a/src/test.rs +++ b/src/test.rs @@ -128,28 +128,28 @@ extern crate std; /// `compile_time_assert_clone::();` fails to compile if `T` doesn't /// implement `Clone`. -pub fn compile_time_assert_clone() {} +pub const fn compile_time_assert_clone() {} /// `compile_time_assert_copy::();` fails to compile if `T` doesn't /// implement `Copy`. -pub fn compile_time_assert_copy() {} +pub const fn compile_time_assert_copy() {} /// `compile_time_assert_eq::();` fails to compile if `T` doesn't /// implement `Eq`. -pub fn compile_time_assert_eq() {} +pub const fn compile_time_assert_eq() {} /// `compile_time_assert_send::();` fails to compile if `T` doesn't /// implement `Send`. -pub fn compile_time_assert_send() {} +pub const fn compile_time_assert_send() {} /// `compile_time_assert_sync::();` fails to compile if `T` doesn't /// implement `Sync`. -pub fn compile_time_assert_sync() {} +pub const fn compile_time_assert_sync() {} /// `compile_time_assert_std_error_error::();` fails to compile if `T` /// doesn't implement `std::error::Error`. #[cfg(feature = "std")] -pub fn compile_time_assert_std_error_error() {} +pub const fn compile_time_assert_std_error_error() {} /// A test case. A test case consists of a set of named attributes. Every /// attribute in the test case must be consumed exactly once; this helps catch