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

[For previewing, reviewing and testing] Move upvars to locals #135527

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

dingxiangfei2009
Copy link
Contributor

Good day, this PR is related to #127522 and it is made easier to the public to test out a new coroutine/async state machine directly.

Prepare the compiler for tests

For starter, you may build the compiler as prescribed in the rustc-dev-guide instruction. If a test in the docker container is desirable, you may build this compiler with src/ci/docker/run.sh dist-x86_64-linux --dev for x86_64 and package the compiler with ../x dist to produce the artifacts in obj/dist-x86_64-linux/build/dist. This Dockerfile gets you a working Rust builder image which allows you to build your Rust applications in bookworm.

The state of performance

So far with this patch, I have been studying the performance impact on the cases of tokio's single- and multi-threaded runtime, as well as a simple axum HTTP service. As far as I can see, I can find a change in performance characteristics that are statistically significant, one-sided p = 0.05.

This time, I would like to call for pooling in your valuable assessments and thoughts on this patch. I kindly request experiments from you and hopefully you can provide regression cases with perf record -e cycles:u,instructions:u,cache-misses:u reports.

Thank you all so much! 🙇

@rustbot
Copy link
Collaborator

rustbot commented Jan 15, 2025

r? @BoxyUwU

rustbot has assigned @BoxyUwU.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 15, 2025
@rustbot
Copy link
Collaborator

rustbot commented Jan 15, 2025

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred to the CTFE machinery

cc @rust-lang/wg-const-eval

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Jan 19, 2025

