anymap3/
any.rs

1#[cfg(not(feature = "std"))]
2use alloc::boxed::Box;
3use core::any::{Any, TypeId};
4use core::fmt;
5
6#[doc(hidden)]
7pub trait CloneToAny {
8    /// Clone `self` into a new `Box<dyn CloneAny>` object.
9    fn clone_to_any(&self) -> Box<dyn CloneAny>;
10}
11
12impl<T: Any + Clone> CloneToAny for T {
13    #[inline]
14    fn clone_to_any(&self) -> Box<dyn CloneAny> {
15        Box::new(self.clone())
16    }
17}
18
19macro_rules! impl_clone {
20    ($t:ty) => {
21        impl Clone for Box<$t> {
22            #[inline]
23            fn clone(&self) -> Box<$t> {
24                // SAFETY: this dance is to reapply any Send/Sync marker. I’m not happy about this
25                // approach, given that I used to do it in safe code, but then came a dodgy
26                // future-compatibility warning where_clauses_object_safety, which is spurious for
27                // auto traits but still super annoying (future-compatibility lints seem to mean
28                // your bin crate needs a corresponding allow!). Although I explained my plight¹
29                // and it was all explained and agreed upon, no action has been taken. So I finally
30                // caved and worked around it by doing it this way, which matches what’s done for
31                // core::any², so it’s probably not *too* bad.
32                //
33                // ¹ https://github.com/rust-lang/rust/issues/51443#issuecomment-421988013
34                // ² https://github.com/rust-lang/rust/blob/e7825f2b690c9a0d21b6f6d84c404bb53b151b38/library/alloc/src/boxed.rs#L1613-L1616
35                let clone: Box<dyn CloneAny> = (**self).clone_to_any();
36                let raw: *mut dyn CloneAny = Box::into_raw(clone);
37
38                // SAFETY:
39                // There's a future incompat warning ptr_cast_add_auto_to_object tracked in [1]
40                // that warns when you use a pointer cast to add auto traits to a dyn Trait
41                // pointer.
42                //
43                // The issue that it is trying to avoid is that the trait may have methods that
44                // are conditional on the auto traits. e.g.
45                //
46                //    #![feature(arbitrary_self_types)]
47                //    trait Trait {
48                //        fn func(self: *const Self) where Self: Send;
49                //    }
50                //
51                // If this happens then the vtable for dyn Trait and the vtable for dyn Trait + Send
52                // may be different and so casting between pointers to each is UB.
53                //
54                // In our case we only care about the CloneAny trait. It has no methods that are
55                // conditional on any auto traits. This means that the vtable will always be the
56                // same and so the future incompatibility lint doesn't apply here.
57                //
58                // So, to avoid the lint, we use a transmute here instead of a pointer cast. As
59                // described in [1], that is the recommended way to suppress the warning.
60                //
61                // [1]: https://github.com/rust-lang/rust/issues/127323
62                unsafe { Box::from_raw(std::mem::transmute::<*mut dyn CloneAny, *mut _>(raw)) }
63            }
64        }
65
66        impl fmt::Debug for $t {
67            #[inline]
68            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69                f.pad(stringify!($t))
70            }
71        }
72    };
73}
74
75/// Methods for downcasting from an `Any`-like trait object.
76///
77/// This should only be implemented on trait objects for subtraits of `Any`, though you can
78/// implement it for other types and it’ll work fine, so long as your implementation is correct.
79pub trait Downcast {
80    /// Gets the `TypeId` of `self`.
81    fn type_id(&self) -> TypeId;
82
83    // Note the bound through these downcast methods is 'static, rather than the inexpressible
84    // concept of Self-but-as-a-trait (where Self is `dyn Trait`). This is sufficient, exceeding
85    // TypeId’s requirements. Sure, you *can* do CloneAny.downcast_unchecked::<NotClone>() and the
86    // type system won’t protect you, but that doesn’t introduce any unsafety: the method is
87    // already unsafe because you can specify the wrong type, and if this were exposing safe
88    // downcasting, CloneAny.downcast::<NotClone>() would just return an error, which is just as
89    // correct.
90    //
91    // Now in theory we could also add T: ?Sized, but that doesn’t play nicely with the common
92    // implementation, so I’m doing without it.
93
94    /// Downcast from `&Any` to `&T`, without checking the type matches.
95    ///
96    /// # Safety
97    ///
98    /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*.
99    unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T;
100
101    /// Downcast from `&mut Any` to `&mut T`, without checking the type matches.
102    ///
103    /// # Safety
104    ///
105    /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*.
106    unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T;
107
108    /// Downcast from `Box<Any>` to `Box<T>`, without checking the type matches.
109    ///
110    /// # Safety
111    ///
112    /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour*.
113    unsafe fn downcast_unchecked<T: 'static>(self: Box<Self>) -> Box<T>;
114}
115
116/// A trait for the conversion of an object into a boxed trait object.
117pub trait IntoBox<A: ?Sized + Downcast>: Any {
118    /// Convert self into the appropriate boxed form.
119    fn into_box(self) -> Box<A>;
120}
121
122macro_rules! implement {
123    ($any_trait:ident $(+ $auto_traits:ident)*) => {
124        impl Downcast for dyn $any_trait $(+ $auto_traits)* {
125            #[inline]
126            fn type_id(&self) -> TypeId {
127                self.type_id()
128            }
129
130            #[inline]
131            unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
132                &*(self as *const Self as *const T)
133            }
134
135            #[inline]
136            unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
137                &mut *(self as *mut Self as *mut T)
138            }
139
140            #[inline]
141            unsafe fn downcast_unchecked<T: 'static>(self: Box<Self>) -> Box<T> {
142                Box::from_raw(Box::into_raw(self) as *mut T)
143            }
144        }
145
146        impl<T: $any_trait $(+ $auto_traits)*> IntoBox<dyn $any_trait $(+ $auto_traits)*> for T {
147            #[inline]
148            fn into_box(self) -> Box<dyn $any_trait $(+ $auto_traits)*> {
149                Box::new(self)
150            }
151        }
152    }
153}
154
155implement!(Any);
156implement!(Any + Send);
157implement!(Any + Send + Sync);
158
159/// [`Any`], but with cloning.
160///
161/// Every type with no non-`'static` references that implements `Clone` implements `CloneAny`.
162/// See [`core::any`] for more details on `Any` in general.
163pub trait CloneAny: Any + CloneToAny {}
164impl<T: Any + Clone> CloneAny for T {}
165implement!(CloneAny);
166implement!(CloneAny + Send);
167implement!(CloneAny + Send + Sync);
168impl_clone!(dyn CloneAny);
169impl_clone!(dyn CloneAny + Send);
170impl_clone!(dyn CloneAny + Send + Sync);