From cf7374633873902765e89ff8e184c4748f3e268d Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Fri, 14 Jun 2024 12:44:32 -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/polyfill/notsend.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 src/polyfill/notsend.rs 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/polyfill/notsend.rs b/src/polyfill/notsend.rs new file mode 100644 index 0000000000..f0e2f5075c --- /dev/null +++ b/src/polyfill/notsend.rs @@ -0,0 +1,29 @@ +// Copyright 2024 Brian Smith. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +use crate::cpu::Features; +use crate::test; +use core::marker::PhantomData; + +/// A ZST that can be added to any type to make the type `!Send`. +#[derive(Clone, Copy)] +pub struct NotSend(PhantomData<*mut ()>); + +impl NotSend { + pub const VALUE: Self = Self(PhantomData); +} + +const _: () = test::compile_time_assert_clone::(); +const _: () = test::compile_time_assert_copy::(); +const _: () = assert!(core::mem::size_of::() == 0);