Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggest cloning Arc moved into closure #124595

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

estebank
Copy link
Contributor

@estebank estebank commented May 1, 2024

error[E0382]: borrow of moved value: `x`
  --> $DIR/moves-based-on-type-capture-clause-bad.rs:9:20
   |
LL |     let x = "Hello world!".to_string();
   |         - move occurs because `x` has type `String`, which does not implement the `Copy` trait
LL |     thread::spawn(move || {
   |                   ------- value moved into closure here
LL |         println!("{}", x);
   |                        - variable moved due to use in closure
LL |     });
LL |     println!("{}", x);
   |                    ^ value borrowed here after move
   |
   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: clone the value before moving it into the closure
   |
LL ~     let value = x.clone();
LL ~     thread::spawn(move || {
LL ~         println!("{}", value);
   |

Fix #104232.

@rustbot
Copy link
Collaborator

rustbot commented May 1, 2024

r? @compiler-errors

rustbot has assigned @compiler-errors.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 1, 2024
@compiler-errors
Copy link
Member

r? compiler

too busy to review this

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

```
error[E0382]: borrow of moved value: `x`
  --> $DIR/moves-based-on-type-capture-clause-bad.rs:9:20
   |
LL |     let x = "Hello world!".to_string();
   |         - move occurs because `x` has type `String`, which does not implement the `Copy` trait
LL |     thread::spawn(move || {
   |                   ------- value moved into closure here
LL |         println!("{}", x);
   |                        - variable moved due to use in closure
LL |     });
LL |     println!("{}", x);
   |                    ^ value borrowed here after move
   |
   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: clone the value before moving it into the closure
   |
LL ~     let value = x.clone();
LL ~     thread::spawn(move || {
LL ~         println!("{}", value);
   |
```

Fix rust-lang#104232.
@rustbot rustbot added A-testsuite Area: The testsuite used to check the correctness of rustc T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) labels May 1, 2024
@pnkfelix
Copy link
Member

pnkfelix commented May 14, 2024

@estebank , isn't this suggesting cloning a lot more stuff than just Arc/Rc ?

The description for issue #104232 explicitly said:

We don't usually suggest cloning values in diagnostics, but for Arc/Rc we probably should.

which I took to mean that we wouldn't jump to suggesting cloning for things like Box nor String. But it looks to me like in this PR, you are indeed suggesting clones for Box and String ?

(for others following along, the reason for pushing back here is the concern that clones are not always cheap, and therefore the compiler should take care before suggesting them. The underling assumption of #104232 is that cloning an Rc is quite cheap, and cloning an Arc is potentially also cheap (apart from the potential for having many threads contending to increment the reference-count). But the cost of cloning a Box or String is dependent on their associated payload.)

@pnkfelix
Copy link
Member

@rfcbot author

@pnkfelix
Copy link
Member

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 14, 2024
@estebank
Copy link
Contributor Author

estebank commented May 17, 2024

The underling assumption of #104232 is that cloning an Rc is quite cheap, and cloning an Arc is potentially also cheap (apart from the potential for having many threads contending to increment the reference-count). But the cost of cloning a Box or String is dependent on their associated payload.)

The thing is that given the case being checked for here, either people clone, or they completely rework the code they have. I know this PR covers strictly more than was requested in the ticket, but I've been leaning lately towards the premise that telling people they can clone when they can is rarely a bad idea, despite the potential costs. I can modify this to rely on an allow-list, but even then I would still include Box and String as "can suggest".

For example, in this case:

use std::thread;

fn main() {
    let x = "Hello world!".to_string();
    thread::spawn(move || {
        println!("{}", x);
    });
    println!("{}", x); //~ ERROR borrow of moved value
}

we suggest to let value = x.clone(); so it can be moved into the closure. We can't tell people to borrow x within the closure (because it is already moved into it) nor we can tell them to have a let value = &x;, because thread::spawn requires 'static. The only option people really have here is to clone. I also want to train people to get less scared of cloning, people who need absolute performance already know what they need to do, those who don't and are just getting started with Rust, just get confused.

@bors
Copy link
Contributor

bors commented May 21, 2024

☔ The latest upstream changes (presumably #125379) made this pull request unmergeable. Please resolve the merge conflicts.

@alex-semenyuk
Copy link
Member

alex-semenyuk commented Sep 14, 2024

Ping from triage.
@pnkfelix Are we interesting in this PR since @estebank answered on your comment? This PR has not received an update for a few months.
Temporary change to waiting on review status, if it's needed @estebank should update it to fix conflicts

@alex-semenyuk alex-semenyuk added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-testsuite Area: The testsuite used to check the correctness of rustc S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Suggest cloning Arc/Rc
7 participants