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?

2 Likes

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.

https://github.com/rust-lang/rust/issues/64960

6 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.

7 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

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.