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 either 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>
Here 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:

Given 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)
A type parameter is 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.