Should the Any trait provide as_any() methods?

It's really common for people to ask how to downcast given some trait Foo: Any {}, and we always give the same canned response:

Is it worth reworking the Any trait so it has auto-implemented as_any() and as_any_mut() methods? That way you won't need any dummy super-traits or have a family of incompatible as_any() methods.

trait Any {
  fn type_id(&self) -> TypeId { TypeId::of::<Self>() }

  fn as_any(&self) -> &dyn Any + 'static where Self: 'static { ... }
  fn as_any_mut(&mut self) -> &mut dyn Any + 'static where Self: 'static { ... }
}
1 Like

Some proposals related to this problem were discussed recently in the Rust Internals forum:

2 Likes

FWIW, the fact that Any has such a "weird" name makes it so my preferred solution in this case is to go with custom-made ::downcast-rs solutions, which do not require that many lines so I don't mind rewriting those each time I need it:

trait Downcast {
    fn as_any (self: &'_ Self)
      -> &'_ dyn Any
    where
        Self : 'static,
    ;

    // others if needed
}
impl<T> Downcast for T {
    fn as_any (self: &'_ Self)
      -> &'_ dyn Any
    where
        Self : 'static,
    {
        self
    }

    // ...
}

and then just add Downcast as a supertrait of the trait, leading to a quite intuitive behavior.

This has also the "benefit" (in some cases) of not imposing the 'static requirement for all the implementors of the "subtrait", only on the instances that do require the .as_any() call.

In other words, I don't find a trait called Downcast to be very "dummy" :smile:, that's why I'm fine either way (there is an argument for providing these methods to ease the usage of Any for beginners, that much is completely true)