References in closures

I'm having trouble with lifetimes in a program I'm writing. It boils down to this:

fn main() {
    let x = 7;
    let v = vec![1,2,3];
    let c = {
        let r = &x;
        |y: u32| r + y + v[2]
    };
    println!("{} {}", v[1], c(2));
}

x, v and c outlive the scope in which r is defined. x and v both outlive c. Let's suppose that x is not directly accessible and that we only have the reference r. In the closure, I want to reference x.

I get the following error:

error[E0373]: closure may outlive the current block, but it borrows `r`, which is owned by the current block
 --> test.rs:6:9
  |
6 |         |y: u32| r + y + v[2]
  |         ^^^^^^^^ - `r` is borrowed here
  |         |
  |         may outlive borrowed value `r`
  |
note: block requires argument type to outlive `'1`
 --> test.rs:4:9
  |
4 |     let c = {
  |         ^
help: to force the closure to take ownership of `r` (and any other referenced variables), use the `move` keyword
  |
6 |         move |y: u32| r + y + v[2]
  |

Apparently r is borrowed, when in reality I want r's underlying pointer to be copied so that I borrow x. Note that I cannot follow the compilers advice, as v must not be moved.

How can I get the closure to borrow x instead or r?

This works for the example.

    let c = {
        let r = &x;
        |y: u32| *r + y + v[2]
    };

Alternatively you can tune move with a dash of tedium.

    let c = {
        let r = &x;
        let v_ref = &v;
        move |y: u32| r + y + v_ref[2]
    };
2 Likes

Ah, thanks. While searching I'd seen similar solutions for more complex problems, but I didn't understand until you said it.

In my actual problem I couldn't dereference r for some trait bounds. So it's the second solution I was after.

So basically,

|arg| something(a, b, c)

is sugar for

{
    let (a, b, c) = (&a, &b, &c); // shadowing previous definition
    move |arg| something(a, b, c)
}

when a, b, c are not Copy.

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.