clone_behavior/
blanket_impls.rs

1#![expect(clippy::absolute_paths, reason = "there's a lot of random types used")]
2
3use crate::call_varargs_macro;
4use crate::{independent::IndependentClone, mirrored::MirroredClone, mixed::MixedClone};
5use crate::speed::{NearInstant, ConstantTime, LogTime, AnySpeed};
6
7
8/// Indicates that the speed of cloning a type does not recursively depend on any generics, opting
9/// the type into several blanket implementations.
10///
11/// As examples, `u8` and `Rc<T>` implement this trait, while `Option<T>` does not.
12///
13/// A `NonRecursive` type need only implement a cloning operation at the fastest applicable speed,
14/// and blanket implementations handle the rest. These blanket implementations would interfere
15/// with, for example, an attempt to pass through the speed of cloning `T` to the speed of cloning
16/// `Option<T>`.
17pub trait NonRecursive {}
18
19
20macro_rules! blanket_impls {
21    ($clone_tr:ident, $clone_fn:ident) => {
22        impl<T: NonRecursive + $clone_tr<NearInstant>> $clone_tr<ConstantTime> for T {
23            #[inline]
24            fn $clone_fn(&self) -> Self {
25                <T as $clone_tr<NearInstant>>::$clone_fn(self)
26            }
27        }
28
29        impl<T: NonRecursive + $clone_tr<ConstantTime>> $clone_tr<LogTime> for T {
30            #[inline]
31            fn $clone_fn(&self) -> Self {
32                <T as $clone_tr<ConstantTime>>::$clone_fn(self)
33            }
34        }
35
36        impl<T: NonRecursive + $clone_tr<LogTime>> $clone_tr<AnySpeed> for T {
37            #[inline]
38            fn $clone_fn(&self) -> Self {
39                <T as $clone_tr<LogTime>>::$clone_fn(self)
40            }
41        }
42    };
43}
44
45blanket_impls!(IndependentClone, independent_clone);
46blanket_impls!(MirroredClone, mirrored_clone);
47blanket_impls!(MixedClone, mixed_clone);
48
49
50macro_rules! int_impls {
51    ($($num:ident),* $(,)?) => {
52        $(
53            impl NonRecursive for $num {}
54            impl NonRecursive for ::core::num::NonZero<$num> {}
55        )*
56    };
57}
58
59int_impls!(
60    i8, i16, i32, i64, i128, isize,
61    u8, u16, u32, u64, u128, usize,
62);
63
64macro_rules! non_recursive {
65    ($($({for $($bounds:tt)+})? $type:ty),* $(,)?) => {
66        $(
67            impl<$($($bounds)+)?> NonRecursive for $type {}
68        )*
69    };
70}
71
72non_recursive! {
73    f32, f64, bool, char, (),
74    {for T: ?Sized} &T,
75    {for T: ?Sized} *const T,
76    {for T: ?Sized} *mut T,
77    core::alloc::Layout,
78    core::any::TypeId,
79    core::cmp::Ordering,
80    core::convert::Infallible,
81    {for T} core::iter::Empty<T>,
82    {for T: ?Sized} core::marker::PhantomData<T>,
83    core::marker::PhantomPinned,
84    {for T} core::mem::Discriminant<T>,
85    core::ops::RangeFull,
86    {for T: ?Sized} core::ptr::NonNull<T>,
87    core::sync::atomic::Ordering,
88    core::time::Duration,
89}
90
91#[cfg(feature = "alloc")]
92non_recursive! {
93    alloc::string::String,
94}
95
96#[cfg(feature = "std")]
97non_recursive! {
98    std::path::Path,
99    std::path::PathBuf,
100    std::time::Instant,
101    std::thread::ThreadId,
102}
103
104macro_rules! atomic {
105    ($($name:ident $bits:literal),* $(,)?) => {
106        $(
107            #[cfg(target_has_atomic = $bits)]
108            impl NonRecursive for core::sync::atomic::$name {}
109        )*
110    };
111}
112
113atomic! {
114    AtomicBool    "8",
115    AtomicI8      "8", AtomicU8      "8",
116    AtomicI16    "16", AtomicU16    "16",
117    AtomicI32    "32", AtomicU32    "32",
118    AtomicI64    "64", AtomicU64    "64",
119    AtomicIsize "ptr", AtomicUsize "ptr",
120}
121
122#[cfg(target_has_atomic = "ptr")]
123impl<T> NonRecursive for core::sync::atomic::AtomicPtr<T> {}
124
125macro_rules! function {
126    ($($args:ident),*) => {
127        impl<R, $($args),*> NonRecursive for fn($($args),*) -> R {}
128    };
129}
130
131function!();
132call_varargs_macro!(function);