[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 authored and GitHub committed 2022-09-26 22:11:36 +02:00
1 parent fd1856e1e9
commit c3e45a04fc
2 files changed
+24 -19

No files matched your search

+21 -16
View File
@@ -46,24 +46,29 @@ impl<Context> Fortified {
}
}
fn main() {
use futures::{executor, pin_mut};
async fn setup() {
let builder = Solo::builder();
executor::block_on(async move {
let (orchestra, _handle): (Solo<_>, _) = Solo::builder()
.goblin_tower(Fortified::default())
.spawner(DummySpawner)
.build()
.unwrap();
let builder = builder.goblin_tower(Fortified::default());
let orchestra_fut = orchestra
.running_subsystems
.into_future()
.timeout(std::time::Duration::from_millis(300))
.fuse();
let builder = builder.spawner(DummySpawner);
let (orchestra, _handle): (Solo<_>, _) = builder.build().unwrap();
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 ) ->
#builder <InitStateSpawner, #( #post_setter_state_generics, )* #( #baggage_passthrough_state_generics, )*>
where
F: 'static + FnOnce(#handle) ->
F: 'static + Send + FnOnce(#handle) ->
::std::result::Result<#field_type, #error_ty>,
{
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, )*>
where
#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>,
{
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! {
/// 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
pub enum Init<T> {