Early returns from FnMut closure

I'm trying to learn rust (again) and obviously I have skill issues trying to do something that seems pretty straightforward.

    // spawn a connection handler for each
    listener
        .incoming()
        .for_each_concurrent(None, |stream| {
            let stream = stream.unwrap();
            let remote_addr = stream.peer_addr();
            let Ok(remote_addr) = remote_addr else {
                stream.shutdown(std::net::Shutdown::Both).unwrap();
                return **<what here>**;
            };

            async move {
                spawn(handle_connection(stream));
            }
        })
        .await;

I want to early return from the for_each_concurrent function but I can't for the life of me work out how to return a futures::future::Future<Output=()> which is what it's expecting. Anything I return seems to infer a different return type to what for_each_concurrent wants.

seems to indicate the |stream|{} closure is a FnMut(Self::Item) -> Fut where Fut is defined as Future<Output = ()> but nothing I try seems to be allowed.

Is it possible to early return from this function ?

Any help much appreciated.

Why don't you just move the early return into the async block?

2 Likes

Function can only have one return type, and every async block has a unique type, so your early return can only return the same block.

You could use Either enum or dyn Future to dynamically abstract away the type of the async block and return two different async blocks.

But the easy solution may be to move all code into the same block.

3 Likes

Oh that's cause I'm an idiot clearly !!

Thank you that actually makes a lot of sense :slight_smile:

@kornel Ah that's good info - I didn't realise they were their own types :+1:

This is a repeat of what others said in slower motion.

Let's simplify:

fn example(condition: bool) -> impl Future<Output = ()> {
    if condition {
        return async move {};
    }
    
    async move {}
}

Similar to closures, every compiler generated future has unique, unnameable type. So in the example, you're trying to return two different types. But Rust is strongly typed, so that's an error.

Putting all the logic in one future would look like so:

fn example(condition: bool) -> impl Future<Output = ()> {
    async move {
        if condition {
            return;
        }
    }
}

Which can be replaced with some sugar:

async fn example(condition: bool) {
    if condition {
        return;
    }
}
2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.