summaryrefslogtreecommitdiff
path: root/rust/alloc/vec/is_zero.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/alloc/vec/is_zero.rs')
-rw-r--r--rust/alloc/vec/is_zero.rs204
1 files changed, 0 insertions, 204 deletions
diff --git a/rust/alloc/vec/is_zero.rs b/rust/alloc/vec/is_zero.rs
deleted file mode 100644
index d928dcf90e80..000000000000
--- a/rust/alloc/vec/is_zero.rs
+++ /dev/null
@@ -1,204 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR MIT
-
-use core::num::{Saturating, Wrapping};
-
-use crate::boxed::Box;
-
-#[rustc_specialization_trait]
-pub(super) unsafe trait IsZero {
- /// Whether this value's representation is all zeros,
- /// or can be represented with all zeroes.
- fn is_zero(&self) -> bool;
-}
-
-macro_rules! impl_is_zero {
- ($t:ty, $is_zero:expr) => {
- unsafe impl IsZero for $t {
- #[inline]
- fn is_zero(&self) -> bool {
- $is_zero(*self)
- }
- }
- };
-}
-
-impl_is_zero!(i8, |x| x == 0); // It is needed to impl for arrays and tuples of i8.
-impl_is_zero!(i16, |x| x == 0);
-impl_is_zero!(i32, |x| x == 0);
-impl_is_zero!(i64, |x| x == 0);
-impl_is_zero!(i128, |x| x == 0);
-impl_is_zero!(isize, |x| x == 0);
-
-impl_is_zero!(u8, |x| x == 0); // It is needed to impl for arrays and tuples of u8.
-impl_is_zero!(u16, |x| x == 0);
-impl_is_zero!(u32, |x| x == 0);
-impl_is_zero!(u64, |x| x == 0);
-impl_is_zero!(u128, |x| x == 0);
-impl_is_zero!(usize, |x| x == 0);
-
-impl_is_zero!(bool, |x| x == false);
-impl_is_zero!(char, |x| x == '\0');
-
-impl_is_zero!(f32, |x: f32| x.to_bits() == 0);
-impl_is_zero!(f64, |x: f64| x.to_bits() == 0);
-
-unsafe impl<T> IsZero for *const T {
- #[inline]
- fn is_zero(&self) -> bool {
- (*self).is_null()
- }
-}
-
-unsafe impl<T> IsZero for *mut T {
- #[inline]
- fn is_zero(&self) -> bool {
- (*self).is_null()
- }
-}
-
-unsafe impl<T: IsZero, const N: usize> IsZero for [T; N] {
- #[inline]
- fn is_zero(&self) -> bool {
- // Because this is generated as a runtime check, it's not obvious that
- // it's worth doing if the array is really long. The threshold here
- // is largely arbitrary, but was picked because as of 2022-07-01 LLVM
- // fails to const-fold the check in `vec![[1; 32]; n]`
- // See https://github.com/rust-lang/rust/pull/97581#issuecomment-1166628022
- // Feel free to tweak if you have better evidence.
-
- N <= 16 && self.iter().all(IsZero::is_zero)
- }
-}
-
-// This is recursive macro.
-macro_rules! impl_for_tuples {
- // Stopper
- () => {
- // No use for implementing for empty tuple because it is ZST.
- };
- ($first_arg:ident $(,$rest:ident)*) => {
- unsafe impl <$first_arg: IsZero, $($rest: IsZero,)*> IsZero for ($first_arg, $($rest,)*){
- #[inline]
- fn is_zero(&self) -> bool{
- // Destructure tuple to N references
- // Rust allows to hide generic params by local variable names.
- #[allow(non_snake_case)]
- let ($first_arg, $($rest,)*) = self;
-
- $first_arg.is_zero()
- $( && $rest.is_zero() )*
- }
- }
-
- impl_for_tuples!($($rest),*);
- }
-}
-
-impl_for_tuples!(A, B, C, D, E, F, G, H);
-
-// `Option<&T>` and `Option<Box<T>>` are guaranteed to represent `None` as null.
-// For fat pointers, the bytes that would be the pointer metadata in the `Some`
-// variant are padding in the `None` variant, so ignoring them and
-// zero-initializing instead is ok.
-// `Option<&mut T>` never implements `Clone`, so there's no need for an impl of
-// `SpecFromElem`.
-
-unsafe impl<T: ?Sized> IsZero for Option<&T> {
- #[inline]
- fn is_zero(&self) -> bool {
- self.is_none()
- }
-}
-
-unsafe impl<T: ?Sized> IsZero for Option<Box<T>> {
- #[inline]
- fn is_zero(&self) -> bool {
- self.is_none()
- }
-}
-
-// `Option<num::NonZeroU32>` and similar have a representation guarantee that
-// they're the same size as the corresponding `u32` type, as well as a guarantee
-// that transmuting between `NonZeroU32` and `Option<num::NonZeroU32>` works.
-// While the documentation officially makes it UB to transmute from `None`,
-// we're the standard library so we can make extra inferences, and we know that
-// the only niche available to represent `None` is the one that's all zeros.
-
-macro_rules! impl_is_zero_option_of_nonzero {
- ($($t:ident,)+) => {$(
- unsafe impl IsZero for Option<core::num::$t> {
- #[inline]
- fn is_zero(&self) -> bool {
- self.is_none()
- }
- }
- )+};
-}
-
-impl_is_zero_option_of_nonzero!(
- NonZeroU8,
- NonZeroU16,
- NonZeroU32,
- NonZeroU64,
- NonZeroU128,
- NonZeroI8,
- NonZeroI16,
- NonZeroI32,
- NonZeroI64,
- NonZeroI128,
- NonZeroUsize,
- NonZeroIsize,
-);
-
-macro_rules! impl_is_zero_option_of_num {
- ($($t:ty,)+) => {$(
- unsafe impl IsZero for Option<$t> {
- #[inline]
- fn is_zero(&self) -> bool {
- const {
- let none: Self = unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
- assert!(none.is_none());
- }
- self.is_none()
- }
- }
- )+};
-}
-
-impl_is_zero_option_of_num!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize,);
-
-unsafe impl<T: IsZero> IsZero for Wrapping<T> {
- #[inline]
- fn is_zero(&self) -> bool {
- self.0.is_zero()
- }
-}
-
-unsafe impl<T: IsZero> IsZero for Saturating<T> {
- #[inline]
- fn is_zero(&self) -> bool {
- self.0.is_zero()
- }
-}
-
-macro_rules! impl_for_optional_bool {
- ($($t:ty,)+) => {$(
- unsafe impl IsZero for $t {
- #[inline]
- fn is_zero(&self) -> bool {
- // SAFETY: This is *not* a stable layout guarantee, but
- // inside `core` we're allowed to rely on the current rustc
- // behaviour that options of bools will be one byte with
- // no padding, so long as they're nested less than 254 deep.
- let raw: u8 = unsafe { core::mem::transmute(*self) };
- raw == 0
- }
- }
- )+};
-}
-impl_for_optional_bool! {
- Option<bool>,
- Option<Option<bool>>,
- Option<Option<Option<bool>>>,
- // Could go further, but not worth the metadata overhead
-}