diff options
| author | mark <markm@cs.wisc.edu> | 2020-06-11 21:31:49 -0500 |
|---|---|---|
| committer | mark <markm@cs.wisc.edu> | 2020-07-27 19:51:13 -0500 |
| commit | 2c31b45ae878b821975c4ebd94cc1e49f6073fd0 (patch) | |
| tree | 14f64e683e3f64dcbcfb8c2c7cb45ac7592e6e09 /src/libcore/mem | |
| parent | 9be8ffcb0206fc1558069a7b4766090df7877659 (diff) | |
| download | rust-2c31b45ae878b821975c4ebd94cc1e49f6073fd0.tar.gz rust-2c31b45ae878b821975c4ebd94cc1e49f6073fd0.zip | |
mv std libs to library/
Diffstat (limited to 'src/libcore/mem')
| -rw-r--r-- | src/libcore/mem/manually_drop.rs | 179 | ||||
| -rw-r--r-- | src/libcore/mem/maybe_uninit.rs | 806 | ||||
| -rw-r--r-- | src/libcore/mem/mod.rs | 1044 |
3 files changed, 0 insertions, 2029 deletions
diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs deleted file mode 100644 index 920f5e9c0bd..00000000000 --- a/src/libcore/mem/manually_drop.rs +++ /dev/null @@ -1,179 +0,0 @@ -use crate::ops::{Deref, DerefMut}; -use crate::ptr; - -/// A wrapper to inhibit compiler from automatically calling `T`’s destructor. -/// This wrapper is 0-cost. -/// -/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`. -/// As a consequence, it has *no effect* on the assumptions that the compiler makes -/// about its contents. For example, initializing a `ManuallyDrop<&mut T>` -/// with [`mem::zeroed`] is undefined behavior. -/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead. -/// -/// Note that accessing the value inside a `ManuallyDrop<T>` is safe. -/// This means that a `ManuallyDrop<T>` whose content has been dropped must not -/// be exposed through a public safe API. -/// Correspondingly, `ManuallyDrop::drop` is unsafe. -/// -/// # Examples -/// -/// This wrapper can be used to enforce a particular drop order on fields, regardless -/// of how they are defined in the struct: -/// -/// ```rust -/// use std::mem::ManuallyDrop; -/// struct Peach; -/// struct Banana; -/// struct Melon; -/// struct FruitBox { -/// // Immediately clear there’s something non-trivial going on with these fields. -/// peach: ManuallyDrop<Peach>, -/// melon: Melon, // Field that’s independent of the other two. -/// banana: ManuallyDrop<Banana>, -/// } -/// -/// impl Drop for FruitBox { -/// fn drop(&mut self) { -/// unsafe { -/// // Explicit ordering in which field destructors are run specified in the intuitive -/// // location – the destructor of the structure containing the fields. -/// // Moreover, one can now reorder fields within the struct however much they want. -/// ManuallyDrop::drop(&mut self.peach); -/// ManuallyDrop::drop(&mut self.banana); -/// } -/// // After destructor for `FruitBox` runs (this function), the destructor for Melon gets -/// // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`. -/// } -/// } -/// ``` -/// -/// However, care should be taken when using this pattern as it can lead to *leak amplification*. -/// In this example, if the `Drop` implementation for `Peach` were to panic, the `banana` field -/// would also be leaked. -/// -/// In contrast, the automatically-generated compiler drop implementation would have ensured -/// that all fields are dropped even in the presence of panics. This is especially important when -/// working with [pinned] data, where reusing the memory without calling the destructor could lead -/// to Undefined Behaviour. -/// -/// [`mem::zeroed`]: fn.zeroed.html -/// [`MaybeUninit<T>`]: union.MaybeUninit.html -/// [pinned]: ../pin/index.html -#[stable(feature = "manually_drop", since = "1.20.0")] -#[lang = "manually_drop"] -#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(transparent)] -pub struct ManuallyDrop<T: ?Sized> { - value: T, -} - -impl<T> ManuallyDrop<T> { - /// Wrap a value to be manually dropped. - /// - /// # Examples - /// - /// ```rust - /// use std::mem::ManuallyDrop; - /// ManuallyDrop::new(Box::new(())); - /// ``` - #[stable(feature = "manually_drop", since = "1.20.0")] - #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")] - #[inline(always)] - pub const fn new(value: T) -> ManuallyDrop<T> { - ManuallyDrop { value } - } - - /// Extracts the value from the `ManuallyDrop` container. - /// - /// This allows the value to be dropped again. - /// - /// # Examples - /// - /// ```rust - /// use std::mem::ManuallyDrop; - /// let x = ManuallyDrop::new(Box::new(())); - /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`. - /// ``` - #[stable(feature = "manually_drop", since = "1.20.0")] - #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")] - #[inline(always)] - pub const fn into_inner(slot: ManuallyDrop<T>) -> T { - slot.value - } - - /// Takes the value from the `ManuallyDrop<T>` container out. - /// - /// This method is primarily intended for moving out values in drop. - /// Instead of using [`ManuallyDrop::drop`] to manually drop the value, - /// you can use this method to take the value and use it however desired. - /// - /// Whenever possible, it is preferable to use [`into_inner`][`ManuallyDrop::into_inner`] - /// instead, which prevents duplicating the content of the `ManuallyDrop<T>`. - /// - /// # Safety - /// - /// This function semantically moves out the contained value without preventing further usage, - /// leaving the state of this container unchanged. - /// It is your responsibility to ensure that this `ManuallyDrop` is not used again. - /// - /// [`ManuallyDrop::drop`]: #method.drop - /// [`ManuallyDrop::into_inner`]: #method.into_inner - #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] - #[stable(feature = "manually_drop_take", since = "1.42.0")] - #[inline] - pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T { - // SAFETY: we are reading from a reference, which is guaranteed - // to be valid for reads. - unsafe { ptr::read(&slot.value) } - } -} - -impl<T: ?Sized> ManuallyDrop<T> { - /// Manually drops the contained value. This is exactly equivalent to calling - /// [`ptr::drop_in_place`] with a pointer to the contained value. As such, unless - /// the contained value is a packed struct, the destructor will be called in-place - /// without moving the value, and thus can be used to safely drop [pinned] data. - /// - /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead. - /// - /// # Safety - /// - /// This function runs the destructor of the contained value. Other than changes made by - /// the destructor itself, the memory is left unchanged, and so as far as the compiler is - /// concerned still holds a bit-pattern which is valid for the type `T`. - /// - /// However, this "zombie" value should not be exposed to safe code, and this function - /// should not be called more than once. To use a value after it's been dropped, or drop - /// a value multiple times, can cause Undefined Behavior (depending on what `drop` does). - /// This is normally prevented by the type system, but users of `ManuallyDrop` must - /// uphold those guarantees without assistance from the compiler. - /// - /// [`ManuallyDrop::into_inner`]: #method.into_inner - /// [`ptr::drop_in_place`]: ../ptr/fn.drop_in_place.html - /// [pinned]: ../pin/index.html - #[stable(feature = "manually_drop", since = "1.20.0")] - #[inline] - pub unsafe fn drop(slot: &mut ManuallyDrop<T>) { - // SAFETY: we are dropping the value pointed to by a mutable reference - // which is guaranteed to be valid for writes. - // It is up to the caller to make sure that `slot` isn't dropped again. - unsafe { ptr::drop_in_place(&mut slot.value) } - } -} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl<T: ?Sized> Deref for ManuallyDrop<T> { - type Target = T; - #[inline(always)] - fn deref(&self) -> &T { - &self.value - } -} - -#[stable(feature = "manually_drop", since = "1.20.0")] -impl<T: ?Sized> DerefMut for ManuallyDrop<T> { - #[inline(always)] - fn deref_mut(&mut self) -> &mut T { - &mut self.value - } -} diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs deleted file mode 100644 index 7732525a0fc..00000000000 --- a/src/libcore/mem/maybe_uninit.rs +++ /dev/null @@ -1,806 +0,0 @@ -use crate::any::type_name; -use crate::fmt; -use crate::intrinsics; -use crate::mem::ManuallyDrop; - -// ignore-tidy-undocumented-unsafe - -/// A wrapper type to construct uninitialized instances of `T`. -/// -/// # Initialization invariant -/// -/// The compiler, in general, assumes that a variable is properly initialized -/// according to the requirements of the variable's type. For example, a variable of -/// reference type must be aligned and non-NULL. This is an invariant that must -/// *always* be upheld, even in unsafe code. As a consequence, zero-initializing a -/// variable of reference type causes instantaneous [undefined behavior][ub], -/// no matter whether that reference ever gets used to access memory: -/// -/// ```rust,no_run -/// # #![allow(invalid_value)] -/// use std::mem::{self, MaybeUninit}; -/// -/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! ⚠️ -/// // The equivalent code with `MaybeUninit<&i32>`: -/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! ⚠️ -/// ``` -/// -/// This is exploited by the compiler for various optimizations, such as eliding -/// run-time checks and optimizing `enum` layout. -/// -/// Similarly, entirely uninitialized memory may have any content, while a `bool` must -/// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior: -/// -/// ```rust,no_run -/// # #![allow(invalid_value)] -/// use std::mem::{self, MaybeUninit}; -/// -/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️ -/// // The equivalent code with `MaybeUninit<bool>`: -/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️ -/// ``` -/// -/// Moreover, uninitialized memory is special in that the compiler knows that -/// it does not have a fixed value. This makes it undefined behavior to have -/// uninitialized data in a variable even if that variable has an integer type, -/// which otherwise can hold any *fixed* bit pattern: -/// -/// ```rust,no_run -/// # #![allow(invalid_value)] -/// use std::mem::{self, MaybeUninit}; -/// -/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️ -/// // The equivalent code with `MaybeUninit<i32>`: -/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️ -/// ``` -/// (Notice that the rules around uninitialized integers are not finalized yet, but -/// until they are, it is advisable to avoid them.) -/// -/// On top of that, remember that most types have additional invariants beyond merely -/// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`] -/// is considered initialized (under the current implementation; this does not constitute -/// a stable guarantee) because the only requirement the compiler knows about it -/// is that the data pointer must be non-null. Creating such a `Vec<T>` does not cause -/// *immediate* undefined behavior, but will cause undefined behavior with most -/// safe operations (including dropping it). -/// -/// [`Vec<T>`]: ../../std/vec/struct.Vec.html -/// -/// # Examples -/// -/// `MaybeUninit<T>` serves to enable unsafe code to deal with uninitialized data. -/// It is a signal to the compiler indicating that the data here might *not* -/// be initialized: -/// -/// ```rust -/// use std::mem::MaybeUninit; -/// -/// // Create an explicitly uninitialized reference. The compiler knows that data inside -/// // a `MaybeUninit<T>` may be invalid, and hence this is not UB: -/// let mut x = MaybeUninit::<&i32>::uninit(); -/// // Set it to a valid value. -/// unsafe { x.as_mut_ptr().write(&0); } -/// // Extract the initialized data -- this is only allowed *after* properly -/// // initializing `x`! -/// let x = unsafe { x.assume_init() }; -/// ``` -/// -/// The compiler then knows to not make any incorrect assumptions or optimizations on this code. -/// -/// You can think of `MaybeUninit<T>` as being a bit like `Option<T>` but without -/// any of the run-time tracking and without any of the safety checks. -/// -/// ## out-pointers -/// -/// You can use `MaybeUninit<T>` to implement "out-pointers": instead of returning data -/// from a function, pass it a pointer to some (uninitialized) memory to put the -/// result into. This can be useful when it is important for the caller to control -/// how the memory the result is stored in gets allocated, and you want to avoid -/// unnecessary moves. -/// -/// ``` -/// use std::mem::MaybeUninit; -/// -/// unsafe fn make_vec(out: *mut Vec<i32>) { -/// // `write` does not drop the old contents, which is important. -/// out.write(vec![1, 2, 3]); -/// } -/// -/// let mut v = MaybeUninit::uninit(); -/// unsafe { make_vec(v.as_mut_ptr()); } -/// // Now we know `v` is initialized! This also makes sure the vector gets -/// // properly dropped. -/// let v = unsafe { v.assume_init() }; -/// assert_eq!(&v, &[1, 2, 3]); -/// ``` -/// -/// ## Initializing an array element-by-element -/// -/// `MaybeUninit<T>` can be used to initialize a large array element-by-element: -/// -/// ``` -/// use std::mem::{self, MaybeUninit}; -/// -/// let data = { -/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is -/// // safe because the type we are claiming to have initialized here is a -/// // bunch of `MaybeUninit`s, which do not require initialization. -/// let mut data: [MaybeUninit<Vec<u32>>; 1000] = unsafe { -/// MaybeUninit::uninit().assume_init() -/// }; -/// -/// // Dropping a `MaybeUninit` does nothing. Thus using raw pointer -/// // assignment instead of `ptr::write` does not cause the old -/// // uninitialized value to be dropped. Also if there is a panic during -/// // this loop, we have a memory leak, but there is no memory safety -/// // issue. -/// for elem in &mut data[..] { -/// *elem = MaybeUninit::new(vec![42]); -/// } -/// -/// // Everything is initialized. Transmute the array to the -/// // initialized type. -/// unsafe { mem::transmute::<_, [Vec<u32>; 1000]>(data) } -/// }; -/// -/// assert_eq!(&data[0], &[42]); -/// ``` -/// -/// You can also work with partially initialized arrays, which could -/// be found in low-level datastructures. -/// -/// ``` -/// use std::mem::MaybeUninit; -/// use std::ptr; -/// -/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is -/// // safe because the type we are claiming to have initialized here is a -/// // bunch of `MaybeUninit`s, which do not require initialization. -/// let mut data: [MaybeUninit<String>; 1000] = unsafe { MaybeUninit::uninit().assume_init() }; -/// // Count the number of elements we have assigned. -/// let mut data_len: usize = 0; -/// -/// for elem in &mut data[0..500] { -/// *elem = MaybeUninit::new(String::from("hello")); -/// data_len += 1; -/// } -/// -/// // For each item in the array, drop if we allocated it. -/// for elem in &mut data[0..data_len] { -/// unsafe { ptr::drop_in_place(elem.as_mut_ptr()); } -/// } -/// ``` -/// -/// ## Initializing a struct field-by-field -/// -/// There is currently no supported way to create a raw pointer or reference -/// to a field of a struct inside `MaybeUninit<Struct>`. That means it is not possible -/// to create a struct by calling `MaybeUninit::uninit::<Struct>()` and then writing -/// to its fields. -/// -/// [ub]: ../../reference/behavior-considered-undefined.html -/// -/// # Layout -/// -/// `MaybeUninit<T>` is guaranteed to have the same size, alignment, and ABI as `T`: -/// -/// ```rust -/// use std::mem::{MaybeUninit, size_of, align_of}; -/// assert_eq!(size_of::<MaybeUninit<u64>>(), size_of::<u64>()); -/// assert_eq!(align_of::<MaybeUninit<u64>>(), align_of::<u64>()); -/// ``` -/// -/// However remember that a type *containing* a `MaybeUninit<T>` is not necessarily the same -/// layout; Rust does not in general guarantee that the fields of a `Foo<T>` have the same order as -/// a `Foo<U>` even if `T` and `U` have the same size and alignment. Furthermore because any bit -/// value is valid for a `MaybeUninit<T>` the compiler can't apply non-zero/niche-filling -/// optimizations, potentially resulting in a larger size: -/// -/// ```rust -/// # use std::mem::{MaybeUninit, size_of}; -/// assert_eq!(size_of::<Option<bool>>(), 1); -/// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2); -/// ``` -/// -/// If `T` is FFI-safe, then so is `MaybeUninit<T>`. -/// -/// While `MaybeUninit` is `#[repr(transparent)]` (indicating it guarantees the same size, -/// alignment, and ABI as `T`), this does *not* change any of the previous caveats. `Option<T>` and -/// `Option<MaybeUninit<T>>` may still have different sizes, and types containing a field of type -/// `T` may be laid out (and sized) differently than if that field were `MaybeUninit<T>`. -/// `MaybeUninit` is a union type, and `#[repr(transparent)]` on unions is unstable (see [the -/// tracking issue](https://github.com/rust-lang/rust/issues/60405)). Over time, the exact -/// guarantees of `#[repr(transparent)]` on unions may evolve, and `MaybeUninit` may or may not -/// remain `#[repr(transparent)]`. That said, `MaybeUninit<T>` will *always* guarantee that it has -/// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that -/// guarantee may evolve. -#[stable(feature = "maybe_uninit", since = "1.36.0")] -// Lang item so we can wrap other types in it. This is useful for generators. -#[lang = "maybe_uninit"] -#[derive(Copy)] -#[repr(transparent)] -pub union MaybeUninit<T> { - uninit: (), - value: ManuallyDrop<T>, -} - -#[stable(feature = "maybe_uninit", since = "1.36.0")] -impl<T: Copy> Clone for MaybeUninit<T> { - #[inline(always)] - fn clone(&self) -> Self { - // Not calling `T::clone()`, we cannot know if we are initialized enough for that. - *self - } -} - -#[stable(feature = "maybe_uninit_debug", since = "1.41.0")] -impl<T> fmt::Debug for MaybeUninit<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad(type_name::<Self>()) - } -} - -impl<T> MaybeUninit<T> { - /// Creates a new `MaybeUninit<T>` initialized with the given value. - /// It is safe to call [`assume_init`] on the return value of this function. - /// - /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code. - /// It is your responsibility to make sure `T` gets dropped if it got initialized. - /// - /// [`assume_init`]: #method.assume_init - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] - #[inline(always)] - pub const fn new(val: T) -> MaybeUninit<T> { - MaybeUninit { value: ManuallyDrop::new(val) } - } - - /// Creates a new `MaybeUninit<T>` in an uninitialized state. - /// - /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code. - /// It is your responsibility to make sure `T` gets dropped if it got initialized. - /// - /// See the [type-level documentation][type] for some examples. - /// - /// [type]: union.MaybeUninit.html - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] - #[inline(always)] - #[rustc_diagnostic_item = "maybe_uninit_uninit"] - pub const fn uninit() -> MaybeUninit<T> { - MaybeUninit { uninit: () } - } - - /// Create a new array of `MaybeUninit<T>` items, in an uninitialized state. - /// - /// Note: in a future Rust version this method may become unnecessary - /// when array literal syntax allows - /// [repeating const expressions](https://github.com/rust-lang/rust/issues/49147). - /// The example below could then use `let mut buf = [MaybeUninit::<u8>::uninit(); 32];`. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(maybe_uninit_uninit_array, maybe_uninit_extra, maybe_uninit_slice_assume_init)] - /// - /// use std::mem::MaybeUninit; - /// - /// extern "C" { - /// fn read_into_buffer(ptr: *mut u8, max_len: usize) -> usize; - /// } - /// - /// /// Returns a (possibly smaller) slice of data that was actually read - /// fn read(buf: &mut [MaybeUninit<u8>]) -> &[u8] { - /// unsafe { - /// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len()); - /// MaybeUninit::slice_get_ref(&buf[..len]) - /// } - /// } - /// - /// let mut buf: [MaybeUninit<u8>; 32] = MaybeUninit::uninit_array(); - /// let data = read(&mut buf); - /// ``` - #[unstable(feature = "maybe_uninit_uninit_array", issue = "none")] - #[inline(always)] - pub fn uninit_array<const LEN: usize>() -> [Self; LEN] { - unsafe { MaybeUninit::<[MaybeUninit<T>; LEN]>::uninit().assume_init() } - } - - /// A promotable constant, equivalent to `uninit()`. - #[unstable( - feature = "internal_uninit_const", - issue = "none", - reason = "hack to work around promotability" - )] - pub const UNINIT: Self = Self::uninit(); - - /// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being - /// filled with `0` bytes. It depends on `T` whether that already makes for - /// proper initialization. For example, `MaybeUninit<usize>::zeroed()` is initialized, - /// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not - /// be null. - /// - /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code. - /// It is your responsibility to make sure `T` gets dropped if it got initialized. - /// - /// # Example - /// - /// Correct usage of this function: initializing a struct with zero, where all - /// fields of the struct can hold the bit-pattern 0 as a valid value. - /// - /// ```rust - /// use std::mem::MaybeUninit; - /// - /// let x = MaybeUninit::<(u8, bool)>::zeroed(); - /// let x = unsafe { x.assume_init() }; - /// assert_eq!(x, (0, false)); - /// ``` - /// - /// *Incorrect* usage of this function: initializing a struct with zero, where some fields - /// cannot hold 0 as a valid value. - /// - /// ```rust,no_run - /// use std::mem::MaybeUninit; - /// - /// enum NotZero { One = 1, Two = 2 }; - /// - /// let x = MaybeUninit::<(u8, NotZero)>::zeroed(); - /// let x = unsafe { x.assume_init() }; - /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. - /// // This is undefined behavior. ⚠️ - /// ``` - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[inline] - #[rustc_diagnostic_item = "maybe_uninit_zeroed"] - pub fn zeroed() -> MaybeUninit<T> { - let mut u = MaybeUninit::<T>::uninit(); - unsafe { - u.as_mut_ptr().write_bytes(0u8, 1); - } - u - } - - /// Sets the value of the `MaybeUninit<T>`. This overwrites any previous value - /// without dropping it, so be careful not to use this twice unless you want to - /// skip running the destructor. For your convenience, this also returns a mutable - /// reference to the (now safely initialized) contents of `self`. - #[unstable(feature = "maybe_uninit_extra", issue = "63567")] - #[inline(always)] - pub fn write(&mut self, val: T) -> &mut T { - unsafe { - self.value = ManuallyDrop::new(val); - self.get_mut() - } - } - - /// Gets a pointer to the contained value. Reading from this pointer or turning it - /// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized. - /// Writing to memory that this pointer (non-transitively) points to is undefined behavior - /// (except inside an `UnsafeCell<T>`). - /// - /// # Examples - /// - /// Correct usage of this method: - /// - /// ```rust - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::<Vec<u32>>::uninit(); - /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); } - /// // Create a reference into the `MaybeUninit<T>`. This is okay because we initialized it. - /// let x_vec = unsafe { &*x.as_ptr() }; - /// assert_eq!(x_vec.len(), 3); - /// ``` - /// - /// *Incorrect* usage of this method: - /// - /// ```rust,no_run - /// use std::mem::MaybeUninit; - /// - /// let x = MaybeUninit::<Vec<u32>>::uninit(); - /// let x_vec = unsafe { &*x.as_ptr() }; - /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ - /// ``` - /// - /// (Notice that the rules around references to uninitialized data are not finalized yet, but - /// until they are, it is advisable to avoid them.) - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[inline(always)] - pub fn as_ptr(&self) -> *const T { - unsafe { &*self.value as *const T } - } - - /// Gets a mutable pointer to the contained value. Reading from this pointer or turning it - /// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized. - /// - /// # Examples - /// - /// Correct usage of this method: - /// - /// ```rust - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::<Vec<u32>>::uninit(); - /// unsafe { x.as_mut_ptr().write(vec![0,1,2]); } - /// // Create a reference into the `MaybeUninit<Vec<u32>>`. - /// // This is okay because we initialized it. - /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; - /// x_vec.push(3); - /// assert_eq!(x_vec.len(), 4); - /// ``` - /// - /// *Incorrect* usage of this method: - /// - /// ```rust,no_run - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::<Vec<u32>>::uninit(); - /// let x_vec = unsafe { &mut *x.as_mut_ptr() }; - /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ - /// ``` - /// - /// (Notice that the rules around references to uninitialized data are not finalized yet, but - /// until they are, it is advisable to avoid them.) - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[inline(always)] - pub fn as_mut_ptr(&mut self) -> *mut T { - unsafe { &mut *self.value as *mut T } - } - - /// Extracts the value from the `MaybeUninit<T>` container. This is a great way - /// to ensure that the data will get dropped, because the resulting `T` is - /// subject to the usual drop handling. - /// - /// # Safety - /// - /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized - /// state. Calling this when the content is not yet fully initialized causes immediate undefined - /// behavior. The [type-level documentation][inv] contains more information about - /// this initialization invariant. - /// - /// [inv]: #initialization-invariant - /// - /// On top of that, remember that most types have additional invariants beyond merely - /// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`] - /// is considered initialized (under the current implementation; this does not constitute - /// a stable guarantee) because the only requirement the compiler knows about it - /// is that the data pointer must be non-null. Creating such a `Vec<T>` does not cause - /// *immediate* undefined behavior, but will cause undefined behavior with most - /// safe operations (including dropping it). - /// - /// # Examples - /// - /// Correct usage of this method: - /// - /// ```rust - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::<bool>::uninit(); - /// unsafe { x.as_mut_ptr().write(true); } - /// let x_init = unsafe { x.assume_init() }; - /// assert_eq!(x_init, true); - /// ``` - /// - /// *Incorrect* usage of this method: - /// - /// ```rust,no_run - /// use std::mem::MaybeUninit; - /// - /// let x = MaybeUninit::<Vec<u32>>::uninit(); - /// let x_init = unsafe { x.assume_init() }; - /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️ - /// ``` - #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[inline(always)] - #[rustc_diagnostic_item = "assume_init"] - pub unsafe fn assume_init(self) -> T { - // SAFETY: the caller must guarantee that `self` is initialized. - // This also means that `self` must be a `value` variant. - unsafe { - intrinsics::assert_inhabited::<T>(); - ManuallyDrop::into_inner(self.value) - } - } - - /// Reads the value from the `MaybeUninit<T>` container. The resulting `T` is subject - /// to the usual drop handling. - /// - /// Whenever possible, it is preferable to use [`assume_init`] instead, which - /// prevents duplicating the content of the `MaybeUninit<T>`. - /// - /// # Safety - /// - /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized - /// state. Calling this when the content is not yet fully initialized causes undefined - /// behavior. The [type-level documentation][inv] contains more information about - /// this initialization invariant. - /// - /// Moreover, this leaves a copy of the same data behind in the `MaybeUninit<T>`. When using - /// multiple copies of the data (by calling `read` multiple times, or first - /// calling `read` and then [`assume_init`]), it is your responsibility - /// to ensure that that data may indeed be duplicated. - /// - /// [inv]: #initialization-invariant - /// [`assume_init`]: #method.assume_init - /// - /// # Examples - /// - /// Correct usage of this method: - /// - /// ```rust - /// #![feature(maybe_uninit_extra)] - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::<u32>::uninit(); - /// x.write(13); - /// let x1 = unsafe { x.read() }; - /// // `u32` is `Copy`, so we may read multiple times. - /// let x2 = unsafe { x.read() }; - /// assert_eq!(x1, x2); - /// - /// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit(); - /// x.write(None); - /// let x1 = unsafe { x.read() }; - /// // Duplicating a `None` value is okay, so we may read multiple times. - /// let x2 = unsafe { x.read() }; - /// assert_eq!(x1, x2); - /// ``` - /// - /// *Incorrect* usage of this method: - /// - /// ```rust,no_run - /// #![feature(maybe_uninit_extra)] - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit(); - /// x.write(Some(vec![0,1,2])); - /// let x1 = unsafe { x.read() }; - /// let x2 = unsafe { x.read() }; - /// // We now created two copies of the same vector, leading to a double-free ⚠️ when - /// // they both get dropped! - /// ``` - #[unstable(feature = "maybe_uninit_extra", issue = "63567")] - #[inline(always)] - pub unsafe fn read(&self) -> T { - // SAFETY: the caller must guarantee that `self` is initialized. - // Reading from `self.as_ptr()` is safe since `self` should be initialized. - unsafe { - intrinsics::assert_inhabited::<T>(); - self.as_ptr().read() - } - } - - /// Gets a shared reference to the contained value. - /// - /// This can be useful when we want to access a `MaybeUninit` that has been - /// initialized but don't have ownership of the `MaybeUninit` (preventing the use - /// of `.assume_init()`). - /// - /// # Safety - /// - /// Calling this when the content is not yet fully initialized causes undefined - /// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really - /// is in an initialized state. - /// - /// # Examples - /// - /// ### Correct usage of this method: - /// - /// ```rust - /// #![feature(maybe_uninit_ref)] - /// use std::mem::MaybeUninit; - /// - /// let mut x = MaybeUninit::<Vec<u32>>::uninit(); - /// // Initialize `x`: - /// unsafe { x.as_mut_ptr().write(vec![1, 2, 3]); } - /// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to - /// // create a shared reference to it: - /// let x: &Vec<u32> = unsafe { - /// // Safety: `x` has been initialized. - /// x.get_ref() - /// }; - /// assert_eq!(x, &vec![1, 2, 3]); - /// ``` - /// - /// ### *Incorrect* usages of this method: - /// - /// ```rust,no_run - /// #![feature(maybe_uninit_ref)] - /// use std::mem::MaybeUninit; - /// - /// let x = MaybeUninit::<Vec<u32>>::uninit(); - /// let x_vec: &Vec<u32> = unsafe { x.get_ref() }; - /// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️ - /// ``` - /// - /// ```rust,no_run - /// #![feature(maybe_uninit_ref)] - /// use std::{cell::Cell, mem::MaybeUninit}; - /// - /// let b = MaybeUninit::<Cell<bool>>::uninit(); - /// // Initialize the `MaybeUninit` using `Cell::set`: - /// unsafe { - /// b.get_ref().set(true); - /// // ^^^^^^^^^^^ - /// // Reference to an uninitialized `Cell<bool>`: UB! - /// } - /// ``` - #[unstable(feature = "maybe_uninit_ref", issue = "63568")] - #[inline(always)] - pub unsafe fn get_ref(&self) -> &T { - // SAFETY: the caller must guarantee that `self` is initialized. - // This also means that `self` must be a `value` variant. - unsafe { - intrinsics::assert_inhabited::<T>(); - &*self.value - } - } - - /// Gets a mutable (unique) reference to the contained value. - /// - /// This can be useful when we want to access a `MaybeUninit` that has been - /// initialized but don't have ownership of the `MaybeUninit` (preventing the use - /// of `.assume_init()`). - /// - /// # Safety - /// - /// Calling this when the content is not yet fully initialized causes undefined - /// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really - /// is in an initialized state. For instance, `.get_mut()` cannot be used to - /// initialize a `MaybeUninit`. - /// - /// # Examples - /// - /// ### Correct usage of this method: - /// - /// ```rust - /// #![feature(maybe_uninit_ref)] - /// use std::mem::MaybeUninit; - /// - /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 2048]) { *buf = [0; 2048] } - /// # #[cfg(FALSE)] - /// extern "C" { - /// /// Initializes *all* the bytes of the input buffer. - /// fn initialize_buffer(buf: *mut [u8; 2048]); - /// } - /// - /// let mut buf = MaybeUninit::<[u8; 2048]>::uninit(); - /// - /// // Initialize `buf`: - /// unsafe { initialize_buffer(buf.as_mut_ptr()); } - /// // Now we know that `buf` has been initialized, so we could `.assume_init()` it. - /// // However, using `.assume_init()` may trigger a `memcpy` of the 2048 bytes. - /// // To assert our buffer has been initialized without copying it, we upgrade - /// // the `&mut MaybeUninit<[u8; 2048]>` to a `&mut [u8; 2048]`: - /// let buf: &mut [u8; 2048] = unsafe { - /// // Safety: `buf` has been initialized. - /// buf.get_mut() - /// }; - /// - /// // Now we can use `buf` as a normal slice: - /// buf.sort_unstable(); - /// assert!( - /// buf.windows(2).all(|pair| pair[0] <= pair[1]), - /// "buffer is sorted", - /// ); - /// ``` - /// - /// ### *Incorrect* usages of this method: - /// - /// You cannot use `.get_mut()` to initialize a value: - /// - /// ```rust,no_run - /// #![feature(maybe_uninit_ref)] - /// use std::mem::MaybeUninit; - /// - /// let mut b = MaybeUninit::<bool>::uninit(); - /// unsafe { - /// *b.get_mut() = true; - /// // We have created a (mutable) reference to an uninitialized `bool`! - /// // This is undefined behavior. ⚠️ - /// } - /// ``` - /// - /// For instance, you cannot [`Read`] into an uninitialized buffer: - /// - /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html - /// - /// ```rust,no_run - /// #![feature(maybe_uninit_ref)] - /// use std::{io, mem::MaybeUninit}; - /// - /// fn read_chunk (reader: &'_ mut dyn io::Read) -> io::Result<[u8; 64]> - /// { - /// let mut buffer = MaybeUninit::<[u8; 64]>::uninit(); - /// reader.read_exact(unsafe { buffer.get_mut() })?; - /// // ^^^^^^^^^^^^^^^^ - /// // (mutable) reference to uninitialized memory! - /// // This is undefined behavior. - /// Ok(unsafe { buffer.assume_init() }) - /// } - /// ``` - /// - /// Nor can you use direct field access to do field-by-field gradual initialization: - /// - /// ```rust,no_run - /// #![feature(maybe_uninit_ref)] - /// use std::{mem::MaybeUninit, ptr}; - /// - /// struct Foo { - /// a: u32, - /// b: u8, - /// } - /// - /// let foo: Foo = unsafe { - /// let mut foo = MaybeUninit::<Foo>::uninit(); - /// ptr::write(&mut foo.get_mut().a as *mut u32, 1337); - /// // ^^^^^^^^^^^^^ - /// // (mutable) reference to uninitialized memory! - /// // This is undefined behavior. - /// ptr::write(&mut foo.get_mut().b as *mut u8, 42); - /// // ^^^^^^^^^^^^^ - /// // (mutable) reference to uninitialized memory! - /// // This is undefined behavior. - /// foo.assume_init() - /// }; - /// ``` - // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references - // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make - // a final decision about the rules before stabilization. - #[unstable(feature = "maybe_uninit_ref", issue = "63568")] - #[inline(always)] - pub unsafe fn get_mut(&mut self) -> &mut T { - // SAFETY: the caller must guarantee that `self` is initialized. - // This also means that `self` must be a `value` variant. - unsafe { - intrinsics::assert_inhabited::<T>(); - &mut *self.value - } - } - - /// Assuming all the elements are initialized, get a slice to them. - /// - /// # Safety - /// - /// It is up to the caller to guarantee that the `MaybeUninit<T>` elements - /// really are in an initialized state. - /// Calling this when the content is not yet fully initialized causes undefined behavior. - #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "none")] - #[inline(always)] - pub unsafe fn slice_get_ref(slice: &[Self]) -> &[T] { - // SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees that - // `slice` is initialized, and`MaybeUninit` is guaranteed to have the same layout as `T`. - // The pointer obtained is valid since it refers to memory owned by `slice` which is a - // reference and thus guaranteed to be valid for reads. - unsafe { &*(slice as *const [Self] as *const [T]) } - } - - /// Assuming all the elements are initialized, get a mutable slice to them. - /// - /// # Safety - /// - /// It is up to the caller to guarantee that the `MaybeUninit<T>` elements - /// really are in an initialized state. - /// Calling this when the content is not yet fully initialized causes undefined behavior. - #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "none")] - #[inline(always)] - pub unsafe fn slice_get_mut(slice: &mut [Self]) -> &mut [T] { - // SAFETY: similar to safety notes for `slice_get_ref`, but we have a - // mutable reference which is also guaranteed to be valid for writes. - unsafe { &mut *(slice as *mut [Self] as *mut [T]) } - } - - /// Gets a pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "63569")] - #[inline(always)] - pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T { - this as *const [MaybeUninit<T>] as *const T - } - - /// Gets a mutable pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "63569")] - #[inline(always)] - pub fn first_ptr_mut(this: &mut [MaybeUninit<T>]) -> *mut T { - this as *mut [MaybeUninit<T>] as *mut T - } -} diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs deleted file mode 100644 index 6ff7baab70f..00000000000 --- a/src/libcore/mem/mod.rs +++ /dev/null @@ -1,1044 +0,0 @@ -//! Basic functions for dealing with memory. -//! -//! This module contains functions for querying the size and alignment of -//! types, initializing and manipulating memory. - -#![stable(feature = "rust1", since = "1.0.0")] - -use crate::clone; -use crate::cmp; -use crate::fmt; -use crate::hash; -use crate::intrinsics; -use crate::marker::{Copy, DiscriminantKind, Sized}; -use crate::ptr; - -mod manually_drop; -#[stable(feature = "manually_drop", since = "1.20.0")] -pub use manually_drop::ManuallyDrop; - -mod maybe_uninit; -#[stable(feature = "maybe_uninit", since = "1.36.0")] -pub use maybe_uninit::MaybeUninit; - -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(inline)] -pub use crate::intrinsics::transmute; - -/// Takes ownership and "forgets" about the value **without running its destructor**. -/// -/// Any resources the value manages, such as heap memory or a file handle, will linger -/// forever in an unreachable state. However, it does not guarantee that pointers -/// to this memory will remain valid. -/// -/// * If you want to leak memory, see [`Box::leak`][leak]. -/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`][into_raw]. -/// * If you want to dispose of a value properly, running its destructor, see -/// [`mem::drop`][drop]. -/// -/// # Safety -/// -/// `forget` is not marked as `unsafe`, because Rust's safety guarantees -/// do not include a guarantee that destructors will always run. For example, -/// a program can create a reference cycle using [`Rc`][rc], or call -/// [`process::exit`][exit] to exit without running destructors. Thus, allowing -/// `mem::forget` from safe code does not fundamentally change Rust's safety -/// guarantees. -/// -/// That said, leaking resources such as memory or I/O objects is usually undesirable. -/// The need comes up in some specialized use cases for FFI or unsafe code, but even -/// then, [`ManuallyDrop`] is typically preferred. -/// -/// Because forgetting a value is allowed, any `unsafe` code you write must -/// allow for this possibility. You cannot return a value and expect that the -/// caller will necessarily run the value's destructor. -/// -/// [rc]: ../../std/rc/struct.Rc.html -/// [exit]: ../../std/process/fn.exit.html -/// -/// # Examples -/// -/// The canonical safe use of `mem::forget` is to circumvent a value's destructor -/// implemented by the `Drop` trait. For example, this will leak a `File`, i.e. reclaim -/// the space taken by the variable but never close the underlying system resource: -/// -/// ```no_run -/// use std::mem; -/// use std::fs::File; -/// -/// let file = File::open("foo.txt").unwrap(); -/// mem::forget(file); -/// ``` -/// -/// This is useful when the ownership of the underlying resource was previously -/// transferred to code outside of Rust, for example by transmitting the raw -/// file descriptor to C code. -/// -/// # Relationship with `ManuallyDrop` -/// -/// While `mem::forget` can also be used to transfer *memory* ownership, doing so is error-prone. -/// [`ManuallyDrop`] should be used instead. Consider, for example, this code: -/// -/// ``` -/// use std::mem; -/// -/// let mut v = vec![65, 122]; -/// // Build a `String` using the contents of `v` -/// let s = unsafe { String::from_raw_parts(v.as_mut_ptr(), v.len(), v.capacity()) }; -/// // leak `v` because its memory is now managed by `s` -/// mem::forget(v); // ERROR - v is invalid and must not be passed to a function -/// assert_eq!(s, "Az"); -/// // `s` is implicitly dropped and its memory deallocated. -/// ``` -/// -/// There are two issues with the above example: -/// -/// * If more code were added between the construction of `String` and the invocation of -/// `mem::forget()`, a panic within it would cause a double free because the same memory -/// is handled by both `v` and `s`. -/// * After calling `v.as_mut_ptr()` and transmitting the ownership of the data to `s`, -/// the `v` value is invalid. Even when a value is just moved to `mem::forget` (which won't -/// inspect it), some types have strict requirements on their values that -/// make them invalid when dangling or no longer owned. Using invalid values in any -/// way, including passing them to or returning them from functions, constitutes -/// undefined behavior and may break the assumptions made by the compiler. -/// -/// Switching to `ManuallyDrop` avoids both issues: -/// -/// ``` -/// use std::mem::ManuallyDrop; -/// -/// let v = vec![65, 122]; -/// // Before we disassemble `v` into its raw parts, make sure it -/// // does not get dropped! -/// let mut v = ManuallyDrop::new(v); -/// // Now disassemble `v`. These operations cannot panic, so there cannot be a leak. -/// let (ptr, len, cap) = (v.as_mut_ptr(), v.len(), v.capacity()); -/// // Finally, build a `String`. -/// let s = unsafe { String::from_raw_parts(ptr, len, cap) }; -/// assert_eq!(s, "Az"); -/// // `s` is implicitly dropped and its memory deallocated. -/// ``` -/// -/// `ManuallyDrop` robustly prevents double-free because we disable `v`'s destructor -/// before doing anything else. `mem::forget()` doesn't allow this because it consumes its -/// argument, forcing us to call it only after extracting anything we need from `v`. Even -/// if a panic were introduced between construction of `ManuallyDrop` and building the -/// string (which cannot happen in the code as shown), it would result in a leak and not a -/// double free. In other words, `ManuallyDrop` errs on the side of leaking instead of -/// erring on the side of (double-)dropping. -/// -/// Also, `ManuallyDrop` prevents us from having to "touch" `v` after transferring the -/// ownership to `s` — the final step of interacting with `v` to dispose of it without -/// running its destructor is entirely avoided. -/// -/// [drop]: fn.drop.html -/// [uninit]: fn.uninitialized.html -/// [clone]: ../clone/trait.Clone.html -/// [swap]: fn.swap.html -/// [box]: ../../std/boxed/struct.Box.html -/// [leak]: ../../std/boxed/struct.Box.html#method.leak -/// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw -/// [ub]: ../../reference/behavior-considered-undefined.html -/// [`ManuallyDrop`]: struct.ManuallyDrop.html -#[inline] -#[rustc_const_stable(feature = "const_forget", since = "1.46.0")] -#[stable(feature = "rust1", since = "1.0.0")] -pub const fn forget<T>(t: T) { - ManuallyDrop::new(t); -} - -/// Like [`forget`], but also accepts unsized values. -/// -/// This function is just a shim intended to be removed when the `unsized_locals` feature gets -/// stabilized. -/// -/// [`forget`]: fn.forget.html -#[inline] -#[unstable(feature = "forget_unsized", issue = "none")] -pub fn forget_unsized<T: ?Sized>(t: T) { - // SAFETY: the forget intrinsic could be safe, but there's no point in making it safe since - // we'll be implementing this function soon via `ManuallyDrop` - unsafe { intrinsics::forget(t) } -} - -/// Returns the size of a type in bytes. -/// -/// More specifically, this is the offset in bytes between successive elements -/// in an array with that item type including alignment padding. Thus, for any -/// type `T` and length `n`, `[T; n]` has a size of `n * size_of::<T>()`. -/// -/// In general, the size of a type is not stable across compilations, but -/// specific types such as primitives are. -/// -/// The following table gives the size for primitives. -/// -/// Type | size_of::\<Type>() -/// ---- | --------------- -/// () | 0 -/// bool | 1 -/// u8 | 1 -/// u16 | 2 -/// u32 | 4 -/// u64 | 8 -/// u128 | 16 -/// i8 | 1 -/// i16 | 2 -/// i32 | 4 -/// i64 | 8 -/// i128 | 16 -/// f32 | 4 -/// f64 | 8 -/// char | 4 -/// -/// Furthermore, `usize` and `isize` have the same size. -/// -/// The types `*const T`, `&T`, `Box<T>`, `Option<&T>`, and `Option<Box<T>>` all have -/// the same size. If `T` is Sized, all of those types have the same size as `usize`. -/// -/// The mutability of a pointer does not change its size. As such, `&T` and `&mut T` -/// have the same size. Likewise for `*const T` and `*mut T`. -/// -/// # Size of `#[repr(C)]` items -/// -/// The `C` representation for items has a defined layout. With this layout, -/// the size of items is also stable as long as all fields have a stable size. -/// -/// ## Size of Structs -/// -/// For `structs`, the size is determined by the following algorithm. -/// -/// For each field in the struct ordered by declaration order: -/// -/// 1. Add the size of the field. -/// 2. Round up the current size to the nearest multiple of the next field's [alignment]. -/// -/// Finally, round the size of the struct to the nearest multiple of its [alignment]. -/// The alignment of the struct is usually the largest alignment of all its -/// fields; this can be changed with the use of `repr(align(N))`. -/// -/// Unlike `C`, zero sized structs are not rounded up to one byte in size. -/// -/// ## Size of Enums -/// -/// Enums that carry no data other than the discriminant have the same size as C enums -/// on the platform they are compiled for. -/// -/// ## Size of Unions -/// -/// The size of a union is the size of its largest field. -/// -/// Unlike `C`, zero sized unions are not rounded up to one byte in size. -/// -/// # Examples -/// -/// ``` -/// use std::mem; -/// -/// // Some primitives -/// assert_eq!(4, mem::size_of::<i32>()); -/// assert_eq!(8, mem::size_of::<f64>()); -/// assert_eq!(0, mem::size_of::<()>()); -/// -/// // Some arrays -/// assert_eq!(8, mem::size_of::<[i32; 2]>()); -/// assert_eq!(12, mem::size_of::<[i32; 3]>()); -/// assert_eq!(0, mem::size_of::<[i32; 0]>()); -/// -/// -/// // Pointer size equality -/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<*const i32>()); -/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Box<i32>>()); -/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Option<&i32>>()); -/// assert_eq!(mem::size_of::<Box<i32>>(), mem::size_of::<Option<Box<i32>>>()); -/// ``` -/// -/// Using `#[repr(C)]`. -/// -/// ``` -/// use std::mem; -/// -/// #[repr(C)] -/// struct FieldStruct { -/// first: u8, -/// second: u16, -/// third: u8 -/// } -/// -/// // The size of the first field is 1, so add 1 to the size. Size is 1. -/// // The alignment of the second field is 2, so add 1 to the size for padding. Size is 2. -/// // The size of the second field is 2, so add 2 to the size. Size is 4. -/// // The alignment of the third field is 1, so add 0 to the size for padding. Size is 4. -/// // The size of the third field is 1, so add 1 to the size. Size is 5. -/// // Finally, the alignment of the struct is 2 (because the largest alignment amongst its -/// // fields is 2), so add 1 to the size for padding. Size is 6. -/// assert_eq!(6, mem::size_of::<FieldStruct>()); -/// -/// #[repr(C)] -/// struct TupleStruct(u8, u16, u8); -/// -/// // Tuple structs follow the same rules. -/// assert_eq!(6, mem::size_of::<TupleStruct>()); -/// -/// // Note that reordering the fields can lower the size. We can remove both padding bytes -/// // by putting `third` before `second`. -/// #[repr(C)] -/// struct FieldStructOptimized { -/// first: u8, -/// third: u8, -/// second: u16 -/// } -/// -/// assert_eq!(4, mem::size_of::<FieldStructOptimized>()); -/// -/// // Union size is the size of the largest field. -/// #[repr(C)] -/// union ExampleUnion { -/// smaller: u8, -/// larger: u16 -/// } -/// -/// assert_eq!(2, mem::size_of::<ExampleUnion>()); -/// ``` -/// -/// [alignment]: ./fn.align_of.html -#[inline(always)] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_promotable] -#[rustc_const_stable(feature = "const_size_of", since = "1.32.0")] -pub const fn size_of<T>() -> usize { - intrinsics::size_of::<T>() -} - -/// Returns the size of the pointed-to value in bytes. -/// -/// This is usually the same as `size_of::<T>()`. However, when `T` *has* no -/// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object], -/// then `size_of_val` can be used to get the dynamically-known size. -/// -/// [slice]: ../../std/primitive.slice.html -/// [trait object]: ../../book/ch17-02-trait-objects.html -/// -/// # Examples -/// -/// ``` -/// use std::mem; -/// -/// assert_eq!(4, mem::size_of_val(&5i32)); -/// -/// let x: [u8; 13] = [0; 13]; -/// let y: &[u8] = &x; -/// assert_eq!(13, mem::size_of_val(y)); -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn size_of_val<T: ?Sized>(val: &T) -> usize { - intrinsics::size_of_val(val) -} - -/// Returns the size of the pointed-to value in bytes. -/// -/// This is usually the same as `size_of::<T>()`. However, when `T` *has* no -/// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object], -/// then `size_of_val_raw` can be used to get the dynamically-known size. -/// -/// # Safety -/// -/// This function is only safe to call if the following conditions hold: -/// -/// - If `T` is `Sized`, this function is always safe to call. -/// - If the unsized tail of `T` is: -/// - a [slice], then the length of the slice tail must be an initialized -/// integer, and the size of the *entire value* -/// (dynamic tail length + statically sized prefix) must fit in `isize`. -/// - a [trait object], then the vtable part of the pointer must point -/// to a valid vtable acquired by an unsizing coercion, and the size -/// of the *entire value* (dynamic tail length + statically sized prefix) -/// must fit in `isize`. -/// - an (unstable) [extern type], then this function is always safe to -/// call, but may panic or otherwise return the wrong value, as the -/// extern type's layout is not known. This is the same behavior as -/// [`size_of_val`] on a reference to a type with an extern type tail. -/// - otherwise, it is conservatively not allowed to call this function. -/// -/// [slice]: ../../std/primitive.slice.html -/// [trait object]: ../../book/ch17-02-trait-objects.html -/// [extern type]: ../../unstable-book/language-features/extern-types.html -/// [`size_of_val`]: ../../core/mem/fn.size_of_val.html -/// -/// # Examples -/// -/// ``` -/// #![feature(layout_for_ptr)] -/// use std::mem; -/// -/// assert_eq!(4, mem::size_of_val(&5i32)); -/// -/// let x: [u8; 13] = [0; 13]; -/// let y: &[u8] = &x; -/// assert_eq!(13, unsafe { mem::size_of_val_raw(y) }); -/// ``` -#[inline] -#[unstable(feature = "layout_for_ptr", issue = "69835")] -pub unsafe fn size_of_val_raw<T: ?Sized>(val: *const T) -> usize { - intrinsics::size_of_val(val) -} - -/// Returns the [ABI]-required minimum alignment of a type. -/// -/// Every reference to a value of the type `T` must be a multiple of this number. -/// -/// This is the alignment used for struct fields. It may be smaller than the preferred alignment. -/// -/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface -/// -/// # Examples -/// -/// ``` -/// # #![allow(deprecated)] -/// use std::mem; -/// -/// assert_eq!(4, mem::min_align_of::<i32>()); -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_deprecated(reason = "use `align_of` instead", since = "1.2.0")] -pub fn min_align_of<T>() -> usize { - intrinsics::min_align_of::<T>() -} - -/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to. -/// -/// Every reference to a value of the type `T` must be a multiple of this number. -/// -/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface -/// -/// # Examples -/// -/// ``` -/// # #![allow(deprecated)] -/// use std::mem; -/// -/// assert_eq!(4, mem::min_align_of_val(&5i32)); -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_deprecated(reason = "use `align_of_val` instead", since = "1.2.0")] -pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize { - intrinsics::min_align_of_val(val) -} - -/// Returns the [ABI]-required minimum alignment of a type. -/// -/// Every reference to a value of the type `T` must be a multiple of this number. -/// -/// This is the alignment used for struct fields. It may be smaller than the preferred alignment. -/// -/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface -/// -/// # Examples -/// -/// ``` -/// use std::mem; -/// -/// assert_eq!(4, mem::align_of::<i32>()); -/// ``` -#[inline(always)] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_promotable] -#[rustc_const_stable(feature = "const_align_of", since = "1.32.0")] -pub const fn align_of<T>() -> usize { - intrinsics::min_align_of::<T>() -} - -/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to. -/// -/// Every reference to a value of the type `T` must be a multiple of this number. -/// -/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface -/// -/// # Examples -/// -/// ``` -/// use std::mem; -/// -/// assert_eq!(4, mem::align_of_val(&5i32)); -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -pub fn align_of_val<T: ?Sized>(val: &T) -> usize { - min_align_of_val(val) -} - -/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to. -/// -/// Every reference to a value of the type `T` must be a multiple of this number. -/// -/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface -/// -/// # Safety -/// -/// This function is only safe to call if the following conditions hold: -/// -/// - If `T` is `Sized`, this function is always safe to call. -/// - If the unsized tail of `T` is: -/// - a [slice], then the length of the slice tail must be an initialized -/// integer, and the size of the *entire value* -/// (dynamic tail length + statically sized prefix) must fit in `isize`. -/// - a [trait object], then the vtable part of the pointer must point -/// to a valid vtable acquired by an unsizing coercion, and the size -/// of the *entire value* (dynamic tail length + statically sized prefix) -/// must fit in `isize`. -/// - an (unstable) [extern type], then this function is always safe to -/// call, but may panic or otherwise return the wrong value, as the -/// extern type's layout is not known. This is the same behavior as -/// [`align_of_val`] on a reference to a type with an extern type tail. -/// - otherwise, it is conservatively not allowed to call this function. -/// -/// [slice]: ../../std/primitive.slice.html -/// [trait object]: ../../book/ch17-02-trait-objects.html -/// [extern type]: ../../unstable-book/language-features/extern-types.html -/// [`align_of_val`]: ../../core/mem/fn.align_of_val.html -/// -/// # Examples -/// -/// ``` -/// #![feature(layout_for_ptr)] -/// use std::mem; -/// -/// assert_eq!(4, unsafe { mem::align_of_val_raw(&5i32) }); -/// ``` -#[inline] -#[unstable(feature = "layout_for_ptr", issue = "69835")] -pub unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize { - intrinsics::min_align_of_val(val) -} - -/// Returns `true` if dropping values of type `T` matters. -/// -/// This is purely an optimization hint, and may be implemented conservatively: -/// it may return `true` for types that don't actually need to be dropped. -/// As such always returning `true` would be a valid implementation of -/// this function. However if this function actually returns `false`, then you -/// can be certain dropping `T` has no side effect. -/// -/// Low level implementations of things like collections, which need to manually -/// drop their data, should use this function to avoid unnecessarily -/// trying to drop all their contents when they are destroyed. This might not -/// make a difference in release builds (where a loop that has no side-effects -/// is easily detected and eliminated), but is often a big win for debug builds. -/// -/// Note that [`drop_in_place`] already performs this check, so if your workload -/// can be reduced to some small number of [`drop_in_place`] calls, using this is -/// unnecessary. In particular note that you can [`drop_in_place`] a slice, and that -/// will do a single needs_drop check for all the values. -/// -/// Types like Vec therefore just `drop_in_place(&mut self[..])` without using -/// `needs_drop` explicitly. Types like [`HashMap`], on the other hand, have to drop -/// values one at a time and should use this API. -/// -/// [`drop_in_place`]: ../ptr/fn.drop_in_place.html -/// [`HashMap`]: ../../std/collections/struct.HashMap.html -/// -/// # Examples -/// -/// Here's an example of how a collection might make use of `needs_drop`: -/// -/// ``` -/// use std::{mem, ptr}; -/// -/// pub struct MyCollection<T> { -/// # data: [T; 1], -/// /* ... */ -/// } -/// # impl<T> MyCollection<T> { -/// # fn iter_mut(&mut self) -> &mut [T] { &mut self.data } -/// # fn free_buffer(&mut self) {} -/// # } -/// -/// impl<T> Drop for MyCollection<T> { -/// fn drop(&mut self) { -/// unsafe { -/// // drop the data -/// if mem::needs_drop::<T>() { -/// for x in self.iter_mut() { -/// ptr::drop_in_place(x); -/// } -/// } -/// self.free_buffer(); -/// } -/// } -/// } -/// ``` -#[inline] -#[stable(feature = "needs_drop", since = "1.21.0")] -#[rustc_const_stable(feature = "const_needs_drop", since = "1.36.0")] -pub const fn needs_drop<T>() -> bool { - intrinsics::needs_drop::<T>() -} - -/// Returns the value of type `T` represented by the all-zero byte-pattern. -/// -/// This means that, for example, the padding byte in `(u8, u16)` is not -/// necessarily zeroed. -/// -/// There is no guarantee that an all-zero byte-pattern represents a valid value -/// of some type `T`. For example, the all-zero byte-pattern is not a valid value -/// for reference types (`&T`, `&mut T`) and functions pointers. Using `zeroed` -/// on such types causes immediate [undefined behavior][ub] because [the Rust -/// compiler assumes][inv] that there always is a valid value in a variable it -/// considers initialized. -/// -/// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed]. -/// It is useful for FFI sometimes, but should generally be avoided. -/// -/// [zeroed]: union.MaybeUninit.html#method.zeroed -/// [ub]: ../../reference/behavior-considered-undefined.html -/// [inv]: union.MaybeUninit.html#initialization-invariant -/// -/// # Examples -/// -/// Correct usage of this function: initializing an integer with zero. -/// -/// ``` -/// use std::mem; -/// -/// let x: i32 = unsafe { mem::zeroed() }; -/// assert_eq!(0, x); -/// ``` -/// -/// *Incorrect* usage of this function: initializing a reference with zero. -/// -/// ```rust,no_run -/// # #![allow(invalid_value)] -/// use std::mem; -/// -/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior! -/// let _y: fn() = unsafe { mem::zeroed() }; // And again! -/// ``` -#[inline(always)] -#[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated_in_future)] -#[allow(deprecated)] -#[rustc_diagnostic_item = "mem_zeroed"] -pub unsafe fn zeroed<T>() -> T { - // SAFETY: the caller must guarantee that an all-zero value is valid for `T`. - unsafe { - intrinsics::assert_zero_valid::<T>(); - MaybeUninit::zeroed().assume_init() - } -} - -/// Bypasses Rust's normal memory-initialization checks by pretending to -/// produce a value of type `T`, while doing nothing at all. -/// -/// **This function is deprecated.** Use [`MaybeUninit<T>`] instead. -/// -/// The reason for deprecation is that the function basically cannot be used -/// correctly: it has the same effect as [`MaybeUninit::uninit().assume_init()`][uninit]. -/// As the [`assume_init` documentation][assume_init] explains, -/// [the Rust compiler assumes][inv] that values are properly initialized. -/// As a consequence, calling e.g. `mem::uninitialized::<bool>()` causes immediate -/// undefined behavior for returning a `bool` that is not definitely either `true` -/// or `false`. Worse, truly uninitialized memory like what gets returned here -/// is special in that the compiler knows that it does not have a fixed value. -/// This makes it undefined behavior to have uninitialized data in a variable even -/// if that variable has an integer type. -/// (Notice that the rules around uninitialized integers are not finalized yet, but -/// until they are, it is advisable to avoid them.) -/// -/// [`MaybeUninit<T>`]: union.MaybeUninit.html -/// [uninit]: union.MaybeUninit.html#method.uninit -/// [assume_init]: union.MaybeUninit.html#method.assume_init -/// [inv]: union.MaybeUninit.html#initialization-invariant -#[inline(always)] -#[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")] -#[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated_in_future)] -#[allow(deprecated)] -#[rustc_diagnostic_item = "mem_uninitialized"] -pub unsafe fn uninitialized<T>() -> T { - // SAFETY: the caller must guarantee that an unitialized value is valid for `T`. - unsafe { - intrinsics::assert_uninit_valid::<T>(); - MaybeUninit::uninit().assume_init() - } -} - -/// Swaps the values at two mutable locations, without deinitializing either one. -/// -/// # Examples -/// -/// ``` -/// use std::mem; -/// -/// let mut x = 5; -/// let mut y = 42; -/// -/// mem::swap(&mut x, &mut y); -/// -/// assert_eq!(42, x); -/// assert_eq!(5, y); -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn swap<T>(x: &mut T, y: &mut T) { - // SAFETY: the raw pointers have been created from safe mutable references satisfying all the - // constraints on `ptr::swap_nonoverlapping_one` - unsafe { - ptr::swap_nonoverlapping_one(x, y); - } -} - -/// Replaces `dest` with the default value of `T`, returning the previous `dest` value. -/// -/// # Examples -/// -/// A simple example: -/// -/// ``` -/// use std::mem; -/// -/// let mut v: Vec<i32> = vec![1, 2]; -/// -/// let old_v = mem::take(&mut v); -/// assert_eq!(vec![1, 2], old_v); -/// assert!(v.is_empty()); -/// ``` -/// -/// `take` allows taking ownership of a struct field by replacing it with an "empty" value. -/// Without `take` you can run into issues like these: -/// -/// ```compile_fail,E0507 -/// struct Buffer<T> { buf: Vec<T> } -/// -/// impl<T> Buffer<T> { -/// fn get_and_reset(&mut self) -> Vec<T> { -/// // error: cannot move out of dereference of `&mut`-pointer -/// let buf = self.buf; -/// self.buf = Vec::new(); -/// buf -/// } -/// } -/// ``` -/// -/// Note that `T` does not necessarily implement [`Clone`], so it can't even clone and reset -/// `self.buf`. But `take` can be used to disassociate the original value of `self.buf` from -/// `self`, allowing it to be returned: -/// -/// ``` -/// use std::mem; -/// -/// # struct Buffer<T> { buf: Vec<T> } -/// impl<T> Buffer<T> { -/// fn get_and_reset(&mut self) -> Vec<T> { -/// mem::take(&mut self.buf) -/// } -/// } -/// -/// let mut buffer = Buffer { buf: vec![0, 1] }; -/// assert_eq!(buffer.buf.len(), 2); -/// -/// assert_eq!(buffer.get_and_reset(), vec![0, 1]); -/// assert_eq!(buffer.buf.len(), 0); -/// ``` -/// -/// [`Clone`]: ../../std/clone/trait.Clone.html -#[inline] -#[stable(feature = "mem_take", since = "1.40.0")] -pub fn take<T: Default>(dest: &mut T) -> T { - replace(dest, T::default()) -} - -/// Moves `src` into the referenced `dest`, returning the previous `dest` value. -/// -/// Neither value is dropped. -/// -/// # Examples -/// -/// A simple example: -/// -/// ``` -/// use std::mem; -/// -/// let mut v: Vec<i32> = vec![1, 2]; -/// -/// let old_v = mem::replace(&mut v, vec![3, 4, 5]); -/// assert_eq!(vec![1, 2], old_v); -/// assert_eq!(vec![3, 4, 5], v); -/// ``` -/// -/// `replace` allows consumption of a struct field by replacing it with another value. -/// Without `replace` you can run into issues like these: -/// -/// ```compile_fail,E0507 -/// struct Buffer<T> { buf: Vec<T> } -/// -/// impl<T> Buffer<T> { -/// fn replace_index(&mut self, i: usize, v: T) -> T { -/// // error: cannot move out of dereference of `&mut`-pointer -/// let t = self.buf[i]; -/// self.buf[i] = v; -/// t -/// } -/// } -/// ``` -/// -/// Note that `T` does not necessarily implement [`Clone`], so we can't even clone `self.buf[i]` to -/// avoid the move. But `replace` can be used to disassociate the original value at that index from -/// `self`, allowing it to be returned: -/// -/// ``` -/// # #![allow(dead_code)] -/// use std::mem; -/// -/// # struct Buffer<T> { buf: Vec<T> } -/// impl<T> Buffer<T> { -/// fn replace_index(&mut self, i: usize, v: T) -> T { -/// mem::replace(&mut self.buf[i], v) -/// } -/// } -/// -/// let mut buffer = Buffer { buf: vec![0, 1] }; -/// assert_eq!(buffer.buf[0], 0); -/// -/// assert_eq!(buffer.replace_index(0, 2), 0); -/// assert_eq!(buffer.buf[0], 2); -/// ``` -/// -/// [`Clone`]: ../../std/clone/trait.Clone.html -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -#[must_use = "if you don't need the old value, you can just assign the new value directly"] -pub fn replace<T>(dest: &mut T, mut src: T) -> T { - swap(dest, &mut src); - src -} - -/// Disposes of a value. -/// -/// This does so by calling the argument's implementation of [`Drop`][drop]. -/// -/// This effectively does nothing for types which implement `Copy`, e.g. -/// integers. Such values are copied and _then_ moved into the function, so the -/// value persists after this function call. -/// -/// This function is not magic; it is literally defined as -/// -/// ``` -/// pub fn drop<T>(_x: T) { } -/// ``` -/// -/// Because `_x` is moved into the function, it is automatically dropped before -/// the function returns. -/// -/// [drop]: ../ops/trait.Drop.html -/// -/// # Examples -/// -/// Basic usage: -/// -/// ``` -/// let v = vec![1, 2, 3]; -/// -/// drop(v); // explicitly drop the vector -/// ``` -/// -/// Since [`RefCell`] enforces the borrow rules at runtime, `drop` can -/// release a [`RefCell`] borrow: -/// -/// ``` -/// use std::cell::RefCell; -/// -/// let x = RefCell::new(1); -/// -/// let mut mutable_borrow = x.borrow_mut(); -/// *mutable_borrow = 1; -/// -/// drop(mutable_borrow); // relinquish the mutable borrow on this slot -/// -/// let borrow = x.borrow(); -/// println!("{}", *borrow); -/// ``` -/// -/// Integers and other types implementing [`Copy`] are unaffected by `drop`. -/// -/// ``` -/// #[derive(Copy, Clone)] -/// struct Foo(u8); -/// -/// let x = 1; -/// let y = Foo(2); -/// drop(x); // a copy of `x` is moved and dropped -/// drop(y); // a copy of `y` is moved and dropped -/// -/// println!("x: {}, y: {}", x, y.0); // still available -/// ``` -/// -/// [`RefCell`]: ../../std/cell/struct.RefCell.html -/// [`Copy`]: ../../std/marker/trait.Copy.html -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -pub fn drop<T>(_x: T) {} - -/// Interprets `src` as having type `&U`, and then reads `src` without moving -/// the contained value. -/// -/// This function will unsafely assume the pointer `src` is valid for -/// [`size_of::<U>`][size_of] bytes by transmuting `&T` to `&U` and then reading -/// the `&U`. It will also unsafely create a copy of the contained value instead of -/// moving out of `src`. -/// -/// It is not a compile-time error if `T` and `U` have different sizes, but it -/// is highly encouraged to only invoke this function where `T` and `U` have the -/// same size. This function triggers [undefined behavior][ub] if `U` is larger than -/// `T`. -/// -/// [ub]: ../../reference/behavior-considered-undefined.html -/// [size_of]: fn.size_of.html -/// -/// # Examples -/// -/// ``` -/// use std::mem; -/// -/// #[repr(packed)] -/// struct Foo { -/// bar: u8, -/// } -/// -/// let foo_array = [10u8]; -/// -/// unsafe { -/// // Copy the data from 'foo_array' and treat it as a 'Foo' -/// let mut foo_struct: Foo = mem::transmute_copy(&foo_array); -/// assert_eq!(foo_struct.bar, 10); -/// -/// // Modify the copied data -/// foo_struct.bar = 20; -/// assert_eq!(foo_struct.bar, 20); -/// } -/// -/// // The contents of 'foo_array' should not have changed -/// assert_eq!(foo_array, [10]); -/// ``` -#[inline] -#[stable(feature = "rust1", since = "1.0.0")] -pub unsafe fn transmute_copy<T, U>(src: &T) -> U { - // If U has a higher alignment requirement, src may not be suitably aligned. - if align_of::<U>() > align_of::<T>() { - // SAFETY: `src` is a reference which is guaranteed to be valid for reads. - // The caller must guarantee that the actual transmutation is safe. - unsafe { ptr::read_unaligned(src as *const T as *const U) } - } else { - // SAFETY: `src` is a reference which is guaranteed to be valid for reads. - // We just checked that `src as *const U` was properly aligned. - // The caller must guarantee that the actual transmutation is safe. - unsafe { ptr::read(src as *const T as *const U) } - } -} - -/// Opaque type representing the discriminant of an enum. -/// -/// See the [`discriminant`] function in this module for more information. -/// -/// [`discriminant`]: fn.discriminant.html -#[stable(feature = "discriminant_value", since = "1.21.0")] -pub struct Discriminant<T>(<T as DiscriminantKind>::Discriminant); - -// N.B. These trait implementations cannot be derived because we don't want any bounds on T. - -#[stable(feature = "discriminant_value", since = "1.21.0")] -impl<T> Copy for Discriminant<T> {} - -#[stable(feature = "discriminant_value", since = "1.21.0")] -impl<T> clone::Clone for Discriminant<T> { - fn clone(&self) -> Self { - *self - } -} - -#[stable(feature = "discriminant_value", since = "1.21.0")] -impl<T> cmp::PartialEq for Discriminant<T> { - fn eq(&self, rhs: &Self) -> bool { - self.0 == rhs.0 - } -} - -#[stable(feature = "discriminant_value", since = "1.21.0")] -impl<T> cmp::Eq for Discriminant<T> {} - -#[stable(feature = "discriminant_value", since = "1.21.0")] -impl<T> hash::Hash for Discriminant<T> { - fn hash<H: hash::Hasher>(&self, state: &mut H) { - self.0.hash(state); - } -} - -#[stable(feature = "discriminant_value", since = "1.21.0")] -impl<T> fmt::Debug for Discriminant<T> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_tuple("Discriminant").field(&self.0).finish() - } -} - -/// Returns a value uniquely identifying the enum variant in `v`. -/// -/// If `T` is not an enum, calling this function will not result in undefined behavior, but the -/// return value is unspecified. -/// -/// # Stability -/// -/// The discriminant of an enum variant may change if the enum definition changes. A discriminant -/// of some variant will not change between compilations with the same compiler. -/// -/// # Examples -/// -/// This can be used to compare enums that carry data, while disregarding -/// the actual data: -/// -/// ``` -/// use std::mem; -/// -/// enum Foo { A(&'static str), B(i32), C(i32) } -/// -/// assert_eq!(mem::discriminant(&Foo::A("bar")), mem::discriminant(&Foo::A("baz"))); -/// assert_eq!(mem::discriminant(&Foo::B(1)), mem::discriminant(&Foo::B(2))); -/// assert_ne!(mem::discriminant(&Foo::B(3)), mem::discriminant(&Foo::C(3))); -/// ``` -#[stable(feature = "discriminant_value", since = "1.21.0")] -#[rustc_const_unstable(feature = "const_discriminant", issue = "69821")] -pub const fn discriminant<T>(v: &T) -> Discriminant<T> { - Discriminant(intrinsics::discriminant_value(v)) -} - -/// Returns the number of variants in the enum type `T`. -/// -/// If `T` is not an enum, calling this function will not result in undefined behavior, but the -/// return value is unspecified. Equally, if `T` is an enum with more variants than `usize::MAX` -/// the return value is unspecified. Uninhabited variants will be counted. -/// -/// # Examples -/// -/// ``` -/// # #![feature(never_type)] -/// # #![feature(variant_count)] -/// -/// use std::mem; -/// -/// enum Void {} -/// enum Foo { A(&'static str), B(i32), C(i32) } -/// -/// assert_eq!(mem::variant_count::<Void>(), 0); -/// assert_eq!(mem::variant_count::<Foo>(), 3); -/// -/// assert_eq!(mem::variant_count::<Option<!>>(), 2); -/// assert_eq!(mem::variant_count::<Result<!, !>>(), 2); -/// ``` -#[inline(always)] -#[unstable(feature = "variant_count", issue = "73662")] -#[rustc_const_unstable(feature = "variant_count", issue = "73662")] -pub const fn variant_count<T>() -> usize { - intrinsics::variant_count::<T>() -} |
