Description
This would allow one to emulate conventional OO inheritance (to some degree) automatically, instead of requiring a lot of boilerplate, e.g.
trait A {
fn foo(&self);
fn bar(&self);
fn baz(&self);
}
struct Basic {
some_field: int
}
impl A for Basic {
fn foo(&self) {}
fn bar(&self) {}
fn baz(&self) {}
}
struct Extended {
inner: Basic,
extra: int
}
#[delegate_to(inner)]
impl A for Extended {
fn foo(&self) {} // new version of `foo`
}
/* automatically created:
fn bar(&self) { self.inner.bar() }
fn baz(&self) { self.inner.baz() }
*/
This isn't possible as a syntax extension, since the methods in a trait are not known at expansion time. And methods returning Self
would have to be implemented by hand.
I guess this is similar to default methods. I think it would allow traits to replace the closures-in-structs pattern entirely (e.g. the ast visitor), since currently it's not easily possible to write Visitor { visit_expr: |e, (a,v)| { ... }, .. some_non_default_visitor }
(i.e. replacing only the visit_expr
method of a visitor defined elsewhere, which is not the default_visitor()
) in terms of default methods only (this came up in my attempt to replace the struct visitors in rustc::middle::lint
with @Aatch's trait+default-methods based one).
Related:
- similar discussion about subtyping & structs
- discussion about this proposal
- "Delegation" in Kotlin is very similar, but this proposal is possibly more flexible
A super-wishlist behaviour would be turning any recursive method calls (i.e. calling a method from the same trait) on the base type into calls on the extended type, so:
impl A for Base {
fn foo(&self) {
if some_condition { self.bar() }
}
fn bar(&self) {}
}
struct Extended { base: Base }
#[delegate_to(base)]
impl A for Extended {}
// is equivalent to
impl A for Extended {
fn foo(&self) {
if some_condition { self.bar() }
// different to plain self.inner.bar(), which is `if some_condition { self.base.bar() }`
}
fn bar(&self) { self.base.bar() }
}
(This is possibly possible by recording "a trait-self" against which to call methods from the same trait, I don't know.)