Skip to content

Commit cb3826d

Browse files
committed
std: Ensure AssertRecoverSafe indeed is more often
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 #30510
1 parent e2834a2 commit cb3826d

File tree

2 files changed

+24
-16
lines changed

2 files changed

+24
-16
lines changed

src/libstd/panic.rs

+19-15
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,19 @@ use thread::Result;
9999
across a recover boundary"]
100100
pub trait RecoverSafe {}
101101

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

113116
/// A simple wrapper around a type to assert that it is panic safe.
114117
///
@@ -157,27 +160,28 @@ pub struct AssertRecoverSafe<T>(T);
157160
// * Our custom AssertRecoverSafe wrapper is indeed recover safe
158161
impl RecoverSafe for .. {}
159162
impl<'a, T: ?Sized> !RecoverSafe for &'a mut T {}
160-
impl<'a, T: NoUnsafeCell + ?Sized> RecoverSafe for &'a T {}
161-
impl<T: NoUnsafeCell + ?Sized> RecoverSafe for *const T {}
162-
impl<T: NoUnsafeCell + ?Sized> RecoverSafe for *mut T {}
163+
impl<'a, T: RefRecoverSafe + ?Sized> RecoverSafe for &'a T {}
164+
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *const T {}
165+
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *mut T {}
163166
impl<T: RecoverSafe> RecoverSafe for Unique<T> {}
164-
impl<T: NoUnsafeCell + ?Sized> RecoverSafe for Shared<T> {}
167+
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Shared<T> {}
165168
impl<T: ?Sized> RecoverSafe for Mutex<T> {}
166169
impl<T: ?Sized> RecoverSafe for RwLock<T> {}
167170
impl<T> RecoverSafe for AssertRecoverSafe<T> {}
168171

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

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

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

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

+5-1
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)