# Proper Notation for Scalar Multiplication in Rust:

Dispatching on the Right-Hand Side of Operators and Rusts's Orphan Rule

2019-04-17
The scalar multiplication in a vector space is written *kv* in math,
where *k* is a scalar value (e.g. a number) and *v* is a vector.
It would be nice to write `k * v`

in programming languages,
to stay close to the familiar notation.
Object-oriented languages typically only support calling methods on the first argument.
But the scalar normally doesn't know about vectors, so it can't easily do that.

Python works around this with the `__rmul__`

special method
for defining the `*`

operator.
`__rmul__`

is called on the right-hand side object with the left-hand side as the argument,
the reverse of what `__mul__`

does.
This works well, but feels a bit like a hack.

In Rust each operator is defined via a single trait,
for example the binary operator `*`

is defined via
`std::ops::Mul`

.

The following code works for defining scalar multiplication with the desired order of operands (playground):

#[derive(Clone, Copy, Debug)] struct V(i64, i64); impl std::ops::Mul<V> for i64 { type Output = V; fn mul(self, v: V) -> V { V(self * v.0, self * v.1) } } fn main() { let v = V(1, 2); println!("{:?}", 3 * v); }As this example shows, we can add a new implementation for

`std::ops::Mul`

on the standard integer type `i64`

.
Normally you can only implement a trait for a type if either the trait or the type is defined in your crate.
This is the so-called *orphan rule* mentioned near the end of the section on
implementing a trait.
It is designed so that the crates defining the trait or the type can add implementations without breaking your code.

Both the type `i64`

and the trait `std::ops::Mul`

are defined in the standard library,
so why is the implementation above allowed?

The reference manual has an expanded definition of the orphan check, as it is called there:

At least one of eitherHere`Self`

or a generic type parameter of the trait must meet the following grammar, where`C`

is a nominal type defined within the containing crate:`T = C | &C | &mut C | Box<C>`

`Self`

is `i64`

, and
`V`

is a generic type parameter of `Mul`

.
So because `V`

appears in `std::ops::Mul<V>`

,
this implementation satisfies the orphan check.
Unfortunately the reference manual doesn't contain the whole story about the orphan rule. Most likely it hasn't been updated with the revised orphan rules from RFC 1023 and RFC 2451.

RFC 2451 contains the full details on the currently implemented orphan rule:

GivenA type parameter is`impl<P1..=Pn> Trait<T1..=Tn> for T0`

, an impl is valid only if at least one of the following is true:

`Trait`

is a local trait- All of

- At least one of the types
`T0..=Tn`

must be a local type. Let`Ti`

be the first such type.- No uncovered type parameters
`P1..=Pn`

may appear in`T0..Ti`

(excluding`Ti`

)

*covered*if it appears below a type constructor, for example the

`T`

is covered in `Vec<T>`

(except for fundamental types like `Box`

).
So our example is still allowed by the latest rule,
but we can't have a generic *blanket implementation* for all primitive types
(playground):

use std::fmt::Debug; #[derive(Clone, Copy, Debug)] struct V<T>(T, T) where T: Clone + Copy + Debug; impl<T> std::ops::Mul<V<T>> for T { type Output = V<T>; fn mul(self, v: V<T>) -> V<T> { V(self * v.0, self * v.1) } } fn main() { let v = V(1, 2); println!("{:?}", 3 * v); }The compiler rightly complains with the error message

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`) --> src/main.rs:8:1 | 8 | impl<T> std::ops::Mul<V<T>> for T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type | = note: only traits defined in the current crate can be implemented for a type parameter

However, we could have a blanket implementation if we accepted the reverse operand order (playground):

use std::fmt::Debug; use std::ops::Mul; #[derive(Clone, Copy, Debug)] struct V<T>(T, T) where T: Clone + Copy + Debug; impl<T> Mul<T> for V<T> where T: Clone + Copy + Debug + Mul<Output = T>, { type Output = V<T>; fn mul(self, k: T) -> V<T> { V(self.0 * k, self.1 * k) } } fn main() { let v = V(1, 2); println!("{:?}", v * 3); }Here the type variable

`T1=T`

appears after `T0=V<T>`

,
where `T`

is covered by `V`

,
so this is allowed by the orphan rule of RFC 2451.
The orphan rule is designed this way to avoid an overlap
between implementations in different crates.
For example, if crate 1 had an implementation with a local type `A`

for `T0`

and a type variable for `T1`

,
and conversely crate 2 had a local type `B`

for `T1`

and a type variable for `T0`

,
then the trait instance with `T0=A`

and `T1=B`

in some third crate could have two conflicting implementations.

If you want even more details you can read the not-so-brief brief history of Rust's orphan rule.