rust-lang / rust-lang/rust

Async function calls not optimized out

Open
#135,468 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-async-await C-optimization E-needs-mcve T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Async function calls that are behind simple if false (or if cfg!() that aren't active) can still affect the binary, even though non-async function calls are optimized out.

I tried this code:

#[tokio::main]
async fn main() {
    if false {
        async fn never_panic() {
            panic!("disco");
        }
        never_panic().await;
    }
    if false {
        panic!("antidisestablishmentarianism");
    }
    println!("All done!");
}

And ran cargo rustc --release -- -C opt-level=s (this behavior also appears on opt-level 3), and checked for the resulting strings in the binary, e.g., strings target/release/minimal | grep -e disco or strings target/release/minimal | grep -e antidis.

As expected, the string "antidisestablishmentarianism" never appears in the binary, but "disco" always does, even though functionally, they should be equivalent.

If I had to guess why this could happen, it's because if false { ... } still internally generates some type for the impl Future, which isn't getting optimized out for some reason.

In a more complex app, we were finding that this was also affecting runtime behavior of the code (maybe due to there being a lot of code and crates not optimized out, and that chaining into additional effects, but it was hard to isolate this behavior).

Meta

This bug exists in nightly going back to 2024-09-30 at least, but also on the latest.

It happens on both x86-64 and riscv32, at least.

rustc --version --verbose:

rustc 1.84.0 (9fc6b4312 2025-01-07)
binary: rustc
commit-hash: 9fc6b43126469e3858e2fe86cafb4f0fd5068869
commit-date: 2025-01-07
host: x86_64-unknown-linux-gnu
release: 1.84.0
LLVM version: 19.1.5

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the provided example with the listed cargo rustc command and compare the resulting binary strings for the async and non-async branches. Trace the compiler behavior for an async call inside an inactive if false or cfg! branch; done means the async branch no longer contributes its string or related code to the optimized binary.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.