This is currently not possible to do in Rust, and it will never be possible; however, you can build similar abstractions as part of your trait:
trait Actor {
fn health(&self) -> Option<&Health>;
}
trait Health { }
impl Actor for Monster {
fn health(&self) -> Option<&Health> { Some(self) }
}
impl Health for Monster { }
impl Actor for Plant {
fn health(&self) -> Option<&Health> { None }
}
, - ; , - :
trait MaybeImplements<Trait: ?Sized> {
fn as_trait_ref(&self) -> Option<&Trait>;
}
macro_rules! impl_maybe_implements {
($trait_:ident) => {
impl<T: $trait_> MaybeImplements<$trait_> for T {
fn as_trait_ref(&self) -> Option<&$trait_> {
Some(self)
}
}
impl<T: !$trait_> MaybeImplements<$trait_> for T {
fn as_trait_ref(&self) -> Option<&$trait_> {
None
}
}
}
}
impl_maybe_implements!(Health);
trait Actor: MaybeImplements<Health> {
}
let health: Option<&Health> = actor.as_trait_ref();
, . , :
trait MaybeImplements<Trait: ?Sized> {
fn as_trait_ref(&self) -> Option<&Trait>;
}
macro_rules! register_impl {
($trait_:ident for $ty:ty) => {
impl MaybeImplements<$trait_> for $ty {
fn as_trait_ref(&self) -> Option<$trait_> {
Some(self)
}
}
}
(!$trait_:ident for $ty:ty) => {
impl MaybeImplements<$trait_> for $ty {
fn as_trait_ref(&self) -> Option<$trait_> {
None
}
}
}
}
register_impl!(Health for Monster);
register_impl!(!Health for Plant);
, , ! ! ( Rust - Turing-complete.)