Skip to content

Discrepancy regarding how closures capture Copy variables #1293

Open
@ross-pure

Description

@ross-pure

There seems to be a discrepancy between the description in the RBE section on capturing (9.2.1) and current stable implementation of rust regarding what happens to a copy variable when it needs to be captured by value in a closure. The RBE says that

mem::drop requires T so this must take by value. A copy type would copy into the closure leaving the original untouched.

However, it appears that the compiler does not do this precisely. Consider the following example:

#![allow(unused)]

#[derive(Clone, Copy)]
struct IsCopy {}

fn main() {
    let y = {
        let x = IsCopy {};

        // x is not copied into the closure here, only taken by reference
        || drop(x)
    };
}

fn foo() -> impl FnOnce() {
    let x = IsCopy {};

    // Also here x is only taken by reference and not copied into the closure
    || drop(x)
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0597]: `x` does not live long enough
  --> src/main.rs:11:17
   |
7  |     let y = {
   |         - borrow later stored here
...
11 |         || drop(x)
   |         --      ^ borrowed value does not live long enough
   |         |
   |         value captured here
12 |     };
   |     - `x` dropped here while still borrowed

error[E0597]: `x` does not live long enough
  --> src/main.rs:19:13
   |
15 | fn foo() -> impl FnOnce() {
   |             ------------- opaque type requires that `x` is borrowed for `'static`
...
19 |     || drop(x)
   |     --      ^ borrowed value does not live long enough
   |     |
   |     value captured here
20 | }
   | - `x` dropped here while still borrowed

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

From the example it seems (I'm not actually 100% sure what is going on behind the scenes) that the closure only takes a reference, and will perform the copy later when it needs to. In any case, this is different to what is implied by the RBE.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions