`downcast-rs` vs `Any`?

I don't get the purpose of downcast_rs - Rust. It's look like Any in std::any - Rust already allow downcasting.

So what is the benefit of using downcast_rs - Rust ?

It's useful for sub-traits, due to an important nuance in the:

statement:

  • Any allows dynamically querying the TypeId of a type, and thus, "descendants" such as trait MyTrait : Any will also allow it for dyn MyTrait.

From there, one, such as the stdlib did for dyn Any specifically, can implement downcasting by comparing typeids and performing an unsafe type cast / type transmutation.

In other words, technically, only dyn Any ... specifically implements / feature non-unsafe downcasting.

That is, given trait MyTrait : Any, you won't be able to call .downcast_ref() on a dyn MyTrait !

This is likely to be fixed or at least palliated in the future, since on nightly with the feature(trait_upcasting), one can call <dyn Any>::downcast...() on a dyn MyTrait.

But in stable Rust, this requires one of two things:

  • either you reïmplement the downcasting functionality off .type_id(), which is unsafe but only requires one virtual call (.type_id()), making it as efficient as calling it on dyn Any;

  • or you feature manual upcasting to dyn Any through an extra helper virtual method, making downcasting non-unsafe but cost twice as many virtual calls.

There may be a few instances of the former in the wild, but there is no helper crate for this to my knowledge (imho the stdlib should have been the one providing this through some helper extension-method trait (for all impl ?Sized + Any), but at this point trait_upcasting doesn't make it worth any more).

downcast-rs, on the other hand, is a helper to go for the latter approach: its Downcast trait, is actually a trait featuring upcasting[1] methods (to dyn Any, one for each commonly-used pointer version) and then the impl_Downcast! macro takes care of implementing the actual downcasting methods thanks to these upcasting ones.


  1. image ↩︎

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.