rust
rust copied to clipboard
Detect when move of !Copy value occurs within loop and should likely not be cloned
When encountering a move error on a value within a loop of any kind, identify if the moved value belongs to a call expression that should not be cloned and avoid the semantically incorrect suggestion. Also try to suggest moving the call expression outside of the loop instead.
error[E0382]: use of moved value: `vec`
--> $DIR/recreating-value-in-loop-condition.rs:6:33
|
LL | let vec = vec!["one", "two", "three"];
| --- move occurs because `vec` has type `Vec<&str>`, which does not implement the `Copy` trait
LL | while let Some(item) = iter(vec).next() {
| ----------------------------^^^--------
| | |
| | value moved here, in previous iteration of loop
| inside of this loop
|
note: consider changing this parameter type in function `iter` to borrow instead if owning the value isn't necessary
--> $DIR/recreating-value-in-loop-condition.rs:1:17
|
LL | fn iter<T>(vec: Vec<T>) -> impl Iterator<Item = T> {
| ---- ^^^^^^ this parameter takes ownership of the value
| |
| in this function
help: consider moving the expression out of the loop so it is only moved once
|
LL ~ let mut value = iter(vec);
LL ~ while let Some(item) = value.next() {
|
We use the presence of a break
in the loop that would be affected by
the moved value as a heuristic for "shouldn't be cloned".
Fix https://github.com/rust-lang/rust/issues/121466.
Point at continue and break that might be in the wrong place
Sometimes move errors are because of a misplaced continue
, but we didn't
surface that anywhere. Now when there are more than one set of nested loops
we show them out and point at the continue
and break
expressions within
that might need to go elsewhere.
error[E0382]: use of moved value: `foo`
--> $DIR/nested-loop-moved-value-wrong-continue.rs:46:18
|
LL | for foo in foos {
| ---
| |
| this reinitialization might get skipped
| move occurs because `foo` has type `String`, which does not implement the `Copy` trait
...
LL | for bar in &bars {
| ---------------- inside of this loop
...
LL | baz.push(foo);
| --- value moved here, in previous iteration of loop
...
LL | qux.push(foo);
| ^^^ value used here after move
|
note: verify that your loop breaking logic is correct
--> $DIR/nested-loop-moved-value-wrong-continue.rs:41:17
|
LL | for foo in foos {
| ---------------
...
LL | for bar in &bars {
| ----------------
...
LL | continue;
| ^^^^^^^^ this `continue` advances the loop at line 33
help: consider moving the expression out of the loop so it is only moved once
|
LL ~ let mut value = baz.push(foo);
LL ~ for bar in &bars {
LL |
...
LL | if foo == *bar {
LL ~ value;
|
help: consider cloning the value if the performance cost is acceptable
|
LL | baz.push(foo.clone());
| ++++++++
Fix https://github.com/rust-lang/rust/issues/92531.
r? @cjgillot
rustbot has assigned @cjgillot. 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
:umbrella: The latest upstream changes (presumably #121489) made this pull request unmergeable. Please resolve the merge conflicts.
I don't currently have the bandwidth to review this. r? compiler
Cool stuff! I don't completely follow the "look for breaks" heuristic but I'll trust you on that. A few comments but looks good overall.
@rustbot author
Nice work, ty
@bors r+
:pushpin: Commit 3b237d7d8ad46259856a42043ae37b25c6496f7f has been approved by Nadrieril
It is now in the queue for this repository.
:hourglass: Testing commit 3b237d7d8ad46259856a42043ae37b25c6496f7f with merge 5608c7f9aaf380bd0c49bbcc350ecf8c5eb4b68c...
:sunny: Test successful - checks-actions Approved by: Nadrieril Pushing 5608c7f9aaf380bd0c49bbcc350ecf8c5eb4b68c to master...
Finished benchmarking commit (5608c7f9aaf380bd0c49bbcc350ecf8c5eb4b68c): comparison URL.
Overall result: ❌✅ regressions and improvements - no action needed
@rustbot label: -perf-regression
Instruction count
This is a highly reliable metric that was used to determine the overall result at the top of this comment.
mean | range | count | |
---|---|---|---|
Regressions ❌ (primary) |
- | - | 0 |
Regressions ❌ (secondary) |
1.3% | [1.3%, 1.3%] | 1 |
Improvements ✅ (primary) |
- | - | 0 |
Improvements ✅ (secondary) |
-1.1% | [-1.1%, -1.1%] | 1 |
All ❌✅ (primary) | - | - | 0 |
Max RSS (memory usage)
Results
This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
mean | range | count | |
---|---|---|---|
Regressions ❌ (primary) |
- | - | 0 |
Regressions ❌ (secondary) |
- | - | 0 |
Improvements ✅ (primary) |
-4.7% | [-5.0%, -4.3%] | 2 |
Improvements ✅ (secondary) |
-2.9% | [-5.4%, -1.8%] | 15 |
All ❌✅ (primary) | -4.7% | [-5.0%, -4.3%] | 2 |
Cycles
Results
This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
mean | range | count | |
---|---|---|---|
Regressions ❌ (primary) |
- | - | 0 |
Regressions ❌ (secondary) |
5.6% | [1.7%, 11.5%] | 8 |
Improvements ✅ (primary) |
- | - | 0 |
Improvements ✅ (secondary) |
- | - | 0 |
All ❌✅ (primary) | - | - | 0 |
Binary size
This benchmark run did not return any relevant results for this metric.
Bootstrap: 669.037s -> 668.349s (-0.10%) Artifact size: 312.76 MiB -> 312.73 MiB (-0.01%)