This is somewhat of a haphazard pre-RFC because it’s really just a collection of paper-cuts.
Motivation
- This would allow private trait helper methods.
- This would allow non-overridable methods on traits.
- This would allow (some) generic trait methods to be called on trait objects. Really, all the
map, fold, etc. functions on Iterator should be implemented this way but it might be a bit late to change that.
Specifically motivated by: https://users.rust-lang.org/t/dynamic-dispatch-and-sized-trait/2918
Design (ish)
Basically, fix the following 4 comments (if possible).
trait Test {
fn call_test(&self) {
// 1. Complains about missing test method. This should (be made to) work.
self.priv_test(0);
// 2. Complains that Self isn't Sized. Is there any reason this can't work?
(self as &Test).priv_test(0);
}
}
// 3. I shouldn't need to specify this lifetime but, if I don't, `&something as &Test`
// complains about `something` not having a static lifetime (because this defaults to
// `impl Test + 'static`). As far as I can tell, this case isn't specified in any of
// the object lifetime bounds RFCs.
impl<'a> Test + 'a {
fn priv_test<A>(&self, a: A) { }
pub fn pub_test<A>(&self, a: A) { }
}
struct MyStruct;
impl Test for MyStruct { }
fn main() {
let s = MyStruct;
// 4. It should be possible to call this method directly.
s.pub_test(0);
}
Drawbacks
Dynamic dispatch. The trait methods rely on dynamic dispatch so calls back into the trait would be somewhat slower in a naive implementation. However, it should be possible to optimize this when the receiver’s type is actually known.