Riccardo Galli
Riccardo Galli

Reputation: 12935

rust: error: lifetime of non-lvalue is too short to guarantee its contents can be safely reborrowed

I can't figure out what does this error in Rust mean:

error: lifetime of non-lvalue is too short to guarantee its contents can be safely reborrowed

What's a non-lvalue? (I suspect is not a right value).

I want to understand what the errror means and to be able to modify "objects" from a vector of mutable references.

This is a minimum test case to produce the error. I insert in a vector a mutable reference to a struct, and then I try to modify the pointed struct.

struct Point {
    x: uint,
    y: uint
}

fn main() {
    let mut p = Point { x: 0, y: 0};
    p.x += 1; // OK, p owns the point

    let mut v: Vec<&mut Point> = Vec::new();
    v.push(&mut p);

    // p.x += 1 // FAIL (expected), v has borrowed the point

    let p1:&mut Point = *v.get_mut(0);  // ERROR, lifetime of non-lvalue...

    // never reached this line
    // p1.x += 1;
}

Upvotes: 0

Views: 144

Answers (1)

A.B.
A.B.

Reputation: 16660

Let's go over what you're trying to do here:

let p1:&mut Point = *v.get_mut(0);

*v.get_mut(0) returns a mutable reference to first the mutable reference in the vector, then dereferences it. If this compiled, you would end up with two mutable references to the same object: one in the vector, the other in the p1 variable. Rust is rejecting this because it's not safe.

By far the best solution is to make the vector the owner of your Point objects. ie. use a Vec<Point> instead of a Vec<&mut Point.

If you need something more complicated, you can use a RefCell for dynamically checked borrowing:

use std::cell::RefCell;

struct Point {
    x: uint,
    y: uint
}

fn main() {
    let p = RefCell::new(Point { x: 0, y: 0});

    p.borrow_mut().x += 1;

    let mut v: Vec<&RefCell<Point>> = Vec::new();

    v.push(&p);

    let p1 = v.get(0);

    p1.borrow_mut().x += 1;

    p.borrow_mut().x += 1;
}

Upvotes: 1

Related Questions