aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-executor-macros/src/macros/task.rs19
-rw-r--r--embassy-executor/src/lib.rs8
-rw-r--r--embassy-executor/tests/test.rs11
-rw-r--r--embassy-executor/tests/ui/bad_return_impl_future_nightly.stderr2
4 files changed, 31 insertions, 9 deletions
diff --git a/embassy-executor-macros/src/macros/task.rs b/embassy-executor-macros/src/macros/task.rs
index 5b360b128..fc8673743 100644
--- a/embassy-executor-macros/src/macros/task.rs
+++ b/embassy-executor-macros/src/macros/task.rs
@@ -5,7 +5,7 @@ use darling::FromMeta;
5use proc_macro2::{Span, TokenStream}; 5use proc_macro2::{Span, TokenStream};
6use quote::{format_ident, quote}; 6use quote::{format_ident, quote};
7use syn::visit::{self, Visit}; 7use syn::visit::{self, Visit};
8use syn::{Expr, ExprLit, Lit, LitInt, ReturnType, Type}; 8use syn::{Expr, ExprLit, Lit, LitInt, ReturnType, Type, Visibility};
9 9
10use crate::util::*; 10use crate::util::*;
11 11
@@ -135,6 +135,13 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream {
135 let task_inner_future_output = match &f.sig.output { 135 let task_inner_future_output = match &f.sig.output {
136 ReturnType::Default => quote! {-> impl ::core::future::Future<Output = ()>}, 136 ReturnType::Default => quote! {-> impl ::core::future::Future<Output = ()>},
137 // Special case the never type since we can't stuff it into a `impl Future<Output = !>` 137 // Special case the never type since we can't stuff it into a `impl Future<Output = !>`
138 ReturnType::Type(arrow, maybe_never)
139 if f.sig.asyncness.is_some() && matches!(**maybe_never, Type::Never(_)) =>
140 {
141 quote! {
142 #arrow impl ::core::future::Future<Output=#embassy_executor::_export::Never>
143 }
144 }
138 ReturnType::Type(arrow, maybe_never) if matches!(**maybe_never, Type::Never(_)) => quote! { 145 ReturnType::Type(arrow, maybe_never) if matches!(**maybe_never, Type::Never(_)) => quote! {
139 #arrow #maybe_never 146 #arrow #maybe_never
140 }, 147 },
@@ -149,14 +156,20 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream {
149 }, 156 },
150 }; 157 };
151 158
159 // We have to rename the function since it might be recursive;
160 let mut task_inner_function = f.clone();
161 let task_inner_function_ident = format_ident!("__{}_task_inner_function", task_ident);
162 task_inner_function.sig.ident = task_inner_function_ident.clone();
163 task_inner_function.vis = Visibility::Inherited;
164
152 let task_inner_body = if errors.is_empty() { 165 let task_inner_body = if errors.is_empty() {
153 quote! { 166 quote! {
154 #f 167 #task_inner_function
155 168
156 // SAFETY: All the preconditions to `#task_ident` apply to 169 // SAFETY: All the preconditions to `#task_ident` apply to
157 // all contexts `#task_inner_ident` is called in 170 // all contexts `#task_inner_ident` is called in
158 #unsafety { 171 #unsafety {
159 #task_ident(#(#full_args,)*) 172 #task_inner_function_ident(#(#full_args,)*)
160 } 173 }
161 } 174 }
162 } else { 175 } else {
diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs
index e174a0594..0747db032 100644
--- a/embassy-executor/src/lib.rs
+++ b/embassy-executor/src/lib.rs
@@ -216,7 +216,7 @@ pub mod _export {
216 ); 216 );
217 217
218 #[allow(dead_code)] 218 #[allow(dead_code)]
219 trait HasOutput { 219 pub trait HasOutput {
220 type Output; 220 type Output;
221 } 221 }
222 222
@@ -225,7 +225,7 @@ pub mod _export {
225 } 225 }
226 226
227 #[allow(dead_code)] 227 #[allow(dead_code)]
228 type Never = <fn() -> ! as HasOutput>::Output; 228 pub type Never = <fn() -> ! as HasOutput>::Output;
229} 229}
230 230
231/// Implementation details for embassy macros. 231/// Implementation details for embassy macros.
@@ -242,7 +242,7 @@ pub mod _export {
242 impl TaskReturnValue for Never {} 242 impl TaskReturnValue for Never {}
243 243
244 #[allow(dead_code)] 244 #[allow(dead_code)]
245 trait HasOutput { 245 pub trait HasOutput {
246 type Output; 246 type Output;
247 } 247 }
248 248
@@ -251,5 +251,5 @@ pub mod _export {
251 } 251 }
252 252
253 #[allow(dead_code)] 253 #[allow(dead_code)]
254 type Never = <fn() -> ! as HasOutput>::Output; 254 pub type Never = <fn() -> ! as HasOutput>::Output;
255} 255}
diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs
index c1e7ec5d7..b84d3785a 100644
--- a/embassy-executor/tests/test.rs
+++ b/embassy-executor/tests/test.rs
@@ -7,7 +7,7 @@ use std::sync::{Arc, Mutex};
7use std::task::Poll; 7use std::task::Poll;
8 8
9use embassy_executor::raw::Executor; 9use embassy_executor::raw::Executor;
10use embassy_executor::task; 10use embassy_executor::{task, Spawner};
11 11
12#[export_name = "__pender"] 12#[export_name = "__pender"]
13fn __pender(context: *mut ()) { 13fn __pender(context: *mut ()) {
@@ -317,3 +317,12 @@ fn executor_task_cfg_args() {
317 let (_, _, _) = (a, b, c); 317 let (_, _, _) = (a, b, c);
318 } 318 }
319} 319}
320
321#[test]
322fn recursive_task() {
323 #[embassy_executor::task(pool_size = 2)]
324 async fn task1() {
325 let spawner = unsafe { Spawner::for_current_executor().await };
326 spawner.spawn(task1());
327 }
328}
diff --git a/embassy-executor/tests/ui/bad_return_impl_future_nightly.stderr b/embassy-executor/tests/ui/bad_return_impl_future_nightly.stderr
index 73ceb989d..3c3c9503b 100644
--- a/embassy-executor/tests/ui/bad_return_impl_future_nightly.stderr
+++ b/embassy-executor/tests/ui/bad_return_impl_future_nightly.stderr
@@ -7,4 +7,4 @@ error[E0277]: task futures must resolve to `()` or `!`
7 = note: use `async fn` or change the return type to `impl Future<Output = ()>` 7 = note: use `async fn` or change the return type to `impl Future<Output = ()>`
8 = help: the following other types implement trait `TaskReturnValue`: 8 = help: the following other types implement trait `TaskReturnValue`:
9 () 9 ()
10 <fn() -> ! as _export::HasOutput>::Output 10 <fn() -> ! as HasOutput>::Output