about summary refs log tree commit diff
path: root/src/libstd/panic.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/panic.rs')
-rw-r--r--src/libstd/panic.rs222
1 files changed, 156 insertions, 66 deletions
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index 4462ce24dce..16401c4527f 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -10,8 +10,7 @@
 
 //! Panic support in the standard library
 
-#![unstable(feature = "std_panic", reason = "awaiting feedback",
-            issue = "27719")]
+#![stable(feature = "std_panic", since = "1.9.0")]
 
 use any::Any;
 use boxed::Box;
@@ -23,6 +22,7 @@ use sync::{Arc, Mutex, RwLock};
 use sys_common::unwind;
 use thread::Result;
 
+#[unstable(feature = "panic_handler", issue = "30449")]
 pub use panicking::{take_hook, set_hook, PanicInfo, Location};
 
 ///
@@ -92,7 +92,7 @@ pub fn take_handler() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
 /// "speed bump" to alert users of `recover` that broken invariants may be
 /// witnessed and may need to be accounted for.
 ///
-/// ## Who implements `RecoverSafe`?
+/// ## Who implements `UnwindSafe`?
 ///
 /// Types such as `&mut T` and `&RefCell<T>` are examples which are **not**
 /// recover safe. The general idea is that any mutable state which can be shared
@@ -104,7 +104,7 @@ pub fn take_handler() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
 /// poisoning by default. They still allow witnessing a broken invariant, but
 /// they already provide their own "speed bumps" to do so.
 ///
-/// ## When should `RecoverSafe` be used?
+/// ## When should `UnwindSafe` be used?
 ///
 /// Is not intended that most types or functions need to worry about this trait.
 /// It is only used as a bound on the `recover` function and as mentioned above,
@@ -112,10 +112,18 @@ pub fn take_handler() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
 /// wrapper struct in this module can be used to force this trait to be
 /// implemented for any closed over variables passed to the `recover` function
 /// (more on this below).
-#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
+#[stable(feature = "catch_unwind", since = "1.9.0")]
 #[rustc_on_unimplemented = "the type {Self} may not be safely transferred \
                             across a recover boundary"]
+pub trait UnwindSafe {}
+
+/// Deprecated, renamed to UnwindSafe
+#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
+#[rustc_deprecated(reason = "renamed to `UnwindSafe`", since = "1.9.0")]
 pub trait RecoverSafe {}
+#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
+#[allow(deprecated)]
+impl<T: UnwindSafe> RecoverSafe for T {}
 
 /// A marker trait representing types where a shared reference is considered
 /// recover safe.
@@ -124,12 +132,12 @@ pub trait RecoverSafe {}
 /// interior mutability.
 ///
 /// This is a "helper marker trait" used to provide impl blocks for the
-/// `RecoverSafe` trait, for more information see that documentation.
-#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
+/// `UnwindSafe` trait, for more information see that documentation.
+#[stable(feature = "catch_unwind", since = "1.9.0")]
 #[rustc_on_unimplemented = "the type {Self} contains interior mutability \
                             and a reference may not be safely transferrable \
                             across a recover boundary"]
-pub trait RefRecoverSafe {}
+pub trait RefUnwindSafe {}
 
 /// A simple wrapper around a type to assert that it is panic safe.
 ///
@@ -143,90 +151,141 @@ pub trait RefRecoverSafe {}
 ///
 /// # Examples
 ///
-/// One way to use `AssertRecoverSafe` is to assert that the entire closure
+/// One way to use `AssertUnwindSafe` is to assert that the entire closure
 /// itself is recover safe, bypassing all checks for all variables:
 ///
 /// ```
-/// #![feature(recover, std_panic)]
-///
-/// use std::panic::{self, AssertRecoverSafe};
+/// use std::panic::{self, AssertUnwindSafe};
 ///
 /// let mut variable = 4;
 ///
 /// // This code will not compile because the closure captures `&mut variable`
 /// // which is not considered panic safe by default.
 ///
-/// // panic::recover(|| {
+/// // panic::catch_unwind(|| {
 /// //     variable += 3;
 /// // });
 ///
-/// // This, however, will compile due to the `AssertRecoverSafe` wrapper
-/// let result = panic::recover(AssertRecoverSafe(|| {
+/// // This, however, will compile due to the `AssertUnwindSafe` wrapper
+/// let result = panic::catch_unwind(AssertUnwindSafe(|| {
 ///     variable += 3;
 /// }));
 /// // ...
 /// ```
 ///
 /// Wrapping the entire closure amounts to a blanket assertion that all captured
-/// variables are recover safe. This has the downside that if new captures are
-/// added in the future, they will also be considered recover safe. Therefore,
+/// variables are unwind safe. This has the downside that if new captures are
+/// added in the future, they will also be considered unwind safe. Therefore,
 /// you may prefer to just wrap individual captures, as shown below. This is
 /// more annotation, but it ensures that if a new capture is added which is not
-/// recover safe, you will get a compilation error at that time, which will
+/// unwind safe, you will get a compilation error at that time, which will
 /// allow you to consider whether that new capture in fact represent a bug or
 /// not.
 ///
 /// ```
