clone_behavior/mixed.rs
1#![expect(clippy::absolute_paths, reason = "there's a lot of random types used")]
2#![warn(clippy::missing_inline_in_public_items, reason = "almost everything is very short")]
3
4use crate::speed::{Speed, NearInstant};
5
6
7/// Get clones that could share some but not all semantically-important mutable state.
8///
9/// This marker is useful for cases where a user needs to check documentation to figure out what
10/// happens.
11///
12/// It is not *strictly* necessary that the clone function doesn't behave like
13/// [`IndependentClone::independent_clone`] or [`MirroredClone::mirrored_clone`], but this type is
14/// not a catch-all for "some sort of clone, maybe also implements [`IndependentClone`] or
15/// [`MirroredClone`]".
16///
17/// This crate *will* provide a better tool for abstracting over all three modes of cloning
18/// provided. It just isn't provided yet. This isn't it.
19///
20/// [`IndependentClone`]: crate::IndependentClone
21/// [`IndependentClone::independent_clone`]: crate::IndependentClone::independent_clone
22/// [`MirroredClone`]: crate::MirroredClone
23/// [`MirroredClone::mirrored_clone`]: crate::MirroredClone::mirrored_clone
24pub trait MixedClone<S: Speed>: Sized {
25 /// Get a clone that could share some but not all semantically-important mutable state.
26 ///
27 /// Exact behavior is very implementation-dependent.
28 ///
29 /// Read [`MixedClone`] for more.
30 #[must_use]
31 fn mixed_clone(&self) -> Self;
32}
33
34
35macro_rules! non_recursive_near_instant {
36 ($($({for $($bounds:tt)+})? $type:ty),* $(,)?) => {
37 $(
38 impl<$($($bounds)+)?> MixedClone<NearInstant> for $type {
39 #[inline]
40 fn mixed_clone(&self) -> Self {
41 self.clone()
42 }
43 }
44 )*
45 };
46}
47
48non_recursive_near_instant! {
49 {for T: ?Sized} &T,
50 {for T: ?Sized} *const T,
51 {for T: ?Sized} *mut T,
52 {for T: ?Sized} core::ptr::NonNull<T>,
53}
54
55#[cfg(target_has_atomic = "ptr")]
56impl<T> MixedClone<NearInstant> for core::sync::atomic::AtomicPtr<T> {
57 #[inline]
58 fn mixed_clone(&self) -> Self {
59 Self::new(self.load(core::sync::atomic::Ordering::Relaxed))
60 }
61}
62
63#[cfg(feature = "alloc")]
64impl<S: Speed, T: ?Sized + alloc::borrow::ToOwned> MixedClone<S> for alloc::borrow::Cow<'_, T> {
65 #[inline]
66 fn mixed_clone(&self) -> Self {
67 self.clone()
68 }
69}
70
71// TODO: consider implementing ones with recursive constraints