From b898ad499f7a2c806e8df0bfde6fbe3f3c5cb925 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Wed, 23 Mar 2022 17:09:44 -0700 Subject: [PATCH 1/3] Ensure io::Error's bitpacked repr doesn't accidentally impl UnwindSafe --- library/std/src/io/error/repr_bitpacked.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index 1a0538f861a1e..e8070dc419b43 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; @@ -115,7 +116,7 @@ const TAG_OS: usize = 0b10; const TAG_SIMPLE: usize = 0b11; #[repr(transparent)] -pub(super) struct Repr(NonNull<()>); +pub(super) struct Repr(NonNull<()>, PhantomData>>); // All the types `Repr` stores internally are Send + Sync, and so is it. unsafe impl Send for Repr {} @@ -145,7 +146,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 +157,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 +171,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 +185,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] From 09d83e292dcb6630c1e8c08734062524466db66e Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Wed, 23 Mar 2022 17:29:19 -0700 Subject: [PATCH 2/3] Add a `compile_fail` doctest to check that `io::Error: !UnwindSafe` --- library/std/src/io/error/repr_bitpacked.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index e8070dc419b43..06614d9f4d16e 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -115,6 +115,15 @@ 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 +/// fn is_unwind_safe() {} +/// is_unwind_safe::(); +/// ``` #[repr(transparent)] pub(super) struct Repr(NonNull<()>, PhantomData>>); From 3ac93abfb220ad3fc0614787a5644e63c162f0d6 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Tue, 29 Mar 2022 11:45:49 -0700 Subject: [PATCH 3/3] Indicate the correct error code in the `compile_fail` block. Co-authored-by: Mara Bos --- library/std/src/io/error/repr_bitpacked.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index 06614d9f4d16e..208d5a80c5a69 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -120,7 +120,7 @@ const TAG_SIMPLE: usize = 0b11; /// 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 +/// ```compile_fail,E0277 /// fn is_unwind_safe() {} /// is_unwind_safe::(); /// ```