@@ -2,7 +2,7 @@ use crate::syntax::{ast::App, Context};
22use crate :: { analyze:: Analysis , codegen:: bindings:: interrupt_mod, codegen:: util} ;
33
44use proc_macro2:: TokenStream as TokenStream2 ;
5- use quote:: quote;
5+ use quote:: { format_ident , quote} ;
66
77#[ allow( clippy:: too_many_lines) ]
88pub fn codegen ( ctxt : Context , app : & App , analysis : & Analysis ) -> TokenStream2 {
@@ -129,26 +129,29 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 {
129129 } ;
130130
131131 let internal_spawn_ident = util:: internal_task_ident ( name, "spawn" ) ;
132+ let internal_spawn_helper_ident = util:: internal_task_ident ( name, "spawn_helper" ) ;
132133 let internal_waker_ident = util:: internal_task_ident ( name, "waker" ) ;
133134 let from_ptr_n_args = util:: from_ptr_n_args_ident ( spawnee. inputs . len ( ) ) ;
134135 let ( input_args, input_tupled, input_untupled, input_ty) =
135136 util:: regroup_inputs ( & spawnee. inputs ) ;
136137
137- let local_task = app. software_tasks [ t] . args . local_task ;
138- let unsafety = if local_task {
139- // local tasks are only safe to call from the same executor
140- quote ! { unsafe }
141- } else {
142- quote ! { }
143- } ;
138+ let generics: Vec < _ > = spawnee. inputs . iter ( ) . enumerate ( ) . map ( |( i, _) | format_ident ! ( "T{i}" ) ) . collect ( ) ;
139+ let generic_input_args = generics. iter ( ) . enumerate ( ) . map ( |( i, generic) | {
140+ let ident = format_ident ! ( "_{i}" ) ;
141+ quote ! { #ident: #generic }
142+ } ) ;
143+ let constraints = generics. iter ( ) . zip ( & spawnee. inputs ) . map ( |( generic, input) | {
144+ let ty = & input. ty ;
145+ quote ! { #generic: Dummy <T =#ty> + Send + Sync }
146+ } ) ;
144147
145148 // Spawn caller
146149 items. push ( quote ! (
147150 #( #cfgs) *
148151 /// Spawns the task directly
149152 #[ allow( non_snake_case) ]
150153 #[ doc( hidden) ]
151- pub #unsafety fn #internal_spawn_ident ( #( #input_args, ) * ) -> :: core:: result:: Result <( ) , #input_ty> {
154+ pub fn #internal_spawn_helper_ident ( #( #input_args, ) * ) -> :: core:: result:: Result <( ) , #input_ty> {
152155 // SAFETY: If `try_allocate` succeeds one must call `spawn`, which we do.
153156 unsafe {
154157 let exec = rtic:: export:: executor:: AsyncTaskExecutor :: #from_ptr_n_args( #name, & #exec_name) ;
@@ -162,6 +165,12 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 {
162165 }
163166 }
164167 }
168+
169+ pub fn #internal_spawn_ident<#( #generics) , * >( #( #generic_input_args, ) * ) -> :: core:: result:: Result <( ) , #input_ty>
170+ where #( #constraints) , *
171+ {
172+ unsafe { #internal_spawn_helper_ident( #( #input_untupled. to( ) ) , * ) }
173+ }
165174 ) ) ;
166175
167176 // Waker
@@ -183,37 +192,31 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 {
183192 }
184193 ) ) ;
185194
186- if !local_task {
187- module_items. push ( quote ! (
188- #( #cfgs) *
189- #[ doc( inline) ]
190- pub use super :: #internal_spawn_ident as spawn;
191- ) ) ;
192- }
195+ module_items. push ( quote ! {
196+ #( #cfgs) *
197+ #[ doc( inline) ]
198+ pub use super :: #internal_spawn_ident as spawn;
199+ } ) ;
193200
194- let local_tasks_on_same_executor : Vec < _ > = app
201+ let tasks_on_same_executor : Vec < _ > = app
195202 . software_tasks
196203 . iter ( )
197- . filter ( |( _, t) | t. args . local_task && t . args . priority == priority)
204+ . filter ( |( _, t) | t. args . priority == priority)
198205 . collect ( ) ;
199206
200- if !local_tasks_on_same_executor . is_empty ( ) {
207+ if !tasks_on_same_executor . is_empty ( ) {
201208 let local_spawner = util:: internal_task_ident ( t, "LocalSpawner" ) ;
202209 fields. push ( quote ! {
203210 /// Used to spawn tasks on the same executor
204211 ///
205212 /// This is useful for tasks that take args which are !Send/!Sync.
206- ///
207- /// NOTE: This only works with tasks marked `local_task = true`
208- /// and which have the same priority and thus will run on the
209- /// same executor.
210213 pub local_spawner: #local_spawner
211214 } ) ;
212- let tasks = local_tasks_on_same_executor
215+ let tasks = tasks_on_same_executor
213216 . iter ( )
214217 . map ( |( ident, task) | {
215218 // Copied mostly from software_tasks.rs
216- let internal_spawn_ident = util:: internal_task_ident ( ident, "spawn " ) ;
219+ let internal_spawn_ident = util:: internal_task_ident ( ident, "spawn_helper " ) ;
217220 let attrs = & task. attrs ;
218221 let cfgs = & task. cfgs ;
219222 let inputs = & task. inputs ;
0 commit comments