#![allow(unknown_features)]
#![feature(macro_rules, globs, linkage, thread_local, asm)]
#![feature(default_type_params, phase, lang_items, unsafe_destructor)]
-#![feature(import_shadowing, slicing_syntax)]
+#![feature(import_shadowing, slicing_syntax, tuple_indexing)]
#![feature(unboxed_closures)]
// Don't link to std. We are std.
//!
//! Currently Rust uses unwind runtime provided by libgcc.
-use core::prelude::*;
+use prelude::*;
use any::Any;
-use boxed::Box;
use cmp;
use failure;
use fmt;
use intrinsics;
use libc::c_void;
use mem;
-use raw::Closure;
-use str::StrAllocating;
-use string::String;
use sync::atomic;
use sync::{Once, ONCE_INIT};
-use vec::Vec;
use sys_common::thread_info;
use rt::libunwind as uw;
/// guaranteed that a rust task is in place when invoking this function.
/// Unwinding twice can lead to resource leaks where some destructors are not
/// run.
-pub unsafe fn try(f: ||) -> ::core::result::Result<(), Box<Any + Send>> {
- let closure: Closure = mem::transmute(f);
- let ep = rust_try(try_fn, closure.code as *mut c_void,
- closure.env as *mut c_void);
+pub unsafe fn try<F: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> {
+ let mut f = Some(f);
+ let ep = rust_try(try_fn::<F>, &mut f as *mut _ as *mut c_void);
return if ep.is_null() {
Ok(())
} else {
Err(cause.unwrap())
};
- extern fn try_fn(code: *mut c_void, env: *mut c_void) {
- unsafe {
- let closure: || = mem::transmute(Closure {
- code: code as *mut (),
- env: env as *mut (),
- });
- closure();
- }
+ extern fn try_fn<F: FnOnce()>(opt_closure: *mut c_void) {
+ let opt_closure = opt_closure as *mut Option<F>;
+ unsafe { (*opt_closure).take().unwrap()(); }
}
#[link(name = "rustrt_native", kind = "static")]
// When f(...) returns normally, the return value is null.
// When f(...) throws, the return value is a pointer to the caught
// exception object.
- fn rust_try(f: extern "C" fn(*mut c_void, *mut c_void),
- code: *mut c_void,
+ fn rust_try(f: extern fn(*mut c_void),
data: *mut c_void) -> *mut uw::_Unwind_Exception;
}
}
pub fn set(stack_bounds: (uint, uint), stack_guard: uint, thread: Thread) {
THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
- let mut thread_opt = Some(thread); // option dance
- THREAD_INFO.with(|c| *c.borrow_mut() = Some(ThreadInfo{
+ THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
stack_bounds: stack_bounds,
stack_guard: stack_guard,
unwinding: false,
- thread: thread_opt.take().unwrap(),
+ thread: thread,
}));
}
// the thread itself. For these reasons, this unsafety should be ok.
unsafe {
let mut output = None;
- let mut f_opt = Some( // option dance
- if stdout.is_some() || stderr.is_some() {
- proc() {
- let _ = stdout.map(stdio::set_stdout);
- let _ = stderr.map(stdio::set_stderr);
- f()
- }
- } else {
- f
- });
- let try_result = unwind::try(|| output = Some((f_opt.take().unwrap())()));
+ let f = if stdout.is_some() || stderr.is_some() {
+ proc() {
+ let _ = stdout.map(stdio::set_stdout);
+ let _ = stderr.map(stdio::set_stderr);
+ f()
+ }
+ } else {
+ f
+ };
+
+ let try_result = {
+ let ptr = &mut output;
+ unwind::try(move || *ptr = Some(f()))
+ };
match (output, try_result) {
(Some(data), Ok(_)) => after(Ok(data)),
(None, Err(cause)) => after(Err(cause)),
/// This function will `panic!()` if the key currently has its
/// destructor running, and it **may** panic if the destructor has
/// previously been run for this thread.
- pub fn with<R, F>(&'static self, f: F) -> R where
- F: FnOnce(&T) -> R,
- {
+ pub fn with<F, R>(&'static self, f: F) -> R
+ where F: FnOnce(&T) -> R {
let slot = (self.inner)();
unsafe {
let slot = slot.get().expect("cannot access a TLS value during or \
; See also: libstd/rt/unwind.rs
-define i8* @rust_try(void (i8*,i8*)* %f, i8* %fptr, i8* %env) {
+define i8* @rust_try(void (i8*)* %f, i8* %env) {
- %1 = invoke i8* @rust_try_inner(void (i8*,i8*)* %f, i8* %fptr, i8* %env)
+ %1 = invoke i8* @rust_try_inner(void (i8*)* %f, i8* %env)
to label %normal
unwind label %catch
ret i8* null
}
-define internal i8* @rust_try_inner(void (i8*,i8*)* %f, i8* %fptr, i8* %env) {
+define internal i8* @rust_try_inner(void (i8*)* %f, i8* %env) {
- invoke void %f(i8* %fptr, i8* %env)
+ invoke void %f(i8* %env)
to label %normal
unwind label %catch