Cursed Pattern for specialization

i found myself in need of specialization for a function and ended up discovering this pattern

use std::any::{Any,TypeId};
pub trait SomeTrait:Sized+'static{
    fn do_stuff(myself:Self)->i32{
        let dyn_self:&dyn Any=&myself;
        if TypeId::of::<Self>()==TypeId::of::<i32>(){
            return *(dyn_self.downcast_ref()).unwrap()
        }
        if TypeId::of::<Self>()==TypeId::of::<u32>(){
            return *(dyn_self.downcast_ref::<u32>()).unwrap() as i32
        }
        non_specialized_impl(self)
    }
}
impl SomeTrait for i32{
}
impl SomeTrait for u32{
}

which thanks to const folding is actually zero cost. not much else to say, probably something to avoid in general but i thought it might still amuse you all

1 Like

Wouldn’t if let Some(int) = dyn_self.downcast_ref::<i32>() { ... } be better?

It already does the TypeId check for you.

3 Likes

See also the recently added unstable try_as_dyn which allows you to try to coerce a value of any Any + 'static type to a dyn Trait for any trait, permitting hilarious parametricity-violating shenanigans (for the win in some cases, such as coercing to a dyn Debug without having to potentially add zillions of Debug bounds just to debug something).

1 Like