Skip to content

inline attribute on async fn doesn't work properly #63647

Open
@comex

Description

@comex

Playground link

In the playground, an async fn is marked #[inline(always)]:

#[inline(always)]
pub async fn test() -> i32 {
    12345
}

However, if you compile it in debug mode (where inlining only happens for #[inline(always)] functions), and search for 12345 in the generated assembly, you can see that it is not inlined.

Indeed, there are multiple levels of function calls that are not inlined:

run_it
GenFuture<T>::poll
std::future::set_task_context
GenFuture<T>::poll::{closure}
playground::test::{{closure}}

That last closure is the generator that contains the actual body of test.

#[inline(always)] is taking effect on the post-transformation function test, but all that does is initialize the generator struct.

As long as async is implemented based on generators, this will be hard to fix. Even if the generator itself were marked alwaysinline, that wouldn't affect GenFuture or set_task_context, both of which are from libstd.

Related to #62918, since if you want an async fn to be #[inline(always)], you probably also want to get rid of the TLS usage by set_task_context.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-async-awaitArea: Async & AwaitA-attributesArea: Attributes (`#[…]`, `#![…]`)A-codegenArea: Code generationAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.C-bugCategory: This is a bug.I-slowIssue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions