For some things I'm playing around with I wanted a little (math) vector, and decided to write it generically as a good exercise.
I wrote up the addition operators, taking ownership of everything, and it all went great.
#[derive(Debug)]
struct Vec2<T>(T, T);
use std::ops::Add;
impl<T> Add for Vec2<T> where T : Add {
type Output = Vec2<T::Output>;
fn add(self, rhs: Vec2<T>) -> Self::Output {
Vec2(self.0 + rhs.0, self.1 + rhs.1)
}
}
use std::ops::AddAssign;
impl<T> AddAssign for Vec2<T> where T : AddAssign {
fn add_assign(&mut self, rhs: Vec2<T>) {
self.0 += rhs.0;
self.1 += rhs.1;
}
}
fn main() {
let mut a = Vec2(1, 2);
let b = Vec2(3, 4);
let c = Vec2(5, 6);
a += b + c;
println!("{:?}", a);
}
But then I tried to consume a value twice, which of course didn't work.
Ok, no problem, I'll just implement versions on borrows. After a few tries I get all the &'a
s in the right place, or at least the compiler is happy
impl<'a, T> Add for &'a Vec2<T> where &'a T : Add {
type Output = Vec2< <&'a T as Add>::Output >;
fn add(self, rhs: &'a Vec2<T>) -> Self::Output {
Vec2(&self.0 + &rhs.0, &self.1 + &rhs.1)
}
}
impl<'a, T> AddAssign<&'a Vec2<T>> for Vec2<T> where T : AddAssign<&'a T> {
fn add_assign(&mut self, rhs: &'a Vec2<T>) {
self.0 += &rhs.0;
self.1 += &rhs.1;
}
}
And my Add
is working fine with borrows:
fn main() {
let mut a = Vec2(1, 2);
let b = Vec2(3, 4);
let c = &a + &b;
a += &b + &c;
println!("{:?}", a);
}
But when I try to use AddAssign
with borrows,
fn main() {
let mut a = Vec2(1, 2);
let b = Vec2(3, 4);
let c = &a + &b;
a += &c;
println!("{:?} {:?}", a, c);
}
I get expected struct `Vec2`, found &Vec2<_>
?! (Or, if I remove the move impl
, cannot use `+=` on type `Vec2<{integer}>`
.)
Checking the docs more closely, I see all of
impl Add<i32> for i32
impl<'a> Add<i32> for &'a i32
impl<'a> Add<&'a i32> for i32
impl<'a, 'b> Add<&'a i32> for &'b i32
but only
impl AddAssign<i32> for i32
Did I write my impl AddAssign
incorrectly? Is there something about Rust that would prevent having the following?
impl<'a> AddAssign<&'a i32> for i32
(Obviously if I'm only using i32
I could just T:Copy
it, but that feels wrong, even though I won't actually be using Vec2<BigInteger>
.)
Edit: Weird, the details collapsers around some of the code worked in the preview, but not when saved.