Consider this:
It fails with:
error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
--> src/main.rs:12:89
|
12 | async fn write_fmt<'args>(&mut self, args: fmt::Arguments<'args>) -> io::Result<()> {
| _________________________________________________________________________________________^
13 | | let string = format!("{}", args);
14 | | self.write_all(string.as_bytes()).await
15 | | }
| |_____^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
|
= help: within `[std::fmt::ArgumentV1<'_>]`, 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 it appears within the type `&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<'_>]`
= note: required because of the requirements on the impl of `std::marker::Send` for `&[std::fmt::ArgumentV1<'_>]`
= note: required because it appears within the type `std::fmt::Arguments<'_>`
= note: required because it appears within the type `[static generator@src/main.rs:12:89: 15:6 _self:&mut tokio::io::stdout::Stdout, args:std::fmt::Arguments<'_> for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6> {&'r mut tokio::io::stdout::Stdout, std::fmt::Arguments<'s>, std::string::String, &'t0 mut tokio::io::stdout::Stdout, &'t1 mut tokio::io::stdout::Stdout, &'t2 std::string::String, std::string::String, &'t3 [u8], &'t4 [u8], tokio::io::util::write_all::WriteAll<'t5, tokio::io::stdout::Stdout>, tokio::io::util::write_all::WriteAll<'t6, tokio::io::stdout::Stdout>, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@src/main.rs:12:89: 15:6 _self:&mut tokio::io::stdout::Stdout, args:std::fmt::Arguments<'_> for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6> {&'r mut tokio::io::stdout::Stdout, std::fmt::Arguments<'s>, std::string::String, &'t0 mut tokio::io::stdout::Stdout, &'t1 mut tokio::io::stdout::Stdout, &'t2 std::string::String, std::string::String, &'t3 [u8], &'t4 [u8], tokio::io::util::write_all::WriteAll<'t5, tokio::io::stdout::Stdout>, tokio::io::util::write_all::WriteAll<'t6, tokio::io::stdout::Stdout>, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
= note: required for the cast to the object type `dyn std::future::Future<Output = std::result::Result<(), std::io::Error>> + std::marker::Send`
This is because fmt::Arguments
are !Send
and !Sync
. This means they cannot even be put in a mutex. So how do I use them in multi-threaded futures? Note that without fmt::Arguments
it is impossible to use fmt::Debug
and fmt::Display
.