mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-12-30 05:10:57 +00:00
embassy-executor: explicitly return impl Future in task inner task
This commit is contained in:
parent
1b42e62424
commit
539ff78ebb
@ -5,7 +5,7 @@ use darling::FromMeta;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{format_ident, quote};
|
||||
use syn::visit::{self, Visit};
|
||||
use syn::{Expr, ExprLit, Lit, LitInt, ReturnType, Type};
|
||||
use syn::{Expr, ExprLit, Lit, LitInt, ReturnType, Type, Visibility};
|
||||
|
||||
use crate::util::*;
|
||||
|
||||
@ -135,6 +135,13 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let task_inner_future_output = match &f.sig.output {
|
||||
ReturnType::Default => quote! {-> impl ::core::future::Future<Output = ()>},
|
||||
// Special case the never type since we can't stuff it into a `impl Future<Output = !>`
|
||||
ReturnType::Type(arrow, maybe_never)
|
||||
if f.sig.asyncness.is_some() && matches!(**maybe_never, Type::Never(_)) =>
|
||||
{
|
||||
quote! {
|
||||
#arrow impl ::core::future::Future<Output=#embassy_executor::_export::Never>
|
||||
}
|
||||
}
|
||||
ReturnType::Type(arrow, maybe_never) if matches!(**maybe_never, Type::Never(_)) => quote! {
|
||||
#arrow #maybe_never
|
||||
},
|
||||
@ -149,14 +156,20 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
},
|
||||
};
|
||||
|
||||
// We have to rename the function since it might be recursive;
|
||||
let mut task_inner_function = f.clone();
|
||||
let task_inner_function_ident = format_ident!("__{}_task_inner_function", task_ident);
|
||||
task_inner_function.sig.ident = task_inner_function_ident.clone();
|
||||
task_inner_function.vis = Visibility::Inherited;
|
||||
|
||||
let task_inner_body = if errors.is_empty() {
|
||||
quote! {
|
||||
#f
|
||||
#task_inner_function
|
||||
|
||||
// SAFETY: All the preconditions to `#task_ident` apply to
|
||||
// all contexts `#task_inner_ident` is called in
|
||||
#unsafety {
|
||||
#task_ident(#(#full_args,)*)
|
||||
#task_inner_function_ident(#(#full_args,)*)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -216,7 +216,7 @@ pub mod _export {
|
||||
);
|
||||
|
||||
#[allow(dead_code)]
|
||||
trait HasOutput {
|
||||
pub trait HasOutput {
|
||||
type Output;
|
||||
}
|
||||
|
||||
@ -225,7 +225,7 @@ pub mod _export {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
type Never = <fn() -> ! as HasOutput>::Output;
|
||||
pub type Never = <fn() -> ! as HasOutput>::Output;
|
||||
}
|
||||
|
||||
/// Implementation details for embassy macros.
|
||||
@ -242,7 +242,7 @@ pub mod _export {
|
||||
impl TaskReturnValue for Never {}
|
||||
|
||||
#[allow(dead_code)]
|
||||
trait HasOutput {
|
||||
pub trait HasOutput {
|
||||
type Output;
|
||||
}
|
||||
|
||||
@ -251,5 +251,5 @@ pub mod _export {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
type Never = <fn() -> ! as HasOutput>::Output;
|
||||
pub type Never = <fn() -> ! as HasOutput>::Output;
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ use std::sync::{Arc, Mutex};
|
||||
use std::task::Poll;
|
||||
|
||||
use embassy_executor::raw::Executor;
|
||||
use embassy_executor::task;
|
||||
use embassy_executor::{task, Spawner};
|
||||
|
||||
#[export_name = "__pender"]
|
||||
fn __pender(context: *mut ()) {
|
||||
@ -317,3 +317,12 @@ fn executor_task_cfg_args() {
|
||||
let (_, _, _) = (a, b, c);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recursive_task() {
|
||||
#[embassy_executor::task(pool_size = 2)]
|
||||
async fn task1() {
|
||||
let spawner = unsafe { Spawner::for_current_executor().await };
|
||||
spawner.spawn(task1());
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,4 +7,4 @@ error[E0277]: task futures must resolve to `()` or `!`
|
||||
= note: use `async fn` or change the return type to `impl Future<Output = ()>`
|
||||
= help: the following other types implement trait `TaskReturnValue`:
|
||||
()
|
||||
<fn() -> ! as _export::HasOutput>::Output
|
||||
<fn() -> ! as HasOutput>::Output
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user