use std::any::Any;
pub trait DynEq: Any {
#[doc(hidden)]
fn as_any(&self) -> &dyn Any;
#[doc(hidden)]
fn dyn_eq(&self, other: &dyn Any) -> bool;
}
impl<T: Eq + 'static> DynEq for T {
fn as_any(&self) -> &dyn Any {
self
}
fn dyn_eq(&self, other: &dyn Any) -> bool {
other.downcast_ref::<T>().is_some_and(|other| self == other)
}
}
pub use crate::eq_trait_object;
#[macro_export]
macro_rules! eq_trait_object {
($trait:ident) => {
$crate::__eq_trait_object!($trait,);
$crate::__eq_trait_object!($trait, + ::core::marker::Send);
$crate::__eq_trait_object!($trait, + ::core::marker::Sync);
$crate::__eq_trait_object!($trait, + ::core::marker::Send + ::core::marker::Sync);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __eq_trait_object {
($trait:ident, $($auto:tt)*) => {
impl<'eq> ::core::cmp::PartialEq for dyn $trait $($auto)* + 'eq {
fn eq(&self, other: &Self) -> bool {
$crate::dyn_eq::DynEq::dyn_eq(self, $crate::dyn_eq::DynEq::as_any(other))
}
}
impl<'eq> ::core::cmp::Eq for dyn $trait $($auto)* + 'eq {}
impl<'eq> ::core::cmp::PartialEq<&Self> for ::std::boxed::Box<dyn $trait $($auto)* + 'eq> {
fn eq(&self, other: &&Self) -> bool {
self == *other
}
}
};
}