"borrowed value does not live long enough", but why do we need it to live so long?

Viewed 85

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.

Code in playground.

0 Answers
Related