Rollup merge of #22696 - stepancheg:use-box, r=alexcrichton

e. g.

```
let b: Box<Foo> = Box::from_raw(p);
```

instead of

```
let b: Box<Foo> = mem::transmute(p);
```

Patch also changes closure release code in `src/libstd/sys/unix/thread.rs`
when `pthread_create` failed. Raw pointer was transmuted to box of
`FnOnce()` instead of `Thunk`. This code was probably never executed,
because `pthread_create` rarely fails.

(And there are two more patches in PR: fix typo in doc and mark `from_raw` and `into_raw` functions inline.)
This commit is contained in:
Manish Goregaokar 2015-02-23 14:48:54 +05:30
commit db04229d23
15 changed files with 65 additions and 48 deletions

View File

@ -105,15 +105,16 @@ impl<T : ?Sized> Box<T> {
/// 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.
/// releases memory is unspecified, the only valid pointer to pass
/// to this function is the one taken from another `Box` with
/// `boxed::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")]
#[inline]
pub unsafe fn from_raw(raw: *mut T) -> Self {
mem::transmute(raw)
}
@ -141,6 +142,7 @@ impl<T : ?Sized> Box<T> {
/// ```
#[unstable(feature = "alloc",
reason = "may be renamed")]
#[inline]
pub unsafe fn into_raw<T : ?Sized>(b: Box<T>) -> *mut T {
mem::transmute(b)
}
@ -248,11 +250,12 @@ impl BoxAny for Box<Any> {
if self.is::<T>() {
unsafe {
// Get the raw representation of the trait object
let raw = into_raw(self);
let to: TraitObject =
mem::transmute::<Box<Any>, TraitObject>(self);
mem::transmute::<*mut Any, TraitObject>(raw);
// Extract the data pointer
Ok(mem::transmute(to.data))
Ok(Box::from_raw(to.data as *mut T))
}
} else {
Err(self)

View File

@ -144,6 +144,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
use boxed;
use core::cell::Cell;
use core::clone::Clone;
use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
@ -151,7 +152,7 @@ use core::default::Default;
use core::fmt;
use core::hash::{Hasher, Hash};
use core::marker;
use core::mem::{transmute, min_align_of, size_of, forget};
use core::mem::{min_align_of, size_of, forget};
use core::nonzero::NonZero;
use core::ops::{Deref, Drop};
use core::option::Option;
@ -201,7 +202,7 @@ impl<T> Rc<T> {
// there is an implicit weak pointer owned by all the strong pointers, which
// ensures that the weak destructor never frees the allocation while the strong
// destructor is running, even if the weak pointer is stored inside the strong one.
_ptr: NonZero::new(transmute(box RcBox {
_ptr: NonZero::new(boxed::into_raw(box RcBox {
value: value,
strong: Cell::new(1),
weak: Cell::new(1)

View File

@ -388,7 +388,7 @@ impl<T> Vec<T> {
pub fn into_boxed_slice(mut self) -> Box<[T]> {
self.shrink_to_fit();
unsafe {
let xs: Box<[T]> = mem::transmute(&mut *self);
let xs: Box<[T]> = Box::from_raw(&mut *self);
mem::forget(self);
xs
}

View File

@ -167,6 +167,7 @@
html_playground_url = "http://play.rust-lang.org/")]
#![deny(missing_docs)]
#![feature(alloc)]
#![feature(staged_api)]
#![feature(box_syntax)]
#![feature(int_uint)]
@ -175,6 +176,7 @@
#![feature(std_misc)]
#![feature(env)]
use std::boxed;
use std::cell::RefCell;
use std::fmt;
use std::old_io::LineBufferedWriter;
@ -205,11 +207,11 @@ const DEFAULT_LOG_LEVEL: u32 = 1;
/// logging statement should be run.
static mut LOG_LEVEL: u32 = MAX_LOG_LEVEL;
static mut DIRECTIVES: *const Vec<directive::LogDirective> =
0 as *const Vec<directive::LogDirective>;
static mut DIRECTIVES: *mut Vec<directive::LogDirective> =
0 as *mut Vec<directive::LogDirective>;
/// Optional filter.
static mut FILTER: *const String = 0 as *const _;
static mut FILTER: *mut String = 0 as *mut _;
/// Debug log level
pub const DEBUG: u32 = 4;
@ -419,23 +421,23 @@ fn init() {
assert!(FILTER.is_null());
match filter {
Some(f) => FILTER = mem::transmute(box f),
Some(f) => FILTER = boxed::into_raw(box f),
None => {}
}
assert!(DIRECTIVES.is_null());
DIRECTIVES = mem::transmute(box directives);
DIRECTIVES = boxed::into_raw(box directives);
// Schedule the cleanup for the globals for when the runtime exits.
rt::at_exit(move || {
assert!(!DIRECTIVES.is_null());
let _directives: Box<Vec<directive::LogDirective>> =
mem::transmute(DIRECTIVES);
DIRECTIVES = ptr::null();
Box::from_raw(DIRECTIVES);
DIRECTIVES = ptr::null_mut();
if !FILTER.is_null() {
let _filter: Box<String> = mem::transmute(FILTER);
FILTER = 0 as *const _;
let _filter: Box<String> = Box::from_raw(FILTER);
FILTER = 0 as *mut _;
}
});
}

View File

@ -27,6 +27,7 @@
use self::StdSource::*;
use boxed;
use boxed::Box;
use cell::RefCell;
use clone::Clone;
@ -218,7 +219,7 @@ impl Reader for StdinReader {
/// See `stdout()` for more notes about this function.
pub fn stdin() -> StdinReader {
// We're following the same strategy as kimundi's lazy_static library
static mut STDIN: *const StdinReader = 0 as *const StdinReader;
static mut STDIN: *mut StdinReader = 0 as *mut StdinReader;
static ONCE: Once = ONCE_INIT;
unsafe {
@ -235,12 +236,12 @@ pub fn stdin() -> StdinReader {
let stdin = StdinReader {
inner: Arc::new(Mutex::new(RaceBox(stdin)))
};
STDIN = mem::transmute(box stdin);
STDIN = boxed::into_raw(box stdin);
// Make sure to free it at exit
rt::at_exit(|| {
mem::transmute::<_, Box<StdinReader>>(STDIN);
STDIN = ptr::null();
Box::from_raw(STDIN);
STDIN = ptr::null_mut();
});
});

View File

@ -14,9 +14,9 @@
use core::prelude::*;
use boxed;
use boxed::Box;
use vec::Vec;
use mem;
use thunk::Thunk;
use sys_common::mutex::{Mutex, MUTEX_INIT};
@ -32,7 +32,7 @@ static mut QUEUE: *mut Queue = 0 as *mut Queue;
unsafe fn init() {
if QUEUE.is_null() {
let state: Box<Queue> = box Vec::new();
QUEUE = mem::transmute(state);
QUEUE = boxed::into_raw(state);
} else {
// can't re-init after a cleanup
rtassert!(QUEUE as uint != 1);
@ -57,7 +57,7 @@ pub fn cleanup() {
// If we never called init, not need to cleanup!
if queue as uint != 0 {
let queue: Box<Queue> = mem::transmute(queue);
let queue: Box<Queue> = Box::from_raw(queue);
for to_run in *queue {
to_run.invoke(());
}

View File

@ -60,6 +60,7 @@
use prelude::v1::*;
use any::Any;
use boxed;
use cell::Cell;
use cmp;
use panicking;
@ -173,7 +174,8 @@ fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
},
cause: Some(cause),
};
let error = uw::_Unwind_RaiseException(mem::transmute(exception));
let exception_param = boxed::into_raw(exception) as *mut uw::_Unwind_Exception;
let error = uw::_Unwind_RaiseException(exception_param);
rtabort!("Could not unwind stack, error = {}", error as int)
}
@ -181,7 +183,7 @@ fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
exception: *mut uw::_Unwind_Exception) {
rtdebug!("exception_cleanup()");
unsafe {
let _: Box<Exception> = mem::transmute(exception);
let _: Box<Exception> = Box::from_raw(exception as *mut Exception);
}
}
}

View File

@ -44,8 +44,8 @@ pub use self::PopResult::*;
use core::prelude::*;
use alloc::boxed;
use alloc::boxed::Box;
use core::mem;
use core::ptr;
use core::cell::UnsafeCell;
@ -82,7 +82,7 @@ unsafe impl<T: Send> Sync for Queue<T> { }
impl<T> Node<T> {
unsafe fn new(v: Option<T>) -> *mut Node<T> {
mem::transmute(box Node {
boxed::into_raw(box Node {
next: AtomicPtr::new(ptr::null_mut()),
value: v,
})
@ -129,7 +129,7 @@ impl<T: Send> Queue<T> {
assert!((*tail).value.is_none());
assert!((*next).value.is_some());
let ret = (*next).value.take().unwrap();
let _: Box<Node<T>> = mem::transmute(tail);
let _: Box<Node<T>> = Box::from_raw(tail);
return Data(ret);
}
@ -146,7 +146,7 @@ impl<T: Send> Drop for Queue<T> {
let mut cur = *self.tail.get();
while !cur.is_null() {
let next = (*cur).next.load(Ordering::Relaxed);
let _: Box<Node<T>> = mem::transmute(cur);
let _: Box<Node<T>> = Box::from_raw(cur);
cur = next;
}
}

View File

@ -37,8 +37,8 @@
use core::prelude::*;
use alloc::boxed;
use alloc::boxed::Box;
use core::mem;
use core::ptr;
use core::cell::UnsafeCell;
@ -81,7 +81,7 @@ unsafe impl<T: Send> Sync for Queue<T> { }
impl<T: Send> Node<T> {
fn new() -> *mut Node<T> {
unsafe {
mem::transmute(box Node {
boxed::into_raw(box Node {
value: None,
next: AtomicPtr::new(ptr::null_mut::<Node<T>>()),
})
@ -200,7 +200,7 @@ impl<T: Send> Queue<T> {
.next.store(next, Ordering::Relaxed);
// We have successfully erased all references to 'tail', so
// now we can safely drop it.
let _: Box<Node<T>> = mem::transmute(tail);
let _: Box<Node<T>> = Box::from_raw(tail);
}
}
return ret;
@ -233,7 +233,7 @@ impl<T: Send> Drop for Queue<T> {
let mut cur = *self.first.get();
while !cur.is_null() {
let next = (*cur).next.load(Ordering::Relaxed);
let _n: Box<Node<T>> = mem::transmute(cur);
let _n: Box<Node<T>> = Box::from_raw(cur);
cur = next;
}
}

View File

@ -22,8 +22,8 @@
use prelude::v1::*;
use boxed;
use cell::UnsafeCell;
use mem;
use ptr;
use rt;
use sync::{StaticMutex, StaticCondvar};
@ -88,7 +88,7 @@ impl<M: Send> Helper<M> {
let _guard = self.lock.lock().unwrap();
if !*self.initialized.get() {
let (tx, rx) = channel();
*self.chan.get() = mem::transmute(box tx);
*self.chan.get() = boxed::into_raw(box tx);
let (receive, send) = helper_signal::new();
*self.signal.get() = send as uint;
@ -132,7 +132,7 @@ impl<M: Send> Helper<M> {
let mut guard = self.lock.lock().unwrap();
// Close the channel by destroying it
let chan: Box<Sender<M>> = mem::transmute(*self.chan.get());
let chan: Box<Sender<M>> = Box::from_raw(*self.chan.get());
*self.chan.get() = ptr::null_mut();
drop(chan);
helper_signal::signal(*self.signal.get() as helper_signal::signal);

View File

@ -27,7 +27,7 @@ pub fn start_thread(main: *mut libc::c_void) -> thread::rust_thread_return {
unsafe {
stack::record_os_managed_stack_bounds(0, usize::MAX);
let handler = stack_overflow::Handler::new();
let f: Box<Thunk> = mem::transmute(main);
let f: Box<Thunk> = Box::from_raw(main as *mut Thunk);
f.invoke(());
drop(handler);
mem::transmute(0 as thread::rust_thread_return)

View File

@ -11,6 +11,7 @@
use core::prelude::*;
use io;
use boxed;
use boxed::Box;
use cmp;
use mem;
@ -241,13 +242,15 @@ pub unsafe fn create(stack: uint, p: Thunk) -> io::Result<rust_thread> {
},
};
let arg: *mut libc::c_void = mem::transmute(box p); // must box since sizeof(p)=2*uint
// must box since sizeof(p)=2*uint
let raw_p = boxed::into_raw(box p);
let arg = raw_p as *mut libc::c_void;
let ret = pthread_create(&mut native, &attr, thread_start, arg);
assert_eq!(pthread_attr_destroy(&mut attr), 0);
if ret != 0 {
// be sure to not leak the closure
let _p: Box<Box<FnOnce()+Send>> = mem::transmute(arg);
let _p: Box<Thunk> = Box::from_raw(raw_p);
Err(io::Error::from_os_error(ret))
} else {
Ok(native)

View File

@ -10,6 +10,8 @@
use prelude::v1::*;
use boxed;
use boxed::Box;
use cmp;
use io;
use mem;
@ -45,7 +47,8 @@ pub mod guard {
}
pub unsafe fn create(stack: uint, p: Thunk) -> io::Result<rust_thread> {
let arg: *mut libc::c_void = mem::transmute(box p);
let raw_p = boxed::into_raw(box p);
let arg = raw_p as *mut libc::c_void;
// FIXME On UNIX, we guard against stack sizes that are too small but
// that's because pthreads enforces that stacks are at least
// PTHREAD_STACK_MIN bytes big. Windows has no such lower limit, it's
@ -61,7 +64,7 @@ pub unsafe fn create(stack: uint, p: Thunk) -> io::Result<rust_thread> {
if ret as uint == 0 {
// be sure to not leak the closure
let _p: Box<Thunk> = mem::transmute(arg);
let _p: Box<Thunk> = Box::from_raw(raw_p);
Err(io::Error::last_os_error())
} else {
Ok(ret)

View File

@ -133,13 +133,13 @@ unsafe fn init_dtors() {
if !DTORS.is_null() { return }
let dtors = box Vec::<(Key, Dtor)>::new();
DTORS = mem::transmute(dtors);
DTORS = boxed::into_raw(dtors);
rt::at_exit(move|| {
DTOR_LOCK.lock();
let dtors = DTORS;
DTORS = ptr::null_mut();
mem::transmute::<_, Box<Vec<(Key, Dtor)>>>(dtors);
Boxed::from_raw(dtors);
assert!(DTORS.is_null()); // can't re-init after destructing
DTOR_LOCK.unlock();
});

View File

@ -330,6 +330,7 @@ impl<T: 'static> Key<T> {
mod imp {
use prelude::v1::*;
use alloc::boxed;
use cell::UnsafeCell;
use intrinsics;
use ptr;
@ -422,14 +423,14 @@ mod imp {
type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
if DTORS.get().is_null() {
let v: Box<List> = box Vec::new();
DTORS.set(mem::transmute(v));
DTORS.set(boxed::into_raw(v) as *mut u8);
}
let list: &mut List = &mut *(DTORS.get() as *mut List);
list.push((t, dtor));
unsafe extern fn run_dtors(mut ptr: *mut u8) {
while !ptr.is_null() {
let list: Box<List> = mem::transmute(ptr);
let list: Box<List> = Box::from_raw(ptr as *mut List);
for &(ptr, dtor) in &*list {
dtor(ptr);
}
@ -467,6 +468,7 @@ mod imp {
mod imp {
use prelude::v1::*;
use alloc::boxed;
use cell::UnsafeCell;
use mem;
use ptr;
@ -517,7 +519,7 @@ mod imp {
key: self,
value: mem::transmute_copy(&self.inner),
};
let ptr: *mut Value<T> = mem::transmute(ptr);
let ptr: *mut Value<T> = boxed::into_raw(ptr);
self.os.set(ptr as *mut u8);
Some(&mut (*ptr).value as *mut T)
}
@ -533,7 +535,7 @@ mod imp {
//
// Note that to prevent an infinite loop we reset it back to null right
// before we return from the destructor ourselves.
let ptr: Box<Value<T>> = mem::transmute(ptr);
let ptr: Box<Value<T>> = Box::from_raw(ptr as *mut Value<T>);
let key = ptr.key;
key.os.set(1 as *mut u8);
drop(ptr);