Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit df53350

Browse files
joshlfjosephlr
andcommittedAug 16, 2024·
Detect atomic support using target_has_atomic
Implements `TryFromBytes` and `FromZeros` for `AtomicPtr`; `FromBytes` and `IntoBytes` are blocked by #170. This is adapted from @josephlr's similar implementation in #1092. Fixes #1086 Co-authored-by: Joe Richey <joerichey@google.com>
1 parent a32a460 commit df53350

32 files changed

+445
-391
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

+81-39
Original file line numberDiff line numberDiff line change
@@ -440,49 +440,91 @@ 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-
)*
443+
#[cfg(zerocopy_target_has_atomics)]
444+
mod atomics {
445+
use core::sync::atomic::{
446+
AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16,
447+
AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
451448
};
452-
}
453449

454-
#[rustfmt::skip]
455-
impl_traits_for_atomics!(
456-
AtomicI16, AtomicI32, AtomicI8, AtomicIsize,
457-
AtomicU16, AtomicU32, AtomicU8, AtomicUsize,
458-
);
450+
use super::*;
459451

460-
impl_for_transparent_wrapper!(=> TryFromBytes for AtomicBool);
461-
impl_for_transparent_wrapper!(=> FromZeros for AtomicBool);
462-
impl_for_transparent_wrapper!(=> IntoBytes for AtomicBool);
452+
macro_rules! impl_traits_for_atomics {
453+
($($atomics:ident),* $(,)?) => {
454+
$(
455+
impl_known_layout!($atomics);
456+
impl_for_transparent_wrapper!(=> TryFromBytes for $atomics);
457+
impl_for_transparent_wrapper!(=> FromZeros for $atomics);
458+
impl_for_transparent_wrapper!(=> FromBytes for $atomics);
459+
impl_for_transparent_wrapper!(=> IntoBytes for $atomics);
460+
)*
461+
};
462+
}
463463

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);
464+
#[cfg(target_has_atomic = "8")]
465+
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "8")))]
466+
mod atomic_8 {
467+
use super::*;
468+
469+
impl_traits_for_atomics!(AtomicU8, AtomicI8);
470+
471+
impl_known_layout!(AtomicBool);
472+
473+
impl_for_transparent_wrapper!(=> TryFromBytes for AtomicBool);
474+
impl_for_transparent_wrapper!(=> FromZeros for AtomicBool);
475+
impl_for_transparent_wrapper!(=> IntoBytes for AtomicBool);
476+
477+
safety_comment! {
478+
/// SAFETY:
479+
/// Per [1], `AtomicBool`, `AtomicU8`, and `AtomicI8` have the same
480+
/// size as `bool`, `u8`, and `i8` respectively. Since a type's
481+
/// alignment cannot be smaller than 1 [2], and since its alignment
482+
/// cannot be greater than its size [3], the only possible value for
483+
/// the alignment is 1. Thus, it is sound to implement `Unaligned`.
484+
///
485+
/// [1] TODO(#896), TODO(https://github.com/rust-lang/rust/pull/121943):
486+
/// Cite docs once they've landed.
487+
///
488+
/// [2] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
489+
///
490+
/// Alignment is measured in bytes, and must be at least 1.
491+
///
492+
/// [3] Per https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment:
493+
///
494+
/// The size of a value is always a multiple of its alignment.
495+
unsafe_impl!(AtomicBool: Unaligned);
496+
unsafe_impl!(AtomicU8: Unaligned);
497+
unsafe_impl!(AtomicI8: Unaligned);
498+
assert_unaligned!(AtomicBool, AtomicU8, AtomicI8);
499+
}
500+
}
501+
502+
#[cfg(target_has_atomic = "16")]
503+
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "16")))]
504+
impl_traits_for_atomics!(AtomicU16, AtomicI16);
505+
506+
#[cfg(target_has_atomic = "32")]
507+
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "32")))]
508+
impl_traits_for_atomics!(AtomicU32, AtomicI32);
509+
510+
#[cfg(target_has_atomic = "64")]
511+
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "64")))]
512+
impl_traits_for_atomics!(AtomicU64, AtomicI64);
513+
514+
#[cfg(target_has_atomic = "ptr")]
515+
#[cfg_attr(doc_cfg, doc(cfg(target_has_atomic = "ptr")))]
516+
mod atomic_ptr {
517+
use super::*;
518+
519+
impl_traits_for_atomics!(AtomicUsize, AtomicIsize);
520+
521+
impl_known_layout!(T => AtomicPtr<T>);
522+
523+
// TODO(#170): Implement `FromBytes` and `IntoBytes` once we implement
524+
// those traits for `*mut T`.
525+
impl_for_transparent_wrapper!(T => TryFromBytes for AtomicPtr<T>);
526+
impl_for_transparent_wrapper!(T => FromZeros for AtomicPtr<T>);
527+
}
486528
}
487529

