There are lots of similar questions, but I couldn't find the answer to my exact question.
In my Rust code, I have a generic type and want to implement a method that takes a reference to another instance of the that type, and then another method that consumes its argument but does exactly the same thing as the first one:
#[derive(Debug, PartialEq, Clone)]
pub struct Wrapper<T> {
v: T,
}
impl<T> Wrapper<T> {
pub fn f_ref(&self, _other: &Wrapper<T>) { /* ... */ }
pub fn f_consume(&self, other: Wrapper<T>) {
self.f_ref(&other)
}
}
It compiles just fine.
Now I want to do basically the same, but while implementing a trait. First, the function that takes a reference:
use std::ops::AddAssign;
impl<'a, T> AddAssign<&'a Wrapper<T>> for Wrapper<T> where T: AddAssign<&'a T> {
fn add_assign(&mut self, other: &'a Wrapper<T>) {
self.v += &other.v;
}
}
#[test]
fn test() {
let mut a = Wrapper { v: 1_i32 };
let b = Wrapper { v: 2 };
a += &b;
drop(b);
assert_eq!(a, Wrapper { v: 3 });
}
It works, too.
Now I want to implement AddAssign
for Wrapper<T>
based on the implementation of AddAssign<&Wrapper<T>>
that I already have. I understand that if T
has references in it, it will cause trouble, so I make sure it has 'static
lifetime. I'm OK with it: in my program, I expect T
to be something like an owned matrix of numbers wrapped in some custom struct.
impl<'a, T> AddAssign for Wrapper<T> where T: 'static + AddAssign<&'a T>, Wrapper<T>: 'static {
fn add_assign(&mut self, other: Wrapper<T>) {
*self += &other;
}
}
And it fails. The compiler says that other
must stay valid after we used a reference to it to in a +=
expression. But when we used such a reference in the test()
function above and dropped b
there (which played the role of other
here) and used the result later, the compiler agreed it's OK. Why?
I suspect that I need to specify some additional trait bounds for T
or Wrapper<T>
but don't understand what these bound should be.