dcchut / async-recursion

Procedural macro for recursive async functions
Apache License 2.0
209 stars 14 forks source link

`no_std` support #4

Open vinaychandra opened 4 years ago

vinaychandra commented 4 years ago

Can this crate be made to use just alloc crate instead of being std dependant? That would help a lot of embedded developers given that the most recent version of rust allows async await in no_std scenarios out of the box.

dcchut commented 4 years ago

Hmm - I don't have any experience with no_std, but at the moment the macro modifies the return type of async functions to something like:

core::pin::Pin<Box<dyn core::future::Future<Output = T> + Send>>

so it'll use whatever Box you have in scope. One way to get it working is to have alloc::boxed::Box in scope anywhere you invoke the macro (something like this).

That being said, it is a bit of a usability fail to have to import alloc::boxed::Box anywhere you want to use the macro - perhaps we could add a no_std feature flag that modifies the return type to:

core::pin::Pin<alloc::boxed::Box<dyn core::future::Future<Output = T> + Send>>

instead. What do you reckon?

Sherlock-Holo commented 2 years ago

use core::pin::Pin<alloc::boxed::Box<dyn core::future::Future<Output = T> + Send>> should can works in std enabled or no_std but enabled alloc situation

so this crate can no longer depend on std

dcchut commented 2 years ago

That unfortunately doesn't work on std - for example:

pub struct Wrapper<T>(core::pin::Pin<alloc::boxed::Box<dyn core::future::Future<Output = T> + Send>>);

gives the error:

error[E0433]: failed to resolve: use of undeclared crate or module `alloc`
 --> src/lib.rs:1:38
  |
1 | pub struct Wrapper<T>(core::pin::Pin<alloc::boxed::Box<dyn core::future::Future<Output = T> + Send>>);
  |                                      ^^^^^ use of undeclared crate or module `alloc`
  |
  = help: add `extern crate alloc` to use the `alloc` crate
which returns the error:

I think my opinion here has coalesced with the comments in https://github.com/dtolnay/async-trait/issues/163. For no_std use cases it's enough to import a Box into scope:

#![no_std]
extern crate alloc;
use alloc::boxed::Box;

#[async_recursion::async_recursion]
async fn foo<T>(_t: T) {}