How does Rust figure out that outer future implements Send?

⚓ rust    📅 2025-05-17    👤 surdeus    👁️ 4      

surdeus

Warning

This post was published 44 days ago. The information described in this article may have changed.

In this example the test_inner method returns a future that does not implement Send, however the test_outer method return a future that clearly implements Send.
I would like to know how Rust understands that the outer future still implements Send, even though the inner future, which is embedded in the outer future, does not?
From common sense point of view this is clear: SomethingDoer implements Send, so the inner future can be "promoted" to being "sendable". However, I would like to understand the actual rules that Rust uses to implement such semantics.

use std::{future::Future, time::Duration};

use futures_timer::Delay;

fn test_outer() -> impl Future<Output = ()> + Send {
    async {
        let something_doer = SomethingDoer {};

        test_inner(&something_doer).await;
    }
}

fn test_inner(do_something: &impl DoSomething) -> impl Future<Output = ()> + '_ {
    async {
        wait().await;

        do_something.do_something();
    }
}

async fn wait() {
    Delay::new(Duration::from_millis(1)).await;
}

struct SomethingDoer {}

trait DoSomething {
    fn do_something(&self) {}
}

impl DoSomething for SomethingDoer {
    fn do_something(&self) {}
}

1 post - 1 participant

Read full topic

🏷️ rust_feed