Skip to content

Commit b94414c

Browse files
joshlfjosephlr
andcommitted
Detect atomic support using target_has_atomic
This is adapted from @josephlr's similar implementation in #1091. Fixes #1086 Co-authored-by: Joe Richey <[email protected]>
1 parent f0a52b5 commit b94414c

File tree

4 files changed

+88
-45
lines changed

4 files changed

+88
-45
lines changed

.github/workflows/ci.yml

+16-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,19 @@ jobs:
4646
matrix:
4747
# See `INTERNAL.md` for an explanation of these pinned toolchain
4848
# versions.
49-
toolchain: [ "msrv", "stable", "nightly", "zerocopy-generic-bounds-in-const-fn", "zerocopy-aarch64-simd", "zerocopy-panic-in-const", ]
49+
toolchain: [
50+
"msrv",
51+
"stable",
52+
"nightly",
53+
54+
# These are the names of specific Rust versions detected in
55+
# `build.rs`. Each of these represents the minimum Rust version for
56+
# which a particular feature is supported.
57+
"zerocopy-generic-bounds-in-const-fn",
58+
"zerocopy-target-has-atomics",
59+
"zerocopy-aarch64-simd",
60+
"zerocopy-panic-in-const"
61+
]
5062
target: [
5163
"i686-unknown-linux-gnu",
5264
"x86_64-unknown-linux-gnu",
@@ -57,6 +69,7 @@ jobs:
5769
"riscv64gc-unknown-linux-gnu",
5870
"s390x-unknown-linux-gnu",
5971
"x86_64-pc-windows-msvc",
72+
"thumbv6m-none-eabi",
6073
"wasm32-wasi"
6174
]
6275
features: [ "--no-default-features", "", "--features __internal_use_only_features_that_work_on_stable", "--all-features" ]
@@ -109,6 +122,8 @@ jobs:
109122
event_name: "pull_request"
110123
- target: "s390x-unknown-linux-gnu"
111124
event_name: "pull_request"
125+
- target: "thumbv6m-none-eabi"
126+
event_name: "pull_request"
112127
- target: "wasm32-wasi"
113128
event_name: "pull_request"
114129

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ exclude = [".*"]
3535
# From 1.61.0, Rust supports generic types with trait bounds in `const fn`.
3636
zerocopy-generic-bounds-in-const-fn = "1.61.0"
3737

38+
# From 1.60.0, Rust supports `cfg(target_has_atomics)`, which allows us to
39+
# detect whether a target supports particular sets of atomics.
40+
zerocopy-target-has-atomics = "1.60.0"
41+
3842
# When the "simd" feature is enabled, include SIMD types from the
3943
# `core::arch::aarch64` module, which was stabilized in 1.59.0. On earlier Rust
4044
# versions, these types require the "simd-nightly" feature.

src/impls.rs

+63-40
Original file line numberDiff line numberDiff line change
@@ -440,49 +440,72 @@ safety_comment! {
440440
unsafe_impl_for_power_set!(A, B, C, D, E, F, G, H, I, J, K, L -> M => Immutable for opt_extern_c_fn!(...));
441441
}
442442

