diff options
Diffstat (limited to 'src/liballoc/boxed.rs')
| -rw-r--r-- | src/liballoc/boxed.rs | 109 |
1 files changed, 99 insertions, 10 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 4341b0b2975..6f125cdba81 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -151,7 +151,7 @@ impl<T> Place<T> for IntermediateBox<T> { unsafe fn finalize<T>(b: IntermediateBox<T>) -> Box<T> { let p = b.ptr as *mut T; mem::forget(b); - mem::transmute(p) + Box::from_raw(p) } fn make_place<T>() -> IntermediateBox<T> { @@ -269,7 +269,38 @@ impl<T: ?Sized> Box<T> { #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub unsafe fn from_raw(raw: *mut T) -> Self { - mem::transmute(raw) + Box::from_unique(Unique::new_unchecked(raw)) + } + + /// Constructs a `Box` from a `Unique<T>` pointer. + /// + /// After calling this function, the memory is owned by a `Box` and `T` can + /// then be destroyed and released upon drop. + /// + /// # Safety + /// + /// A `Unique<T>` can be safely created via [`Unique::new`] and thus doesn't + /// necessarily own the data pointed to nor is the data guaranteed to live + /// as long as the pointer. + /// + /// [`Unique::new`]: ../../core/ptr/struct.Unique.html#method.new + /// + /// # Examples + /// + /// ``` + /// #![feature(unique)] + /// + /// fn main() { + /// let x = Box::new(5); + /// let ptr = Box::into_unique(x); + /// let x = unsafe { Box::from_unique(ptr) }; + /// } + /// ``` + #[unstable(feature = "unique", reason = "needs an RFC to flesh out design", + issue = "27730")] + #[inline] + pub unsafe fn from_unique(u: Unique<T>) -> Self { + Box(u) } /// Consumes the `Box`, returning the wrapped raw pointer. @@ -295,7 +326,7 @@ impl<T: ?Sized> Box<T> { #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub fn into_raw(b: Box<T>) -> *mut T { - unsafe { mem::transmute(b) } + Box::into_unique(b).as_ptr() } /// Consumes the `Box`, returning the wrapped pointer as `Unique<T>`. @@ -303,13 +334,18 @@ impl<T: ?Sized> Box<T> { /// After calling this function, the caller is responsible for the /// memory previously managed by the `Box`. In particular, the /// caller should properly destroy `T` and release the memory. The - /// proper way to do so is to convert the raw pointer back into a - /// `Box` with the [`Box::from_raw`] function. + /// proper way to do so is to either convert the `Unique<T>` pointer: + /// + /// - Into a `Box` with the [`Box::from_unique`] function. + /// + /// - Into a raw pointer and back into a `Box` with the [`Box::from_raw`] + /// function. /// /// Note: this is an associated function, which means that you have /// to call it as `Box::into_unique(b)` instead of `b.into_unique()`. This /// is so that there is no conflict with a method on the inner type. /// + /// [`Box::from_unique`]: struct.Box.html#method.from_unique /// [`Box::from_raw`]: struct.Box.html#method.from_raw /// /// # Examples @@ -326,7 +362,62 @@ impl<T: ?Sized> Box<T> { issue = "27730")] #[inline] pub fn into_unique(b: Box<T>) -> Unique<T> { - unsafe { mem::transmute(b) } + let unique = b.0; + mem::forget(b); + unique + } + + /// Consumes and leaks the `Box`, returning a mutable reference, + /// `&'a mut T`. Here, the lifetime `'a` may be chosen to be `'static`. + /// + /// This function is mainly useful for data that lives for the remainder of + /// the program's life. Dropping the returned reference will cause a memory + /// leak. If this is not acceptable, the reference should first be wrapped + /// with the [`Box::from_raw`] function producing a `Box`. This `Box` can + /// then be dropped which will properly destroy `T` and release the + /// allocated memory. + /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::leak(b)` instead of `b.leak()`. This + /// is so that there is no conflict with a method on the inner type. + /// + /// [`Box::from_raw`]: struct.Box.html#method.from_raw + /// + /// # Examples + /// + /// Simple usage: + /// + /// ``` + /// #![feature(box_leak)] + /// + /// fn main() { + /// let x = Box::new(41); + /// let static_ref: &'static mut usize = Box::leak(x); + /// *static_ref += 1; + /// assert_eq!(*static_ref, 42); + /// } + /// ``` + /// + /// Unsized data: + /// + /// ``` + /// #![feature(box_leak)] + /// + /// fn main() { + /// let x = vec![1, 2, 3].into_boxed_slice(); + /// let static_ref = Box::leak(x); + /// static_ref[0] = 4; + /// assert_eq!(*static_ref, [4, 2, 3]); + /// } + /// ``` + #[unstable(feature = "box_leak", reason = "needs an FCP to stabilize", + issue = "46179")] + #[inline] + pub fn leak<'a>(b: Box<T>) -> &'a mut T + where + T: 'a // Technically not needed, but kept to be explicit. + { + unsafe { &mut *Box::into_raw(b) } } } @@ -528,9 +619,7 @@ impl<'a> From<&'a str> for Box<str> { #[stable(feature = "boxed_str_conv", since = "1.19.0")] impl From<Box<str>> for Box<[u8]> { fn from(s: Box<str>) -> Self { - unsafe { - mem::transmute(s) - } + unsafe { Box::from_raw(Box::into_raw(s) as *mut [u8]) } } } @@ -593,7 +682,7 @@ impl Box<Any + Send> { pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any + Send>> { <Box<Any>>::downcast(self).map_err(|s| unsafe { // reapply the Send marker - mem::transmute::<Box<Any>, Box<Any + Send>>(s) + Box::from_raw(Box::into_raw(s) as *mut (Any + Send)) }) } } |
