Left multiplication for custom template type

I am trying to get familiar with Rust and implement some code for learning the ropes. I got stuck here with left-multiplication:

impl<K: Float> ops::Mul<Vec2<K>> for K {
    type Output = Vec2<K>;
    fn mul(self, rhs: Vec2<K>) -> Vec2<K> {
        Vec2::new(self * rhs.x, self * rhs.y)
    }
}

It gives an error which I don't understand and I am not able to find a solution on other sites:
error: type parameter `K` must be covered by another type when it appears before the first local type

My goal is to allow 2.0 * v where v is a custom template type. How can I do that?

Basically you can't, because that type could have already defined a blanket impl that would conflict.

I could have written

struct Foo;
impl<T> ops::Mul<T> for Foo {
    ... whatever ...
}

and that would conflict with your implementation for Vec2.

So you have two basic options:

  1. Accept just v * 2.0 instead
  2. Use macros to generate impls for f32 and f64 specifically instead of doing generics.
1 Like

You can't have a generic (non-local) K on the left-hand-side in this case. Some other crate might have a K: Float where they defined ops::Mul<T> for K for a generic T that covers your Vec2<K>, and that would result in multiple implementations for the same type.

Making sure the implementations are unambiguous is the role of coherence, and these particular rules are called the orphan rules. You can find the precise rules here. Using that terminology, K is an uncovered type parameter in position T0, while your local type is in position T1.

You could cover the generic K with a local type, though this won't be as ergonomic.

// Probably you'd pick a different name...
pub struct LocalCover<T>(pub T);

impl<K: Float> ops::Mul<Vec2<K>> for LocalCover<K> {
    type Output = Vec2<K>;
    fn mul(self, rhs: Vec2<K>) -> Vec2<K> {
        Vec2::new(self.0 * rhs.x, self.0 * rhs.y)
    }
}

// Elsewhere: let v = LocalCover(2.0) * v;

Otherwise you need non-generic implementations for the left-hand case.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.