Binding "does not live long enough" even though it's being returned


#1

Hey guys,

I’ve got some code which I don’t understand. Rust is giving me the old “…does not live long enough” error, but the owned value appears to live longer than Rust says it does? How would one make this work:

struct Abc<'a> {
    name: &'a str,
}

fn def<'a>() -> (String, Abc<'a>) {
    let name = String::from("xyz");
    let abc = Abc { name: &name };
    (name, abc)
}

Here’s a link to play.rust-lang: https://is.gd/rPjWZy

Cheers!


#2

Note that your code creates a reference to the local variable name, and then proceeds to move name into the tuple. This is a ‘use after move’ error.

However, even if you managed to get a reference to the tuple’s name into the Abc, you’d still have a problem: Since the tuple now contains a reference to itself, the tuple as a whole can no longer be moved. If you memcpy the struct to a new spot, the referenced address remains the same – but the struct is no longer there, since it was just moved!

Rust doesn’t support self-referential structs with &references in general due to this problem.

I guess the fundamental issue is that you’re trying to reference a value that’s moving.


#3

Thanks for the reply, mate. I had to read it several times, but I think that makes sense. It seems like the struct will have to store an owned value rather than a ref, as I want to pass them around, store them in a vector etc.


#4

No prob, I started with this a few weeks back and it’s…not easy to say the least lol.


#5

You can also consider using std::borrow::Cow as the type of the name field. That will allow you to borrow values when their lifetime outlives the Abc instance (and avoid copies), or use an owned value when you cannot.


#6

That’s a good idea. Thanks!


#7

Also check out https://crates.io/crates/owning_ref