2022-01-25 19:47:19 +11:00
|
|
|
|
use core::fmt;
|
|
|
|
|
use core::any::Any;
|
2022-01-25 21:24:48 +11:00
|
|
|
|
#[cfg(not(feature = "std"))]
|
|
|
|
|
use alloc::boxed::Box;
|
2015-04-25 14:01:01 +10:00
|
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
|
pub trait CloneToAny {
|
2022-01-25 12:57:35 +11:00
|
|
|
|
/// Clone `self` into a new `Box<dyn CloneAny>` object.
|
|
|
|
|
fn clone_to_any(&self) -> Box<dyn CloneAny>;
|
2015-04-25 14:01:01 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: Any + Clone> CloneToAny for T {
|
2016-06-11 13:30:33 +10:00
|
|
|
|
#[inline]
|
2022-01-25 12:57:35 +11:00
|
|
|
|
fn clone_to_any(&self) -> Box<dyn CloneAny> {
|
2015-04-25 14:01:01 +10:00
|
|
|
|
Box::new(self.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! impl_clone {
|
2022-01-25 13:48:23 +11:00
|
|
|
|
($t:ty) => {
|
2015-04-25 14:01:01 +10:00
|
|
|
|
impl Clone for Box<$t> {
|
2016-06-11 13:30:33 +10:00
|
|
|
|
#[inline]
|
2015-04-25 14:01:01 +10:00
|
|
|
|
fn clone(&self) -> Box<$t> {
|
2022-01-25 13:48:23 +11:00
|
|
|
|
// SAFETY: this dance is to reapply any Send/Sync marker. I’m not happy about this
|
|
|
|
|
// approach, given that I used to do it in safe code, but then came a dodgy
|
|
|
|
|
// future-compatibility warning where_clauses_object_safety, which is spurious for
|
|
|
|
|
// auto traits but still super annoying (future-compatibility lints seem to mean
|
|
|
|
|
// your bin crate needs a corresponding allow!). Although I explained my plight¹
|
|
|
|
|
// and it was all explained and agreed upon, no action has been taken. So I finally
|
|
|
|
|
// caved and worked around it by doing it this way, which matches what’s done for
|
2022-01-25 19:47:19 +11:00
|
|
|
|
// core::any², so it’s probably not *too* bad.
|
2022-01-25 13:48:23 +11:00
|
|
|
|
//
|
|
|
|
|
// ¹ https://github.com/rust-lang/rust/issues/51443#issuecomment-421988013
|
|
|
|
|
// ² https://github.com/rust-lang/rust/blob/e7825f2b690c9a0d21b6f6d84c404bb53b151b38/library/alloc/src/boxed.rs#L1613-L1616
|
|
|
|
|
let clone: Box<dyn CloneAny> = (**self).clone_to_any();
|
|
|
|
|
let raw: *mut dyn CloneAny = Box::into_raw(clone);
|
|
|
|
|
unsafe { Box::from_raw(raw as *mut $t) }
|
2015-04-25 14:01:01 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-25 15:59:28 +11:00
|
|
|
|
|
|
|
|
|
impl fmt::Debug for $t {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
|
f.pad(stringify!($t))
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-04-25 14:01:01 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[allow(missing_docs)] // Bogus warning (it’s not public outside the crate), ☹
|
|
|
|
|
pub trait UncheckedAnyExt: Any {
|
|
|
|
|
unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T;
|
|
|
|
|
unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T;
|
|
|
|
|
unsafe fn downcast_unchecked<T: Any>(self: Box<Self>) -> Box<T>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
|
/// A trait for the conversion of an object into a boxed trait object.
|
|
|
|
|
pub trait IntoBox<A: ?Sized + UncheckedAnyExt>: Any {
|
|
|
|
|
/// Convert self into the appropriate boxed form.
|
|
|
|
|
fn into_box(self) -> Box<A>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! implement {
|
|
|
|
|
($base:ident, $(+ $bounds:ident)*) => {
|
2022-01-25 12:57:35 +11:00
|
|
|
|
impl UncheckedAnyExt for dyn $base $(+ $bounds)* {
|
2016-06-11 13:30:33 +10:00
|
|
|
|
#[inline]
|
2015-04-25 14:01:01 +10:00
|
|
|
|
unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
|
2016-06-11 10:46:30 +10:00
|
|
|
|
&*(self as *const Self as *const T)
|
2015-04-25 14:01:01 +10:00
|
|
|
|
}
|
|
|
|
|
|
2016-06-11 13:30:33 +10:00
|
|
|
|
#[inline]
|
2015-04-25 14:01:01 +10:00
|
|
|
|
unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
|
2016-06-11 10:46:30 +10:00
|
|
|
|
&mut *(self as *mut Self as *mut T)
|
2015-04-25 14:01:01 +10:00
|
|
|
|
}
|
|
|
|
|
|
2016-06-11 13:30:33 +10:00
|
|
|
|
#[inline]
|
2015-04-25 14:01:01 +10:00
|
|
|
|
unsafe fn downcast_unchecked<T: 'static>(self: Box<Self>) -> Box<T> {
|
2016-06-11 10:46:30 +10:00
|
|
|
|
Box::from_raw(Box::into_raw(self) as *mut T)
|
2015-04-25 14:01:01 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-25 12:57:35 +11:00
|
|
|
|
impl<T: $base $(+ $bounds)*> IntoBox<dyn $base $(+ $bounds)*> for T {
|
2016-06-11 13:30:33 +10:00
|
|
|
|
#[inline]
|
2022-01-25 12:57:35 +11:00
|
|
|
|
fn into_box(self) -> Box<dyn $base $(+ $bounds)*> {
|
2015-04-25 14:01:01 +10:00
|
|
|
|
Box::new(self)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
implement!(Any,);
|
|
|
|
|
implement!(Any, + Send);
|
|
|
|
|
implement!(Any, + Send + Sync);
|
2022-01-25 13:06:15 +11:00
|
|
|
|
|
2022-01-25 15:59:28 +11:00
|
|
|
|
/// [`Any`], but with cloning.
|
2022-01-25 13:06:15 +11:00
|
|
|
|
///
|
2022-01-25 15:59:28 +11:00
|
|
|
|
/// Every type with no non-`'static` references that implements `Clone` implements `CloneAny`.
|
2022-01-25 19:47:19 +11:00
|
|
|
|
/// See [`core::any`] for more details on `Any` in general.
|
2022-01-25 13:06:15 +11:00
|
|
|
|
pub trait CloneAny: Any + CloneToAny { }
|
2022-01-25 15:59:28 +11:00
|
|
|
|
impl<T: Any + Clone> CloneAny for T { }
|
2015-04-25 14:01:01 +10:00
|
|
|
|
implement!(CloneAny,);
|
|
|
|
|
implement!(CloneAny, + Send);
|
|
|
|
|
implement!(CloneAny, + Send + Sync);
|
2022-01-25 13:48:23 +11:00
|
|
|
|
impl_clone!(dyn CloneAny);
|
|
|
|
|
impl_clone!(dyn CloneAny + Send);
|
|
|
|
|
impl_clone!(dyn CloneAny + Send + Sync);
|