diff options
| author | Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> | 2022-03-29 22:46:33 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-29 22:46:33 +0200 |
| commit | 3208ed7b21b8b8f035b8a6bb3172be0763cf45ab (patch) | |
| tree | d85a20e80af6a529613e3c7a7ae6a51b6f134f3b | |
| parent | bba2a64d0c5ba20c4153676a09381b8703c197ba (diff) | |
| parent | 3ac93abfb220ad3fc0614787a5644e63c162f0d6 (diff) | |
| download | rust-3208ed7b21b8b8f035b8a6bb3172be0763cf45ab.tar.gz rust-3208ed7b21b8b8f035b8a6bb3172be0763cf45ab.zip | |
Rollup merge of #95256 - thomcc:fix-unwind-safe, r=m-ou-se
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
| -rw-r--r-- | library/std/src/io/error/repr_bitpacked.rs | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index 1a0538f861a..208d5a80c5a 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -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; @@ -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 {} @@ -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"); @@ -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!( @@ -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!( @@ -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] |