-/// #![feature(recover, std_panic)]
-///
-/// use std::panic::{self, AssertRecoverSafe};
+/// use std::panic::{self, AssertUnwindSafe};
 ///
 /// let mut variable = 4;
 /// let other_capture = 3;
 ///
 /// let result = {
-///     let mut wrapper = AssertRecoverSafe(&mut variable);
-///     panic::recover(move || {
+///     let mut wrapper = AssertUnwindSafe(&mut variable);
+///     panic::catch_unwind(move || {
 ///         **wrapper += other_capture;
 ///     })
 /// };
 /// // ...
 /// ```
-#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+pub struct AssertUnwindSafe<T>(
+    #[stable(feature = "catch_unwind", since = "1.9.0")]
+    pub T
+);
+
+/// Deprecated, renamed to `AssertUnwindSafe`
+#[unstable(feature = "recover", issue = "27719")]
+#[rustc_deprecated(reason = "renamed to `AssertUnwindSafe`", since = "1.9.0")]
 pub struct AssertRecoverSafe<T>(pub T);
 
-// Implementations of the `RecoverSafe` trait:
+// Implementations of the `UnwindSafe` trait:
 //
-// * By default everything is recover safe
-// * pointers T contains mutability of some form are not recover safe
+// * By default everything is unwind safe
+// * pointers T contains mutability of some form are not unwind safe
 // * Unique, an owning pointer, lifts an implementation
