Skip to content

Commit

Permalink
Detect atomic support using target_has_atomic
Browse files Browse the repository at this point in the history
Note that `cfg(target_has_atomic = ...)` was only added in Rust 1.60.
However, we do not add a version detection feature for this since,
prior to 1.60, these cfgs are not present, so none of the atomics will
be supported. This is identical to the behavior if we were to add
version detection, so there is no point in doing so.

This is adapted from @josephlr's similar implementation in #1091.

Fixes #1086

Co-authored-by: Joe Richey <[email protected]>
  • Loading branch information
joshlf and josephlr committed Aug 9, 2024
1 parent f0a52b5 commit 6f61fab
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 35 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ jobs:
"riscv64gc-unknown-linux-gnu",
"s390x-unknown-linux-gnu",
"x86_64-pc-windows-msvc",
"thumbv6m-none-eabi",
"wasm32-wasi"
]
features: [ "--no-default-features", "", "--features __internal_use_only_features_that_work_on_stable", "--all-features" ]
Expand Down Expand Up @@ -109,6 +110,8 @@ jobs:
event_name: "pull_request"
- target: "s390x-unknown-linux-gnu"
event_name: "pull_request"
- target: "thumbv6m-none-eabi"
event_name: "pull_request"
- target: "wasm32-wasi"
event_name: "pull_request"

Expand Down
80 changes: 49 additions & 31 deletions src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,40 +451,58 @@ macro_rules! impl_traits_for_atomics {
};
}

#[rustfmt::skip]
impl_traits_for_atomics!(
AtomicI16, AtomicI32, AtomicI8, AtomicIsize,
AtomicU16, AtomicU32, AtomicU8, AtomicUsize,
);

impl_for_transparent_wrapper!(=> TryFromBytes for AtomicBool);
impl_for_transparent_wrapper!(=> FromZeros for AtomicBool);
impl_for_transparent_wrapper!(=> IntoBytes for AtomicBool);
#[cfg(target_has_atomic = "8")]
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "8")))]
mod atomic_8 {
use super::*;

safety_comment! {
/// SAFETY:
/// Per [1], `AtomicBool`, `AtomicU8`, and `AtomicI8` have the same size as
/// `bool`, `u8`, and `i8` respectively. Since a type's alignment cannot be
/// smaller than 1 [2], and since its alignment cannot be greater than its
/// size [3], the only possible value for the alignment is 1. Thus, it is
/// sound to implement `Unaligned`.
///
/// [1] TODO(#896), TODO(https://github.com/rust-lang/rust/pull/121943):
/// Cite docs once they've landed.
///
/// [2] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
///
/// Alignment is measured in bytes, and must be at least 1.
///
/// [3] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
///
/// The size of a value is always a multiple of its alignment.
unsafe_impl!(AtomicBool: Unaligned);
unsafe_impl!(AtomicU8: Unaligned);
unsafe_impl!(AtomicI8: Unaligned);
assert_unaligned!(AtomicBool, AtomicU8, AtomicI8);
impl_traits_for_atomics!(AtomicU8, AtomicI8);

impl_for_transparent_wrapper!(=> TryFromBytes for AtomicBool);
impl_for_transparent_wrapper!(=> FromZeros for AtomicBool);
impl_for_transparent_wrapper!(=> IntoBytes for AtomicBool);

safety_comment! {
/// SAFETY:
/// Per [1], `AtomicBool`, `AtomicU8`, and `AtomicI8` have the same size
/// as `bool`, `u8`, and `i8` respectively. Since a type's alignment
/// cannot be smaller than 1 [2], and since its alignment cannot be
/// greater than its size [3], the only possible value for the alignment
/// is 1. Thus, it is sound to implement `Unaligned`.
///
/// [1] TODO(#896), TODO(https://github.com/rust-lang/rust/pull/121943):
/// Cite docs once they've landed.
///
/// [2] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
///
/// Alignment is measured in bytes, and must be at least 1.
///
/// [3] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
///
/// The size of a value is always a multiple of its alignment.
unsafe_impl!(AtomicBool: Unaligned);
unsafe_impl!(AtomicU8: Unaligned);
unsafe_impl!(AtomicI8: Unaligned);
assert_unaligned!(AtomicBool, AtomicU8, AtomicI8);
}
}

#[cfg(target_has_atomic = "16")]
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "16")))]
impl_traits_for_atomics!(AtomicU16, AtomicI16);

#[cfg(target_has_atomic = "32")]
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "32")))]
impl_traits_for_atomics!(AtomicU32, AtomicI32);

#[cfg(target_has_atomic = "64")]
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "64")))]
impl_traits_for_atomics!(AtomicU64, AtomicI64);

#[cfg(target_has_atomic = "ptr")]
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "ptr")))]
impl_traits_for_atomics!(AtomicUsize, AtomicIsize);

safety_comment! {
/// SAFETY:
/// Per reference [1]:
Expand Down
9 changes: 5 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,8 @@ use core::{
ptr::{self, NonNull},
slice,
sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU32,
AtomicU8, AtomicUsize,
AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16,
AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
},
};

Expand Down Expand Up @@ -820,8 +820,9 @@ impl_known_layout!(
bool, char,
NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32,
NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize,
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
AtomicU8, AtomicUsize
AtomicBool,
AtomicU8, AtomicU16, AtomicU32, AtomicU64, AtomicUsize,
AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize
);
#[rustfmt::skip]
impl_known_layout!(
Expand Down

0 comments on commit 6f61fab

Please sign in to comment.