Skip to content

Commit

Permalink
Rollup merge of #95256 - thomcc:fix-unwind-safe, r=m-ou-se
Browse files Browse the repository at this point in the history
Ensure io::Error's bitpacked repr doesn't accidentally impl UnwindSafe

Sadly, I'm not sure how to easily test that we don't impl a trait, though (or can libstd use `where io::Error: !UnwindSafe` or something).

Fixes #95203
  • Loading branch information
Dylan-DPC authored Mar 29, 2022
2 parents bba2a64 + 3ac93ab commit 3208ed7
Showing 1 changed file with 15 additions and 5 deletions.
20 changes: 15 additions & 5 deletions library/std/src/io/error/repr_bitpacked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@

use super::{Custom, ErrorData, ErrorKind, SimpleMessage};
use alloc::boxed::Box;
use core::marker::PhantomData;
use core::mem::{align_of, size_of};
use core::ptr::NonNull;

Expand All @@ -114,8 +115,17 @@ const TAG_CUSTOM: usize = 0b01;
const TAG_OS: usize = 0b10;
const TAG_SIMPLE: usize = 0b11;

/// The internal representation.
///
/// See the module docs for more, this is just a way to hack in a check that we
/// indeed are not unwind-safe.
///
/// ```compile_fail,E0277
/// fn is_unwind_safe<T: core::panic::UnwindSafe>() {}
/// is_unwind_safe::<std::io::Error>();
/// ```
#[repr(transparent)]
pub(super) struct Repr(NonNull<()>);
pub(super) struct Repr(NonNull<()>, PhantomData<ErrorData<Box<Custom>>>);

// All the types `Repr` stores internally are Send + Sync, and so is it.
unsafe impl Send for Repr {}
Expand Down Expand Up @@ -145,7 +155,7 @@ impl Repr {
// box, and `TAG_CUSTOM` just... isn't zero -- it's `0b01`). Therefore,
// `TAG_CUSTOM + p` isn't zero and so `tagged` can't be, and the
// `new_unchecked` is safe.
let res = Self(unsafe { NonNull::new_unchecked(tagged) });
let res = Self(unsafe { NonNull::new_unchecked(tagged) }, PhantomData);
// quickly smoke-check we encoded the right thing (This generally will
// only run in libstd's tests, unless the user uses -Zbuild-std)
debug_assert!(matches!(res.data(), ErrorData::Custom(_)), "repr(custom) encoding failed");
Expand All @@ -156,7 +166,7 @@ impl Repr {
pub(super) fn new_os(code: i32) -> Self {
let utagged = ((code as usize) << 32) | TAG_OS;
// Safety: `TAG_OS` is not zero, so the result of the `|` is not 0.
let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) });
let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }, PhantomData);
// quickly smoke-check we encoded the right thing (This generally will
// only run in libstd's tests, unless the user uses -Zbuild-std)
debug_assert!(
Expand All @@ -170,7 +180,7 @@ impl Repr {
pub(super) fn new_simple(kind: ErrorKind) -> Self {
let utagged = ((kind as usize) << 32) | TAG_SIMPLE;
// Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0.
let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) });
let res = Self(unsafe { NonNull::new_unchecked(utagged as *mut ()) }, PhantomData);
// quickly smoke-check we encoded the right thing (This generally will
// only run in libstd's tests, unless the user uses -Zbuild-std)
debug_assert!(
Expand All @@ -184,7 +194,7 @@ impl Repr {
#[inline]
pub(super) const fn new_simple_message(m: &'static SimpleMessage) -> Self {
// Safety: References are never null.
Self(unsafe { NonNull::new_unchecked(m as *const _ as *mut ()) })
Self(unsafe { NonNull::new_unchecked(m as *const _ as *mut ()) }, PhantomData)
}

#[inline]
Expand Down

0 comments on commit 3208ed7

Please sign in to comment.