Implementing generic trait with local struct on local trait


#1

Hi!

I encountered a problem, which I know has currently no solution, but I wanted help understanding why it’s not allowed. I have a struct Vector, which is a 2D vector, and a trait Scalar, which is implemented on e.g. f32. I want to be able to multiply a scalar by a vector, by implementing std::ops::Mul<Vector> on Scalar:

struct Vector {
    pub x: f32,
    pub y: f32,
}

impl Vector {
    fn new(x: f32, y: f32) -> Self {
        Vector { x, y }
    }
}

trait Scalar {
    fn to_float(self) -> f32;
}

// Vector-by-Scalar.  This works
impl<T: Scalar> std::ops::Mul<T> for Vector
{
    type Output = Vector;

    fn mul(self, rhs: T) -> Vector {
        let rhs = rhs.to_float();
        Vector::new(self.x * rhs, self.y * rhs)
    }
}

// Scalar-by-Vector.  This is not permitted
impl<T: Scalar> std::ops::Mul<Vector> for T
{
    type Output = Vector;

    fn mul(self, rhs: Vector) -> Vector {
        let lhs = self.to_float();
        Vector::new(lhs * rhs.x, lhs * rhs.y)
    }
}

When checking, I’m getting the following error:

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct<T>`)                                                                                          
  --> src/main.rs:28:1                                                                                                                                                                                
   |                                                                                                                                                                                                  
28 | impl<T: Scalar> std::ops::Mul<Vector> 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

Now, I found a thread that tells me I can’t implement, say, Display on Scalar, and I understand why: Display is defined outside the local crate. However, here, I want to implement Mul<Vector>, which is a generic trait parameterized by a local struct. In a sense, Mul<Vector> is itself akin to a local trait, right? Then, why is this not authorized?

Thank you very much for your time!


#2

This is the type of thing the following RFC attempts to allow (or fix, depending on your perspective):


#3

Alright, that answers my question. Thanks a lot!