Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

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

Open
comex opened this issue Aug 16, 2019 · 1 comment
Open

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

comex opened this issue Aug 16, 2019 · 1 comment
Labels
A-async-await Area: Async & Await A-attributes Area: #[attributes(..)] A-codegen Area: Code generation AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. C-bug Category: This is a bug. I-slow Issue: Problems and improvements with respect to performance of generated code. requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@comex
Copy link
Contributor

comex commented Aug 16, 2019

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.

@Centril Centril added A-attributes Area: #[attributes(..)] A-async-await Area: Async & Await AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. requires-nightly This issue requires a nightly compiler in some way. I-slow Issue: Problems and improvements with respect to performance of generated code. A-codegen Area: Code generation labels Aug 17, 2019
@jonas-schievink jonas-schievink added C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Aug 17, 2019
@Nemo157
Copy link
Member

Nemo157 commented Aug 17, 2019

It appears that #[inline(always)] works on generators already, by inspection of the ASM for this playground. So getting the resume function inlined just requires effectively duplicating the attribute onto both the function and generator during the transform.

The gen_future infrastructure also seems trivial enough that it could make sense to put #[inline(always)] on it all (or at the very least the GenFuture::poll method), especially since it's a workaround that will disappear in the future.

The only downside I see is if someone does want the current behaviour of inlining just the initialization, in that case I guess they would need to write an explicit #[inline(always)] fn() -> impl Future { async { } } so that the inline attribute will only apply to the function and not the async block.

Actually, on that last point it appears you cannot apply #[inline(always)] on an async block either, that seems like something that should also be supported.

error[E0518]: attribute should be applied to function or closure
 --> src/main.rs:6:5
  |
6 |     #[inline(always)] async { 12345 }
  |     ^^^^^^^^^^^^^^^^^ --------------- not a function or closure

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-async-await Area: Async & Await A-attributes Area: #[attributes(..)] A-codegen Area: Code generation AsyncAwait-Triaged Async-await issues that have been triaged during a working group meeting. C-bug Category: This is a bug. I-slow Issue: Problems and improvements with respect to performance of generated code. requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants