Require commutative operation in Rust trait bound

267 Views Asked by At

Suppose I have a group of related non-scalar structs with a commutative arithmetic operation defined on them. For example,

struct Foo {
    a: f64,
    b: f64
}

impl Add<f64> for Foo {
    type Output = Foo;
    
    fn add(self, v: f64) -> Self::Output {
        Foo {
            a: self.a + v,
            b: self.b + v
        }
    }
}

impl Add<Foo> for f64 {
    type Output = Foo;
    
    fn add(self, foo: Foo) -> Self::Output {
        Foo {
            a: foo.a + self,
            b: foo.b + self
        }
    }
}

I want to implement a trait on this group of structs, taking advantage of this operation. That is, I want something like the following:

trait Bar: Add<f64, Output = Self> + Sized {
    fn right_add(self, f: f64) -> Self {
        self + f
    }
    
    // Doesn't compile!
    fn left_add(self, f: f64) -> Self {
        f + self
    }
}

However, this currently doesn't compile, since the super-trait bound doesn't include the left addition of f64 to Self. My question is: How can I state this commutative trait bound?

(Playground link.)

Edit: To be clear, I'm aware that right_add and left_add have the same output. I'm mainly interested in the ergonomics of not having to remember which is "correct" according to the compiler. In addition, I'm curious to learn how to do this, even if it's not strictly necessary.

1

There are 1 best solutions below

1
Aplet123 On BEST ANSWER

Inverted trait bounds like this are the exact usecase for where syntax:

trait Bar
where
    f64: Add<Self, Output = Self>,
    Self: Add<f64, Output = Self> + Sized,
{
    fn right_add(self, f: f64) -> Self {
        self + f
    }

    fn left_add(self, f: f64) -> Self {
        f + self
    }
}

Playground link