mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	This customizes the subset of the Rust standard library `alloc` that
was just imported as-is, mainly by:
  - Adding SPDX license identifiers.
  - Skipping modules (e.g. `rc` and `sync`) via new `cfg`s.
  - Adding fallible (`try_*`) versions of existing infallible methods
    (i.e. returning a `Result` instead of panicking).
    Since the standard library requires stable/unstable attributes,
    these additions are annotated with:
        #[stable(feature = "kernel", since = "1.0.0")]
    Using "kernel" as the feature allows to have the additions
    clearly marked. The "1.0.0" version is just a placeholder.
    (At the moment, only one is needed, but in the future more
    fallible methods will be added).
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Matthew Bakhtiari <dev@mtbk.me>
Signed-off-by: Matthew Bakhtiari <dev@mtbk.me>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
		
	
			
		
			
				
	
	
		
			120 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
// SPDX-License-Identifier: Apache-2.0 OR MIT
 | 
						|
 | 
						|
use crate::boxed::Box;
 | 
						|
 | 
						|
#[rustc_specialization_trait]
 | 
						|
pub(super) unsafe trait IsZero {
 | 
						|
    /// Whether this value's representation is all zeros
 | 
						|
    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!(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!(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-05-01 LLVM
 | 
						|
        // can const-fold the check in `vec![[0; 32]; n]` but not in
 | 
						|
        // `vec![[0; 64]; n]`: https://godbolt.org/z/WTzjzfs5b
 | 
						|
        // Feel free to tweak if you have better evidence.
 | 
						|
 | 
						|
        N <= 32 && self.iter().all(IsZero::is_zero)
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// `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,
 | 
						|
);
 |