Can't borrow Box<dyn Type>

trait Name<'a> {
    fn set_name(&'a mut self, s: &'a str);
}
struct User<'a> {
    name: &'a str,
}
impl<'a> Name<'a> for User<'a> {
    fn set_name(&'a mut self, s: &'a str) {
        self.name = s;
    }
}

fn main() {
    let b = "something";

    let mut a2: Box<dyn Name> = Box::new(User { name: "abc" });

    a2.set_name(b);
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0597]: `*a2` does not live long enough
  --> src/main.rs:18:5
   |
18 |     a2.set_name(b);
   |     ^^^^^^^^^^^^^^ borrowed value does not live long enough
19 | }
   | -
   | |
   | `*a2` dropped here while still borrowed
   | borrow might be used here, when `a2` is dropped and runs the destructor for type `Box<dyn Name<'_>>`

For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground` due to previous error

I'm struggling to understand this. Why is this not allowed?

This is a red flag in general and incorrect here, since it means &'a mut User<'a> - that is, "this unique reference must be valid for at least as long as the reference inside User is valid". In other words, call to set_name currently locks the User forever.

You want to use two (in fact, even three, counting the implicit one in &mut self, which is as long as the function call) distinct lifetimes, like this:

trait Name<'name> {
    fn set_name(&mut self, s: &'name str);
}
struct User<'a> {
    name: &'a str,
}
impl<'user, 'name: 'user> Name<'name> for User<'user> {
    fn set_name(&mut self, s: &'name str) {
        self.name = s;
    }
}

...or just make User owning the String and drop the references entirely.

3 Likes

Don't use temporary scope-bound loans inside structs. This will make the structs temporary themselves and prevent them from storing data. It will require data to be stored elsewhere, outside of the struct, in the outer scope. It will make a total lifetime mess of your program.

In structs use only self-contained owning types, like String.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.