488530
safety_comment! {

‎src/lib.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -337,10 +337,6 @@ use core::{
337337
ops::{Deref, DerefMut},
338338
ptr::{self, NonNull},
339339
slice,
340-
sync::atomic::{
341-
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU32,
342-
AtomicU8, AtomicUsize,
343-
},
344340
};
345341

346342
use crate::pointer::{invariant, BecauseExclusive, BecauseImmutable};
@@ -819,9 +815,7 @@ impl_known_layout!(
819815
u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize, f32, f64,
820816
bool, char,
821817
NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32,
822-
NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize,
823-
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
824-
AtomicU8, AtomicUsize
818+
NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize
825819
);
826820
#[rustfmt::skip]
827821
impl_known_layout!(
@@ -830,8 +824,7 @@ impl_known_layout!(
830824
T => Wrapping<T>,
831825
T => MaybeUninit<T>,
832826
T: ?Sized => *const T,
833-
T: ?Sized => *mut T,
834-
T => AtomicPtr<T>
827+
T: ?Sized => *mut T
835828
);
836829
impl_known_layout!(const N: usize, T => [T; N]);
837830

‎tests/ui-nightly/include_value_not_from_bytes.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ error[E0277]: the trait bound `NotZerocopy<u32>: zerocopy::FromBytes` is not sat
1010
= help: the following other types implement trait `zerocopy::FromBytes`:
1111
()
1212
AU16
13-
AtomicI16
14-
AtomicI32
15-
AtomicI8
16-
AtomicIsize
17-
AtomicU16
18-
AtomicU32
13+
F32<O>
14+
F64<O>
15+
I128<O>
16+
I16<O>
17+
I32<O>
18+
I64<O>
1919
and $N others
2020
note: required by a bound in `AssertIsFromBytes`
2121
--> tests/ui-nightly/include_value_not_from_bytes.rs:15:42

‎tests/ui-nightly/transmute-dst-not-frombytes.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfie
1010
= help: the following other types implement trait `zerocopy::FromBytes`:
1111
()
1212
AU16
13-
AtomicI16
14-
AtomicI32
15-
AtomicI8
16-
AtomicIsize
17-
AtomicU16
18-
AtomicU32
13+
F32<O>
14+
F64<O>
15+
I128<O>
16+
I16<O>
17+
I32<O>
18+
I64<O>
1919
and $N others
2020
note: required by a bound in `AssertIsFromBytes`
2121
--> tests/ui-nightly/transmute-dst-not-frombytes.rs:19:41

‎tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr

+7-7
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ error[E0277]: the trait bound `Dst: FromBytes` is not satisfied
99
|
1010
= help: the following other types implement trait `FromBytes`:
1111
()
12-
AtomicI16
13-
AtomicI32
14-
AtomicI8
15-
AtomicIsize
16-
AtomicU16
17-
AtomicU32
18-
AtomicU8
12+
F32<O>
13+
F64<O>
14+
I128<O>
15+
I16<O>
16+
I32<O>
17+
I64<O>
18+
Isize<O>
1919
and $N others
2020
note: required by a bound in `AssertDstIsFromBytes`
2121
--> tests/ui-nightly/transmute-mut-dst-not-frombytes.rs:24:38

‎tests/ui-nightly/transmute-mut-dst-not-intobytes.stderr

+7-7
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ error[E0277]: the trait bound `Dst: IntoBytes` is not satisfied
99
|
1010
= help: the following other types implement trait `IntoBytes`:
1111
()
12-
AtomicBool
13-
AtomicI16
14-
AtomicI32
15-
AtomicI8
16-
AtomicIsize
17-
AtomicU16
18-
AtomicU32
12+
F32<O>
13+
F64<O>
14+
I128<O>
15+
I16<O>
16+
I32<O>
17+
I64<O>
18+
Isize<O>
1919
and $N others
2020
note: required by a bound in `AssertDstIsIntoBytes`
2121
--> tests/ui-nightly/transmute-mut-dst-not-intobytes.rs:24:36

‎tests/ui-nightly/transmute-mut-src-not-frombytes.stderr

+14-14
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ error[E0277]: the trait bound `Src: FromBytes` is not satisfied
99
|
1010
= help: the following other types implement trait `FromBytes`:
1111
()
12-
AtomicI16
13-
AtomicI32
14-
AtomicI8
15-
AtomicIsize
16-
AtomicU16
17-
AtomicU32
18-
AtomicU8
12+
Dst
13+
F32<O>
14+
F64<O>
15+
I128<O>
16+
I16<O>
17+
I32<O>
18+
I64<O>
1919
and $N others
2020
note: required by a bound in `AssertSrcIsFromBytes`
2121
--> tests/ui-nightly/transmute-mut-src-not-frombytes.rs:24:38
@@ -32,13 +32,13 @@ error[E0277]: the trait bound `Src: FromBytes` is not satisfied
3232
|
3333
= help: the following other types implement trait `FromBytes`:
3434
()
35-
AtomicI16
36-
AtomicI32
37-
AtomicI8
38-
AtomicIsize
39-
AtomicU16
40-
AtomicU32
41-
AtomicU8
35+
Dst
36+
F32<O>
37+
F64<O>
38+
I128<O>
39+
I16<O>
40+
I32<O>
41+
I64<O>
4242
and $N others
4343
note: required by a bound in `AssertSrcIsFromBytes`
4444
--> tests/ui-nightly/transmute-mut-src-not-frombytes.rs:24:38

‎tests/ui-nightly/transmute-mut-src-not-intobytes.stderr

+14-14
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ error[E0277]: the trait bound `Src: IntoBytes` is not satisfied
99
|
1010
= help: the following other types implement trait `IntoBytes`:
1111
()
12-
AtomicBool
13-
AtomicI16
14-
AtomicI32
15-
AtomicI8
16-
AtomicIsize
17-
AtomicU16
18-
AtomicU32
12+
Dst
13+
F32<O>
14+
F64<O>
15+
I128<O>
16+
I16<O>
17+
I32<O>
18+
I64<O>
1919
and $N others
2020
note: required by a bound in `AssertSrcIsIntoBytes`
2121
--> tests/ui-nightly/transmute-mut-src-not-intobytes.rs:24:36
@@ -32,13 +32,13 @@ error[E0277]: the trait bound `Src: IntoBytes` is not satisfied
3232
|
3333
= help: the following other types implement trait `IntoBytes`:
3434
()
35-
AtomicBool
36-
AtomicI16
37-
AtomicI32
38-
AtomicI8
39-
AtomicIsize
40-
AtomicU16
41-
AtomicU32
35+
Dst
36+
F32<O>
37+
F64<O>
38+
I128<O>
39+
I16<O>
40+
I32<O>
41+
I64<O>
4242
and $N others
4343
note: required by a bound in `AssertSrcIsIntoBytes`
4444
--> tests/ui-nightly/transmute-mut-src-not-intobytes.rs:24:36

‎tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ error[E0277]: the trait bound `Dst: zerocopy::FromBytes` is not satisfied
1010
= help: the following other types implement trait `zerocopy::FromBytes`:
1111
()
1212
AU16
13-
AtomicI16
14-
AtomicI32
15-
AtomicI8
16-
AtomicIsize
17-
AtomicU16
18-
AtomicU32
13+
F32<O>
14+
F64<O>
15+
I128<O>
16+
I16<O>
17+
I32<O>
18+
I64<O>
1919
and $N others
2020
note: required by a bound in `AssertDstIsFromBytes`
2121
--> tests/ui-nightly/transmute-ref-dst-not-frombytes.rs:23:34

0 commit comments

Comments
 (0)
Please sign in to comment.