Description
Code
use futures::StreamExt;
#[tokio::main]
async fn main() {
let vec = vec!["one", "two", "three"];
while let Some(item) = futures::stream::iter(vec).next().await {
println!("{:?}", item);
}
}
Current output
Compiling playground v0.0.1 (/playground)
error[E0382]: use of moved value: `vec`
--> src/lib.rs:6:54
|
5 | let vec = vec!["one", "two", "three"];
| --- move occurs because `vec` has type `Vec<&str>`, which does not implement the `Copy` trait
6 | while let Some(item) = futures::stream::iter(vec).next().await {
| ---------------------------------------------^^^--------------
| | |
| | value moved here, in previous iteration of loop
| inside of this loop
|
help: consider cloning the value if the performance cost is acceptable
|
6 | while let Some(item) = futures::stream::iter(vec.clone()).next().await {
| ++++++++
For more information about this error, try `rustc --explain E0382`.
error: could not compile `playground` (lib) due to 1 previous error
Desired output
A slightly different example:
use futures::StreamExt;
#[tokio::main]
async fn main() {
let vec = vec!["one", "two", "three"];
while let item = futures::stream::iter(vec).next().await {
println!("{:?}", item);
}
}
produces an "irrefutable loop" warning at least
Standard Error
Compiling playground v0.0.1 (/playground)
warning: irrefutable `while let` pattern
--> src/lib.rs:6:15
|
6 | while let item = futures::stream::iter(vec).next().await {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this pattern will always match, so the loop will never exit
= help: consider instead using a `loop { ... }` with a `let` inside it
= note: `#[warn(irrefutable_let_patterns)]` on by default
error[E0382]: use of moved value: `vec`
--> src/lib.rs:6:48
|
5 | let vec = vec!["one", "two", "three"];
| --- move occurs because `vec` has type `Vec<&str>`, which does not implement the `Copy` trait
6 | while let item = futures::stream::iter(vec).next().await {
| ---------------------------------------^^^--------------
| | |
| | value moved here, in previous iteration of loop
| inside of this loop
|
help: consider cloning the value if the performance cost is acceptable
|
6 | while let item = futures::stream::iter(vec.clone()).next().await {
| ++++++++
For more information about this error, try `rustc --explain E0382`.
warning: `playground` (lib) generated 1 warning
error: could not compile `playground` (lib) due to 1 previous error; 1 warning emitted
Standard Output
Rationale and extra context
I'm a rust beginner: When I mistakenly wrote code matching irrefutable_let_patterns
the warning was helpful to me that I had made a mistake.
But I still had a flaw in that I should have made the stream outside the while let match stanza - The code is re-initializain the loop variable on each iteration. The rustc suggestion to add a clone()
on vec
as vec
was moved in the previous loop iteration is "technically correct" but the suggestion creates another irrefutable loop which doesn't produce such a warning. I know this pattern is harder to recognize as it involves the r-value instead of the match side (while let x =
).
while let Some(item) = futures::stream::iter(vec.clone()).next().await
Since I'm a beginner I didn't realize that when rustc said value moved here, in previous iteration of loop
that I had put use of vec
in the wrong place. It should have been.
let mut s = futures::stream::iter(vec);
while let Some(item) = s.next().await {
...
While I ran into this when using an async stream, I think it a general situation whenever the right hand side creates a new and same object on the right side. Here's an example with an iterator along.
fn main() {
let vec = vec!["one", "two", "three"];
while let Some(item) = vec.iter().next() {
println!("{:?}", item);
}
}
It's a problem in the class of loop variable issues. I come from golang which says a similar issue that everone hits once or twice (and hopefully recognizes when!). Goland is introducing a way to systematically addres this class of error: https://go.dev/blog/loopvar-preview
I was encourage to report this by @carols10cents.
Other cases
No response
Rust Version
1.76.0 - I used the playground to reproduce it.
Anything else?
No response