1
Fork 0

Use boxed functions instead of transmute

... to convert between Box and raw pointers. E. g. use

```
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 in practice.
This commit is contained in:
Stepan Koltsov 2015-02-23 02:58:22 +03:00
parent 554022e583
commit 26d9f0ab1a
15 changed files with 60 additions and 45 deletions

View file

@ -250,11 +250,12 @@ impl BoxAny for Box<Any> {
if self.is::<T>() { if self.is::<T>() {
unsafe { unsafe {
// Get the raw representation of the trait object // Get the raw representation of the trait object
let raw = into_raw(self);
let to: TraitObject = let to: TraitObject =
mem::transmute::<Box<Any>, TraitObject>(self); mem::transmute::<*mut Any, TraitObject>(raw);
// Extract the data pointer // Extract the data pointer
Ok(mem::transmute(to.data)) Ok(Box::from_raw(to.data as *mut T))
} }
} else { } else {
Err(self) Err(self)

View file

@ -144,6 +144,7 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
use boxed;
use core::cell::Cell; use core::cell::Cell;
use core::clone::Clone; use core::clone::Clone;
use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering}; use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
@ -151,7 +152,7 @@ use core::default::Default;
use core::fmt; use core::fmt;
use core::hash::{Hasher, Hash}; use core::hash::{Hasher, Hash};
use core::marker; 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::nonzero::NonZero;
use core::ops::{Deref, Drop}; use core::ops::{Deref, Drop};
use core::option::Option; 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 // 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 // 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. // 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, value: value,
strong: Cell::new(1), strong: Cell::new(1),
weak: 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]> { pub fn into_boxed_slice(mut self) -> Box<[T]> {
self.shrink_to_fit(); self.shrink_to_fit();
unsafe { unsafe {
let xs: Box<[T]> = mem::transmute(&mut *self); let xs: Box<[T]> = Box::from_raw(&mut *self);
mem::forget(self); mem::forget(self);
xs xs
} }

View file

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

View file

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

View file

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

View file

@ -60,6 +60,7 @@
use prelude::v1::*; use prelude::v1::*;
use any::Any; use any::Any;
use boxed;
use cell::Cell; use cell::Cell;
use cmp; use cmp;
use panicking; use panicking;
@ -173,7 +174,8 @@ fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
}, },
cause: Some(cause), 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) 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) { exception: *mut uw::_Unwind_Exception) {
rtdebug!("exception_cleanup()"); rtdebug!("exception_cleanup()");
unsafe { 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 core::prelude::*;
use alloc::boxed;
use alloc::boxed::Box; use alloc::boxed::Box;
use core::mem;
use core::ptr; use core::ptr;
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
@ -82,7 +82,7 @@ unsafe impl<T: Send> Sync for Queue<T> { }
impl<T> Node<T> { impl<T> Node<T> {
unsafe fn new(v: Option<T>) -> *mut 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()), next: AtomicPtr::new(ptr::null_mut()),
value: v, value: v,
}) })
@ -129,7 +129,7 @@ impl<T: Send> Queue<T> {
assert!((*tail).value.is_none()); assert!((*tail).value.is_none());
assert!((*next).value.is_some()); assert!((*next).value.is_some());
let ret = (*next).value.take().unwrap(); let ret = (*next).value.take().unwrap();
let _: Box<Node<T>> = mem::transmute(tail); let _: Box<Node<T>> = Box::from_raw(tail);
return Data(ret); return Data(ret);
} }
@ -146,7 +146,7 @@ impl<T: Send> Drop for Queue<T> {
let mut cur = *self.tail.get(); let mut cur = *self.tail.get();
while !cur.is_null() { while !cur.is_null() {
let next = (*cur).next.load(Ordering::Relaxed); let next = (*cur).next.load(Ordering::Relaxed);
let _: Box<Node<T>> = mem::transmute(cur); let _: Box<Node<T>> = Box::from_raw(cur);
cur = next; cur = next;
} }
} }

View file

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

View file

@ -22,8 +22,8 @@
use prelude::v1::*; use prelude::v1::*;
use boxed;
use cell::UnsafeCell; use cell::UnsafeCell;
use mem;
use ptr; use ptr;
use rt; use rt;
use sync::{StaticMutex, StaticCondvar}; use sync::{StaticMutex, StaticCondvar};
@ -88,7 +88,7 @@ impl<M: Send> Helper<M> {
let _guard = self.lock.lock().unwrap(); let _guard = self.lock.lock().unwrap();
if !*self.initialized.get() { if !*self.initialized.get() {
let (tx, rx) = channel(); 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(); let (receive, send) = helper_signal::new();
*self.signal.get() = send as uint; *self.signal.get() = send as uint;
@ -132,7 +132,7 @@ impl<M: Send> Helper<M> {
let mut guard = self.lock.lock().unwrap(); let mut guard = self.lock.lock().unwrap();
// Close the channel by destroying it // 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(); *self.chan.get() = ptr::null_mut();
drop(chan); drop(chan);
helper_signal::signal(*self.signal.get() as helper_signal::signal); 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 { unsafe {
stack::record_os_managed_stack_bounds(0, usize::MAX); stack::record_os_managed_stack_bounds(0, usize::MAX);
let handler = stack_overflow::Handler::new(); 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(()); f.invoke(());
drop(handler); drop(handler);
mem::transmute(0 as thread::rust_thread_return) mem::transmute(0 as thread::rust_thread_return)

View file

@ -11,6 +11,7 @@
use core::prelude::*; use core::prelude::*;
use io; use io;
use boxed;
use boxed::Box; use boxed::Box;
use cmp; use cmp;
use mem; 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); let ret = pthread_create(&mut native, &attr, thread_start, arg);
assert_eq!(pthread_attr_destroy(&mut attr), 0); assert_eq!(pthread_attr_destroy(&mut attr), 0);
if ret != 0 { if ret != 0 {
// be sure to not leak the closure // 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)) Err(io::Error::from_os_error(ret))
} else { } else {
Ok(native) Ok(native)

View file

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

View file

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

View file

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