2

I'm trying to implement Add for a simple generic type:

use std::ops::Add;

pub struct Vector2<T> {
    x: T,
    y: T,
}

impl<T> Vector2<T> {
    fn new(x: T, y: T) -> Self {
        Vector2::<T> { x, y }
    }
}

impl<T: Add> Add<Vector2<T>> for Vector2<T> {
    type Output = Vector2<T>;

    fn add(self, other: Vector2<T>) -> Vector2<T> {
        let x = self.x + other.x;
        let y = self.y + other.y;

        Vector2::<T> {
            x: self.x + other.x,
            y: self.y + other.y,
        }
    }
}

Here's the result:

error[E0308]: mismatched types
  --> src/main.rs:22:16
   |
22 |             x: self.x + other.x,
   |                ^^^^^^^^^^^^^^^^ expected type parameter, found associated type
   |
   = note: expected type `T`
              found type `<T as std::ops::Add>::Output`

If I interpret this correctly, it's saying "You said you were giving me T, but instead all I have is the result of T + T, and I don't have visibility to know whether that is T."

How do I explain to the compiler that T not only implements Add, but it does so in a way that returns the same type?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Damian
  • 53
  • 4

1 Answers1

4

The problem you are facing is that a generic T + the same T is not necessarily T.

Your Add impl has to look something like this:

impl<T: Add> Add<Vector2<T>> for Vector2<T> {
    type Output = Vector2<<T as Add>::Output>;

    fn add(self, other: Vector2<T>) -> Self::Output {
        Vector2 {
            x: self.x + other.x,
            y: self.y + other.y,
        }
    }
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
hellow
  • 12,430
  • 7
  • 56
  • 79
  • Ah! I see now. Instead of convincing the compiler the result would be T, type the output to be flexible. Perfect. Thanks! – Damian Jul 30 '18 at 07:52