Absolutely massive error with async and tokio::spawn

So, I'm trying to run a future on tokio::spawn, and it spits out a huge error that starts with:

151 |             tokio::spawn(async move {
   |             ^^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
   | 
  ::: /home/elaina/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.0-alpha.6/src/executor.rs:100:40
   |
100 |     F: Future<Output = ()> + 'static + Send,
   |                                        ---- required by this bound in `tokio::executor::spawn`
   |
   = help: within `core::fmt::Void`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
   = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>`
   = note: required because it appears within the type `core::fmt::Void`
   = note: required because of the requirements on the impl of `std::marker::Send` for `&core::fmt::Void`
   = note: required because it appears within the type `std::fmt::ArgumentV1<'_>`
   = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>; 1]`
   = note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7, 't8, 't9, 't10, 't11, 't12, 't13, 't14, 't15, 't16, 't17, 't18, 't19, 't20, 't21, 't22, 't23, 't24, 't25, 't26, 't27, 't28, 't29, 't30, 't31, 't32, 't33, 't34, 't35, 't36, 't37, 't38, 't39, 't40, 't41, 't42, 't43, 't44, 't45, 't46, 't47, 't48, 't49, 't50, 't51, 't52, 't53, 't54, 't55, 't56, 't57, 't58, 't59, 't60, 't61, 't62, 't63, 't64, 't65, 't66, 't67, 't68, 't69, 't70, 't71, 't72, 't73, 't74, 't75, 't76, 't77, 't78, 't79, 't80, 't81, 't82, 't83, 't84, 't85, 't86, 't87, 't88, 't89, 't90, 't91, 't92, 't93>

It seems like somewhere in the chain of futures I'm using, something isn't Send or Sync, but how do I figure out what's causing it?

1 Like

It seems like this is from fmt::Arguments, which are not Send/Sync. Are you doing something like:

let args = format_args!(...)
some_async_fn().await;
some_writer.write_fmt(args)?

?

No, I'm not - although I'm using format! in a bunch of places, I can't find anywhere I'm doing it across an await.

5 Likes

That explains it, thanks! That's weird that format! would do that...

For anyone who comes across this thread looking for a way to make there code compile. Look for format! in temporary locations and move them to a variable.

For example in a function's arguments:

foo(format!("{}", x)).await;

changing it to:

let formatted_string = format!("{}", x);
foo(formatted_string).await;

will allow the code to compile.

2 Likes

You (and OP) are my heroes, I had this exact issue and the error was so large I was almost completely at a loss. So I did the natural thing and googled the error - well, the small part of the error the compiler points out for you - and I found this post :slight_smile:

and hoo boy was it a big error!
error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
   --> src/commands/to_delimited_data.rs:179:15
    |
179 |     Ok(stream.to_output_stream())
    |               ^^^^^^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
    |
    = help: within `core::fmt::Void`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
    = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>`
    = note: required because it appears within the type `core::fmt::Void`
    = note: required because of the requirements on the impl of `std::marker::Send` for `&core::fmt::Void`
    = note: required because it appears within the type `std::fmt::ArgumentV1<'_>`
    = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>; 1]`
    = note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7, 't8, 't9, 't10, 't11, 't12, 't13, 't14, 't15, 't16, 't17, 't18, 't19, 't20, 't21, 't22, 't23, 't24, 't25, 't26, 't27, 't28, 't29, 't30, 't31, 't32, 't33, 't34, 't35, 't36, 't37, 't38, 't39, 't40, 't41, 't42, 't43, 't44, 't45, 't46, 't47> {stream::InputStream, std::pin::Pin<std::boxed::Box<(dyn futures_core::stream::Stream<Item = data::meta::Tagged<data::base::Value>> + std::marker::Send + 'r)>>, futures_util::stream::collect::Collect<std::pin::Pin<std::boxed::Box<(dyn futures_core::stream::Stream<Item = data::meta::Tagged<data::base::Value>> + std::marker::Send + 's)>>, std::vec::Vec<data::meta::Tagged<data::base::Value>>>, futures_util::stream::collect::Collect<std::pin::Pin<std::boxed::Box<(dyn futures_core::stream::Stream<Item = data::meta::Tagged<data::base::Value>> + std::marker::Send + 't0)>>, std::vec::Vec<data::meta::Tagged<data::base::Value>>>, (), std::vec::Vec<data::meta::Tagged<data::base::Value>>, std::vec::Vec<data::meta::Tagged<data::base::Value>>, std::vec::Vec<data::meta::Tagged<data::base::Value>>, std::vec::IntoIter<data::meta::Tagged<data::base::Value>>, std::vec::IntoIter<data::meta::Tagged<data::base::Value>>, data::meta::Tagged<data::base::Value>, data::meta::Tagged<data::base::Value>, data::meta::Tagged<data::base::Value>, &'t1 data::meta::Tagged<data::base::Value>, &'t2 data::meta::Tagged<data::base::Value>, data::meta::Tagged<data::base::Value>, &'t3 data::meta::Tagged<data::base::Value>, &'t4 data::meta::Tagged<data::base::Value>, char, std::result::Result<std::string::String, errors::ShellError>, std::string::String, std::string::String, &'t5 mut async_stream::yielder::Sender<std::result::Result<commands::command::ReturnSuccess, errors::ShellError>>, async_stream::yielder::Sender<std::result::Result<commands::command::ReturnSuccess, errors::ShellError>>, std::string::String, data::base::Primitive, data::base::Value, data::meta::Tag, &'t6 data::meta::Tag, data::meta::Tagged<data::base::Value>, std::result::Result<commands::command::ReturnSuccess, errors::ShellError>, impl core::future::future::Future, impl core::future::future::Future, (), &'t7 mut async_stream::yielder::Sender<std::result::Result<commands::command::ReturnSuccess, errors::ShellError>>, &'t8 str, &'t9 str, [&'t10 str; 2], &'t11 [&'t12 str], &'t13 [&'t14 str; 2], &'t15 str, &'t16 &'t17 str, (&'t18 &'t19 str,), [std::fmt::ArgumentV1<'t20>; 1], &'t21 [std::fmt::ArgumentV1<'t22>], &'t23 [std::fmt::ArgumentV1<'t24>; 1], std::fmt::Arguments<'t25>, std::string::String, &'t26 str, &'t27 str, [&'t28 str; 2], &'t29 [&'t30 str], &'t31 [&'t32 str; 2], &'t33 str, &'t34 &'t35 str, (&'t36 &'t37 str,), [std::fmt::ArgumentV1<'t38>; 1], &'t39 [std::fmt::ArgumentV1<'t40>], &'t41 [std::fmt::ArgumentV1<'t42>; 1], std::fmt::Arguments<'t43>, std::string::String, data::meta::Tag, &'t44 data::meta::Tag, &'t45 str, &'t46 str, std::string::String, &'t47 data::meta::Tagged<data::base::Value>, data::meta::Tagged<data::base::Value>, data::meta::Tag, errors::ShellError, std::result::Result<commands::command::ReturnSuccess, errors::ShellError>, impl core::future::future::Future, ()}`
    = note: required because it appears within the type `[static generator@<::async_stream::stream macros>:7:10: 11:11 input:stream::InputStream, sep:char, headerless:bool, __yield_tx:async_stream::yielder::Sender<std::result::Result<commands::command::ReturnSuccess, errors::ShellError>>, name_tag:data::meta::Tag, format_name:&str for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7, 't8, 't9, 't10, 't11, 't12, 't13, 't14, 't15, 't16, 't17, 't18, 't19, 't20, 't21, 't22, 't23, 't24, 't25, 't26, 't27, 't28, 't29, 't30, 't31, 't32, 't33, 't34, 't35, 't36, 't37, 't38, 't39, 't40, 't41, 't42, 't43, 't44, 't45, 't46, 't47> {stream::InputStream, std::pin::Pin<std::boxed::Box<(dyn futures_core::stream::Stream<Item = data::meta::Tagged<data::base::Value>> + std::marker::Send + 'r)>>, futures_util::stream::collect::Collect<std::pin::Pin<std::boxed::Box<(dyn futures_core::stream::Stream<Item = data::meta::Tagged<data::base::Value>> + std::marker::Send + 's)>>, std::vec::Vec<data::meta::Tagged<data::base::Value>>>, futures_util::stream::collect::Collect<std::pin::Pin<std::boxed::Box<(dyn futures_core::stream::Stream<Item = data::meta::Tagged<data::base::Value>> + std::marker::Send + 't0)>>, std::vec::Vec<data::meta::Tagged<data::base::Value>>>, (), std::vec::Vec<data::meta::Tagged<data::base::Value>>, std::vec::Vec<data::meta::Tagged<data::base::Value>>, std::vec::Vec<data::meta::Tagged<data::base::Value>>, std::vec::IntoIter<data::meta::Tagged<data::base::Value>>, std::vec::IntoIter<data::meta::Tagged<data::base::Value>>, data::meta::Tagged<data::base::Value>, data::meta::Tagged<data::base::Value>, data::meta::Tagged<data::base::Value>, &'t1 data::meta::Tagged<data::base::Value>, &'t2 data::meta::Tagged<data::base::Value>, data::meta::Tagged<data::base::Value>, &'t3 data::meta::Tagged<data::base::Value>, &'t4 data::meta::Tagged<data::base::Value>, char, std::result::Result<std::string::String, errors::ShellError>, std::string::String, std::string::String, &'t5 mut async_stream::yielder::Sender<std::result::Result<commands::command::ReturnSuccess, errors::ShellError>>, async_stream::yielder::Sender<std::result::Result<commands::command::ReturnSuccess, errors::ShellError>>, std::string::String, data::base::Primitive, data::base::Value, data::meta::Tag, &'t6 data::meta::Tag, data::meta::Tagged<data::base::Value>, std::result::Result<commands::command::ReturnSuccess, errors::ShellError>, impl core::future::future::Future, impl core::future::future::Future, (), &'t7 mut async_stream::yielder::Sender<std::result::Result<commands::command::ReturnSuccess, errors::ShellError>>, &'t8 str, &'t9 str, [&'t10 str; 2], &'t11 [&'t12 str], &'t13 [&'t14 str; 2], &'t15 str, &'t16 &'t17 str, (&'t18 &'t19 str,), [std::fmt::ArgumentV1<'t20>; 1], &'t21 [std::fmt::ArgumentV1<'t22>], &'t23 [std::fmt::ArgumentV1<'t24>; 1], std::fmt::Arguments<'t25>, std::string::String, &'t26 str, &'t27 str, [&'t28 str; 2], &'t29 [&'t30 str], &'t31 [&'t32 str; 2], &'t33 str, &'t34 &'t35 str, (&'t36 &'t37 str,), [std::fmt::ArgumentV1<'t38>; 1], &'t39 [std::fmt::ArgumentV1<'t40>], &'t41 [std::fmt::ArgumentV1<'t42>; 1], std::fmt::Arguments<'t43>, std::string::String, data::meta::Tag, &'t44 data::meta::Tag, &'t45 str, &'t46 str, std::string::String, &'t47 data::meta::Tagged<data::base::Value>, data::meta::Tagged<data::base::Value>, data::meta::Tag, errors::ShellError, std::result::Result<commands::command::ReturnSuccess, errors::ShellError>, impl core::future::future::Future, ()}]`
    = note: required because it appears within the type `std::future::GenFuture<[static generator@<::async_stream::stream macros>:7:10: 11:11 input:stream::InputStream, sep:char, headerless:bool, __yield_tx:async_stream::yielder::Sender<std::result::Result<commands::command::ReturnSuccess, errors::ShellError>>, name_tag:data::meta::Tag, format_name:&str for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7, 't8, 't9, 't10, 't11, 't12, 't13, 't14, 't15, 't16, 't17, 't18, 't19, 't20, 't21, 't22, 't23, 't24, 't25, 't26, 't27, 't28, 't29, 't30, 't31, 't32, 't33, 't34, 't35, 't36, 't37, 't38, 't39, 't40, 't41, 't42, 't43, 't44, 't45, 't46, 't47> {stream::InputStream, std::pin::Pin<std::boxed::Box<(dyn futures_core::stream::Stream<Item = data::meta::Tagged<data::base::Value>> + std::marker::Send + 'r)>>, futures_util::stream::collect::Collect<std::pin::Pin<std::boxed::Box<(dyn futures_core::stream::Stream<Item = data::meta::Tagged<data::base::Value>> + std::marker::Send + 's)>>, std::vec::Vec<data::meta::Tagged<data::base::Value>>>, futures_util::stream::collect::Collect<std::pin::Pin<std::boxed::Box<(dyn futures_core::stream::Stream<Item = data::meta::Tagged<data::base::Value>> + std::marker::Send + 't0)>>, std::vec::Vec<data::meta::Tagged<data::base::Value>>>, (), std::vec::Vec<data::meta::Tagged<data::base::Value>>, std::vec::Vec<data::meta::Tagged<data::base::Value>>, std::vec::Vec<data::meta::Tagged<data::base::Value>>, std::vec::IntoIter<data::meta::Tagged<data::base::Value>>, std::vec::IntoIter<data::meta::Tagged<data::base::Value>>, data::meta::Tagged<data::base::Value>, data::meta::Tagged<data::base::Value>, data::meta::Tagged<data::base::Value>, &'t1 data::meta::Tagged<data::base::Value>, &'t2 data::meta::Tagged<data::base::Value>, data::meta::Tagged<data::base::Value>, &'t3 data::meta::Tagged<data::base::Value>, &'t4 data::meta::Tagged<data::base::Value>, char, std::result::Result<std::string::String, errors::ShellError>, std::string::String, std::string::String, &'t5 mut async_stream::yielder::Sender<std::result::Result<commands::command::ReturnSuccess, errors::ShellError>>, async_stream::yielder::Sender<std::result::Result<commands::command::ReturnSuccess, errors::ShellError>>, std::string::String, data::base::Primitive, data::base::Value, data::meta::Tag, &'t6 data::meta::Tag, data::meta::Tagged<data::base::Value>, std::result::Result<commands::command::ReturnSuccess, errors::ShellError>, impl core::future::future::Future, impl core::future::future::Future, (), &'t7 mut async_stream::yielder::Sender<std::result::Result<commands::command::ReturnSuccess, errors::ShellError>>, &'t8 str, &'t9 str, [&'t10 str; 2], &'t11 [&'t12 str], &'t13 [&'t14 str; 2], &'t15 str, &'t16 &'t17 str, (&'t18 &'t19 str,), [std::fmt::ArgumentV1<'t20>; 1], &'t21 [std::fmt::ArgumentV1<'t22>], &'t23 [std::fmt::ArgumentV1<'t24>; 1], std::fmt::Arguments<'t25>, std::string::String, &'t26 str, &'t27 str, [&'t28 str; 2], &'t29 [&'t30 str], &'t31 [&'t32 str; 2], &'t33 str, &'t34 &'t35 str, (&'t36 &'t37 str,), [std::fmt::ArgumentV1<'t38>; 1], &'t39 [std::fmt::ArgumentV1<'t40>], &'t41 [std::fmt::ArgumentV1<'t42>; 1], std::fmt::Arguments<'t43>, std::string::String, data::meta::Tag, &'t44 data::meta::Tag, &'t45 str, &'t46 str, std::string::String, &'t47 data::meta::Tagged<data::base::Value>, data::meta::Tagged<data::base::Value>, data::meta::Tag, errors::ShellError, std::result::Result<commands::command::ReturnSuccess, errors::ShellError>, impl core::future::future::Future, ()}]>`
    = note: required because it appears within the type `impl core::future::future::Future`
    = note: required because it appears within the type `async_stream::async_stream::AsyncStream<std::result::Result<commands::command::ReturnSuccess, errors::ShellError>, impl core::future::future::Future>`
    = note: required because of the requirements on the impl of `prelude::ToOutputStream` for `async_stream::async_stream::AsyncStream<std::result::Result<commands::command::ReturnSuccess, errors::ShellError>, impl core::future::future::Future>`

error: aborting due to previous error

Shout out to the compiler team as well, the rust's compiler errors are really good