]> git.lizzy.rs Git - rust.git/blobdiff - src/libstd/panic.rs
Auto merge of #30917 - arthurprs:bs_bounds_check, r=alexcrichton
[rust.git] / src / libstd / panic.rs
index 1550d55d177a27051f0bf89892a8fa8e0df221f0..3677bd27b16194f90fe6b37f8439c9735331647b 100644 (file)
@@ -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};
 ///    panics.
 /// 2. This broken invariant is then later observed.
 ///
-/// Typically in Rust it is difficult to perform step (2) because catching a
+/// Typically in Rust, it is difficult to perform step (2) because catching a
 /// panic involves either spawning a thread (which in turns makes it difficult
 /// to later witness broken invariants) or using the `recover` function in this
-/// module. Additionally, even if an invariant is witness, it typically isn't a
+/// module. Additionally, even if an invariant is witnessed, it typically isn't a
 /// problem in Rust because there's no uninitialized values (like in C or C++).
 ///
 /// It is possible, however, for **logical** invariants to be broken in Rust,
 /// which can end up causing behavioral bugs. Another key aspect of panic safety
-/// in Rust is that in the absence of `unsafe` code, a panic cannot lead to
+/// in Rust is that, in the absence of `unsafe` code, a panic cannot lead to
 /// memory unsafety.
 ///
 /// That was a bit of a whirlwind tour of panic safety, but for more information
 /// ## What is `RecoverSafe`?
 ///
 /// Now that we've got an idea of what panic safety is in Rust, it's also
-/// important to understand that this trait represents. As mentioned above, one
+/// important to understand what this trait represents. As mentioned above, one
 /// way to witness broken invariants is through the `recover` function in this
 /// module as it allows catching a panic and then re-using the environment of
 /// the closure.
 ///
-/// Simply but, a type `T` implements `RecoverSafe` if it cannot easily allow
+/// Simply put, a type `T` implements `RecoverSafe` if it cannot easily allow
 /// witnessing a broken invariant through the use of `recover` (catching a
 /// panic). This trait is a marker trait, so it is automatically implemented for
 /// many types, and it is also structurally composed (e.g. a struct is recover
                             across a recover boundary"]
 pub trait RecoverSafe {}
 
-/// A marker trait representing types which do not contain an `UnsafeCell` by
-/// value internally.
+/// A marker trait representing types where a shared reference is considered
+/// recover safe.
+///
+/// This trait is namely not implemented by `UnsafeCell`, the root of all
+/// interior mutability.
 ///
 /// This is a "helper marker trait" used to provide impl blocks for the
 /// `RecoverSafe` trait, for more information see that documentation.
@@ -110,7 +115,7 @@ pub trait RecoverSafe {}
 #[rustc_on_unimplemented = "the type {Self} contains interior mutability \
                             and a reference may not be safely transferrable \
                             across a recover boundary"]
-pub trait NoUnsafeCell {}
+pub trait RefRecoverSafe {}
 
 /// A simple wrapper around a type to assert that it is panic safe.
 ///
@@ -131,7 +136,7 @@ pub trait NoUnsafeCell {}
 ///
 /// let mut variable = 4;
 ///
-/// // This code will not compile becuause the closure captures `&mut variable`
+/// // This code will not compile because the closure captures `&mut variable`
 /// // which is not considered panic safe by default.
 ///
 /// // panic::recover(|| {
@@ -159,11 +164,11 @@ pub trait NoUnsafeCell {}
 // * Our custom AssertRecoverSafe wrapper is indeed recover safe
 impl RecoverSafe for .. {}
 impl<'a, T: ?Sized> !RecoverSafe for &'a mut T {}
-impl<'a, T: NoUnsafeCell + ?Sized> RecoverSafe for &'a T {}
-impl<T: NoUnsafeCell + ?Sized> RecoverSafe for *const T {}
-impl<T: NoUnsafeCell + ?Sized> RecoverSafe for *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: NoUnsafeCell + ?Sized> RecoverSafe for Shared<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> {}
@@ -171,15 +176,16 @@ impl<T> RecoverSafe 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: NoUnsafeCell + ?Sized> RecoverSafe for Rc<T> {}
-impl<T: NoUnsafeCell + ?Sized> RecoverSafe for Arc<T> {}
+impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Rc<T> {}
+impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Arc<T> {}
 
-// Pretty simple implementations for the `NoUnsafeCell` 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 NoUnsafeCell for .. {}
-impl<T: ?Sized> !NoUnsafeCell for UnsafeCell<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> {}
 
 impl<T> AssertRecoverSafe<T> {
     /// Creates a new `AssertRecoverSafe` wrapper around the provided type.
@@ -255,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)
+}