Right now apparently static methods cannot be called from trait objects. Is there any inherent reason why this is the case? It seems like trait objects could easily grow vtable slots to include static methods?
My motivating use case is a size_hint() method used in Askama Template trait. It used to take &self, but someone reasonably pointed out that, since the size was computed at compile time, the parameter wasn’t needed. However, I then got an issue that templates can now no longer be used as trait objects, which is desirable in some use cases to prevent code size blowup.
I’m happy to write up an RFC if this turns out to be non-controversial, but maybe there’s something I’m overlooking.
This seems to indicate that it could be safely done. It seems like if you are able to implement manually this way, then, the compiler could relatively easily grow a vtable to support it.
So, my idea of having a default delegating implementation for dyn_size_hintdoesn’t actually work, there might be some way to structure this so that you don’t need to implement both methods for every implementation, but best I could come up with quickly is
This two-trait solution looks like an improvement, in particular it means that size_hint can be called for all T: Sized + Template, and dyn_size_hint can be called on any T: TemplateDyn, including unsized types like str and [u8] if they implement both traits.
There’s one case that the above doesn’t support: you can’t call size_hint (the static version) on unsized types other than the trait object type, such as str and [u8]. However, with a couple tweaks this is possible:
If the Template trait has other non-static methods, you can either copy them into TemplateDyn and delegate to the Template implementation in the impl<T: Template + ?Sized> TemplateDyn for T block, or use a common subtrait with a name like TemplateBase. The first option would be more work for the library maintainer but would provide a slightly nicer API for implementors.