443-
macro_rules! impl_traits_for_atomics {
444-
($($atomics:ident),* $(,)?) => {
445-
$(
446-
impl_for_transparent_wrapper!(=> TryFromBytes for $atomics);
447-
impl_for_transparent_wrapper!(=> FromZeros for $atomics);
448-
impl_for_transparent_wrapper!(=> FromBytes for $atomics);
449-
impl_for_transparent_wrapper!(=> IntoBytes for $atomics);
450-
)*
451-
};
452-
}
443+
#[cfg(zerocopy_target_has_atomics)]
444+
mod atomics {
445+
use super::*;
453446

454-
#[rustfmt::skip]
455-
impl_traits_for_atomics!(
456-
AtomicI16, AtomicI32, AtomicI8, AtomicIsize,
457-
AtomicU16, AtomicU32, AtomicU8, AtomicUsize,
458-
);
447+
macro_rules! impl_traits_for_atomics {
448+
($($atomics:ident),* $(,)?) => {
449+
$(
450+
impl_for_transparent_wrapper!(=> TryFromBytes for $atomics);
451+
impl_for_transparent_wrapper!(=> FromZeros for $atomics);
452+
impl_for_transparent_wrapper!(=> FromBytes for $atomics);
453+
impl_for_transparent_wrapper!(=> IntoBytes for $atomics);
454+
)*
455+
};
456+
}
459457

460-
impl_for_transparent_wrapper!(=> TryFromBytes for AtomicBool);
461-
impl_for_transparent_wrapper!(=> FromZeros for AtomicBool);
462-
impl_for_transparent_wrapper!(=> IntoBytes for AtomicBool);
458+
#[cfg(target_has_atomic = "8")]
459+
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "8")))]
460+
mod atomic_8 {
461+
use super::*;
462+
463+
impl_traits_for_atomics!(AtomicU8, AtomicI8);
464+
465+
impl_for_transparent_wrapper!(=> TryFromBytes for AtomicBool);
466+
impl_for_transparent_wrapper!(=> FromZeros for AtomicBool);
467+
impl_for_transparent_wrapper!(=> IntoBytes for AtomicBool);
468+
469+
safety_comment! {
470+
/// SAFETY:
471+
/// Per [1], `AtomicBool`, `AtomicU8`, and `AtomicI8` have the same
472+
/// size as `bool`, `u8`, and `i8` respectively. Since a type's
473+
/// alignment cannot be smaller than 1 [2], and since its alignment
474+
/// cannot be greater than its size [3], the only possible value for
475+
/// the alignment is 1. Thus, it is sound to implement `Unaligned`.
476+
///
477+
/// [1] TODO(#896), TODO(https://github.com/rust-lang/rust/pull/121943):
478+
/// Cite docs once they've landed.
479+
///
480+
/// [2] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
481+
///
482+
/// Alignment is measured in bytes, and must be at least 1.
483+
///
484+
/// [3] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
485+
///
486+
/// The size of a value is always a multiple of its alignment.
487+
unsafe_impl!(AtomicBool: Unaligned);
488+
unsafe_impl!(AtomicU8: Unaligned);
489+
unsafe_impl!(AtomicI8: Unaligned);
490+
assert_unaligned!(AtomicBool, AtomicU8, AtomicI8);
491+
}
492+
}
463493

464-
safety_comment! {
465-
/// SAFETY:
466-
/// Per [1], `AtomicBool`, `AtomicU8`, and `AtomicI8` have the same size as
467-
/// `bool`, `u8`, and `i8` respectively. Since a type's alignment cannot be
468-
/// smaller than 1 [2], and since its alignment cannot be greater than its
469-
/// size [3], the only possible value for the alignment is 1. Thus, it is
470-
/// sound to implement `Unaligned`.
471-
///
472-
/// [1] TODO(#896), TODO(https://github.com/rust-lang/rust/pull/121943):
473-
/// Cite docs once they've landed.
474-
///
475-
/// [2] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
476-
///
477-
/// Alignment is measured in bytes, and must be at least 1.
478-
///
479-
/// [3] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
480-
///
481-
/// The size of a value is always a multiple of its alignment.
482-
unsafe_impl!(AtomicBool: Unaligned);
483-
unsafe_impl!(AtomicU8: Unaligned);
484-
unsafe_impl!(AtomicI8: Unaligned);
485-
assert_unaligned!(AtomicBool, AtomicU8, AtomicI8);
494+
#[cfg(target_has_atomic = "16")]
495+
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "16")))]
496+
impl_traits_for_atomics!(AtomicU16, AtomicI16);
497+
498+
#[cfg(target_has_atomic = "32")]
499+
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "32")))]
500+
impl_traits_for_atomics!(AtomicU32, AtomicI32);
501+
502+
#[cfg(target_has_atomic = "64")]
503+
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "64")))]
504+
impl_traits_for_atomics!(AtomicU64, AtomicI64);
505+
506+
#[cfg(target_has_atomic = "ptr")]
507+
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "ptr")))]
508+
impl_traits_for_atomics!(AtomicUsize, AtomicIsize);
486509
}
487510

488511
safety_comment! {

src/lib.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,8 @@ use core::{
338338
ptr::{self, NonNull},
339339
slice,
340340
sync::atomic::{
341-
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU32,
342-
AtomicU8, AtomicUsize,
341+
AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16,
342+
AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
343343
},
344344
};
345345

@@ -820,8 +820,9 @@ impl_known_layout!(
820820
bool, char,
821821
NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32,
822822
NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize,
823-
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
824-
AtomicU8, AtomicUsize
823+
AtomicBool,
824+
AtomicU8, AtomicU16, AtomicU32, AtomicU64, AtomicUsize,
825+
AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize
825826
);
826827
#[rustfmt::skip]
827828
impl_known_layout!(

0 commit comments

Comments
 (0)