vise
vise

Reputation: 13363

Create and assign reference data from within a struct method

I have abstracted my problem inside the following code:

struct List<'a> {
    attr: &'a String
}

impl<'a> List<'a> {
    fn new() -> List<'a> {
        let my_attr = "Something";
        List {
            attr: &my_attr.to_string()
        }
    }
}

fn main() {
    List::new();
}

It yields some notices and fails compiling claiming that the borrowed value (my_attr) doesn't live long enough.

It makes sense, so for instance the following does indeed compile:

struct List<'a> {
    attr: &'a String
}

impl<'a> List<'a> {
    fn new(my_attr: &'a String) -> List<'a> {
        List {
            attr: my_attr
        }
    }
}

fn main() {
    let my_attr = "Something".to_string();
    List::new(&my_attr);
}

However, I like the first form more, especially from an encapsulation stand point.

Is it possible to create and also assign a reference to a value from within the new method (as per the failing example)?

Upvotes: 0

Views: 98

Answers (1)

Renato Zannon
Renato Zannon

Reputation: 29941

The issue here is that a &'a String is a borrowed value - that is, it is a reference to a value that is stored elsewhere. On your first example, that "elsewhere" is the new function stack, and on the second it's main's stack.

You don't get an error on the second case because main's lifetime is bigger than your List's lifetime - that is, the List will die before main finishes. That is not the case of your first scenario, where the List is returned by new, and thus the reference is invalid.

The solution here is to make List own its String, instead of just taking a reference to it. This way, List's lifetime isn't linked to anything else.

struct List {
    attr: String,
}

impl List {
    fn new() -> List {
        let my_attr = "Something";

        List {
            attr: my_attr.to_string()
        }
    }
}

Upvotes: 2

Related Questions