I can't find a way to implement Add when primitive type is on the left side of addition:
#[derive(Clone, Copy, Debug, PartialEq)]
struct Point<T> {
x: T,
y: T,
}
impl<T> Add<T> for Point<T>
where
T: Copy + PartialEq + Default + Add<Output = T> + PartialOrd,
{
type Output = Point<T>;
fn add(self, right: T) -> Point<T> {
Point {
x: self.x + right,
y: self.y + right,
}
}
}
#[cfg(test)]
mod tests {
// Note this useful idiom: importing names from outer (for mod tests) scope.
use super::*;
#[test]
fn test_add_Point_and_f32() {
assert_eq!(Point { x: 1., y: 1. } + 1., Point { x: 2., y: 2. });
}
#[test]
fn test_add_f32_and_Point() {
assert_eq!(1. + Point { x: 1., y: 1. }, Point { x: 2., y: 2. });
}
}
The first test is working as expected, but the second one failed.
Why rust compiler doesn't guess that the order doesn't change the final result ?
I need to add f32 from any side, but rust restricts things to current crate. Such a restriction should be able to be bypassed by an attribute.
first, addition is not necessarily commutative. more importantly, the + operator desugars to a method call with different type for the self receiver.
the "restriction" you mentioned is called coherent rule. it's necessary to to ensure the type system can be locally checked.
for this particular case, it's might be possible to implement the Add trait for the concrete type (e.g. f32 or f64), but I don't think a blanket implementation is possible due to coherence.
impl Add<Point<f64>> for f64 {
type Output = Point<f64>;
fn add(self, rhs: Point<f64>) -> Point<f64> {
Point {
x: self + rhs.x,
y: self + rhs.y,
}
}
}
#[test]
fn test_add_f32_and_Point() {
assert_eq!(1. + Point { x: 1., y: 1. }, Point { x: 2., y: 2. });
}