Vec<Pin<Box<dyn Future<Output = Result<()>> + Send + 'static>>>

I need to write a function that equivalent to remove_all_dir.
This is an encrypted filesystem, so std lib will not know how to navigate it.
Recursion feels like the right way to do it, but I cannot get the futures to implement Send.

This works fine (except for threadesafety) if I remove the + Send.
But as soon as I add it I get this error related to the futures.push(...):
type annotations needed: cannot satisfy impl futures_util::Future<Output = std::result::Result<(), anyhow::Error>>: std::marker::Send
cannot satisfy impl futures_util::Future<Output = std::result::Result<(), anyhow::Error>>: std::marker::Send
required for the cast from Pin<Box<impl futures_util::Future<Output = std::result::Result<(), anyhow::Error>>>> to Pin<Box<dyn Future<Output = Result<(), Error>> + Send>>

I'm still not that familiar with rust async. Is there any way to make this work?
Simply wrapping it inside an Arc<Mutex<>> does not help.
Every other function inside this seems to implement Send.

    async fn remove_dir_recursive(target_inode: u64) -> Result<()> {
        let fs = get_fs().await?;
        let mut queue: Vec<(u64, SecretBox<String>)> = Vec::new();

        let mut futures: Vec<Pin<Box<dyn Future<Output = Result<()>> + Send + 'static>>> = vec![];

        for node in fs.read_dir_plus(target_inode).await? {
            let node = node?;
            match node.kind {
                FileType::Directory => match fs.len(node.ino)? {
                    0 => {
                        fs.remove_dir(target_inode, &node.name).await?;
                    }
                    _ => {
                        queue.push((target_inode, node.name));
                        futures.push(Box::pin(remove_dir_recursive(node.ino)));
                    }
                },
                FileType::RegularFile => {
                    fs.remove_file(target_inode, &node.name).await?;
                }
            }
        }

        for future in futures {
            future.await?;
        }

        for node in queue.into_iter().rev() {
            fs.remove_dir(node.0, &node.1).await?;
        }

        Ok(())
    }

When asking for help with an error message, please always post the full error message. If you don't know how to get the full error message from your IDE then: Go to your terminal, execute cargo check in your Rust project from there, copy the full error message which starts with some like like

error[E028…]: type annotations needed

and includes at least everything until (excluding) the next error[CODE]: message… (or it's the last error only followed by the error: could not compile… footer).

2 Likes

This have been solved. Solution here.
PS: Thanks for the heads up about the error message. I'll keep that in mind.
https://www.reddit.com/r/learnrust/comments/1hmi0qf/vecpinboxdyn_futureoutput_result_send_static/m3uvmjb/