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