Skip to content

Why async move block is not needed? #162

Open
@mkbanchi

Description

@mkbanchi

Looking at the very interesting crawler implementation in ch-05, i'm struggling with the fact that async block at crawler.rs:137 does not need to be move. queued_url is String that is not Copy so, even if it is cloneed inside the closure passed to for_each_concurrent, this should not suffice, it is borrowed inside the async block. I reprodued the problem with a similar (I think) example:

use futures::stream::StreamExt;
use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio_stream::wrappers::ReceiverStream;

#[tokio::main]
async fn main() {
    let v: Vec<String> = vec!["1".into(), "2".into(), "3".into()];

    let (tx, rx): (Sender<String>, Receiver<String>) = channel(3);

    let f = tokio::spawn(async move {
        ReceiverStream::new(rx)
            .for_each_concurrent(3, |val| {
                let val = val.clone();
                async {  // <-- This needs to be move
                    println!("Processed value: {}", val.clone());
                }
            })
            .await;
    });

    for i in v.iter() {
        tx.send(i.clone()).await.unwrap();
    }

    drop(tx);

    f.await.unwrap();

    println!("Finished");
}

The above code does not compile because of the missing move async block highlighted by the comment in the above snippet.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions