This is something I’ve wanted for a while now, which I run into occasionally:
trait A {
type K;
fn foo(self) -> Self::K;
}
trait B: A { // note that B: A. this is required!
fn bar(self) -> Self;
// the gramatical change here
// is that associated items allow paths,
// rather than identifiers, for their names
type A::K = Self;
fn A::foo(self) -> Self { self.bar() }
}
With this definition we have the following desugaring:
impl B for C {
fn bar(self) -> Self { self.baz() }
}
// if the following impl is permitted by
// coherence and orphan rules, it is automatically
// generated. Note that it is *not* a blanket <T: B> impl!
impl A for C {
type K = Self;
fn foo(self) -> Self { self.bar() }
}
The use-case I care about is the following, for a numerics project I’m working on:
/// an algebra over F_2
trait F2Alg: Add<Self> + AddAssign<Self> + Mul<Self> + MulAssign<Self> {
fn add(self) -> Self;
fn mul(self) -> Self;
fn zero() -> Self;
fn one() -> Self;
type Add::Output = Self;
fn Add::add(self, that: Self) -> Self { F2Alg::add(self, that) }
// and so on
}
// an impl for one of the algebras I work with
impl F2Alg for Milnor {
fn add(self) -> Self { .. }
// ..
}
I deal with this by generating operator impls via macros, but it’s quite cumbersome. I’m not aware of where the delegation RFC ended up going, but this is of a distinctly different flavor of what that was about AFAIK; this is at trait-definition time, rather than at implementation time.
This would also make implementing some of the num
traits for custom numerics much less of a hassle (as with any large trait hierarchy).