rust-lang / rust-lang/rust

#[inline(never)] does not work for async functions

Open
#129,347 16 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

A-async-await A-codegen A-LLVM AsyncAwait-Triaged C-bug disposition-merge finished-final-comment-period S-has-mcve T-lang
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I would expect the following code produced a Future::poll() impl with the noinline attribute.

#![feature(noop_waker)]

use std::task::{Context, Waker, Poll};
use std::future::Future;

#[inline(never)]
pub async fn foo() -> u32 {
    std::hint::black_box(1)
}

pub fn bar() -> Poll<u32> {
    let f = std::pin::pin!(foo());
    f.poll(&mut Context::from_waker(Waker::noop()))
}

Instead, the poll method has inlinehint applied to it and gets inlined accordingly:

; This is the function creating the async fn obj:
; Function Attrs: noinline nonlazybind uwtable
define i8 @_RNvCs8Nh0J9OTdDr_15async_fn_inline3foo() unnamed_addr #2 {
  %1 = alloca [1 x i8], align 1
  store i8 0, ptr %1, align 1
  %2 = load i8, ptr %1, align 1
  ret i8 %2
}

; This the poll method:
; Function Attrs: inlinehint nonlazybind uwtable <== this should arguably be noinline too
define internal { i32, i32 } @_RNCNvCs8Nh0J9OTdDr_15async_fn_inline3foo0B3_(...)
Meta

rustc --version --verbose:

rustc 1.82.0-nightly (636d7ff91 2024-08-19)
binary: rustc
commit-hash: 636d7ff91b9847d6d43c7bbe023568828f6e3246
commit-date: 2024-08-19
host: x86_64-unknown-linux-gnu
release: 1.82.0-nightly
LLVM version: 19.1.0

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 with the linked Godbolt reproducer and inspect the generated LLVM for the async function's Future::poll implementation. Trace how #[inline(never)] on foo is translated to that poll entry point; done means the poll method preserves the noinline attribute instead of inlinehint and inlining.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.