[orchestra] fix: require the initialization with F: FnOnce to be Send (#6051)

* add regression test for missing Send requirement

* fix: require the initialization with `F: FnOnce` to be `Send` as well

If creating intermediate variables of the builder type within
a future, rustc will complain about the future not being send,
while the thing itself isn't even using the closure based field
initialization. Adding an additional bound, resolves this and
pushes the error message "closer" to the user, and out of the
generated code.

* import fixins
This commit is contained in:
Bernhard Schuster
2022-09-26 22:11:36 +02:00
committed by GitHub
parent fd1856e1e9
commit c3e45a04fc
2 changed files with 24 additions and 19 deletions
+21 -16
View File
@@ -46,24 +46,29 @@ impl<Context> Fortified {
} }
} }
fn main() { async fn setup() {
use futures::{executor, pin_mut}; let builder = Solo::builder();
executor::block_on(async move { let builder = builder.goblin_tower(Fortified::default());
let (orchestra, _handle): (Solo<_>, _) = Solo::builder()
.goblin_tower(Fortified::default())
.spawner(DummySpawner)
.build()
.unwrap();
let orchestra_fut = orchestra let builder = builder.spawner(DummySpawner);
.running_subsystems let (orchestra, _handle): (Solo<_>, _) = builder.build().unwrap();
.into_future()
.timeout(std::time::Duration::from_millis(300))
.fuse();
pin_mut!(orchestra_fut); let orchestra_fut = orchestra
.running_subsystems
.into_future()
.timeout(std::time::Duration::from_millis(300))
.fuse();
orchestra_fut.await futures::pin_mut!(orchestra_fut);
});
orchestra_fut.await;
}
fn assert_t_impl_trait_send<T: Send>(_: &T) {}
fn main() {
let x = setup();
assert_t_impl_trait_send(&x);
futures::executor::block_on(x);
} }
@@ -172,7 +172,7 @@ pub(crate) fn impl_builder(info: &OrchestraInfo) -> proc_macro2::TokenStream {
pub fn #field_name_with<'a, F>(self, subsystem_init_fn: F ) -> pub fn #field_name_with<'a, F>(self, subsystem_init_fn: F ) ->
#builder <InitStateSpawner, #( #post_setter_state_generics, )* #( #baggage_passthrough_state_generics, )*> #builder <InitStateSpawner, #( #post_setter_state_generics, )* #( #baggage_passthrough_state_generics, )*>
where where
F: 'static + FnOnce(#handle) -> F: 'static + Send + FnOnce(#handle) ->
::std::result::Result<#field_type, #error_ty>, ::std::result::Result<#field_type, #error_ty>,
{ {
let boxed_func = Init::<#field_type>::Fn( let boxed_func = Init::<#field_type>::Fn(
@@ -206,7 +206,7 @@ pub(crate) fn impl_builder(info: &OrchestraInfo) -> proc_macro2::TokenStream {
-> #builder <InitStateSpawner, #( #post_replace_state_generics, )* #( #baggage_passthrough_state_generics, )*> -> #builder <InitStateSpawner, #( #post_replace_state_generics, )* #( #baggage_passthrough_state_generics, )*>
where where
#field_type: 'static, #field_type: 'static,
F: 'static + FnOnce(#field_type) -> NEW, F: 'static + Send + FnOnce(#field_type) -> NEW,
NEW: #support_crate ::Subsystem<#subsystem_ctx_name< #subsystem_consumes >, #error_ty>, NEW: #support_crate ::Subsystem<#subsystem_ctx_name< #subsystem_consumes >, #error_ty>,
{ {
let replacement: Init<NEW> = match self.#field_name { let replacement: Init<NEW> = match self.#field_name {
@@ -333,7 +333,7 @@ pub(crate) fn impl_builder(info: &OrchestraInfo) -> proc_macro2::TokenStream {
let mut ts = quote! { let mut ts = quote! {
/// Convenience alias. /// Convenience alias.
type SubsystemInitFn<T> = Box<dyn FnOnce(#handle) -> ::std::result::Result<T, #error_ty> >; type SubsystemInitFn<T> = Box<dyn FnOnce(#handle) -> ::std::result::Result<T, #error_ty> + Send + 'static>;
/// Type for the initialized field of the orchestra builder /// Type for the initialized field of the orchestra builder
pub enum Init<T> { pub enum Init<T> {