Skip to content

Commit

Permalink
Merge rust-bitcoin#3920: Make io::Error Sync
Browse files Browse the repository at this point in the history
11a9dce api: Run just check-api (Tobin C. Harding)
31dda6d Make io::Error Sync (Tobin C. Harding)

Pull request description:

  Currently we use a marker that contains an `UnsafeCell` but `UnsafeCell` is not `Sync` so this makes `io::Error` not `Sync`. We can instead wrap the `UnsafeCell` and implement `Sync` for it.

  Fix: rust-bitcoin#3883

ACKs for top commit:
  apoelstra:
    ACK 11a9dce; successfully ran local tests

Tree-SHA512: 77c89a32e6d409be9db3a40573b78f69eadf24f2d6d4739510753e339ba30a5e6082d21fef52b44481ff2b60f49c1b31dfe45fa12299f97176ba48853b9487a6
  • Loading branch information
apoelstra committed Jan 21, 2025
2 parents aea7b1a + 11a9dce commit 39dd3ca
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 7 deletions.
2 changes: 1 addition & 1 deletion api/io/all-features.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#[repr(transparent)] pub struct bitcoin_io::FromStd<T>(_)
#[repr(transparent)] pub struct bitcoin_io::ToStd<T>(_)
impl !core::marker::Sync for bitcoin_io::Error
impl !core::panic::unwind_safe::RefUnwindSafe for bitcoin_io::Error
impl !core::panic::unwind_safe::UnwindSafe for bitcoin_io::Error
impl bitcoin_io::BufRead for &[u8]
Expand Down Expand Up @@ -70,6 +69,7 @@ impl core::marker::Send for bitcoin_io::Error
impl core::marker::Send for bitcoin_io::ErrorKind
impl core::marker::Send for bitcoin_io::Sink
impl core::marker::StructuralPartialEq for bitcoin_io::ErrorKind
impl core::marker::Sync for bitcoin_io::Error
impl core::marker::Sync for bitcoin_io::ErrorKind
impl core::marker::Sync for bitcoin_io::Sink
impl core::marker::Unpin for bitcoin_io::Error
Expand Down
2 changes: 1 addition & 1 deletion api/io/alloc-only.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
impl !core::marker::Sync for bitcoin_io::Error
impl !core::panic::unwind_safe::RefUnwindSafe for bitcoin_io::Error
impl !core::panic::unwind_safe::UnwindSafe for bitcoin_io::Error
impl bitcoin_io::BufRead for &[u8]
Expand Down Expand Up @@ -28,6 +27,7 @@ impl core::marker::Send for bitcoin_io::Error
impl core::marker::Send for bitcoin_io::ErrorKind
impl core::marker::Send for bitcoin_io::Sink
impl core::marker::StructuralPartialEq for bitcoin_io::ErrorKind
impl core::marker::Sync for bitcoin_io::Error
impl core::marker::Sync for bitcoin_io::ErrorKind
impl core::marker::Sync for bitcoin_io::Sink
impl core::marker::Unpin for bitcoin_io::Error
Expand Down
2 changes: 1 addition & 1 deletion api/io/no-features.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
impl !core::marker::Sync for bitcoin_io::Error
impl !core::panic::unwind_safe::RefUnwindSafe for bitcoin_io::Error
impl !core::panic::unwind_safe::UnwindSafe for bitcoin_io::Error
impl bitcoin_io::BufRead for &[u8]
Expand Down Expand Up @@ -27,6 +26,7 @@ impl core::marker::Send for bitcoin_io::Error
impl core::marker::Send for bitcoin_io::ErrorKind
impl core::marker::Send for bitcoin_io::Sink
impl core::marker::StructuralPartialEq for bitcoin_io::ErrorKind
impl core::marker::Sync for bitcoin_io::Error
impl core::marker::Sync for bitcoin_io::ErrorKind
impl core::marker::Sync for bitcoin_io::Sink
impl core::marker::Unpin for bitcoin_io::Error
Expand Down
17 changes: 13 additions & 4 deletions io/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ use core::fmt;
#[derive(Debug)]
pub struct Error {
kind: ErrorKind,
/// Indicates that the `struct` can pretend to own a mutable static reference
/// and an [`UnsafeCell`](core::cell::UnsafeCell), which are not unwind safe.
/// This is so that it does not introduce non-additive cargo features.
_not_unwind_safe: core::marker::PhantomData<(&'static mut (), core::cell::UnsafeCell<()>)>,
/// We want this type to be `?UnwindSafe` and `?RefUnwindSafe` - the same as `std::io::Error`.
///
/// In `std` builds the existence of `dyn std::error:Error` prevents `UnwindSafe` and
/// `RefUnwindSafe` from being automatically implemented. But in `no-std` builds without the
/// marker nothing prevents it.
_not_unwind_safe: core::marker::PhantomData<NotUnwindSafe>,

#[cfg(feature = "std")]
error: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
Expand Down Expand Up @@ -100,6 +102,13 @@ impl From<Error> for std::io::Error {
}
}

/// Useful for preventing `UnwindSafe` and `RefUnwindSafe` from being automatically implemented.
struct NotUnwindSafe {
_not_unwind_safe: core::marker::PhantomData<(&'static mut (), core::cell::UnsafeCell<()>)>,
}

unsafe impl Sync for NotUnwindSafe {}

macro_rules! define_errorkind {
($($(#[$($attr:tt)*])* $kind:ident),*) => {
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
Expand Down
4 changes: 4 additions & 0 deletions io/tests/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,8 @@ fn all_non_error_tyes_implement_send_sync() {
// Types are `Send` and `Sync` where possible (C-SEND-SYNC).
assert_send::<Types>();
assert_sync::<Types>();

// Error types are meaningful and well-behaved (C-GOOD-ERR)
assert_send::<Errors>();
assert_sync::<Errors>();
}

0 comments on commit 39dd3ca

Please sign in to comment.