How to run two concurrent futures manually

Hi, I'm trying to learn future, I want manually run two future concurrently. but with following code, I got some weird error. here is my code, and playground linke is:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8b4f713be6582527fac3c62f3169b345

error msg also pasted here. but I already have trait bound in where clause. I know I don't have any runtime in this code, because I want keep the example code as simple as possible. but the idea should work? right? Thanks

54 |             match self.a.poll(cx) {
   |                          ^^^^ method not found in `A`
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `poll`, perhaps you need to restrict type parameter `A` with it:
use std::{                                                                    
    future::Future,                                                   
    pin::Pin,                                       
    task::{Context, Poll},                                              
};

fn main() {
    let f1 = async {
        println!("async1");
    };
    let f2 = async {
        println!("async2");
    };
    let join = Join2::new(f1, f2);
}

struct Join2<A, B>                                                                                                                                                      
where                                                                                                                                                                   
    A: std::future::Future,                                                                                                                                             
    B: std::future::Future,
{                                      
    a: A,                                                  
    ar: Option<A::Output>,                                    
    b: B,                                                                  
    br: Option<B::Output>,                                          
}                                                                         
                                                           
impl<A, B> Join2<A, B>                       
where                                                
    A: std::future::Future,                                     
    B: std::future::Future,                                     
{                                                                                
    fn new(a: A, b: B) -> Self {                      
        Join2 {                            
            a,                                                               
            ar: None,                                               
            b,                                                          
            br: None,                                                         
        }                
    }                                                               
}                       
                                                                               
impl<A, B> Future for Join2<A, B>   
where                                       
    A: std::future::Future,                                           
    B: std::future::Future,           
{
    type Output = (A::Output, B::Output);
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let mut done = true;
        if self.ar.is_none() {
            // let mut future = unsafe { Pin::new_unchecked(&mut self.a) };
            // match Future::poll(future, &mut cx) {
            match self.a.poll(cx) {
                Poll::Ready(val) => {
                    self.ar = Some(val);
                }
                Poll::Pending => {
                    done = false;
                }
            }
        }
        if self.br.is_none() {
            // let mut future = unsafe { Pin::new_unchecked(&mut self.b) };
            // match Future::poll(future, &mut cx) {
            match self.b.poll(cx) {
                Poll::Ready(val) => {
                    self.br = Some(val);
                }
                Poll::Pending => {
                    done = false;
                }
            }
        }

        if done {
            Poll::Ready((self.ar.unwrap(), self.br.unwrap()))
        } else {
            Poll::Pending
        }
    }
}

Disclaimer: I’m a novice when it comes to Pin code, so this might be wrong in some subtle way.

Your commented code is on the right line, but you need to use map_unchecked_mut to get a pinned version of the internal futures, and get_unchecked_mut when you need to change the stored results. I poked at it on the playground until it compiles, but can’t really speak to its correctness.

Thanks! your change works. Just in case you are interested. I put full code to
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ec15bafff0bd6667a7b1a0578280a307
I copy the executor from this excellent book.
https://cfsamson.github.io/books-futures-explained/8_finished_example.html

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.