diff options
| author | bors <bors@rust-lang.org> | 2023-11-24 00:26:24 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-11-24 00:26:24 +0000 |
| commit | 1fd418f92ed13db88a21865ba5d909abcf16b6cc (patch) | |
| tree | 4d790550dec9277300e1ef7d5a676491cfacf847 /compiler/rustc_mir_transform/src | |
| parent | e68f935117fef05e7663605a5a6671a6bb4ce719 (diff) | |
| parent | 543e559c5300e8bd3be6d491897eaac327f9dc71 (diff) | |
| download | rust-1fd418f92ed13db88a21865ba5d909abcf16b6cc.tar.gz rust-1fd418f92ed13db88a21865ba5d909abcf16b6cc.zip | |
Auto merge of #118219 - bjorn3:fix_generator_fn_abi, r=compiler-errors
Fix fn_sig_for_fn_abi and the coroutine transform for generators There were three issues previously: * The self argument was pinned, despite Iterator::next taking an unpinned mutable reference. * A resume argument was passed, despite Iterator::next not having one. * The return value was CoroutineState<Item, ()> rather than Option<Item> While these things just so happened to work with the LLVM backend, cg_clif does much stricter checks when trying to assign a value to a place. In addition it can't handle the mismatch between the amount of arguments specified by the FnAbi and the FnSig.
Diffstat (limited to 'compiler/rustc_mir_transform/src')
| -rw-r--r-- | compiler/rustc_mir_transform/src/coroutine.rs | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index aa4d8ddad56..42540911785 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -617,6 +617,22 @@ fn replace_resume_ty_local<'tcx>( } } +/// Transforms the `body` of the coroutine applying the following transform: +/// +/// - Remove the `resume` argument. +/// +/// Ideally the async lowering would not add the `resume` argument. +/// +/// The async lowering step and the type / lifetime inference / checking are +/// still using the `resume` argument for the time being. After this transform, +/// the coroutine body doesn't have the `resume` argument. +fn transform_gen_context<'tcx>(_tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + // This leaves the local representing the `resume` argument in place, + // but turns it into a regular local variable. This is cheaper than + // adjusting all local references in the body after removing it. + body.arg_count = 1; +} + struct LivenessInfo { /// Which locals are live across any suspension point. saved_locals: CoroutineSavedLocals, @@ -1337,7 +1353,15 @@ fn create_coroutine_resume_function<'tcx>( insert_switch(body, cases, &transform, TerminatorKind::Unreachable); make_coroutine_state_argument_indirect(tcx, body); - make_coroutine_state_argument_pinned(tcx, body); + + match coroutine_kind { + // Iterator::next doesn't accept a pinned argument, + // unlike for all other coroutine kinds. + CoroutineKind::Gen(_) => {} + _ => { + make_coroutine_state_argument_pinned(tcx, body); + } + } // Make sure we remove dead blocks to remove // unrelated code from the drop part of the function @@ -1504,6 +1528,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { }; let is_async_kind = matches!(body.coroutine_kind(), Some(CoroutineKind::Async(_))); + let is_gen_kind = matches!(body.coroutine_kind(), Some(CoroutineKind::Gen(_))); let (state_adt_ref, state_args) = match body.coroutine_kind().unwrap() { CoroutineKind::Async(_) => { // Compute Poll<return_ty> @@ -1609,6 +1634,11 @@ impl<'tcx> MirPass<'tcx> for StateTransform { body.arg_count = 2; // self, resume arg body.spread_arg = None; + // Remove the context argument within generator bodies. + if is_gen_kind { + transform_gen_context(tcx, body); + } + // The original arguments to the function are no longer arguments, mark them as such. // Otherwise they'll conflict with our new arguments, which although they don't have // argument_index set, will get emitted as unnamed arguments. |
