Skip to content

Commit 91440ad

Browse files
committed
Rollup merge of rust-lang#30513 - alexcrichton:assert-is-safe, r=aturon
Types like `&AssertRecoverSafe<T>` and `Rc<AssertRecoverSafe<T>>` were mistakenly not considered recover safe, but the point of the assertion wrapper is that it indeed is! This was caused by an interaction between the `RecoverSafe` and `NoUnsafeCell` marker traits, and this is updated by adding an impl of the `NoUnsafeCell` marker trait for `AssertRecoverSafe` to ensure that it never interacts with the other negative impls of `RecoverSafe`. cc rust-lang#30510
2 parents 12f171b + cb3826d commit 91440ad

File tree

2 files changed

+24
-16
lines changed

2 files changed

+24
-16
lines changed

src/libstd/panic.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -101,16 +101,19 @@ pub use panicking::{take_handler, set_handler, PanicInfo, Location};
101101
across a recover boundary"]
102102
pub trait RecoverSafe {}
103103

104-
/// A marker trait representing types which do not contain an `UnsafeCell` by
105-
/// value internally.
104+
/// A marker trait representing types where a shared reference is considered
105+
/// recover safe.
106+
///
107+
/// This trait is namely not implemented by `UnsafeCell`, the root of all
108+
/// interior mutability.
106109
///
107110
/// This is a "helper marker trait" used to provide impl blocks for the
108111
/// `RecoverSafe` trait, for more information see that documentation.
109112
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
110113
#[rustc_on_unimplemented = "the type {Self} contains interior mutability \
111114
and a reference may not be safely transferrable \
112115
across a recover boundary"]
113-
pub trait NoUnsafeCell {}
116+
pub trait RefRecoverSafe {}
114117

115118
/// A simple wrapper around a type to assert that it is panic safe.
116119
///
@@ -159,27 +162,28 @@ pub struct AssertRecoverSafe<T>(T);
159162
// * Our custom AssertRecoverSafe wrapper is indeed recover safe
160163
impl RecoverSafe for .. {}
161164
impl<'a, T: ?Sized> !RecoverSafe for &'a mut T {}
162-
impl<'a, T: NoUnsafeCell + ?Sized> RecoverSafe for &'a T {}
163-
impl<T: NoUnsafeCell + ?Sized> RecoverSafe for *const T {}
164-
impl<T: NoUnsafeCell + ?Sized> RecoverSafe for *mut T {}
165+
impl<'a, T: RefRecoverSafe + ?Sized> RecoverSafe for &'a T {}
166+
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *const T {}
167+
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *mut T {}
165168
impl<T: RecoverSafe> RecoverSafe for Unique<T> {}
166-
impl<T: NoUnsafeCell + ?Sized> RecoverSafe for Shared<T> {}
169+
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Shared<T> {}
167170
impl<T: ?Sized> RecoverSafe for Mutex<T> {}
168171
impl<T: ?Sized> RecoverSafe for RwLock<T> {}
169172
impl<T> RecoverSafe for AssertRecoverSafe<T> {}
170173

171174
// not covered via the Shared impl above b/c the inner contents use
172175
// Cell/AtomicUsize, but the usage here is recover safe so we can lift the
173176
// impl up one level to Arc/Rc itself
174-
impl<T: NoUnsafeCell + ?Sized> RecoverSafe for Rc<T> {}
175-
impl<T: NoUnsafeCell + ?Sized> RecoverSafe for Arc<T> {}
177+
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Rc<T> {}
178+
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Arc<T> {}
176179

177-
// Pretty simple implementations for the `NoUnsafeCell` marker trait, basically
178-
// just saying that this is a marker trait and `UnsafeCell` is the only thing
179-
// which doesn't implement it (which then transitively applies to everything
180-
// else.
181-
impl NoUnsafeCell for .. {}
182-
impl<T: ?Sized> !NoUnsafeCell for UnsafeCell<T> {}
180+
// Pretty simple implementations for the `RefRecoverSafe` marker trait,
181+
// basically just saying that this is a marker trait and `UnsafeCell` is the
182+
// only thing which doesn't implement it (which then transitively applies to
183+
// everything else.
184+
impl RefRecoverSafe for .. {}
185+
impl<T: ?Sized> !RefRecoverSafe for UnsafeCell<T> {}
186+
impl<T> RefRecoverSafe for AssertRecoverSafe<T> {}
183187

184188
impl<T> AssertRecoverSafe<T> {
185189
/// Creates a new `AssertRecoverSafe` wrapper around the provided type.

src/test/run-pass/panic-safe.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#![allow(dead_code)]
1212
#![feature(recover)]
1313

14-
use std::panic::RecoverSafe;
14+
use std::panic::{RecoverSafe, AssertRecoverSafe};
1515
use std::cell::RefCell;
1616
use std::sync::{Mutex, RwLock, Arc};
1717
use std::rc::Rc;
@@ -47,5 +47,9 @@ fn main() {
4747
assert::<Box<T>>();
4848
assert::<Vec<T>>();
4949
assert::<RefCell<T>>();
50+
assert::<AssertRecoverSafe<T>>();
51+
assert::<&AssertRecoverSafe<T>>();
52+
assert::<Rc<AssertRecoverSafe<T>>>();
53+
assert::<Arc<AssertRecoverSafe<T>>>();
5054
}
5155
}

0 commit comments

Comments
 (0)