diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 91577e30d9a01..504b58d8ad105 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -102,6 +102,52 @@ impl Box { } } +impl Box { + /// Constructs a box from the raw pointer. + /// + /// After this function call, pointer is owned by resulting box. + /// In particular, it means that `Box` destructor calls destructor + /// of `T` and releases memory. Since the way `Box` allocates and + /// releases memory is unspecified, so the only valid pointer to + /// pass to this function is the one taken from another `Box` with + /// `box::into_raw` function. + /// + /// Function is unsafe, because improper use of this function may + /// lead to memory problems like double-free, for example if the + /// function is called twice on the same raw pointer. + #[unstable(feature = "alloc", + reason = "may be renamed or moved out of Box scope")] + pub unsafe fn from_raw(raw: *mut T) -> Self { + mem::transmute(raw) + } +} + +/// Consumes the `Box`, returning the wrapped raw pointer. +/// +/// After call to this function, caller is responsible for the memory +/// previously managed by `Box`, in particular caller should properly +/// destroy `T` and release memory. The proper way to do it is to +/// convert pointer back to `Box` with `Box::from_raw` function, because +/// `Box` does not specify, how memory is allocated. +/// +/// Function is unsafe, because result of this function is no longer +/// automatically managed that may lead to memory or other resource +/// leak. +/// +/// # Example +/// ``` +/// use std::boxed; +/// +/// let seventeen = Box::new(17u32); +/// let raw = unsafe { boxed::into_raw(seventeen) }; +/// let boxed_again = unsafe { Box::from_raw(raw) }; +/// ``` +#[unstable(feature = "alloc", + reason = "may be renamed")] +pub unsafe fn into_raw(b: Box) -> *mut T { + mem::transmute(b) +} + #[stable(feature = "rust1", since = "1.0.0")] impl Default for Box { #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/boxed_test.rs b/src/liballoc/boxed_test.rs index 4ffb94e7a6106..f7ddfcb09d7fb 100644 --- a/src/liballoc/boxed_test.rs +++ b/src/liballoc/boxed_test.rs @@ -15,6 +15,7 @@ use core::ops::Deref; use core::result::Result::{Ok, Err}; use core::clone::Clone; +use std::boxed; use std::boxed::Box; use std::boxed::BoxAny; @@ -73,3 +74,44 @@ fn deref() { fn homura>(_: T) { } homura(Box::new(765i32)); } + +#[test] +fn raw_sized() { + unsafe { + let x = Box::new(17i32); + let p = boxed::into_raw(x); + assert_eq!(17, *p); + *p = 19; + let y = Box::from_raw(p); + assert_eq!(19, *y); + } +} + +#[test] +fn raw_trait() { + trait Foo { + fn get(&self) -> u32; + fn set(&mut self, value: u32); + } + + struct Bar(u32); + + impl Foo for Bar { + fn get(&self) -> u32 { + self.0 + } + + fn set(&mut self, value: u32) { + self.0 = value; + } + } + + unsafe { + let x: Box = Box::new(Bar(17)); + let p = boxed::into_raw(x); + assert_eq!(17, (*p).get()); + (*p).set(19); + let y: Box = Box::from_raw(p); + assert_eq!(19, y.get()); + } +}