From 126730edc877668008f4a4b23800076e6d7ee790 Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Sun, 11 Dec 2022 12:55:51 +0100 Subject: [PATCH] Use `target_has_atomic` on Rust 1.60+ to enable atomic (de)serialization --- serde/build.rs | 30 +++++++++++++++++------------- serde/src/de/impls.rs | 38 +++++++++++++++++++++++++++++++++++--- serde/src/lib.rs | 17 +++++++++++++++-- serde/src/ser/impls.rs | 39 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 103 insertions(+), 21 deletions(-) diff --git a/serde/build.rs b/serde/build.rs index 590dbb8cd..4d4c7f6c5 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -95,19 +95,23 @@ fn main() { // Whitelist of archs that support std::sync::atomic module. Ideally we // would use #[cfg(target_has_atomic = "...")] but it is not stable yet. // Instead this is based on rustc's compiler/rustc_target/src/spec/*.rs. - let has_atomic64 = target.starts_with("x86_64") - || target.starts_with("i686") - || target.starts_with("aarch64") - || target.starts_with("powerpc64") - || target.starts_with("sparc64") - || target.starts_with("mips64el") - || target.starts_with("riscv64"); - let has_atomic32 = has_atomic64 || emscripten; - if minor < 34 || !has_atomic64 { - println!("cargo:rustc-cfg=no_std_atomic64"); - } - if minor < 34 || !has_atomic32 { - println!("cargo:rustc-cfg=no_std_atomic"); + if minor >= 60 { + println!("cargo:rustc-cfg=use_target_has_atomic"); + } else { + let has_atomic64 = target.starts_with("x86_64") + || target.starts_with("i686") + || target.starts_with("aarch64") + || target.starts_with("powerpc64") + || target.starts_with("sparc64") + || target.starts_with("mips64el") + || target.starts_with("riscv64"); + let has_atomic32 = has_atomic64 || emscripten; + if minor < 34 || !has_atomic64 { + println!("cargo:rustc-cfg=no_std_atomic64"); + } + if minor < 34 || !has_atomic32 { + println!("cargo:rustc-cfg=no_std_atomic"); + } } } diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index c048f7145..f474b94a0 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -2660,7 +2660,7 @@ where } } -#[cfg(all(feature = "std", not(no_std_atomic)))] +#[cfg(all(feature = "std", not(use_target_has_atomic), not(no_std_atomic)))] macro_rules! atomic_impl { ($($ty:ident)*) => { $( @@ -2676,18 +2676,50 @@ macro_rules! atomic_impl { }; } -#[cfg(all(feature = "std", not(no_std_atomic)))] +#[cfg(all(feature = "std", use_target_has_atomic))] +macro_rules! atomic_impl { + ( $( $ty:ident $size:expr ),* ) => { + $( + #[cfg(target_has_atomic = $size)] + impl<'de> Deserialize<'de> for $ty { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(Self::new) + } + } + )* + }; +} + +#[cfg(all(feature = "std", not(use_target_has_atomic), not(no_std_atomic)))] atomic_impl! { AtomicBool AtomicI8 AtomicI16 AtomicI32 AtomicIsize AtomicU8 AtomicU16 AtomicU32 AtomicUsize } -#[cfg(all(feature = "std", not(no_std_atomic64)))] +#[cfg(all(feature = "std", not(use_target_has_atomic), not(no_std_atomic64)))] atomic_impl! { AtomicI64 AtomicU64 } +#[cfg(all(feature = "std", use_target_has_atomic))] +atomic_impl! { + AtomicBool "8", + AtomicI8 "8", + AtomicI16 "16", + AtomicI32 "32", + AtomicI64 "64", + AtomicIsize "ptr", + AtomicU8 "8", + AtomicU16 "16", + AtomicU32 "32", + AtomicU64 "64", + AtomicUsize "ptr" +} + #[cfg(feature = "std")] struct FromStrVisitor { expecting: &'static str, diff --git a/serde/src/lib.rs b/serde/src/lib.rs index ebaec5e2b..403bcf0ec 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -236,14 +236,27 @@ mod lib { #[cfg(not(no_range_inclusive))] pub use self::core::ops::RangeInclusive; - #[cfg(all(feature = "std", not(no_std_atomic)))] + #[cfg(all(feature = "std", not(use_target_has_atomic), not(no_std_atomic)))] pub use std::sync::atomic::{ AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8, AtomicUsize, Ordering, }; - #[cfg(all(feature = "std", not(no_std_atomic64)))] + #[cfg(all(feature = "std", not(use_target_has_atomic), not(no_std_atomic64)))] pub use std::sync::atomic::{AtomicI64, AtomicU64}; + #[cfg(all(feature = "std", use_target_has_atomic))] + pub use std::sync::atomic::Ordering; + #[cfg(all(feature = "std", use_target_has_atomic, target_has_atomic = "8"))] + pub use std::sync::atomic::{AtomicBool, AtomicI8, AtomicU8}; + #[cfg(all(feature = "std", use_target_has_atomic, target_has_atomic = "16"))] + pub use std::sync::atomic::{AtomicI16, AtomicU16}; + #[cfg(all(feature = "std", use_target_has_atomic, target_has_atomic = "32"))] + pub use std::sync::atomic::{AtomicI32, AtomicU32}; + #[cfg(all(feature = "std", use_target_has_atomic, target_has_atomic = "64"))] + pub use std::sync::atomic::{AtomicI64, AtomicU64}; + #[cfg(all(feature = "std", use_target_has_atomic, target_has_atomic = "ptr"))] + pub use std::sync::atomic::{AtomicUsize, AtomicIsize}; + #[cfg(any(feature = "std", not(no_core_duration)))] pub use self::core::time::Duration; } diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index bd4313c33..3ca1f6ee5 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -945,7 +945,7 @@ where //////////////////////////////////////////////////////////////////////////////// -#[cfg(all(feature = "std", not(no_std_atomic)))] +#[cfg(all(feature = "std", not(use_target_has_atomic), not(no_std_atomic)))] macro_rules! atomic_impl { ($($ty:ident)*) => { $( @@ -962,14 +962,47 @@ macro_rules! atomic_impl { } } -#[cfg(all(feature = "std", not(no_std_atomic)))] +#[cfg(all(feature = "std", use_target_has_atomic))] +macro_rules! atomic_impl { + ( $( $ty:ident $size:expr ),* ) => { + $( + #[cfg(target_has_atomic = $size)] + impl Serialize for $ty { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // Matches the atomic ordering used in libcore for the Debug impl + self.load(Ordering::Relaxed).serialize(serializer) + } + } + )* + } +} + +#[cfg(all(feature = "std", not(use_target_has_atomic), not(no_std_atomic)))] atomic_impl! { AtomicBool AtomicI8 AtomicI16 AtomicI32 AtomicIsize AtomicU8 AtomicU16 AtomicU32 AtomicUsize } -#[cfg(all(feature = "std", not(no_std_atomic64)))] +#[cfg(all(feature = "std", not(use_target_has_atomic), not(no_std_atomic64)))] atomic_impl! { AtomicI64 AtomicU64 } + +#[cfg(all(feature = "std", use_target_has_atomic))] +atomic_impl! { + AtomicBool "8", + AtomicI8 "8", + AtomicI16 "16", + AtomicI32 "32", + AtomicI64 "64", + AtomicIsize "ptr", + AtomicU8 "8", + AtomicU16 "16", + AtomicU32 "32", + AtomicU64 "64", + AtomicUsize "ptr" +}