I'm starting to understand what Rust's coherence restrictions are, but it really seems like they aren't quite right. I've read "Little Orphan Impls", and it seems like there has to be a better way which just hasn't been considered yet.
As an example, consider a template Matrix type from one crate and Decimal type from another crate. The Matrix should support scalar multiplication on both the left and the right
let d: Decimal = value();
let m: Matrix<decimal> = ident();
let md = m * d;
let dm = d * m;
In the crate for Matrix, you can have:
impl<T: Mul<T, Output=T>> Mul<T> for Matrix<T> { ... }
But the symmetric implementation is not allowed:
impl<T: Mul<T, Output=T>> Mul<Matrix<T>> for T { ... }
This means you can't generically specify scalar multiplication from the left, and anyone who intends to use Rust for math or science should be a bit annoyed about that:
let md = m * d; // this one works just like you'd expect
let dm = d * m; // this one doesn't but really should
It turns out you can implement the trait if you don't use a type parameter:
impl Mul<Decimal> for Matrix { ... }
impl Mul<Matrix> for Decimal { ... }
And that naturally leads to a workaround using a macro to explicitly implement all the operators necessary to marry Decimal and Matrix. Something like:
implement_matrix_operators!(Decimal)
However, it seems like requiring macros to implement templates means that type parameters aren't doing what they should be. This same issue is going to come up in Complex numbers, linear algebra Vector, MultiArrays (tensors), Quaternions, and so on...
Is there any chance of fixing this in some future version of Rust?