- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
          Implement MaybeUninit
          #53508
        
          New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
  
    Implement MaybeUninit
  
  #53508
                      Changes from all commits
7bb5b3e
              851acdd
              96572cb
              7c37c6d
              ce8503d
              a6d011a
              af101fd
              ce6e6f9
              33c10ea
              bc5b567
              d864edc
              758ce16
              8fb0e80
              8482c93
              7fea7f4
              dd9f019
              41b242e
              d266722
              1cdbad2
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -9,7 +9,7 @@ | |
| // except according to those terms. | ||
|  | ||
| use fmt::{Formatter, Result, LowerExp, UpperExp, Display, Debug}; | ||
| use mem; | ||
| use mem::MaybeUninit; | ||
| use num::flt2dec; | ||
|  | ||
| // Don't inline this so callers don't use the stack space this function | ||
|  | @@ -20,11 +20,11 @@ fn float_to_decimal_common_exact<T>(fmt: &mut Formatter, num: &T, | |
| where T: flt2dec::DecodableFloat | ||
| { | ||
| unsafe { | ||
| let mut buf: [u8; 1024] = mem::uninitialized(); // enough for f32 and f64 | ||
| let mut parts: [flt2dec::Part; 4] = mem::uninitialized(); | ||
| let mut buf = MaybeUninit::<[u8; 1024]>::uninitialized(); // enough for f32 and f64 | ||
| let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninitialized(); | ||
| let formatted = flt2dec::to_exact_fixed_str(flt2dec::strategy::grisu::format_exact, | ||
| *num, sign, precision, | ||
| false, &mut buf, &mut parts); | ||
| false, buf.get_mut(), parts.get_mut()); | ||
|          | ||
| fmt.pad_formatted_parts(&formatted) | ||
| } | ||
| } | ||
|  | @@ -38,10 +38,11 @@ fn float_to_decimal_common_shortest<T>(fmt: &mut Formatter, num: &T, | |
| { | ||
| unsafe { | ||
| // enough for f32 and f64 | ||
| let mut buf: [u8; flt2dec::MAX_SIG_DIGITS] = mem::uninitialized(); | ||
| let mut parts: [flt2dec::Part; 4] = mem::uninitialized(); | ||
| let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninitialized(); | ||
| let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninitialized(); | ||
| let formatted = flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest, *num, | ||
| sign, precision, false, &mut buf, &mut parts); | ||
| sign, precision, false, buf.get_mut(), | ||
| parts.get_mut()); | ||
| fmt.pad_formatted_parts(&formatted) | ||
| } | ||
| } | ||
|  | @@ -75,11 +76,11 @@ fn float_to_exponential_common_exact<T>(fmt: &mut Formatter, num: &T, | |
| where T: flt2dec::DecodableFloat | ||
| { | ||
| unsafe { | ||
| let mut buf: [u8; 1024] = mem::uninitialized(); // enough for f32 and f64 | ||
| let mut parts: [flt2dec::Part; 6] = mem::uninitialized(); | ||
| let mut buf = MaybeUninit::<[u8; 1024]>::uninitialized(); // enough for f32 and f64 | ||
| let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninitialized(); | ||
| let formatted = flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact, | ||
| *num, sign, precision, | ||
| upper, &mut buf, &mut parts); | ||
| upper, buf.get_mut(), parts.get_mut()); | ||
| fmt.pad_formatted_parts(&formatted) | ||
| } | ||
| } | ||
|  | @@ -94,11 +95,11 @@ fn float_to_exponential_common_shortest<T>(fmt: &mut Formatter, | |
| { | ||
| unsafe { | ||
| // enough for f32 and f64 | ||
| let mut buf: [u8; flt2dec::MAX_SIG_DIGITS] = mem::uninitialized(); | ||
| let mut parts: [flt2dec::Part; 6] = mem::uninitialized(); | ||
| let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninitialized(); | ||
| let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninitialized(); | ||
| let formatted = flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest, | ||
| *num, sign, (0, 0), upper, | ||
| &mut buf, &mut parts); | ||
| buf.get_mut(), parts.get_mut()); | ||
| fmt.pad_formatted_parts(&formatted) | ||
| } | ||
| } | ||
|  | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -514,6 +514,7 @@ pub fn needs_drop<T>() -> bool { | |
| /// assert_eq!(0, x); | ||
| /// ``` | ||
| #[inline] | ||
| #[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::zeroed` instead")] | ||
| #[stable(feature = "rust1", since = "1.0.0")] | ||
| pub unsafe fn zeroed<T>() -> T { | ||
| intrinsics::init() | ||
|  | @@ -608,6 +609,7 @@ pub unsafe fn zeroed<T>() -> T { | |
| /// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html | ||
| /// [`Drop`]: ../ops/trait.Drop.html | ||
| #[inline] | ||
| #[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::uninitialized` instead")] | ||
| #[stable(feature = "rust1", since = "1.0.0")] | ||
| pub unsafe fn uninitialized<T>() -> T { | ||
| intrinsics::uninit() | ||
|  | @@ -1024,3 +1026,97 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> { | |
| &mut self.value | ||
| } | ||
| } | ||
|  | ||
| /// A newtype to construct uninitialized instances of `T` | ||
| #[allow(missing_debug_implementations)] | ||
| #[unstable(feature = "maybe_uninit", issue = "53491")] | ||
| // NOTE after stabilizing `MaybeUninit` proceed to deprecate `mem::{uninitialized,zeroed}` | ||
| pub union MaybeUninit<T> { | ||
| uninit: (), | ||
| value: ManuallyDrop<T>, | ||
| } | ||
|  | ||
| impl<T> MaybeUninit<T> { | ||
| /// Create a new `MaybeUninit` in an uninitialized state. | ||
| /// | ||
| /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. | ||
| /// It is your responsibility to make sure `T` gets dropped if it got initialized. | ||
| #[unstable(feature = "maybe_uninit", issue = "53491")] | ||
| pub const fn uninitialized() -> MaybeUninit<T> { | ||
|          | ||
| MaybeUninit { uninit: () } | ||
| } | ||
|  | ||
| /// Create a new `MaybeUninit` 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` will never call `T`'s drop code. | ||
| /// It is your responsibility to make sure `T` gets dropped if it got initialized. | ||
| #[unstable(feature = "maybe_uninit", issue = "53491")] | ||
| pub fn zeroed() -> MaybeUninit<T> { | ||
| let mut u = MaybeUninit::<T>::uninitialized(); | ||
| unsafe { | ||
| u.as_mut_ptr().write_bytes(0u8, 1); | ||
| } | ||
| u | ||
| } | ||
|  | ||
| /// Set the value of the `MaybeUninit`. This overwrites any previous value without dropping it. | ||
| #[unstable(feature = "maybe_uninit", issue = "53491")] | ||
| pub fn set(&mut self, val: T) { | ||
| unsafe { | ||
| self.value = ManuallyDrop::new(val); | ||
| } | ||
| } | ||
|  | ||
| /// Extract the value from the `MaybeUninit` 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. | ||
| /// | ||
| /// # Unsafety | ||
| /// | ||
| /// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized | ||
| /// state, otherwise this will immediately cause undefined behavior. | ||
| #[unstable(feature = "maybe_uninit", issue = "53491")] | ||
| pub unsafe fn into_inner(self) -> T { | ||
| ManuallyDrop::into_inner(self.value) | ||
| } | ||
|  | ||
| /// Get a reference to the contained value. | ||
| /// | ||
| /// # Unsafety | ||
| /// | ||
| /// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized | ||
| /// state, otherwise this will immediately cause undefined behavior. | ||
| #[unstable(feature = "maybe_uninit", issue = "53491")] | ||
| pub unsafe fn get_ref(&self) -> &T { | ||
| &*self.value | ||
| } | ||
|  | ||
| /// Get a mutable reference to the contained value. | ||
| /// | ||
| /// # Unsafety | ||
| /// | ||
| /// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized | ||
| /// state, otherwise this will immediately cause undefined behavior. | ||
| #[unstable(feature = "maybe_uninit", issue = "53491")] | ||
| pub unsafe fn get_mut(&mut self) -> &mut T { | ||
| &mut *self.value | ||
| } | ||
|  | ||
| /// Get a pointer to the contained value. Reading from this pointer will be undefined | ||
| /// behavior unless the `MaybeUninit` is initialized. | ||
| #[unstable(feature = "maybe_uninit", issue = "53491")] | ||
| pub fn as_ptr(&self) -> *const T { | ||
| unsafe { &*self.value as *const T } | ||
| } | ||
|  | ||
| /// Get a mutable pointer to the contained value. Reading from this pointer will be undefined | ||
| /// behavior unless the `MaybeUninit` is initialized. | ||
| #[unstable(feature = "maybe_uninit", issue = "53491")] | ||
| pub fn as_mut_ptr(&mut self) -> *mut T { | ||
| unsafe { &mut *self.value as *mut T } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the comment above, should this instead be
[MaybeUninit<V>; CAPACITY]?(That might be a pain, though, and this is no worse than before, so might not be this PR.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems like a pretty equivalent type to me. Which comment above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we document that you can partially-initialize
MaybeUninit, i.e. that it "distributes over products"?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is forth saying, yes.
Unfortunately actually implementing this is not easy, same problem as for
Cell(which also distributes over products).