]> git.lizzy.rs Git - rust.git/commitdiff
Avoid .take().unwrap() with FnOnce closures
authorAlex Crichton <alex@alexcrichton.com>
Wed, 10 Dec 2014 15:49:45 +0000 (07:49 -0800)
committerAaron Turon <aturon@mozilla.com>
Fri, 19 Dec 2014 07:31:52 +0000 (23:31 -0800)
src/libstd/lib.rs
src/libstd/rt/unwind.rs
src/libstd/sys/common/thread_info.rs
src/libstd/thread.rs
src/libstd/thread_local/mod.rs
src/libstd/thread_local/scoped.rs
src/rt/rust_try.ll

index 7219fef3732ea14c0b643df1822b6e0508788cbf..5796f8946611a952dedc5e629a908dfc40ce9ada 100644 (file)
 #![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.
index 1beab8be90965a3b4145d5ccafa05151442eb0c5..c896f4e39daef74f0070fb5b4e4a206afc0ca0b2 100644 (file)
 //!
 //! 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;
@@ -119,10 +114,9 @@ struct Exception {
 ///   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 {
@@ -133,14 +127,9 @@ pub unsafe fn try(f: ||) -> ::core::result::Result<(), Box<Any + Send>> {
         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")]
@@ -152,8 +141,7 @@ pub unsafe fn try(f: ||) -> ::core::result::Result<(), Box<Any + Send>> {
         // 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;
     }
 }
index 0612448cfa01ae43a276c0b1bef56411045b639e..206d443d2943bea90bca74d6bdf85917d2ced698 100644 (file)
@@ -60,12 +60,11 @@ pub fn set_unwinding(unwinding: bool) {
 
 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,
     }));
 }
 
index f179219884f8becc14ad04f3cf8bb3897728182a..7ccfe0ab74b46ca6ca11a1d584924a8a626d83c6 100644 (file)
@@ -243,17 +243,20 @@ fn core_spawn<T: Send>(self, f: proc():Send -> T, after: proc(Result<T>):Send)
             // 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)),
index e2cedae1be6374e0d9a09eb1b85d7f2f488f9fb7..4c052a4ce09f6a0560a2cf6967e134418af97236 100644 (file)
@@ -217,9 +217,8 @@ impl<T: 'static> Key<T> {
     /// 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 \
index 7762d225b9a046cb3ad2e9f3075eda11082963f2..96f09190c2fe4c00bbe2f969fca85cbcc83e7349 100644 (file)
@@ -262,4 +262,3 @@ fn cell_allowed() {
         });
     }
 }
-
index 18b23b4143a58430a02dfac512a7f10e7c986a77..226dc55cb8d5af5b4f8ed604290eb8bd572a0c1e 100644 (file)
@@ -14,9 +14,9 @@
 
 ; 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
 
@@ -30,9 +30,9 @@ 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