Skip to content

Using the format!() macro with an async function makes the whole Future non-Send #101650

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
Hocuri opened this issue Sep 10, 2022 · 5 comments
Open
Labels
A-fmt Area: `core::fmt` C-bug Category: This is a bug. E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@Hocuri
Copy link

Hocuri commented Sep 10, 2022

I tried this code: (minimal reproducible example; for the actual code see chatmail/core#3591)

use core::future::Future;
use core::pin::Pin;

fn build_string() -> Pin<Box<dyn Future<Output = String> + Send>> {
    Box::pin(async move {
        let mut string_builder = "<h>".to_string();
        string_builder += &format!("Hello {}", helper().await);
        string_builder += "</h>";
        string_builder
    })
}

async fn helper() -> String {
    "World".to_string()
}

Playground

Note that we are using,

format!("Hello {}", helper().await)

in a context where the Future needs to be Send; only this line without the string_builder seems not to be able to reproduce the issue though.

I expected to see this happen: That the code behaves the same as

let s = helper().await;
format!("Hello {}", s)

Instead, this happened:

There are two error messages (about line 5 and line 7); this issue is about the first one:

error: future cannot be sent between threads safely
 --> src/lib.rs:5:5
  |
5 |     Box::pin(async move {
  |     ^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
  |
  = help: the trait `Sync` is not implemented for `core::fmt::Opaque`
note: future is not `Send` as this value is used across an await
 --> src/lib.rs:7:56
  |
7 |         string_builder += &format!("Hello {}", helper().await);
  |                            ----------------------------^^^^^^-
  |                            |                   |       |
  |                            |                   |       await occurs here, with `helper().await` maybe used later
  |                            |                   has type `ArgumentV1<'_>` which is not `Send`
  |                            `helper().await` is later dropped here
  = note: required for the cast to the object type `dyn Future<Output = String> + Send`

The second error message didn't appear in the original issue in chatmail/core#3591, possibly because there the call to Box::pin() and the format!() call are in two different crates:

error: generator cannot be sent between threads safely
  --> deltachat-jsonrpc/src/api/mod.rs:74:1
   |
74 | #[rpc(all_positional, ts_outdir = "typescript/generated")]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
   |
   = help: the trait `Sync` is not implemented for `core::fmt::Opaque`
   = note: required for the cast to the object type `dyn Future<Output = Result<Value, yerpc::Error>> + Send`
   = note: this error originates in the attribute macro `rpc` (in Nightly builds, run with -Z macro-backtrace for more info)

Meta

rustc --version --verbose

Probably doesn't matter, anyway:

rustc 1.61.0 (fe5b13d68 2022-05-18)
binary: rustc
commit-hash: fe5b13d681f25ee6474be29d748c65adcd91f69e
commit-date: 2022-05-18
host: x86_64-unknown-linux-gnu
release: 1.61.0
LLVM version: 14.0.0

@rustbot label +A-fmt

@Hocuri Hocuri added the C-bug Category: This is a bug. label Sep 10, 2022
@rustbot rustbot added the A-fmt Area: `core::fmt` label Sep 10, 2022
@Hocuri
Copy link
Author

Hocuri commented Sep 10, 2022

Notes:

I'll guess this is
@rustbot label +T-libs

@rustbot rustbot added the T-libs Relevant to the library team, which will review and decide on the PR/issue. label Sep 10, 2022
Jikstra added a commit to chatmail/core that referenced this issue Sep 10, 2022
Fix get_connectivity_html and get_encrinfo futures not being Send. See rust-lang/rust#101650 for more information.

Co-authored-by: jikstra <jikstra@disroot.org>
Simon-Laux added a commit to chatmail/core that referenced this issue Sep 11, 2022
Fix get_connectivity_html and get_encrinfo futures not being Send. See rust-lang/rust#101650 for more information.

Co-authored-by: jikstra <jikstra@disroot.org>
Simon-Laux added a commit to chatmail/core that referenced this issue Sep 11, 2022
* add more functions, see changelog for details

* add pr number to changelog

* clarify doc comment

* clarify usage of BasicChat
and adjust properties acordingly

r10s is right it should only contain what we need of the expensive calls

* fix doc typos

* run cargo fmt

* jsonrpc: add connectivity functions

* fix typo

* fix typo

* Add get_contact_encryption_info and get_connectivity_html

Fix get_connectivity_html and get_encrinfo futures not being Send. See rust-lang/rust#101650 for more information.

Co-authored-by: jikstra <jikstra@disroot.org>

* Update CHANGELOG

* Update typescript files

* remove todo from changelog

Co-authored-by: jikstra <jikstra@disroot.org>
@bjorn3

This comment has been minimized.

@m-ou-se

This comment has been minimized.

@lolbinarycat lolbinarycat added E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. labels Apr 11, 2025
@lolbinarycat
Copy link
Contributor

triage: seems to have been fixed, now we just need someone to add this as a test.

@m-ou-se
Copy link
Member

m-ou-se commented Apr 11, 2025

The issue of yield points in formatting arguments was actually already fixed by #93461, but that was already merged far before this issue was even opened.

Looks like this specific issue is not triggered just by the format!(..) invocation. It was only triggered when doing string += &format!(..);.

And that was fixed by #107421

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-fmt Area: `core::fmt` C-bug Category: This is a bug. E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants