use crate::libstd::{self, any};
pub trait AsAny: private::Sealed + any::Any {
fn as_any(&self) -> &dyn any::Any;
fn as_mut_any(&mut self) -> &mut dyn any::Any;
}
impl<T: any::Any> AsAny for T {
fn as_any(&self) -> &dyn any::Any {
self
}
fn as_mut_any(&mut self) -> &mut dyn any::Any {
self
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(any(noeldoc, docsrs), doc(cfg(any(feature = "std", feature = "alloc"))))]
pub trait AsArcAny: any::Any {
fn as_arc_any(self: libstd::Arc<Self>) -> libstd::Arc<dyn any::Any>;
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(any(noeldoc, docsrs), doc(cfg(any(feature = "std", feature = "alloc"))))]
impl<T: any::Any> AsArcAny for T {
fn as_arc_any(self: libstd::Arc<Self>) -> libstd::Arc<dyn any::Any> {
self
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(any(noeldoc, docsrs), doc(cfg(any(feature = "std", feature = "alloc"))))]
pub trait AsRcAny: any::Any {
fn as_rc_any(self: libstd::Rc<Self>) -> libstd::Rc<dyn any::Any>;
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(any(noeldoc, docsrs), doc(cfg(any(feature = "std", feature = "alloc"))))]
impl<T: any::Any> AsRcAny for T {
fn as_rc_any(self: libstd::Rc<Self>) -> libstd::Rc<dyn any::Any> {
self
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(any(noeldoc, docsrs), doc(cfg(any(feature = "std", feature = "alloc"))))]
pub trait AsBoxAny: any::Any {
fn as_box_any(self: libstd::Box<Self>) -> libstd::Box<dyn any::Any>;
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[cfg_attr(any(noeldoc, docsrs), doc(cfg(any(feature = "std", feature = "alloc"))))]
impl<T: any::Any> AsBoxAny for T {
fn as_box_any(self: libstd::Box<Self>) -> libstd::Box<dyn any::Any> {
self
}
}
#[macro_export]
#[cfg(not(upcast_for_dyn_any))]
macro_rules! impl_dyn_any {
($Ty:ident) => {
const _: () = {
impl dyn $Ty + 'static {
pub fn is<T: ::core::any::Any>(&self) -> bool {
::core::any::Any::type_id(self) == ::core::any::TypeId::of::<T>()
}
pub fn downcast<T: ::core::any::Any>(&self) -> ::core::option::Option<&T> {
if self.is::<T>() {
Some(unsafe { self.downcast_unchecked() })
} else {
None
}
}
pub fn downcast_mut<T: ::core::any::Any>(&mut self) -> ::core::option::Option<&mut T> {
if self.is::<T>() {
Some(unsafe { self.downcast_mut_unchecked() })
} else {
None
}
}
pub unsafe fn downcast_unchecked<T: ::core::any::Any>(&self) -> &T {
::core::debug_assert!(self.is::<T>());
unsafe { &*(self as *const dyn $Ty as *const T) }
}
pub unsafe fn downcast_mut_unchecked<T: ::core::any::Any>(&mut self) -> &mut T {
::core::debug_assert!(self.is::<T>());
unsafe { &mut *(self as *mut dyn $Ty as *mut T) }
}
}
impl dyn $Ty + Send + 'static {
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::is`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::is`]: trait.", stringify!($Ty), ".html#method.is")]
pub fn is<T: ::core::any::Any>(&self) -> bool {
<dyn $Ty>::is::<T>(self)
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast`]: trait.", stringify!($Ty), ".html#method.downcast")]
pub fn downcast<T: ::core::any::Any>(&self) -> Option<&T> {
<dyn $Ty>::downcast::<T>(self)
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast_mut`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast_mut`]: trait.", stringify!($Ty), ".html#method.downcast_mut")]
pub fn downcast_mut<T: ::core::any::Any>(&mut self) -> Option<&mut T> {
<dyn $Ty>::downcast_mut::<T>(self)
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast_unchecked`].")]
#[doc = concat!("Review the `Safety` section of [`<dyn ", stringify!($Ty), ">::downcast_unchecked`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast_unchecked`]: trait.", stringify!($Ty), ".html#method.downcast_unchecked")]
pub unsafe fn downcast_unchecked<T: ::core::any::Any>(&self) -> &T {
unsafe { <dyn $Ty>::downcast_unchecked::<T>(self) }
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast_mut_unchecked`].")]
#[doc = concat!("Review the `Safety` section of [`<dyn ", stringify!($Ty), ">::downcast_mut_unchecked`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast_mut_unchecked`]: trait.", stringify!($Ty), ".html#method.downcast_mut_unchecked")]
pub unsafe fn downcast_mut_unchecked<T: ::core::any::Any>(&mut self) -> &mut T {
unsafe { <dyn $Ty>::downcast_mut_unchecked::<T>(self) }
}
}
impl dyn $Ty + Send + Sync + 'static {
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::is`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::is`]: trait.", stringify!($Ty), ".html#method.is")]
pub fn is<T: ::core::any::Any>(&self) -> bool {
<dyn $Ty>::is::<T>(self)
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast`]: trait.", stringify!($Ty), ".html#method.downcast")]
pub fn downcast<T: ::core::any::Any>(&self) -> Option<&T> {
<dyn $Ty>::downcast::<T>(self)
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast_mut`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast_mut`]: trait.", stringify!($Ty), ".html#method.downcast_mut")]
pub fn downcast_mut<T: ::core::any::Any>(&mut self) -> Option<&mut T> {
<dyn $Ty>::downcast_mut::<T>(self)
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast_unchecked`].")]
#[doc = concat!("Review the `Safety` section of [`<dyn ", stringify!($Ty), ">::downcast_unchecked`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast_unchecked`]: trait.", stringify!($Ty), ".html#method.downcast_unchecked")]
pub unsafe fn downcast_unchecked<T: ::core::any::Any>(&self) -> &T {
unsafe { <dyn $Ty>::downcast_unchecked::<T>(self) }
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast_mut_unchecked`].")]
#[doc = concat!("Review the `Safety` section of [`<dyn ", stringify!($Ty), ">::downcast_mut_unchecked`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast_mut_unchecked`]: trait.", stringify!($Ty), ".html#method.downcast_mut_unchecked")]
pub unsafe fn downcast_mut_unchecked<T: ::core::any::Any>(&mut self) -> &mut T {
unsafe { <dyn $Ty>::downcast_mut_unchecked::<T>(self) }
}
}
};
};
}
#[macro_export]
#[cfg(upcast_for_dyn_any)] macro_rules! impl_dyn_any {
($Ty:ident) => {
const _: () = {
impl dyn $Ty + 'static {
pub fn is<T: ::core::any::Any>(&self) -> bool {
(self as &dyn ::core::any::Any).is::<T>()
}
pub fn downcast<T: ::core::any::Any>(&self) -> ::core::option::Option<&T> {
(self as &dyn ::core::any::Any).downcast_ref::<T>()
}
pub fn downcast_mut<T: ::core::any::Any>(&mut self) -> ::core::option::Option<&mut T> {
(self as &mut dyn ::core::any::Any).downcast_mut::<T>()
}
pub unsafe fn downcast_unchecked<T: ::core::any::Any>(&self) -> &T {
::core::debug_assert!(self.is::<T>());
unsafe { &*(self as *const dyn $Ty as *const T) }
}
pub unsafe fn downcast_mut_unchecked<T: ::core::any::Any>(&mut self) -> &mut T {
::core::debug_assert!(self.is::<T>());
unsafe { &mut *(self as *mut dyn $Ty as *mut T) }
}
}
impl dyn $Ty + Send + 'static {
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::is`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::is`]: trait.", stringify!($Ty), ".html#method.is")]
pub fn is<T: ::core::any::Any>(&self) -> bool {
<dyn $Ty>::is::<T>(self)
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast`]: trait.", stringify!($Ty), ".html#method.downcast")]
pub fn downcast<T: ::core::any::Any>(&self) -> Option<&T> {
<dyn $Ty>::downcast::<T>(self)
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast_mut`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast_mut`]: trait.", stringify!($Ty), ".html#method.downcast_mut")]
pub fn downcast_mut<T: ::core::any::Any>(&mut self) -> Option<&mut T> {
<dyn $Ty>::downcast_mut::<T>(self)
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast_unchecked`].")]
#[doc = concat!("Review the `Safety` section of [`<dyn ", stringify!($Ty), ">::downcast_unchecked`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast_unchecked`]: trait.", stringify!($Ty), ".html#method.downcast_unchecked")]
pub unsafe fn downcast_unchecked<T: ::core::any::Any>(&self) -> &T {
unsafe { <dyn $Ty>::downcast_unchecked::<T>(self) }
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast_mut_unchecked`].")]
#[doc = concat!("Review the `Safety` section of [`<dyn ", stringify!($Ty), ">::downcast_mut_unchecked`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast_mut_unchecked`]: trait.", stringify!($Ty), ".html#method.downcast_mut_unchecked")]
pub unsafe fn downcast_mut_unchecked<T: ::core::any::Any>(&mut self) -> &mut T {
unsafe { <dyn $Ty>::downcast_mut_unchecked::<T>(self) }
}
}
impl dyn $Ty + Send + Sync + 'static {
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::is`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::is`]: trait.", stringify!($Ty), ".html#method.is")]
pub fn is<T: ::core::any::Any>(&self) -> bool {
<dyn $Ty>::is::<T>(self)
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast`]: trait.", stringify!($Ty), ".html#method.downcast")]
pub fn downcast<T: ::core::any::Any>(&self) -> Option<&T> {
<dyn $Ty>::downcast::<T>(self)
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast_mut`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast_mut`]: trait.", stringify!($Ty), ".html#method.downcast_mut")]
pub fn downcast_mut<T: ::core::any::Any>(&mut self) -> Option<&mut T> {
<dyn $Ty>::downcast_mut::<T>(self)
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast_unchecked`].")]
#[doc = concat!("Review the `Safety` section of [`<dyn ", stringify!($Ty), ">::downcast_unchecked`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast_unchecked`]: trait.", stringify!($Ty), ".html#method.downcast_unchecked")]
pub unsafe fn downcast_unchecked<T: ::core::any::Any>(&self) -> &T {
unsafe { <dyn $Ty>::downcast_unchecked::<T>(self) }
}
#[doc = concat!("Forwards to [`<dyn ", stringify!($Ty), ">::downcast_mut_unchecked`].")]
#[doc = concat!("Review the `Safety` section of [`<dyn ", stringify!($Ty), ">::downcast_mut_unchecked`].")]
#[doc = concat!("[`<dyn ", stringify!($Ty), ">::downcast_mut_unchecked`]: trait.", stringify!($Ty), ".html#method.downcast_mut_unchecked")]
pub unsafe fn downcast_mut_unchecked<T: ::core::any::Any>(&mut self) -> &mut T {
unsafe { <dyn $Ty>::downcast_mut_unchecked::<T>(self) }
}
}
};
};
}
mod private {
pub trait Sealed {}
impl<T: ?Sized + super::AsAny> Sealed for T {}
}
#[cfg(test)]
mod tests {
#[cfg(upcast_for_dyn_any)]
#[allow(dead_code)]
#[test]
fn upcast_for_dyn_any_compiles_correctly() {
use core::any::Any;
trait A: Any {}
impl A for String {}
impl_dyn_any!(A);
let mut a: Box<dyn A> = Box::new(String::new());
assert!(a.is::<String>());
assert!(a.downcast::<String>().is_some());
assert!(a.downcast_mut::<String>().is_some());
}
}