☔ The latest upstream changes (presumably #135715) made this pull request unmergeable. Please resolve the merge conflicts.

@BoxyUwU BoxyUwU removed their assignment Jan 28, 2025
@BoxyUwU
Copy link
Member

BoxyUwU commented Jan 28, 2025

I don't think this needs a reviewer?

@dingxiangfei2009 dingxiangfei2009 force-pushed the move-upvars-to-locals-for-tests branch from 3e6a399 to 9603ad6 Compare January 28, 2025 23:17
@traviscross
Copy link
Contributor

cc @Darksonn @tmandry @eholk @rust-lang/wg-async

Ding here is reworking the layout of coroutines to try to reduce their memory footprint (and that of Futures). He's curious to find whether this introduces any performance or other regressions. In this own testing, he's not been able to find any, but he's curious in more data and experience here to help inform whether this is a worthwhile change.

What do people think?

@rust-log-analyzer

This comment has been minimized.

@tmandry
Copy link
Member

tmandry commented Jan 30, 2025

For anyone searching for a description of what this PR changes, it's summarized at the top of compiler/rustc_mir_transform/src/coroutine/relocate_upvars.rs.

Comment on lines 20 to 21
//! The reason is that it is possible that coroutine layout may change and the source memory location of
//! an upvar may not necessarily be mapped exactly to the same place as in the `Unresumed` state.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we decide the offsets of upvars in Unresumed in the same place as we decide the offset of saved locals? Couldn't we then "backpropagate" the field offsets for each upvar's local as the offset for the corresponding upvar?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for reviewing! I had a backlog of things due to sickness.

True indeed. This statement is completely voided by the work in the second commit. I will reword this section in the following way.


By enabling the feature gate coroutine_new_layout the field offsets of the upvars in Unresumed state are further exactly placed in the same place as their corresponding saved locals, which is guaranteed by the alternative coroutine layout calculator that enters in effect. <... quote the relevant comment/file/etc. ...>

@tmandry
Copy link
Member

tmandry commented Jan 30, 2025

I don't personally have any means of performance testing this at the moment. It would be much easier if it landed behind a feature gate.

@bors
Copy link
Contributor

bors commented Jan 31, 2025

☔ The latest upstream changes (presumably #135318) made this pull request unmergeable. Please resolve the merge conflicts.

@nikomatsakis
Copy link
Contributor

nikomatsakis commented Feb 1, 2025 via email

@dingxiangfei2009
Copy link
Contributor Author

@tmandry

I don't personally have any means of performance testing this at the moment. It would be much easier if it landed behind a feature gate.

I think it is fair to land with a feature gate so that we can get to play with it. The PR has temporarily disabled the check on the feature gate. However, given that coroutine layout data is keyed individually by their DefId, I think it is still safe to allow code to link to each other even when the feature gate status varies among the crates.

Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
@dingxiangfei2009 dingxiangfei2009 force-pushed the move-upvars-to-locals-for-tests branch from 9603ad6 to 3a1e04a Compare February 9, 2025 20:19
@rust-log-analyzer

This comment has been minimized.

Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
@dingxiangfei2009 dingxiangfei2009 force-pushed the move-upvars-to-locals-for-tests branch from 3a1e04a to 61d4bbd Compare February 9, 2025 23:12
@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-llvm-18 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
#21 exporting to docker image format
#21 sending tarball 28.1s done
#21 DONE 41.1s
##[endgroup]
Setting extra environment values for docker:  --env ENABLE_GCC_CODEGEN=1 --env GCC_EXEC_PREFIX=/usr/lib/gcc/
[CI_JOB_NAME=x86_64-gnu-llvm-18]
debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured.
---
sccache: Starting the server...
##[group]Configure the build
configure: processing command line
configure: 
configure: build.configure-args := ['--build=x86_64-unknown-linux-gnu', '--llvm-root=/usr/lib/llvm-18', '--enable-llvm-link-shared', '--set', 'rust.randomize-layout=true', '--set', 'rust.thin-lto-import-instr-limit=10', '--enable-verbose-configure', '--enable-sccache', '--disable-manage-submodules', '--enable-locked-deps', '--enable-cargo-native-static', '--set', 'rust.codegen-units-std=1', '--set', 'dist.compression-profile=balanced', '--dist-compression-formats=xz', '--set', 'rust.lld=false', '--disable-dist-src', '--release-channel=nightly', '--enable-debug-assertions', '--enable-overflow-checks', '--enable-llvm-assertions', '--set', 'rust.verify-llvm-ir', '--set', 'rust.codegen-backends=llvm,cranelift,gcc', '--set', 'llvm.static-libstdcpp', '--enable-new-symbol-mangling']
configure: target.x86_64-unknown-linux-gnu.llvm-config := /usr/lib/llvm-18/bin/llvm-config
configure: llvm.link-shared     := True
configure: rust.randomize-layout := True
configure: rust.thin-lto-import-instr-limit := 10
---
---- [ui] tests/ui/async-await/async-drop.rs stdout ----
Saved the actual run.stdout to "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/async-await/async-drop/async-drop.run.stdout"
diff of run.stdout:

8 AsyncInt::Dropper::poll: 8
9 AsyncReference::Dropper::poll: 10
10 AsyncInt::Dropper::poll: 11
- AsyncEnum(A)::Dropper::poll: 12
- SyncInt::drop: 12
- AsyncEnum(B)::Dropper::poll: 13
- AsyncInt::Dropper::poll: 13
- SyncInt::drop: 14
- SyncThenAsync::drop: 15
- AsyncInt::Dropper::poll: 16
- SyncInt::drop: 17
- AsyncInt::Dropper::poll: 18
- AsyncInt::Dropper::poll: 19
- AsyncInt::Dropper::poll: 20
- AsyncUnion::Dropper::poll: 21, 21


The actual run.stdout differed from the expected run.stdout.
Saved the actual run.stderr to "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/async-await/async-drop/async-drop.run.stderr"
---
------------------------------------------


---- [ui] tests/ui/async-await/future-sizes/async-awaiting-fut.rs stdout ----
Saved the actual stdout to "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/async-await/future-sizes/async-awaiting-fut/async-awaiting-fut.stdout"


- print-type-size type: `{async fn body of test()}`: 2053 bytes, alignment: 1 bytes
+ print-type-size type: `{async fn body of test()}`: 1029 bytes, alignment: 1 bytes
2 print-type-size     discriminant: 1 bytes
3 print-type-size     variant `Unresumed`: 0 bytes
- print-type-size     variant `Suspend0`: 2052 bytes
- print-type-size         local `.__awaitee`: 2052 bytes, type: {async fn body of calls_fut<{async fn body of big_fut()}>()}
+ print-type-size     variant `Suspend0`: 1028 bytes
+ print-type-size         local `.__awaitee`: 1028 bytes, offset: 0 bytes, alignment: 1 bytes, type: {async fn body of calls_fut<{async fn body of big_fut()}>()}
6 print-type-size     variant `Returned`: 0 bytes
7 print-type-size     variant `Panicked`: 0 bytes
- print-type-size type: `std::mem::ManuallyDrop<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 2052 bytes, alignment: 1 bytes
- print-type-size     field `.value`: 2052 bytes
- print-type-size type: `std::mem::MaybeUninit<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 2052 bytes, alignment: 1 bytes
- print-type-size     variant `MaybeUninit`: 2052 bytes
- print-type-size         field `.uninit`: 0 bytes
- print-type-size         field `.value`: 2052 bytes
- print-type-size type: `{async fn body of calls_fut<{async fn body of big_fut()}>()}`: 2052 bytes, alignment: 1 bytes
+ print-type-size type: `{async fn body of calls_fut<{async fn body of big_fut()}>()}`: 1028 bytes, alignment: 1 bytes
15 print-type-size     discriminant: 1 bytes
- print-type-size     variant `Unresumed`: 2051 bytes
- print-type-size         padding: 1026 bytes
- print-type-size         local `.fut`: 1025 bytes, alignment: 1 bytes
- print-type-size         upvar `.fut`: 1025 bytes, offset: 1027 bytes, alignment: 1 bytes
+ print-type-size     variant `Unresumed`: 1025 bytes
+ print-type-size         local `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
+ print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
20 print-type-size     variant `Suspend0`: 1027 bytes
- print-type-size         local `.fut`: 1025 bytes
+ print-type-size         local `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
22 print-type-size         local `..coroutine_field4`: 1 bytes, type: bool
23 print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
- print-type-size     variant `Suspend1`: 2051 bytes
- print-type-size         padding: 1025 bytes
- print-type-size         local `..coroutine_field4`: 1 bytes, alignment: 1 bytes, type: bool
- print-type-size         local `.__awaitee`: 1025 bytes, type: {async fn body of big_fut()}
+ print-type-size     variant `Suspend1`: 1026 bytes
+ print-type-size         local `.__awaitee`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes, type: {async fn body of big_fut()}
+ print-type-size         local `..coroutine_field4`: 1 bytes, type: bool
28 print-type-size     variant `Suspend2`: 1027 bytes
- print-type-size         local `.fut`: 1025 bytes
+ print-type-size         local `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
30 print-type-size         local `..coroutine_field4`: 1 bytes, type: bool
31 print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
- print-type-size     variant `Returned`: 2051 bytes
- print-type-size     variant `Panicked`: 2051 bytes
- print-type-size type: `std::mem::ManuallyDrop<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes
- print-type-size     field `.value`: 1025 bytes
- print-type-size type: `std::mem::MaybeUninit<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes
- print-type-size     variant `MaybeUninit`: 1025 bytes
- print-type-size         field `.uninit`: 0 bytes
- print-type-size         field `.value`: 1025 bytes
+ print-type-size     variant `Returned`: 1025 bytes
+ print-type-size     variant `Panicked`: 1025 bytes
40 print-type-size type: `{async fn body of big_fut()}`: 1025 bytes, alignment: 1 bytes
41 print-type-size     discriminant: 1 bytes
42 print-type-size     variant `Unresumed`: 1024 bytes

- print-type-size         local `.arg`: 1024 bytes
- print-type-size         upvar `.arg`: 1024 bytes, offset: 1 bytes, alignment: 1 bytes
+ print-type-size         local `.arg`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+ print-type-size         upvar `.arg`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
45 print-type-size     variant `Returned`: 1024 bytes
46 print-type-size     variant `Panicked`: 1024 bytes
- print-type-size type: `std::mem::ManuallyDrop<[u8; 1024]>`: 1024 bytes, alignment: 1 bytes
- print-type-size     field `.value`: 1024 bytes
- print-type-size type: `std::mem::MaybeUninit<[u8; 1024]>`: 1024 bytes, alignment: 1 bytes
- print-type-size     variant `MaybeUninit`: 1024 bytes
- print-type-size         field `.uninit`: 0 bytes
- print-type-size         field `.value`: 1024 bytes
- print-type-size type: `std::mem::ManuallyDrop<bool>`: 1 bytes, alignment: 1 bytes
- print-type-size     field `.value`: 1 bytes
- print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes
- print-type-size     field `.value`: 1 bytes
- print-type-size type: `std::mem::MaybeUninit<bool>`: 1 bytes, alignment: 1 bytes
- print-type-size     variant `MaybeUninit`: 1 bytes
- print-type-size         field `.uninit`: 0 bytes
- print-type-size         field `.value`: 1 bytes
- print-type-size type: `std::mem::MaybeUninit<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes
- print-type-size     variant `MaybeUninit`: 1 bytes
- print-type-size         field `.uninit`: 0 bytes
- print-type-size         field `.value`: 1 bytes
65 print-type-size type: `std::task::Poll<()>`: 1 bytes, alignment: 1 bytes
66 print-type-size     discriminant: 1 bytes
67 print-type-size     variant `Ready`: 0 bytes

The actual stdout differed from the expected stdout.
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args async-await/future-sizes/async-awaiting-fut.rs`
To only update this specific test, also pass `--test-args async-await/future-sizes/async-awaiting-fut.rs`

error: 1 errors occurred comparing output.
status: exit status: 0
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/async-await/future-sizes/async-awaiting-fut.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/async-await/future-sizes/async-awaiting-fut" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-Z" "print-type-sizes" "--crate-type" "lib" "--edition=2021"
--- stdout -------------------------------
print-type-size type: `{async fn body of test()}`: 1029 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Unresumed`: 0 bytes
print-type-size     variant `Suspend0`: 1028 bytes
print-type-size         local `.__awaitee`: 1028 bytes, offset: 0 bytes, alignment: 1 bytes, type: {async fn body of calls_fut<{async fn body of big_fut()}>()}
print-type-size     variant `Returned`: 0 bytes
print-type-size     variant `Panicked`: 0 bytes
print-type-size type: `{async fn body of calls_fut<{async fn body of big_fut()}>()}`: 1028 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Unresumed`: 1025 bytes
print-type-size         local `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size     variant `Suspend0`: 1027 bytes
print-type-size         local `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size         local `..coroutine_field4`: 1 bytes, type: bool
print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
print-type-size     variant `Suspend1`: 1026 bytes
print-type-size         local `.__awaitee`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes, type: {async fn body of big_fut()}
print-type-size         local `..coroutine_field4`: 1 bytes, type: bool
print-type-size     variant `Suspend2`: 1027 bytes
print-type-size         local `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size         local `..coroutine_field4`: 1 bytes, type: bool
print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
print-type-size     variant `Returned`: 1025 bytes
print-type-size     variant `Panicked`: 1025 bytes
print-type-size type: `{async fn body of big_fut()}`: 1025 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Unresumed`: 1024 bytes
print-type-size         local `.arg`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size         upvar `.arg`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size     variant `Returned`: 1024 bytes
print-type-size     variant `Panicked`: 1024 bytes
print-type-size type: `std::task::Poll<()>`: 1 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Ready`: 0 bytes
print-type-size         field `.0`: 0 bytes
print-type-size     variant `Pending`: 0 bytes
print-type-size type: `{async fn body of wait()}`: 1 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Unresumed`: 0 bytes
print-type-size     variant `Returned`: 0 bytes
print-type-size     variant `Panicked`: 0 bytes
stderr: none


---- [ui] tests/ui/async-await/future-sizes/large-arg.rs stdout ----
---- [ui] tests/ui/async-await/future-sizes/large-arg.rs stdout ----
Saved the actual stdout to "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/async-await/future-sizes/large-arg/large-arg.stdout"
diff of stdout:

2 print-type-size     discriminant: 1 bytes
3 print-type-size     variant `Unresumed`: 0 bytes
4 print-type-size     variant `Suspend0`: 1027 bytes
- print-type-size         local `.__awaitee`: 1027 bytes, type: {async fn body of a<[u8; 1024]>()}
+ print-type-size         local `.__awaitee`: 1027 bytes, offset: 0 bytes, alignment: 1 bytes, type: {async fn body of a<[u8; 1024]>()}
6 print-type-size     variant `Returned`: 0 bytes
7 print-type-size     variant `Panicked`: 0 bytes
- print-type-size type: `std::mem::ManuallyDrop<{async fn body of a<[u8; 1024]>()}>`: 1027 bytes, alignment: 1 bytes
- print-type-size     field `.value`: 1027 bytes
- print-type-size type: `std::mem::MaybeUninit<{async fn body of a<[u8; 1024]>()}>`: 1027 bytes, alignment: 1 bytes
- print-type-size     variant `MaybeUninit`: 1027 bytes
- print-type-size         field `.uninit`: 0 bytes
- print-type-size         field `.value`: 1027 bytes
14 print-type-size type: `{async fn body of a<[u8; 1024]>()}`: 1027 bytes, alignment: 1 bytes
15 print-type-size     discriminant: 1 bytes
16 print-type-size     variant `Unresumed`: 1024 bytes

- print-type-size         local `.t`: 1024 bytes
- print-type-size         upvar `.t`: 1024 bytes, offset: 1 bytes, alignment: 1 bytes
+ print-type-size         local `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+ print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
19 print-type-size     variant `Suspend0`: 1026 bytes
- print-type-size         local `.__awaitee`: 1026 bytes, type: {async fn body of b<[u8; 1024]>()}
+ print-type-size         local `.__awaitee`: 1026 bytes, offset: 0 bytes, alignment: 1 bytes, type: {async fn body of b<[u8; 1024]>()}
21 print-type-size     variant `Returned`: 1024 bytes
22 print-type-size     variant `Panicked`: 1024 bytes
- print-type-size type: `std::mem::ManuallyDrop<{async fn body of b<[u8; 1024]>()}>`: 1026 bytes, alignment: 1 bytes
- print-type-size     field `.value`: 1026 bytes
- print-type-size type: `std::mem::MaybeUninit<{async fn body of b<[u8; 1024]>()}>`: 1026 bytes, alignment: 1 bytes
- print-type-size     variant `MaybeUninit`: 1026 bytes
- print-type-size         field `.uninit`: 0 bytes
- print-type-size         field `.value`: 1026 bytes
29 print-type-size type: `{async fn body of b<[u8; 1024]>()}`: 1026 bytes, alignment: 1 bytes
30 print-type-size     discriminant: 1 bytes
31 print-type-size     variant `Unresumed`: 1024 bytes

- print-type-size         local `.t`: 1024 bytes
- print-type-size         upvar `.t`: 1024 bytes, offset: 1 bytes, alignment: 1 bytes
+ print-type-size         local `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+ print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
34 print-type-size     variant `Suspend0`: 1025 bytes
- print-type-size         local `.__awaitee`: 1025 bytes, type: {async fn body of c<[u8; 1024]>()}
+ print-type-size         local `.__awaitee`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes, type: {async fn body of c<[u8; 1024]>()}
36 print-type-size     variant `Returned`: 1024 bytes
37 print-type-size     variant `Panicked`: 1024 bytes
- print-type-size type: `std::mem::ManuallyDrop<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes
- print-type-size     field `.value`: 1025 bytes
- print-type-size type: `std::mem::MaybeUninit<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes
- print-type-size     variant `MaybeUninit`: 1025 bytes
- print-type-size         field `.uninit`: 0 bytes
- print-type-size         field `.value`: 1025 bytes
44 print-type-size type: `std::task::Poll<[u8; 1024]>`: 1025 bytes, alignment: 1 bytes
45 print-type-size     discriminant: 1 bytes
46 print-type-size     variant `Ready`: 1024 bytes

49 print-type-size type: `{async fn body of c<[u8; 1024]>()}`: 1025 bytes, alignment: 1 bytes
50 print-type-size     discriminant: 1 bytes
51 print-type-size     variant `Unresumed`: 1024 bytes
- print-type-size         local `.t`: 1024 bytes
- print-type-size         upvar `.t`: 1024 bytes, offset: 1 bytes, alignment: 1 bytes
+ print-type-size         local `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+ print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
54 print-type-size     variant `Returned`: 1024 bytes
55 print-type-size     variant `Panicked`: 1024 bytes
- print-type-size type: `std::mem::ManuallyDrop<[u8; 1024]>`: 1024 bytes, alignment: 1 bytes
- print-type-size     field `.value`: 1024 bytes
- print-type-size type: `std::mem::MaybeUninit<[u8; 1024]>`: 1024 bytes, alignment: 1 bytes
- print-type-size     variant `MaybeUninit`: 1024 bytes
- print-type-size         field `.uninit`: 0 bytes
- print-type-size         field `.value`: 1024 bytes


The actual stdout differed from the expected stdout.
To update references, rerun the tests and pass the `--bless` flag
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args async-await/future-sizes/large-arg.rs`

error: 1 errors occurred comparing output.
status: exit status: 0
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/async-await/future-sizes/large-arg.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/async-await/future-sizes/large-arg" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-Z" "print-type-sizes" "--crate-type=lib" "--edition=2021"
--- stdout -------------------------------
print-type-size type: `{async fn body of test()}`: 1028 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Unresumed`: 0 bytes
print-type-size     variant `Suspend0`: 1027 bytes
print-type-size         local `.__awaitee`: 1027 bytes, offset: 0 bytes, alignment: 1 bytes, type: {async fn body of a<[u8; 1024]>()}
print-type-size     variant `Returned`: 0 bytes
print-type-size     variant `Panicked`: 0 bytes
print-type-size type: `{async fn body of a<[u8; 1024]>()}`: 1027 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Unresumed`: 1024 bytes
print-type-size         local `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size     variant `Suspend0`: 1026 bytes
print-type-size         local `.__awaitee`: 1026 bytes, offset: 0 bytes, alignment: 1 bytes, type: {async fn body of b<[u8; 1024]>()}
print-type-size     variant `Returned`: 1024 bytes
print-type-size     variant `Panicked`: 1024 bytes
print-type-size type: `{async fn body of b<[u8; 1024]>()}`: 1026 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Unresumed`: 1024 bytes
print-type-size         local `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size     variant `Suspend0`: 1025 bytes
print-type-size         local `.__awaitee`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes, type: {async fn body of c<[u8; 1024]>()}
print-type-size     variant `Returned`: 1024 bytes
print-type-size     variant `Panicked`: 1024 bytes
print-type-size type: `std::task::Poll<[u8; 1024]>`: 1025 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Ready`: 1024 bytes
print-type-size         field `.0`: 1024 bytes
print-type-size     variant `Pending`: 0 bytes
print-type-size type: `{async fn body of c<[u8; 1024]>()}`: 1025 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Unresumed`: 1024 bytes
print-type-size         local `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size         upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size     variant `Returned`: 1024 bytes
print-type-size     variant `Panicked`: 1024 bytes
stderr: none


---- [ui] tests/ui/async-await/in-trait/async-recursive-generic.rs stdout ----
---- [ui] tests/ui/async-await/in-trait/async-recursive-generic.rs stdout ----
Saved the actual stderr to "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/async-await/in-trait/async-recursive-generic/async-recursive-generic.stderr"
diff of stderr:

3    |
4 LL |     async fn foo_recursive(&self, n: usize) -> T {
+ ...
+ ...
+ LL |             self.foo_recursive(n - 1).await
+    |             ------------------------------- recursive call here
6    |
7    = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future


The actual stderr differed from the expected stderr.
To update references, rerun the tests and pass the `--bless` flag
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args async-await/in-trait/async-recursive-generic.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/async-await/in-trait/async-recursive-generic.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/async-await/in-trait/async-recursive-generic" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--edition=2021"
--- stderr -------------------------------
error[E0733]: recursion in an async fn requires boxing
##[error]  --> /checkout/tests/ui/async-await/in-trait/async-recursive-generic.rs:8:5
   |
   |
LL |     async fn foo_recursive(&self, n: usize) -> T {
...
...
LL |             self.foo_recursive(n - 1).await
   |             ------------------------------- recursive call here
   |
   = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0733`.
------------------------------------------
------------------------------------------


---- [ui] tests/ui/async-await/in-trait/async-recursive.rs stdout ----
Saved the actual stderr to "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/async-await/in-trait/async-recursive/async-recursive.stderr"
diff of stderr:

3    |
4 LL |     async fn foo_recursive(&self, n: usize) -> i32 {
+ ...
+ ...
+ LL |             self.foo_recursive(n - 1).await
+    |             ------------------------------- recursive call here
6    |
7    = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future


The actual stderr differed from the expected stderr.
To update references, rerun the tests and pass the `--bless` flag
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args async-await/in-trait/async-recursive.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/async-await/in-trait/async-recursive.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/async-await/in-trait/async-recursive" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--edition=2021"
--- stderr -------------------------------
error[E0733]: recursion in an async fn requires boxing
##[error]  --> /checkout/tests/ui/async-await/in-trait/async-recursive.rs:8:5
   |
   |
LL |     async fn foo_recursive(&self, n: usize) -> i32 {
...
...
LL |             self.foo_recursive(n - 1).await
   |             ------------------------------- recursive call here
   |
   = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0733`.
------------------------------------------
---
+ LL |
+ LL |         self.first().await.second().await;
+    |         --------------------------------- recursive call here
6    |
7    = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future

Note: some mismatched output was normalized before being compared
- LL |         //~^ ERROR recursion in an async fn requires boxing
+ LL |
---
To only update this specific test, also pass `--test-args async-await/in-trait/indirect-recursion-issue-112047.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/async-await/in-trait/indirect-recursion-issue-112047" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--edition=2021"
--- stderr -------------------------------
error[E0733]: recursion in an async fn requires boxing
##[error]  --> /checkout/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs:31:5
   |
   |
LL |     async fn second(self) {
   |     ^^^^^^^^^^^^^^^^^^^^^
LL |         //~^ ERROR recursion in an async fn requires boxing
LL |         self.first().await.second().await;
   |         --------------------------------- recursive call here
   |
   = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0733`.
------------------------------------------
------------------------------------------


---- [ui] tests/ui/feature-gates/feature-gate-coroutine-new-layout.rs stdout ----
Saved the actual stderr to "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/feature-gates/feature-gate-coroutine-new-layout/feature-gate-coroutine-new-layout.stderr"
error: this is an experimental flag that has no obvious user-facing changes
##[error]  --> $DIR/feature-gate-coroutine-new-layout.rs:2:5
   |
LL |     compile_error!("this is an experimental flag that has no obvious user-facing changes");
---
To only update this specific test, also pass `--test-args feature-gates/feature-gate-coroutine-new-layout.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/feature-gates/feature-gate-coroutine-new-layout.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/feature-gates/feature-gate-coroutine-new-layout" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers"
--- stderr -------------------------------
error: this is an experimental flag that has no obvious user-facing changes
##[error]  --> /checkout/tests/ui/feature-gates/feature-gate-coroutine-new-layout.rs:2:5
   |
---
---- [ui] tests/ui/layout/post-mono-layout-cycle-2.rs stdout ----

error: `build-fail` test is required to pass check build, but check build failed
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/layout/post-mono-layout-cycle-2.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/layout/post-mono-layout-cycle-2" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--edition=2021"
--- stderr -------------------------------
error[E0733]: recursion in an async fn requires boxing
##[error]  --> /checkout/tests/ui/layout/post-mono-layout-cycle-2.rs:28:5
   |
   |
LL | /     async fn iter<T>(&mut self, iterator: T)
LL | |     //~^ ERROR recursion in an async fn requires boxing
LL | |         T: IntoIterator<Item = ()>,
   | |___________________________________^
LL |       {
LL |       {
LL |           Blah::iter(self, iterator).await
   |           -------------------------------- recursive call here
   |
   = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0733`.
------------------------------------------
------------------------------------------


---- [ui] tests/ui/print_type_sizes/coroutine_discr_placement.rs stdout ----
Saved the actual stdout to "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/print_type_sizes/coroutine_discr_placement/coroutine_discr_placement.stdout"
diff of stdout:

1 print-type-size type: `{coroutine@$DIR/coroutine_discr_placement.rs:13:5: 13:7}`: 8 bytes, alignment: 4 bytes
2 print-type-size     discriminant: 1 bytes
3 print-type-size     variant `Unresumed`: 0 bytes
- print-type-size     variant `Suspend0`: 7 bytes
- print-type-size         padding: 3 bytes
- print-type-size         local `.w`: 4 bytes, alignment: 4 bytes
- print-type-size     variant `Suspend1`: 7 bytes
- print-type-size         padding: 3 bytes
- print-type-size         local `.z`: 4 bytes, alignment: 4 bytes
+ print-type-size     variant `Suspend0`: 4 bytes
+ print-type-size         local `.w`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
+ print-type-size     variant `Suspend1`: 4 bytes
+ print-type-size         local `.z`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
10 print-type-size     variant `Returned`: 0 bytes
11 print-type-size     variant `Panicked`: 0 bytes
- print-type-size type: `std::mem::ManuallyDrop<i32>`: 4 bytes, alignment: 4 bytes
- print-type-size     field `.value`: 4 bytes
- print-type-size type: `std::mem::MaybeUninit<i32>`: 4 bytes, alignment: 4 bytes
- print-type-size     variant `MaybeUninit`: 4 bytes
- print-type-size         field `.uninit`: 0 bytes
- print-type-size         field `.value`: 4 bytes
18 


The actual stdout differed from the expected stdout.
The actual stdout differed from the expected stdout.
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args print_type_sizes/coroutine_discr_placement.rs`

error: 1 errors occurred comparing output.
status: exit status: 0
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/print_type_sizes/coroutine_discr_placement.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/print_type_sizes/coroutine_discr_placement" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-Z" "print-type-sizes" "--crate-type" "lib"
--- stdout -------------------------------
print-type-size type: `{coroutine@/checkout/tests/ui/print_type_sizes/coroutine_discr_placement.rs:13:5: 13:7}`: 8 bytes, alignment: 4 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Unresumed`: 0 bytes
print-type-size     variant `Suspend0`: 4 bytes
print-type-size         local `.w`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
print-type-size     variant `Suspend1`: 4 bytes
print-type-size         local `.z`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
print-type-size     variant `Returned`: 0 bytes
print-type-size     variant `Panicked`: 0 bytes
------------------------------------------
stderr: none



---- [ui] tests/ui/print_type_sizes/coroutine.rs stdout ----
Saved the actual stdout to "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/print_type_sizes/coroutine/coroutine.stdout"
diff of stdout:

1 print-type-size type: `{coroutine@$DIR/coroutine.rs:11:5: 11:14}`: 8193 bytes, alignment: 1 bytes
2 print-type-size     discriminant: 1 bytes
3 print-type-size     variant `Unresumed`: 8192 bytes
- print-type-size         upvar `.array`: 1 bytes, offset: 0 bytes, alignment: 1 bytes
- print-type-size         local `.array`: 8192 bytes
+ print-type-size         local `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+ print-type-size         upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
6 print-type-size     variant `Suspend0`: 8192 bytes
- print-type-size         local `.array`: 8192 bytes
- print-type-size     variant `Returned`: 0 bytes
- print-type-size     variant `Panicked`: 0 bytes
- print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
- print-type-size     field `.value`: 8192 bytes
- print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
- print-type-size     variant `MaybeUninit`: 8192 bytes
- print-type-size         field `.uninit`: 0 bytes
- print-type-size         field `.value`: 8192 bytes
+ print-type-size         local `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+ print-type-size     variant `Returned`: 8192 bytes
+ print-type-size     variant `Panicked`: 8192 bytes


The actual stdout differed from the expected stdout.
To update references, rerun the tests and pass the `--bless` flag
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args print_type_sizes/coroutine.rs`

error: 1 errors occurred comparing output.
status: exit status: 0
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/print_type_sizes/coroutine.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/print_type_sizes/coroutine" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-Z" "print-type-sizes" "--crate-type=lib"
--- stdout -------------------------------
print-type-size type: `{coroutine@/checkout/tests/ui/print_type_sizes/coroutine.rs:11:5: 11:14}`: 8193 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Unresumed`: 8192 bytes
print-type-size         local `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size         upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size     variant `Suspend0`: 8192 bytes
print-type-size         local `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size     variant `Returned`: 8192 bytes
print-type-size     variant `Panicked`: 8192 bytes
stderr: none


---- [ui] tests/ui/print_type_sizes/async.rs stdout ----
---- [ui] tests/ui/print_type_sizes/async.rs stdout ----
Saved the actual stdout to "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/print_type_sizes/async/async.stdout"
diff of stdout:

1 print-type-size type: `{async fn body of test()}`: 8194 bytes, alignment: 1 bytes
2 print-type-size     discriminant: 1 bytes
3 print-type-size     variant `Unresumed`: 8192 bytes
- print-type-size         upvar `.arg`: 1 bytes, offset: 0 bytes, alignment: 1 bytes
- print-type-size         local `.arg`: 8192 bytes
+ print-type-size         local `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+ print-type-size         upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
6 print-type-size     variant `Suspend0`: 8193 bytes
+ print-type-size         local `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
7 print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
- print-type-size         local `.arg`: 8192 bytes
- print-type-size     variant `Returned`: 0 bytes
- print-type-size     variant `Panicked`: 0 bytes
- print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
- print-type-size     field `.value`: 8192 bytes
- print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
- print-type-size     variant `MaybeUninit`: 8192 bytes
- print-type-size         field `.uninit`: 0 bytes
- print-type-size         field `.value`: 8192 bytes
- print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes
- print-type-size     field `.value`: 1 bytes
- print-type-size type: `std::mem::MaybeUninit<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes
- print-type-size     variant `MaybeUninit`: 1 bytes
- print-type-size         field `.uninit`: 0 bytes
- print-type-size         field `.value`: 1 bytes
+ print-type-size     variant `Returned`: 8192 bytes
+ print-type-size     variant `Panicked`: 8192 bytes
23 print-type-size type: `std::task::Poll<()>`: 1 bytes, alignment: 1 bytes
24 print-type-size     discriminant: 1 bytes
25 print-type-size     variant `Ready`: 0 bytes

The actual stdout differed from the expected stdout.
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args print_type_sizes/async.rs`
To only update this specific test, also pass `--test-args print_type_sizes/async.rs`

error: 1 errors occurred comparing output.
status: exit status: 0
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/print_type_sizes/async.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/print_type_sizes/async" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-Z" "print-type-sizes" "--crate-type" "lib" "--edition=2021"
--- stdout -------------------------------
print-type-size type: `{async fn body of test()}`: 8194 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Unresumed`: 8192 bytes
print-type-size         local `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size         upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size     variant `Suspend0`: 8193 bytes
print-type-size         local `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
print-type-size     variant `Returned`: 8192 bytes
print-type-size     variant `Panicked`: 8192 bytes
print-type-size type: `std::task::Poll<()>`: 1 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Ready`: 0 bytes
print-type-size         field `.0`: 0 bytes
print-type-size     variant `Pending`: 0 bytes
print-type-size type: `{async fn body of wait()}`: 1 bytes, alignment: 1 bytes
print-type-size     discriminant: 1 bytes
print-type-size     variant `Unresumed`: 0 bytes
print-type-size     variant `Returned`: 0 bytes
print-type-size     variant `Panicked`: 0 bytes
stderr: none


---- [ui] tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs stdout ----
---- [ui] tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs stdout ----
Saved the actual stderr to "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/type-alias-impl-trait/indirect-recursion-issue-112047/indirect-recursion-issue-112047.stderr"
diff of stderr:

2   --> $DIR/indirect-recursion-issue-112047.rs:21:9
3    |
4 LL |         async move { recur(self).await; }
+    |         ^^^^^^^^^^   ----------------- recursive call here
6    |
+ note: which leads to this async fn
+   --> $DIR/indirect-recursion-issue-112047.rs:13:1
+   --> $DIR/indirect-recursion-issue-112047.rs:13:1
+    |
+ LL | async fn recur(t: impl Recur) {
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ LL |     t.recur().await;
+    |     --------------- ...leading to this recursive call
7    = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
9 error: aborting due to 1 previous error

Note: some mismatched output was normalized before being compared
-   --> /checkout/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs:13:1
-   --> /checkout/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs:13:1
+    |         ^^^^^^^^^^   ----------------- recursive call here
+ note: which leads to this async fn
+   --> $DIR/indirect-recursion-issue-112047.rs:13:1
+    |
+ LL | async fn recur(t: impl Recur) {
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ LL |     t.recur().await;
+    |     --------------- ...leading to this recursive call

The actual stderr differed from the expected stderr.
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args type-alias-impl-trait/indirect-recursion-issue-112047.rs`
To only update this specific test, also pass `--test-args type-alias-impl-trait/indirect-recursion-issue-112047.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/type-alias-impl-trait/indirect-recursion-issue-112047" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--edition=2021"
--- stderr -------------------------------
error[E0733]: recursion in an async block requires boxing
##[error]  --> /checkout/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs:21:9
   |
   |
LL |         async move { recur(self).await; }
   |         ^^^^^^^^^^   ----------------- recursive call here
note: which leads to this async fn
  --> /checkout/tests/ui/type-alias-impl-trait/indirect-recursion-issue-112047.rs:13:1
   |
   |
LL | async fn recur(t: impl Recur) {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL |     t.recur().await;
   |     --------------- ...leading to this recursive call
   = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0733`.
------------------------------------------

@eholk
Copy link
Contributor

eholk commented Feb 12, 2025

I don't personally have any means of performance testing this at the moment. It would be much easier if it landed behind a feature gate.

Would this be better as a #[feature(...)] gate, or as -Z new_coroutine_layout? I think the compiler flag feels like a better fit for something like this.

@oli-obk
Copy link
Contributor

oli-obk commented Feb 13, 2025

Are there any issues if only one crate activates it but others do not? if there are no issues, a feature gate seems ok (and easier to use ^^)

@bors
Copy link
Contributor

bors commented Feb 14, 2025

☔ The latest upstream changes (presumably #137030) made this pull request unmergeable. Please resolve the merge conflicts.

@Dirbaio
Copy link
Contributor

Dirbaio commented Feb 15, 2025

A feature doesn't allow turning it on for the whole build, you'd have to fork every single crate that uses async. A -Z flag would be better IMO.

@tmandry
Copy link
Member

tmandry commented Feb 18, 2025

Agreed on a -Z flag being better for testing for the reason @Dirbaio gave.

If my understanding is correct, we shouldn't expect any regression from this approach (only upside), but since we currently rely on later passes eliding copies there might be some regression. We could be more aggressive in eliding the copies ourselves, but maybe this is hard.

@dingxiangfei2009
Copy link
Contributor Author

Thanks for looking into this!

I will have time this week to clean this up a bit and I will ask rustbot to set it to ready-for-review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.