rust-lang / rust-lang/rust-by-example

Discrepancy regarding how closures capture Copy variables

Open
#1,293 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Handlebars
Stars
8.1k
Forks
1.6k
PR merge metrics
No merged PRs in 30d

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the capturing section 9.2.1 in Rust By Example and reproduce the supplied closure example on stable Rust. Compare the documented behavior with the compiler's actual capture semantics, then update the explanation so it accurately describes what happens to Copy variables; the example should compile or fail consistently with that explanation.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
documentation
Issue type
Documentation
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.