-// * Types like Mutex/RwLock which are explicilty poisoned are recover safe
-// * Our custom AssertRecoverSafe wrapper is indeed recover safe
-impl RecoverSafe for .. {}
-impl<'a, T: ?Sized> !RecoverSafe for &'a mut T {}
-impl<'a, T: RefRecoverSafe + ?Sized> RecoverSafe for &'a T {}
-impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *const T {}
-impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *mut T {}
-impl<T: RecoverSafe> RecoverSafe for Unique<T> {}
-impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Shared<T> {}
-impl<T: ?Sized> RecoverSafe for Mutex<T> {}
-impl<T: ?Sized> RecoverSafe for RwLock<T> {}
-impl<T> RecoverSafe for AssertRecoverSafe<T> {}
+// * Types like Mutex/RwLock which are explicilty poisoned are unwind safe
+// * Our custom AssertUnwindSafe wrapper is indeed unwind safe
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl UnwindSafe for .. {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<'a, T: ?Sized> !UnwindSafe for &'a mut T {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<'a, T: RefUnwindSafe + ?Sized> UnwindSafe for &'a T {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *const T {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<T: UnwindSafe> UnwindSafe for Unique<T> {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Shared<T> {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<T: ?Sized> UnwindSafe for Mutex<T> {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<T: ?Sized> UnwindSafe for RwLock<T> {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<T> UnwindSafe for AssertUnwindSafe<T> {}
+#[unstable(feature = "recover", issue = "27719")]
+#[allow(deprecated)]
+impl<T> UnwindSafe for AssertRecoverSafe<T> {}
 
 // not covered via the Shared impl above b/c the inner contents use
 // Cell/AtomicUsize, but the usage here is recover safe so we can lift the
 // impl up one level to Arc/Rc itself
-impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Rc<T> {}
-impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Arc<T> {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Rc<T> {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Arc<T> {}
 
 // Pretty simple implementations for the `RefRecoverSafe` marker trait,
 // basically just saying that this is a marker trait and `UnsafeCell` is the
 // only thing which doesn't implement it (which then transitively applies to
 // everything else).
-impl RefRecoverSafe for .. {}
-impl<T: ?Sized> !RefRecoverSafe for UnsafeCell<T> {}
-impl<T> RefRecoverSafe for AssertRecoverSafe<T> {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl RefUnwindSafe for .. {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<T: ?Sized> !RefUnwindSafe for UnsafeCell<T> {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<T> RefUnwindSafe for AssertUnwindSafe<T> {}
+#[unstable(feature = "recover", issue = "27719")]
+#[allow(deprecated)]
+impl<T> RefUnwindSafe for AssertRecoverSafe<T> {}
+
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<T> Deref for AssertUnwindSafe<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<T> DerefMut for AssertUnwindSafe<T> {
+    fn deref_mut(&mut self) -> &mut T {
+        &mut self.0
+    }
+}
 
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl<R, F: FnOnce() -> R> FnOnce<()> for AssertUnwindSafe<F> {
+    type Output = R;
+
+    extern "rust-call" fn call_once(self, _args: ()) -> R {
+        (self.0)()
+    }
+}
+
+#[allow(deprecated)]
 impl<T> AssertRecoverSafe<T> {
     /// Creates a new `AssertRecoverSafe` wrapper around the provided type.
     #[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
@@ -245,6 +304,8 @@ impl<T> AssertRecoverSafe<T> {
     }
 }
 
+#[unstable(feature = "recover", issue = "27719")]
+#[allow(deprecated)]
 impl<T> Deref for AssertRecoverSafe<T> {
     type Target = T;
 
@@ -253,12 +314,16 @@ impl<T> Deref for AssertRecoverSafe<T> {
     }
 }
 
+#[unstable(feature = "recover", issue = "27719")]
+#[allow(deprecated)]
 impl<T> DerefMut for AssertRecoverSafe<T> {
     fn deref_mut(&mut self) -> &mut T {
         &mut self.0
     }
 }
 
+#[unstable(feature = "recover", issue = "27719")]
+#[allow(deprecated)]
 impl<R, F: FnOnce() -> R> FnOnce<()> for AssertRecoverSafe<F> {
     type Output = R;
 
@@ -267,7 +332,7 @@ impl<R, F: FnOnce() -> R> FnOnce<()> for AssertRecoverSafe<F> {
     }
 }
 
-/// Invokes a closure, capturing the cause of panic if one occurs.
+/// Invokes a closure, capturing the cause of an unwinding panic if one occurs.
 ///
 /// This function will return `Ok` with the closure's result if the closure
 /// does not panic, and will return `Err(cause)` if the closure panics. The
@@ -280,38 +345,44 @@ impl<R, F: FnOnce() -> R> FnOnce<()> for AssertRecoverSafe<F> {
 ///
 /// It is **not** recommended to use this function for a general try/catch
 /// mechanism. The `Result` type is more appropriate to use for functions that
-/// can fail on a regular basis.
-///
-/// The closure provided is required to adhere to the `RecoverSafe` to ensure
-/// that all captured variables are safe to cross this recover boundary. The
-/// purpose of this bound is to encode the concept of [exception safety][rfc] in
-/// the type system. Most usage of this function should not need to worry about
-/// this bound as programs are naturally panic safe without `unsafe` code. If it
-/// becomes a problem the associated `AssertRecoverSafe` wrapper type in this
+/// can fail on a regular basis. Additionally, this function is not guaranteed
+/// to catch all panics, see the "Notes" sectino below.
+///
+/// The closure provided is required to adhere to the `UnwindSafe` to ensure
+/// that all captured variables are safe to cross this boundary. The purpose of
+/// this bound is to encode the concept of [exception safety][rfc] in the type
+/// system. Most usage of this function should not need to worry about this
+/// bound as programs are naturally panic safe without `unsafe` code. If it
+/// becomes a problem the associated `AssertUnwindSafe` wrapper type in this
 /// module can be used to quickly assert that the usage here is indeed exception
 /// safe.
 ///
 /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
 ///
+/// # Notes
+///
+/// Note that this function **may not catch all panics** in Rust. A panic in
+/// Rust is not always implemented via unwinding, but can be implemented by
+/// aborting the process as well. This function *only* catches unwinding panics,
+/// not those that abort the process.
+///
 /// # Examples
 ///
 /// ```
-/// #![feature(recover, std_panic)]
-///
 /// use std::panic;
 ///
-/// let result = panic::recover(|| {
+/// let result = panic::catch_unwind(|| {
 ///     println!("hello!");
 /// });
 /// assert!(result.is_ok());
 ///
-/// let result = panic::recover(|| {
+/// let result = panic::catch_unwind(|| {
 ///     panic!("oh no!");
 /// });
 /// assert!(result.is_err());
 /// ```
-#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
-pub fn recover<F: FnOnce() -> R + RecoverSafe, R>(f: F) -> Result<R> {
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
     let mut result = None;
     unsafe {
         let result = &mut result;
@@ -320,27 +391,46 @@ pub fn recover<F: FnOnce() -> R + RecoverSafe, R>(f: F) -> Result<R> {
     Ok(result.unwrap())
 }
 
+/// Deprecated, renamed to `catch_unwind`
+#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
+#[rustc_deprecated(reason = "renamed to `catch_unwind`", since = "1.9.0")]
+pub fn recover<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
+    catch_unwind(f)
+}
+
 /// 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.
+/// This is designed to be used in conjunction with `catch_unwind` to, for
+/// example, carry a panic across a layer of C code.
+///
+/// # Notes
+///
+/// Note that panics in Rust are not always implemented via unwinding, but they
+/// may be implemented by aborting the process. If this function is called when
+/// panics are implemented this way then this function will abort the process,
+/// not trigger an unwind.
 ///
 /// # Examples
 ///
 /// ```should_panic
-/// #![feature(std_panic, recover, panic_propagate)]
-///
 /// use std::panic;
 ///
-/// let result = panic::recover(|| {
+/// let result = panic::catch_unwind(|| {
 ///     panic!("oh no!");
 /// });
 ///
 /// if let Err(err) = result {
-///     panic::propagate(err);
+///     panic::resume_unwind(err);
 /// }
 /// ```
+#[stable(feature = "resume_unwind", since = "1.9.0")]
+pub fn resume_unwind(payload: Box<Any + Send>) -> ! {
+    unwind::rust_panic(payload)
+}
+
+/// Deprecated, use resume_unwind instead
 #[unstable(feature = "panic_propagate", reason = "awaiting feedback", issue = "30752")]
+#[rustc_deprecated(reason = "renamed to `resume_unwind`", since = "1.9.0")]
 pub fn propagate(payload: Box<Any + Send>) -> ! {
-    unwind::rust_panic(payload)
+    resume_unwind(payload)
 }