Search code examples
rustcomponents

How to solve "temporary value dropped while borrowed"


I'm learning Rust (coming from Javascript), and in Rust I'm trying to create a component-based UI template. This is the minimum example I can reproduce in a Rust playground.

I have a Vector of Enums. I want to add components that will return a new set of vectors. The component returns a vector from a member function that is not a reference.

let _new_children = match new_view.unwrap() {
    View::View(children) => children, // reference &Vec<View>
    View::Render(ref component) => component.render(), // struct Vec<View>
};

let _new_children = match new_view.unwrap() {
    View::View(children) => children,
    View::Render(ref component) => &component.render(), //  temporary value dropped while borrowed
};

How can I solve this problem? Do I need to rewrite the way functions check the difference between two vectors (itertools has a zip_longest method, which I also use).


Solution

  • In order to return a reference to a temporary you need to make the temporary live longer than the use of that reference.

    In your code the temporary object is dropped as soon as the match branch ends, so a reference to it cannot escape the match.

    There is a nice trick in Rust to extend the lifetime of a temporary. It consist in declaring the temporary name+ in the larger block where you want it to live, without initializing it. Then you assign-initialize it where the object temporary is actually created. Something like this:

        let tmp_new;
        let new_children = match new_view.unwrap() {
            View::View(children) => children,
            View::Render(ref component) => {
                tmp_new = component.render();
                &tmp_new }
        };
    

    Now new_children is of type &Vec<_> and it will live for the shorter of the two lifetimes of the match branches.

    Note that unless you initialize the temporary in every branch of your match you cannot use tmp_new after it, because you will get:

    use of possibly-uninitialized variable: tmp_new