about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-01-07 01:26:45 +0000
committerbors <bors@rust-lang.org>2016-01-07 01:26:45 +0000
commit3ed6e9e6f0213bec36b92fd8e8aa71f954fef99e (patch)
tree5c71bd2a5d3697048cac6802e82a420a07f4430a
parent43403b416907e6b965c37daa53d071e1c054a302 (diff)
parent022c9c70c48581b8caa17895b447a941a9750076 (diff)
downloadrust-3ed6e9e6f0213bec36b92fd8e8aa71f954fef99e.tar.gz
rust-3ed6e9e6f0213bec36b92fd8e8aa71f954fef99e.zip
Auto merge of #30557 - sfackler:panic-propagate, r=aturon
See rust-lang/rfcs#1413.

r? @alexcrichton
-rw-r--r--src/libstd/panic.rs27
-rw-r--r--src/libstd/sys/common/unwind/mod.rs2
-rw-r--r--src/test/run-pass/panic-recover-propagate.rs35
3 files changed, 63 insertions, 1 deletions
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index 76d9c194b45..8c0a785a102 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -13,6 +13,8 @@
 #![unstable(feature = "std_panic", reason = "awaiting feedback",
             issue = "27719")]
 
+use any::Any;
+use boxed::Box;
 use cell::UnsafeCell;
 use ops::{Deref, DerefMut};
 use ptr::{Unique, Shared};
@@ -259,3 +261,28 @@ pub fn recover<F: FnOnce() -> R + RecoverSafe, R>(f: F) -> Result<R> {
     }
     Ok(result.unwrap())
 }
+
+/// Triggers a panic without invoking the panic handler.
+///
+/// This is designed to be used in conjunction with `recover` to, for example,
+/// carry a panic across a layer of C code.
+///
+/// # Examples
+///
+/// ```should_panic
+/// #![feature(std_panic, recover, panic_propagate)]
+///
+/// use std::panic;
+///
+/// let result = panic::recover(|| {
+///     panic!("oh no!");
+/// });
+///
+/// if let Err(err) = result {
+///     panic::propagate(err);
+/// }
+/// ```
+#[unstable(feature = "panic_propagate", reason = "awaiting feedback", issue = "30752")]
+pub fn propagate(payload: Box<Any + Send>) -> ! {
+    unwind::rust_panic(payload)
+}
diff --git a/src/libstd/sys/common/unwind/mod.rs b/src/libstd/sys/common/unwind/mod.rs
index 0f10e727461..666b2ed72ad 100644
--- a/src/libstd/sys/common/unwind/mod.rs
+++ b/src/libstd/sys/common/unwind/mod.rs
@@ -172,7 +172,7 @@ pub fn panicking() -> bool {
 #[inline(never)]
 #[no_mangle]
 #[allow(private_no_mangle_fns)]
-fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
+pub fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
     unsafe {
         imp::panic(cause)
     }
diff --git a/src/test/run-pass/panic-recover-propagate.rs b/src/test/run-pass/panic-recover-propagate.rs
new file mode 100644
index 00000000000..c0b2f25d99c
--- /dev/null
+++ b/src/test/run-pass/panic-recover-propagate.rs
@@ -0,0 +1,35 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(std_panic, recover, panic_propagate, panic_handler, const_fn)]
+
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::panic;
+use std::thread;
+
+static A: AtomicUsize = AtomicUsize::new(0);
+
+fn main() {
+    panic::set_handler(|_| {
+        A.fetch_add(1, Ordering::SeqCst);
+    });
+
+    let result = thread::spawn(|| {
+        let result = panic::recover(|| {
+            panic!("hi there");
+        });
+
+        panic::propagate(result.err().unwrap());
+    }).join();
+
+    let msg = *result.err().unwrap().downcast::<&'static str>().unwrap();
+    assert_eq!("hi there", msg);
+    assert_eq!(1, A.load(Ordering::SeqCst));
+}