diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 8b9f4291603a9..3491ca34631f6 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -880,14 +880,7 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, TerminatorKind::SwitchInt { discr, targets: _ } => { self.consume_operand(loc, (discr, span), state); } - TerminatorKind::Drop { - place, - target: _, - unwind: _, - replace, - drop: _, - async_fut: _, - } => { + TerminatorKind::Drop { place, target: _, unwind: _, replace, drop: _ } => { debug!( "visit_terminator_drop \ loc: {:?} term: {:?} place: {:?} span: {:?}", diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs index 31df87dabf815..a686a27a80caf 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs @@ -99,14 +99,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> { TerminatorKind::SwitchInt { discr, targets: _ } => { self.consume_operand(location, discr); } - TerminatorKind::Drop { - place: drop_place, - target: _, - unwind: _, - replace, - drop: _, - async_fut: _, - } => { + TerminatorKind::Drop { place: drop_place, target: _, unwind: _, replace, drop: _ } => { let write_kind = if *replace { WriteKind::Replace } else { WriteKind::StorageDeadOrDrop }; self.access_place( diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 1d90c8e0dadcf..2edbdb560f52b 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -582,9 +582,9 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { | TerminatorKind::CoroutineDrop => { bug!("shouldn't exist at codegen {:?}", bb_data.terminator()); } - TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut } => { + TerminatorKind::Drop { place, target, unwind, replace: _, drop } => { assert!( - async_fut.is_none() && drop.is_none(), + drop.is_none(), "Async Drop must be expanded or reset to sync before codegen" ); let drop_place = codegen_place(fx, *place); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index f4e08e08ef8db..dc0721fbeec84 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1548,9 +1548,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { MergingSucc::False } - mir::TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut } => { + mir::TerminatorKind::Drop { place, target, unwind, replace: _, drop } => { assert!( - async_fut.is_none() && drop.is_none(), + drop.is_none(), "Async Drop must be expanded or reset to sync before codegen" ); self.codegen_drop_terminator( diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index c60fb92a7a200..900dd693b1257 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -590,9 +590,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } - Drop { place, target, unwind, replace: _, drop, async_fut } => { + Drop { place, target, unwind, replace: _, drop } => { assert!( - async_fut.is_none() && drop.is_none(), + drop.is_none(), "Async Drop must be expanded or reset to sync in runtime MIR" ); let place = self.eval_place(place)?; diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 35d0188769f51..f96a4e5c89a82 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2327,6 +2327,13 @@ impl CoroutineKind { matches!(self, CoroutineKind::Desugared(_, CoroutineSource::Fn)) } + pub fn is_async_desugaring(self) -> bool { + matches!( + self, + CoroutineKind::Desugared(CoroutineDesugaring::Async | CoroutineDesugaring::AsyncGen, _) + ) + } + pub fn to_plural_string(&self) -> String { match self { CoroutineKind::Desugared(d, CoroutineSource::Fn) => format!("{d:#}fn bodies"), diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 60c829311c4b1..a648517e5eb8d 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -15,6 +15,7 @@ use crate::mir::interpret::{ }; use crate::mir::visit::Visitor; use crate::mir::*; +use crate::ty::CoroutineArgsExt; const INDENT: &str = " "; /// Alignment for lining up comments following MIR statements @@ -185,9 +186,6 @@ impl<'a, 'tcx> MirDumper<'a, 'tcx> { Some(promoted) => write!(w, "::{promoted:?}`")?, } writeln!(w, " {} {}", self.disambiguator, self.pass_name)?; - if let Some(ref layout) = body.coroutine_layout_raw() { - writeln!(w, "/* coroutine_layout = {layout:#?} */")?; - } writeln!(w)?; (self.writer.extra_data)(PassWhere::BeforeCFG, w)?; write_user_type_annotations(self.tcx(), body, w)?; @@ -429,6 +427,31 @@ fn write_scope_tree( } } + // Coroutine debuginfo. + if let Some(layout) = body.coroutine_layout_raw() { + for (field, name) in layout.field_names.iter_enumerated() { + if let Some(name) = name + && let source_info = layout.field_tys[field].source_info + && source_info.scope == parent + { + let indented_debug_info = + format!("{0:1$}coroutine debug {2} => {3:?};", INDENT, indent, name, field); + + if options.include_extra_comments { + writeln!( + w, + "{0:1$} // in {2}", + indented_debug_info, + ALIGN, + comment(tcx, source_info), + )?; + } else { + writeln!(w, "{indented_debug_info}")?; + } + } + } + } + // Local variable types. for (local, local_decl) in body.local_decls.iter_enumerated() { if (1..body.arg_count + 1).contains(&local.index()) { @@ -530,6 +553,50 @@ impl Debug for VarDebugInfo<'_> { } } +fn write_coroutine_layout<'tcx>( + tcx: TyCtxt<'tcx>, + layout: &CoroutineLayout<'_>, + w: &mut dyn io::Write, + options: PrettyPrintMirOptions, +) -> io::Result<()> { + let CoroutineLayout { + field_tys, + field_names: _, // Dumped in scope tree with debug info. + variant_fields, + variant_source_info, + storage_conflicts, + } = layout; + + writeln!(w, "{INDENT}coroutine layout {{")?; + + for (field, CoroutineSavedTy { ty, source_info, ignore_for_traits }) in + field_tys.iter_enumerated() + { + let ignore_for_traits = if *ignore_for_traits { " (ignored for traits)" } else { "" }; + let indented_body = format!("{INDENT}{INDENT}field {field:?}: {ty}{ignore_for_traits};",); + if options.include_extra_comments { + writeln!(w, "{0:ALIGN$} // in {1}", indented_body, comment(tcx, *source_info))?; + } else { + writeln!(w, "{}", indented_body)?; + } + } + + writeln!(w, "{INDENT}{INDENT}variant_fields = {{")?; + for (variant, fields) in variant_fields.iter_enumerated() { + let variant_name = ty::CoroutineArgs::variant_name(variant); + let header = format!("{INDENT}{INDENT}{INDENT}{variant_name:9}({variant:?}): {fields:?},"); + if options.include_extra_comments { + let source_info = variant_source_info[variant]; + writeln!(w, "{0:ALIGN$} // in {1}", header, comment(tcx, source_info))?; + } else { + writeln!(w, "{}", header)?; + } + } + writeln!(w, "{INDENT}{INDENT}}}")?; + writeln!(w, "{INDENT}{INDENT}storage_conflicts = {storage_conflicts:?}")?; + writeln!(w, "{INDENT}}}") +} + /// Write out a human-readable textual representation of the MIR's `fn` type and the types of its /// local variables (both user-defined bindings and compiler temporaries). fn write_mir_intro<'tcx>( @@ -541,6 +608,10 @@ fn write_mir_intro<'tcx>( write_mir_sig(tcx, body, w)?; writeln!(w, "{{")?; + if let Some(ref layout) = body.coroutine_layout_raw() { + write_coroutine_layout(tcx, layout, w, options)?; + } + // construct a scope tree and write it out let mut scope_tree: FxHashMap> = Default::default(); for (index, scope_data) in body.source_scopes.iter_enumerated() { @@ -920,10 +991,7 @@ impl<'tcx> TerminatorKind<'tcx> { } Yield { value, resume_arg, .. } => write!(fmt, "{resume_arg:?} = yield({value:?})"), Unreachable => write!(fmt, "unreachable"), - Drop { place, async_fut: None, .. } => write!(fmt, "drop({place:?})"), - Drop { place, async_fut: Some(async_fut), .. } => { - write!(fmt, "async drop({place:?}; poll={async_fut:?})") - } + Drop { place, .. } => write!(fmt, "drop({place:?})"), Call { func, args, destination, .. } => { write!(fmt, "{destination:?} = ")?; write!(fmt, "{func:?}(")?; diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 4c619f825fa8b..f25eaf3c6d32e 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -624,11 +624,7 @@ impl<'tcx> Operand<'tcx> { span: Span, ) -> Self { let ty = Ty::new_fn_def(tcx, def_id, args); - Operand::Constant(Box::new(ConstOperand { - span, - user_ty: None, - const_: Const::Val(ConstValue::ZeroSized, ty), - })) + Operand::zero_sized_constant(ty, span) } /// Convenience helper to make a constant that refers to the given `DefId` and args. Since this @@ -643,6 +639,12 @@ impl<'tcx> Operand<'tcx> { Operand::Constant(Box::new(ConstOperand { span, user_ty: None, const_ })) } + /// Convenience helper to make a constant that refers to a zero-sized type. + pub fn zero_sized_constant(ty: Ty<'tcx>, span: Span) -> Self { + let const_ = Const::Val(ConstValue::ZeroSized, ty); + Operand::Constant(Box::new(ConstOperand { span, user_ty: None, const_ })) + } + pub fn is_move(&self) -> bool { matches!(self, Operand::Move(..)) } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 8b015e6cecaae..cd61b7b4aa9fc 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -760,21 +760,16 @@ pub enum TerminatorKind<'tcx> { /// meaning. /// /// Async drop processing: - /// In compiler/rustc_mir_build/src/build/scope.rs we detect possible async drop: - /// drop of object with `needs_async_drop`. - /// Async drop later, in StateTransform pass, may be expanded into additional yield-point - /// for poll-loop of async drop future. - /// So we need prepared 'drop' target block in the similar way as for `Yield` terminator - /// (see `drops.build_mir::` in scopes.rs). - /// In compiler/rustc_mir_transform/src/elaborate_drops.rs for object implementing `AsyncDrop` trait - /// we need to prepare async drop feature - resolve `AsyncDrop::drop` and codegen call. - /// `async_fut` is set to the corresponding local. - /// For coroutine drop we don't need this logic because coroutine drop works with the same - /// layout object as coroutine itself. So `async_fut` will be `None` for coroutine drop. - /// Both `drop` and `async_fut` fields are only used in compiler/rustc_mir_transform/src/coroutine.rs, - /// StateTransform pass. In `expand_async_drops` async drops are expanded - /// into one or two yield points with poll ready/pending switch. - /// When a coroutine has any internal async drop, the coroutine drop function will be async + /// MIR building detects possible async drops, and constructs a complete CFG. To correctly + /// handle the coroutine being dropped while itself drops, we need a 'drop' target + /// similar to `Yield` terminator (see `drops.build_mir::`). + /// + /// Drop elaboration later refines the set of useful async drops. If there is no need for an + /// async drop, it is downgraded to a sync drop by setting `drop` to `None` If this is an + /// actual async drop, it is expanded to an `await` loop over the `async_drop_in_place` or + /// `AsyncDrop::drop` coroutine. + /// + /// When a coroutine has any internal async drop, the coroutine drop function will be async /// (generated by `create_coroutine_drop_shim_async`, not `create_coroutine_drop_shim`). Drop { place: Place<'tcx>, @@ -783,8 +778,6 @@ pub enum TerminatorKind<'tcx> { replace: bool, /// Cleanup to be done if the coroutine is dropped at this suspend point (for async drop). drop: Option, - /// Prepared async future local (for async drop) - async_fut: Option, }, /// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 1cd11bbd9ce4f..7920ca82aaf3a 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -743,7 +743,7 @@ impl<'tcx> TerminatorKind<'tcx> { // FIXME: Maybe we need also TerminatorEdges::Trio for async drop // (target + unwind + dropline) Assert { target, unwind, expected: _, msg: _, cond: _ } - | Drop { target, unwind, place: _, replace: _, drop: _, async_fut: _ } + | Drop { target, unwind, place: _, replace: _, drop: _ } | FalseUnwind { real_target: target, unwind } => match unwind { UnwindAction::Cleanup(unwind) => TerminatorEdges::Double(target, unwind), UnwindAction::Continue | UnwindAction::Terminate(_) | UnwindAction::Unreachable => { diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index e6e911dece742..fbe22ecc06e47 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -555,20 +555,12 @@ macro_rules! make_mir_visitor { unwind: _, replace: _, drop: _, - async_fut, } => { self.visit_place( place, PlaceContext::MutatingUse(MutatingUseContext::Drop), location ); - if let Some(async_fut) = async_fut { - self.visit_local( - $(&$mutability)? *async_fut, - PlaceContext::MutatingUse(MutatingUseContext::Borrow), - location - ); - } } TerminatorKind::Call { diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs index 5d9a2382ba419..84203c5caefea 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs @@ -63,7 +63,6 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { unwind: self.parse_unwind_action(args[2])?, replace: false, drop: None, - async_fut: None, }) }, @call(mir_call, args) => { diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs index ce443d66dc619..dd36411658305 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs @@ -642,7 +642,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { unwind: UnwindAction::Continue, replace: false, drop: None, - async_fut: None, }, ); this.diverge_from(block); diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 3343bec30caf5..3f80d7872a407 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -427,7 +427,6 @@ impl DropTree { place: drop_node.data.local.into(), replace: false, drop: None, - async_fut: None, }; cfg.terminate(block, drop_node.data.source_info, terminator); } @@ -1170,7 +1169,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { unwind: UnwindAction::Continue, replace: false, drop: None, - async_fut: None, }, ); block = next; @@ -1745,7 +1743,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { unwind: UnwindAction::Cleanup(assign_unwind), replace: true, drop: None, - async_fut: None, }, ); self.diverge_from(block); @@ -1916,7 +1913,6 @@ where unwind: UnwindAction::Continue, replace: false, drop: None, - async_fut: None, }, ); block = next; diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index e045b0e950779..b4cbe7d1da14c 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -412,14 +412,8 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { // the result of `is_unwind_dead`. let mut edges = terminator.edges(); if self.skip_unreachable_unwind - && let mir::TerminatorKind::Drop { - target, - unwind, - place, - replace: _, - drop: _, - async_fut: _, - } = terminator.kind + && let mir::TerminatorKind::Drop { target, unwind, place, replace: _, drop: _ } = + terminator.kind && matches!(unwind, mir::UnwindAction::Cleanup(_)) && self.is_unwind_dead(place, state) { diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 46d5773102583..f47751ea83223 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -83,9 +83,7 @@ fn add_move_for_packed_drop<'tcx>( is_cleanup: bool, ) { debug!("add_move_for_packed_drop({:?} @ {:?})", terminator, loc); - let TerminatorKind::Drop { ref place, target, unwind, replace, drop, async_fut } = - terminator.kind - else { + let TerminatorKind::Drop { ref place, target, unwind, replace, drop } = terminator.kind else { unreachable!(); }; @@ -109,7 +107,6 @@ fn add_move_for_packed_drop<'tcx>( unwind, replace, drop, - async_fut, }, ); } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 4ae6e9a8885d1..668ebea9a811d 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -56,9 +56,9 @@ use std::ops; pub(super) use by_move_body::coroutine_by_move_body_def_id; use drop::{ - cleanup_async_drops, create_coroutine_drop_shim, create_coroutine_drop_shim_async, - create_coroutine_drop_shim_proxy_async, elaborate_coroutine_drops, expand_async_drops, - has_expandable_async_drops, insert_clean_drop, + create_coroutine_drop_shim, create_coroutine_drop_shim_async, + create_coroutine_drop_shim_proxy_async, elaborate_coroutine_drops, has_async_drops, + insert_clean_drop, }; use itertools::izip; use rustc_abi::{FieldIdx, VariantIdx}; @@ -70,7 +70,6 @@ use rustc_index::bit_set::{BitMatrix, DenseBitSet, GrowableBitSet}; use rustc_index::{Idx, IndexVec, indexvec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::util::Discr; use rustc_middle::ty::{ self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, TypingMode, }; @@ -82,8 +81,8 @@ use rustc_mir_dataflow::impls::{ use rustc_mir_dataflow::{ Analysis, Results, ResultsCursor, ResultsVisitor, visit_reachable_results, }; +use rustc_span::Span; use rustc_span::def_id::{DefId, LocalDefId}; -use rustc_span::{DUMMY_SP, Span, dummy_spanned}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::TyCtxtInferExt as _; use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt}; @@ -169,7 +168,7 @@ fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtx } const SELF_ARG: Local = Local::arg(0); -const CTX_ARG: Local = Local::arg(1); +pub(crate) const CTX_ARG: Local = Local::arg(1); /// A `yield` point in the coroutine. struct SuspensionPoint<'tcx> { @@ -585,7 +584,7 @@ fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body /// still using the `ResumeTy` indirection for the time being, and that indirection /// is removed here. After this transform, the coroutine body only knows about `&mut Context<'_>`. #[tracing::instrument(level = "trace", skip(tcx, body), ret)] -fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> Ty<'tcx> { +fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let context_mut_ref = Ty::new_task_context(tcx); // replace the type of the `resume` argument @@ -615,7 +614,6 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> Ty _ => {} } } - context_mut_ref } fn eliminate_get_context_call<'tcx>(bb_data: &mut BasicBlockData<'tcx>) -> Local { @@ -1314,6 +1312,9 @@ fn create_coroutine_resume_function<'tcx>( pm::run_passes_no_validate(tcx, body, &[&abort_unwinding_calls::AbortUnwindingCalls], None); + // Run derefer to fix Derefs that are not in the first place + deref_finder(tcx, body, false); + if let Some(dumper) = MirDumper::new(tcx, "coroutine_resume", body) { dumper.dump_mir(body); } @@ -1519,24 +1520,12 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { // (finally in open_drop_for_tuple) before async drop expansion. // Async drops, produced by this drop elaboration, will be expanded, // and corresponding futures kept in layout. - let has_async_drops = matches!( - coroutine_kind, - CoroutineKind::Desugared(CoroutineDesugaring::Async | CoroutineDesugaring::AsyncGen, _) - ) && has_expandable_async_drops(tcx, body, coroutine_ty); + let coroutine_is_async = coroutine_kind.is_async_desugaring(); + let has_async_drops = has_async_drops(body); // Replace all occurrences of `ResumeTy` with `&mut Context<'_>` within async bodies. - if matches!( - coroutine_kind, - CoroutineKind::Desugared(CoroutineDesugaring::Async | CoroutineDesugaring::AsyncGen, _) - ) { - let context_mut_ref = transform_async_context(tcx, body); - expand_async_drops(tcx, body, context_mut_ref, coroutine_kind, coroutine_ty); - - if let Some(dumper) = MirDumper::new(tcx, "coroutine_async_drop_expand", body) { - dumper.dump_mir(body); - } - } else { - cleanup_async_drops(body); + if coroutine_is_async { + transform_async_context(tcx, body); } let always_live_locals = always_storage_live_locals(body); @@ -1650,30 +1639,22 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { // Create a copy of our MIR and use it to create the drop shim for the coroutine if has_async_drops { // If coroutine has async drops, generating async drop shim - let mut drop_shim = + let drop_shim = create_coroutine_drop_shim_async(tcx, &transform, body, drop_clean, can_unwind); - // Run derefer to fix Derefs that are not in the first place - deref_finder(tcx, &mut drop_shim, false); body.coroutine.as_mut().unwrap().coroutine_drop_async = Some(drop_shim); } else { // If coroutine has no async drops, generating sync drop shim - let mut drop_shim = + let drop_shim = create_coroutine_drop_shim(tcx, &transform, coroutine_ty, body, drop_clean); - // Run derefer to fix Derefs that are not in the first place - deref_finder(tcx, &mut drop_shim, false); body.coroutine.as_mut().unwrap().coroutine_drop = Some(drop_shim); // For coroutine with sync drop, generating async proxy for `future_drop_poll` call - let mut proxy_shim = create_coroutine_drop_shim_proxy_async(tcx, body); - deref_finder(tcx, &mut proxy_shim, false); + let proxy_shim = create_coroutine_drop_shim_proxy_async(tcx, body); body.coroutine.as_mut().unwrap().coroutine_drop_proxy_async = Some(proxy_shim); } // Create the Coroutine::resume / Future::poll function create_coroutine_resume_function(tcx, transform, body, can_return, can_unwind); - - // Run derefer to fix Derefs that are not in the first place - deref_finder(tcx, body, false); } fn is_required(&self) -> bool { diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs index 372f7117a0119..9c1d2509a2743 100644 --- a/compiler/rustc_mir_transform/src/coroutine/drop.rs +++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs @@ -31,438 +31,37 @@ impl<'tcx> MutVisitor<'tcx> for FixReturnPendingVisitor<'tcx> { } } -// rv = call fut.poll() -fn build_poll_call<'tcx>( - tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, - poll_unit_place: &Place<'tcx>, - switch_block: BasicBlock, - fut_pin_place: &Place<'tcx>, - fut_ty: Ty<'tcx>, - context_ref_place: &Place<'tcx>, - unwind: UnwindAction, -) -> BasicBlock { - let poll_fn = tcx.require_lang_item(LangItem::FuturePoll, DUMMY_SP); - let poll_fn = Ty::new_fn_def(tcx, poll_fn, [fut_ty]); - let poll_fn = Operand::Constant(Box::new(ConstOperand { - span: DUMMY_SP, - user_ty: None, - const_: Const::zero_sized(poll_fn), - })); - let call = TerminatorKind::Call { - func: poll_fn.clone(), - args: [ - dummy_spanned(Operand::Move(*fut_pin_place)), - dummy_spanned(Operand::Move(*context_ref_place)), - ] - .into(), - destination: *poll_unit_place, - target: Some(switch_block), - unwind, - call_source: CallSource::Misc, - fn_span: DUMMY_SP, - }; - insert_term_block(body, call) -} - -// pin_fut = Pin::new_unchecked(&mut fut) -fn build_pin_fut<'tcx>( - tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, - fut_place: Place<'tcx>, - unwind: UnwindAction, -) -> (BasicBlock, Place<'tcx>) { - let span = body.span; - let source_info = SourceInfo::outermost(span); - let fut_ty = fut_place.ty(&body.local_decls, tcx).ty; - let fut_ref_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, fut_ty); - let fut_ref_place = Place::from(body.local_decls.push(LocalDecl::new(fut_ref_ty, span))); - let pin_fut_new_unchecked_fn = - Ty::new_fn_def(tcx, tcx.require_lang_item(LangItem::PinNewUnchecked, span), [fut_ref_ty]); - let fut_pin_ty = pin_fut_new_unchecked_fn.fn_sig(tcx).output().skip_binder(); - let fut_pin_place = Place::from(body.local_decls.push(LocalDecl::new(fut_pin_ty, span))); - let pin_fut_new_unchecked_fn = Operand::Constant(Box::new(ConstOperand { - span, - user_ty: None, - const_: Const::zero_sized(pin_fut_new_unchecked_fn), - })); - - let storage_live = Statement::new(source_info, StatementKind::StorageLive(fut_pin_place.local)); - - let fut_ref_assign = Statement::new( - source_info, - StatementKind::Assign(Box::new(( - fut_ref_place, - Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { kind: MutBorrowKind::Default }, - fut_place, - ), - ))), - ); - - // call Pin::new_unchecked(&mut fut) - let pin_fut_bb = body.basic_blocks_mut().push(BasicBlockData::new_stmts( - [storage_live, fut_ref_assign].to_vec(), - Some(Terminator { - source_info, - kind: TerminatorKind::Call { - func: pin_fut_new_unchecked_fn, - args: [dummy_spanned(Operand::Move(fut_ref_place))].into(), - destination: fut_pin_place, - target: None, // will be fixed later - unwind, - call_source: CallSource::Misc, - fn_span: span, - }, - }), - false, - )); - (pin_fut_bb, fut_pin_place) -} - -// Build Poll switch for async drop -// match rv { -// Ready() => ready_block -// Pending => yield_block -//} -#[tracing::instrument(level = "trace", skip(tcx, body), ret)] -fn build_poll_switch<'tcx>( - tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, - poll_enum: Ty<'tcx>, - poll_unit_place: &Place<'tcx>, - fut_pin_place: &Place<'tcx>, - ready_block: BasicBlock, - yield_block: BasicBlock, -) -> BasicBlock { - let poll_enum_adt = poll_enum.ty_adt_def().unwrap(); - - let Discr { val: poll_ready_discr, ty: poll_discr_ty } = poll_enum - .discriminant_for_variant( - tcx, - poll_enum_adt - .variant_index_with_id(tcx.require_lang_item(LangItem::PollReady, DUMMY_SP)), - ) - .unwrap(); - let poll_pending_discr = poll_enum - .discriminant_for_variant( - tcx, - poll_enum_adt - .variant_index_with_id(tcx.require_lang_item(LangItem::PollPending, DUMMY_SP)), - ) - .unwrap() - .val; - let source_info = SourceInfo::outermost(body.span); - let poll_discr_place = - Place::from(body.local_decls.push(LocalDecl::new(poll_discr_ty, source_info.span))); - let discr_assign = Statement::new( - source_info, - StatementKind::Assign(Box::new((poll_discr_place, Rvalue::Discriminant(*poll_unit_place)))), - ); - let storage_dead = Statement::new(source_info, StatementKind::StorageDead(fut_pin_place.local)); - let unreachable_block = insert_term_block(body, TerminatorKind::Unreachable); - body.basic_blocks_mut().push(BasicBlockData::new_stmts( - [storage_dead, discr_assign].to_vec(), - Some(Terminator { - source_info, - kind: TerminatorKind::SwitchInt { - discr: Operand::Move(poll_discr_place), - targets: SwitchTargets::new( - [(poll_ready_discr, ready_block), (poll_pending_discr, yield_block)] - .into_iter(), - unreachable_block, - ), - }, - }), - false, - )) -} - -// Gather blocks, reachable through 'drop' targets of Yield and Drop terminators (chained) +/// Drop elaboration has transformed all async drops into `yield` loops. +/// The resulting coroutine needs `async drop` if it yields on a path +/// reachable through 'drop' targets of a Yield terminator. #[tracing::instrument(level = "trace", skip(body), ret)] -fn gather_dropline_blocks<'tcx>(body: &mut Body<'tcx>) -> DenseBitSet { +pub(super) fn has_async_drops<'tcx>(body: &mut Body<'tcx>) -> bool { + let mut has_async_drops = false; + let mut dropline: DenseBitSet = DenseBitSet::new_empty(body.basic_blocks.len()); for (bb, data) in traversal::reverse_postorder(body) { - if dropline.contains(bb) { - data.terminator().successors().for_each(|v| { - dropline.insert(v); - }); - } else { - match data.terminator().kind { - TerminatorKind::Yield { drop: Some(v), .. } => { - dropline.insert(v); - } - TerminatorKind::Drop { drop: Some(v), .. } => { - dropline.insert(v); - } - _ => (), - } + // Cleanup edges are not async drops. + if data.is_cleanup { + continue; } - } - dropline -} -/// Cleanup all async drops (reset to sync) -pub(super) fn cleanup_async_drops<'tcx>(body: &mut Body<'tcx>) { - for block in body.basic_blocks_mut() { - if let TerminatorKind::Drop { - place: _, - target: _, - unwind: _, - replace: _, - ref mut drop, - ref mut async_fut, - } = block.terminator_mut().kind - { - if drop.is_some() || async_fut.is_some() { - *drop = None; - *async_fut = None; + if let TerminatorKind::Yield { drop, .. } = data.terminator().kind { + if dropline.contains(bb) { + has_async_drops = true + } + if let Some(v) = drop { + dropline.insert(v); } } - } -} -pub(super) fn has_expandable_async_drops<'tcx>( - tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, - coroutine_ty: Ty<'tcx>, -) -> bool { - for bb in START_BLOCK..body.basic_blocks.next_index() { - // Drops in unwind path (cleanup blocks) are not expanded to async drops, only sync drops in unwind path - if body[bb].is_cleanup { - continue; - } - let TerminatorKind::Drop { place, target: _, unwind: _, replace: _, drop: _, async_fut } = - body[bb].terminator().kind - else { - continue; - }; - let place_ty = place.ty(&body.local_decls, tcx).ty; - if place_ty == coroutine_ty { - continue; - } - if async_fut.is_none() { - continue; + if dropline.contains(bb) { + data.terminator().successors().for_each(|v| { + dropline.insert(v); + }); } - return true; } - return false; -} - -/// Expand Drop terminator for async drops into mainline poll-switch and dropline poll-switch -#[tracing::instrument(level = "trace", skip(tcx, body), ret)] -pub(super) fn expand_async_drops<'tcx>( - tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, - context_mut_ref: Ty<'tcx>, - coroutine_kind: hir::CoroutineKind, - coroutine_ty: Ty<'tcx>, -) { - let dropline = gather_dropline_blocks(body); - // Clean drop and async_fut fields if potentially async drop is not expanded (stays sync) - let remove_asyncness = |block: &mut BasicBlockData<'tcx>| { - tracing::trace!("remove_asyncness"); - if let TerminatorKind::Drop { - place: _, - target: _, - unwind: _, - replace: _, - ref mut drop, - ref mut async_fut, - } = block.terminator_mut().kind - { - *drop = None; - *async_fut = None; - } - }; - for bb in START_BLOCK..body.basic_blocks.next_index() { - // Drops in unwind path (cleanup blocks) are not expanded to async drops, only sync drops in unwind path - if body[bb].is_cleanup { - remove_asyncness(&mut body[bb]); - continue; - } - let TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut } = - body[bb].terminator().kind - else { - continue; - }; - - let place_ty = place.ty(&body.local_decls, tcx).ty; - if place_ty == coroutine_ty { - remove_asyncness(&mut body[bb]); - continue; - } - - let Some(fut_local) = async_fut else { - remove_asyncness(&mut body[bb]); - continue; - }; - let is_dropline_bb = dropline.contains(bb); - - if !is_dropline_bb && drop.is_none() { - remove_asyncness(&mut body[bb]); - continue; - } - - let fut_place = Place::from(fut_local); - let fut_ty = fut_place.ty(&body.local_decls, tcx).ty; - - // poll-code: - // state_call_drop: - // #bb_pin: fut_pin = Pin::new_unchecked(&mut fut) - // #bb_call: rv = call fut.poll() (or future_drop_poll(fut) for internal future drops) - // #bb_check: match (rv) - // pending => return rv (yield) - // ready => *continue_bb|drop_bb* - - let source_info = body[bb].terminator.as_ref().unwrap().source_info; - - // Compute Poll<> (aka Poll with void return) - let poll_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Poll, source_info.span)); - let poll_enum = Ty::new_adt(tcx, poll_adt_ref, tcx.mk_args(&[tcx.types.unit.into()])); - let poll_decl = LocalDecl::new(poll_enum, source_info.span); - let poll_unit_place = Place::from(body.local_decls.push(poll_decl)); - - // First state-loop yield for mainline - let context_ref_place = - Place::from(body.local_decls.push(LocalDecl::new(context_mut_ref, source_info.span))); - let arg = Rvalue::Use(Operand::Move(Place::from(CTX_ARG)), WithRetag::Yes); - body[bb].statements.push(Statement::new( - source_info, - StatementKind::Assign(Box::new((context_ref_place, arg))), - )); - let yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield - let (pin_bb, fut_pin_place) = - build_pin_fut(tcx, body, fut_place.clone(), UnwindAction::Continue); - let switch_block = build_poll_switch( - tcx, - body, - poll_enum, - &poll_unit_place, - &fut_pin_place, - target, - yield_block, - ); - let call_bb = build_poll_call( - tcx, - body, - &poll_unit_place, - switch_block, - &fut_pin_place, - fut_ty, - &context_ref_place, - unwind, - ); - - // Second state-loop yield for transition to dropline (when coroutine async drop started) - let mut dropline_transition_bb: Option = None; - let mut dropline_yield_bb: Option = None; - let mut dropline_context_ref: Option> = None; - let mut dropline_call_bb: Option = None; - if !is_dropline_bb { - let context_ref_place2: Place<'_> = Place::from( - body.local_decls.push(LocalDecl::new(context_mut_ref, source_info.span)), - ); - let drop_yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield - let (pin_bb2, fut_pin_place2) = - build_pin_fut(tcx, body, fut_place, UnwindAction::Continue); - let drop_switch_block = build_poll_switch( - tcx, - body, - poll_enum, - &poll_unit_place, - &fut_pin_place2, - drop.unwrap(), - drop_yield_block, - ); - let drop_call_bb = build_poll_call( - tcx, - body, - &poll_unit_place, - drop_switch_block, - &fut_pin_place2, - fut_ty, - &context_ref_place2, - unwind, - ); - dropline_transition_bb = Some(pin_bb2); - dropline_yield_bb = Some(drop_yield_block); - dropline_context_ref = Some(context_ref_place2); - dropline_call_bb = Some(drop_call_bb); - } - - let value = - if matches!(coroutine_kind, CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) - { - // For AsyncGen we need `yield Poll::Pending` - let full_yield_ty = body.yield_ty().unwrap(); - let ty::Adt(_poll_adt, args) = *full_yield_ty.kind() else { bug!() }; - let ty::Adt(_option_adt, args) = *args.type_at(0).kind() else { bug!() }; - let yield_ty = args.type_at(0); - Operand::Constant(Box::new(ConstOperand { - span: source_info.span, - const_: Const::Unevaluated( - UnevaluatedConst::new( - tcx.require_lang_item(LangItem::AsyncGenPending, source_info.span), - tcx.mk_args(&[yield_ty.into()]), - ), - full_yield_ty, - ), - user_ty: None, - })) - } else { - // value needed only for return-yields or gen-coroutines, so just const here - Operand::Constant(Box::new(ConstOperand { - span: source_info.span, - user_ty: None, - const_: Const::from_bool(tcx, false), - })) - }; - - use rustc_middle::mir::AssertKind::ResumedAfterDrop; - let panic_bb = insert_panic_block(tcx, body, ResumedAfterDrop(coroutine_kind)); - - if is_dropline_bb { - body[yield_block].terminator_mut().kind = TerminatorKind::Yield { - value: value.clone(), - resume: panic_bb, - resume_arg: context_ref_place, - drop: Some(pin_bb), - }; - } else { - body[yield_block].terminator_mut().kind = TerminatorKind::Yield { - value: value.clone(), - resume: pin_bb, - resume_arg: context_ref_place, - drop: dropline_transition_bb, - }; - body[dropline_yield_bb.unwrap()].terminator_mut().kind = TerminatorKind::Yield { - value, - resume: panic_bb, - resume_arg: dropline_context_ref.unwrap(), - drop: dropline_transition_bb, - }; - } - - if let TerminatorKind::Call { ref mut target, .. } = body[pin_bb].terminator_mut().kind { - *target = Some(call_bb); - } else { - bug!() - } - if !is_dropline_bb { - if let TerminatorKind::Call { ref mut target, .. } = - body[dropline_transition_bb.unwrap()].terminator_mut().kind - { - *target = dropline_call_bb; - } else { - bug!() - } - } - - body[bb].terminator_mut().kind = TerminatorKind::Goto { target: pin_bb }; - } + has_async_drops } #[tracing::instrument(level = "trace", skip(tcx, body))] @@ -488,7 +87,7 @@ pub(super) fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body let (target, unwind, source_info, dropline) = match block_data.terminator() { Terminator { source_info, - kind: TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut: _ }, + kind: TerminatorKind::Drop { place, target, unwind, replace: _, drop }, } => { if let Some(local) = place.as_local() && local == SELF_ARG @@ -530,7 +129,6 @@ pub(super) fn insert_clean_drop<'tcx>( body: &mut Body<'tcx>, has_async_drops: bool, ) -> BasicBlock { - let source_info = SourceInfo::outermost(body.span); let return_block = if has_async_drops { insert_poll_ready_block(tcx, body) } else { @@ -548,12 +146,10 @@ pub(super) fn insert_clean_drop<'tcx>( unwind: UnwindAction::Continue, replace: false, drop: dropline, - async_fut: None, }; // Create a block to destroy an unresumed coroutines. This can only destroy upvars. - body.basic_blocks_mut() - .push(BasicBlockData::new(Some(Terminator { source_info, kind: term }), false)) + insert_term_block(body, term) } #[tracing::instrument(level = "trace", skip(tcx, transform, body))] @@ -600,6 +196,9 @@ pub(super) fn create_coroutine_drop_shim<'tcx>( // unrelated code from the resume part of the function simplify::remove_dead_blocks(&mut body); + // Run derefer to fix Derefs that are not in the first place + deref_finder(tcx, &mut body, false); + // Update the body's def to become the drop glue. let coroutine_instance = body.source.instance; let drop_glue = tcx.require_lang_item(LangItem::DropGlue, body.span); @@ -703,6 +302,9 @@ pub(super) fn create_coroutine_drop_shim_async<'tcx>( None, ); + // Run derefer to fix Derefs that are not in the first place + deref_finder(tcx, &mut body, false); + if let Some(dumper) = MirDumper::new(tcx, "coroutine_drop_async", &body) { dumper.dump_mir(&body); } @@ -746,10 +348,12 @@ pub(super) fn create_coroutine_drop_shim_proxy_async<'tcx>( unwind: UnwindAction::Continue, replace: false, drop: None, - async_fut: None, }; body.basic_blocks_mut()[call_bb].terminator = Some(Terminator { source_info, kind }); + // Run derefer to fix Derefs that are not in the first place + deref_finder(tcx, &mut body, false); + if let Some(dumper) = MirDumper::new(tcx, "coroutine_drop_proxy_async", &body) { dumper.dump_mir(&body); } diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index c835ff7dbe070..e7f8af54be3b2 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -1,17 +1,18 @@ use std::{fmt, iter, mem}; use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; -use rustc_hir::def::DefKind; use rustc_hir::lang_items::LangItem; +use rustc_hir::{CoroutineDesugaring, CoroutineKind}; use rustc_index::Idx; use rustc_middle::mir::*; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt}; -use rustc_middle::{bug, span_bug, traits}; -use rustc_span::{DUMMY_SP, Spanned, dummy_spanned}; +use rustc_middle::ty::util::{Discr, IntTypeExt}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt}; +use rustc_middle::{bug, span_bug}; +use rustc_span::{DUMMY_SP, dummy_spanned}; use tracing::{debug, instrument}; +use crate::coroutine::CTX_ARG; use crate::patch::MirPatch; /// Describes how/if a value should be dropped. @@ -96,8 +97,6 @@ pub(crate) trait DropElaborator<'a, 'tcx>: fmt::Debug { fn typing_env(&self) -> ty::TypingEnv<'tcx>; fn allow_async_drops(&self) -> bool; - fn terminator_loc(&self, bb: BasicBlock) -> Location; - // Drop logic /// Returns how `path` should be dropped, given `mode`. @@ -200,19 +199,35 @@ where self.elaborator.tcx() } - // Generates three blocks: - // * #1:pin_obj_bb: call Pin::new_unchecked(&mut obj) - // * #2:call_drop_bb: fut = call obj.() OR call async_drop_in_place(obj) - // * #3:drop_term_bb: drop (obj, fut, ...) - // We keep async drop unexpanded to poll-loop here, to expand it later, at StateTransform - - // into states expand. - // call_destructor_only - to call only AsyncDrop::drop, not full async_drop_in_place glue + /// Async-drop `place: drop_ty`. + /// + /// Conceptually, we want to run `async_drop_in_place(&mut obj).await`. + /// + /// Await syntax does not exist in MIR, so we need to manually expand it into a poll-yield + /// loop, essentially: + /// ```mir + /// let fut = async_drop_in_place(&mut obj); + /// loop { + /// let pin_fut = Pin::new_unchecked(&mut fut); + /// match Future::poll(pin_fut, CTX_ARG) { + /// Poll::Ready => break, + /// Poll:Pending(..) => CTX_ARG = yield (), + /// } + /// } + /// // continue to `succ` + /// ``` + /// + /// We also need to ensure that async drop also happens on the coroutine drop path, ie. when + /// `yield` branches along its `drop` target. This requires a second loop, this time jumping to + /// `dropline`. + /// + /// Arguments: + /// `call_destructor_only`: call only `AsyncDrop::drop`, not full `async_drop_in_place` glue #[instrument(level = "debug", skip(self), ret)] fn build_async_drop( &mut self, place: Place<'tcx>, drop_ty: Ty<'tcx>, - bb: Option, succ: BasicBlock, unwind: Unwind, dropline: Option, @@ -220,81 +235,155 @@ where ) -> BasicBlock { let tcx = self.tcx(); let span = self.source_info.span; + let obj_ref_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, drop_ty); - let pin_obj_bb = bb.unwrap_or_else(|| { - // Temporary terminator, will be replaced by patch - self.new_block(unwind, TerminatorKind::Return) - }); - - let (fut_ty, drop_fn_def_id, trait_args) = if call_destructor_only { + let async_drop_fn_def_id = if call_destructor_only { // Resolving obj.() - let trait_ref = - ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::AsyncDrop, span), [drop_ty]); - let (drop_trait, trait_args) = match tcx.codegen_select_candidate( - ty::TypingEnv::fully_monomorphized().as_query_input(trait_ref), - ) { - Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData { - impl_def_id, - args, - .. - })) => (*impl_def_id, *args), - impl_source => { - span_bug!(span, "invalid `AsyncDrop` impl_source: {:?}", impl_source); - } - }; - // impl_item_refs may be empty if drop fn is not implemented in 'impl AsyncDrop for ...' - // (#140974). - // Such code will report error, so just generate sync drop here and return - let Some(drop_fn_def_id) = - tcx.associated_item_def_ids(drop_trait).first().and_then(|&def_id| { - if tcx.def_kind(def_id) == DefKind::AssocFn - && tcx.check_args_compatible(def_id, trait_args) - { - Some(def_id) - } else { - None - } - }) - else { - tcx.dcx().span_delayed_bug( - self.elaborator.body().span, - "AsyncDrop type without correct `async fn drop(...)`.", - ); - self.elaborator.patch().patch_terminator( - pin_obj_bb, - TerminatorKind::Drop { - place, - target: succ, - unwind: unwind.into_action(), - replace: false, - drop: None, - async_fut: None, - }, - ); - return pin_obj_bb; - }; - let drop_fn = Ty::new_fn_def(tcx, drop_fn_def_id, trait_args); - let sig = drop_fn.fn_sig(tcx); - let sig = tcx.instantiate_bound_regions_with_erased(sig); - (sig.output(), drop_fn_def_id, trait_args) + let async_drop_trait = tcx.require_lang_item(LangItem::AsyncDrop, span); + tcx.associated_item_def_ids(async_drop_trait)[0] } else { // Resolving async_drop_in_place function for drop_ty - let drop_fn_def_id = tcx.require_lang_item(LangItem::AsyncDropInPlace, span); - let trait_args = tcx.mk_args(&[drop_ty.into()]); - let sig = tcx.fn_sig(drop_fn_def_id).instantiate(tcx, trait_args).skip_norm_wip(); - let sig = tcx.instantiate_bound_regions_with_erased(sig); - (sig.output(), drop_fn_def_id, trait_args) + tcx.require_lang_item(LangItem::AsyncDropInPlace, span) }; - let fut = Place::from(self.new_temp(fut_ty)); + let fut_ty = tcx + .instantiate_bound_regions_with_erased( + Ty::new_fn_def(tcx, async_drop_fn_def_id, [drop_ty]).fn_sig(tcx), + ) + .output(); + let fut = self.new_temp(fut_ty); - // #1:pin_obj_bb >>> obj_ref = &mut obj - let obj_ref_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, drop_ty); - let obj_ref_place = Place::from(self.new_temp(obj_ref_ty)); + // Create an intermediate block that does StorageDead(fut) then jumps to succ. + // This is necessary because we do not want to modify statements + // in existing blocks, in case those are used somewhere else in MIR. + let succ_with_dead = self.new_block_with_statements( + unwind, + vec![self.storage_dead(fut)], + TerminatorKind::Goto { target: succ }, + ); + let dropline_with_dead = dropline.map(|target| { + self.new_block_with_statements( + unwind, + vec![self.storage_dead(fut)], + TerminatorKind::Goto { target }, + ) + }); + let unwind_with_dead = unwind.map(|target| { + self.new_block_with_statements( + Unwind::InCleanup, + vec![self.storage_dead(fut)], + TerminatorKind::Goto { target }, + ) + }); + + // The yielded value depends on the kind of coroutine, to match what AST lowering does. + let coroutine_kind = self.elaborator.body().coroutine_kind().unwrap(); + let yield_value = match coroutine_kind { + // For async gen, we need `yield Poll::Pending`. + CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _) => { + let full_yield_ty = self.elaborator.body().yield_ty().unwrap(); + let ty::Adt(_poll_adt, args) = *full_yield_ty.kind() else { bug!() }; + let ty::Adt(_option_adt, args) = *args.type_at(0).kind() else { bug!() }; + let yield_ty = args.type_at(0); + Operand::unevaluated_constant( + tcx, + tcx.require_lang_item(LangItem::AsyncGenPending, span), + tcx.mk_args(&[yield_ty.into()]), + span, + ) + } + // For regular async fn, we need `yield ()`. + CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => { + Operand::zero_sized_constant(tcx.types.unit, span) + } + // `is_async_drop` should have checked that. + _ => panic!("unexpected coroutine for async drop {coroutine_kind:?}"), + }; - let term_loc = self.elaborator.terminator_loc(pin_obj_bb); - self.elaborator.patch().add_assign( - term_loc, + // The branching here is tricky and deserves some explanation. + // + // If we are in the drop code path, ie. we are currently dropping the coroutine. + // The state machine follows the `drop` branch in the `yield` terminator. + // To repeatedly poll the future, the `drop` branch must loop. + // Meanwhile, the `resume` branch corresponds to anomalous execution, + // trying to resume the coroutine while it is being dropped. So that branch panics + // (`panic_bb`). + let panic_bb = self.build_resumed_after_drop_abort_block(unwind_with_dead, coroutine_kind); + let (drop_pin_bb, drop_resume_bb, drop_drop_bb) = self.build_pin_poll_yield_loop( + CTX_ARG.into(), + fut.into(), + yield_value.clone(), + // If `dropline_with_dead` is set, it points to the continuation of the drop execution. + // Otherwise, we are already dropping the coroutine, and `succ_with_dead` does. + dropline_with_dead.unwrap_or(succ_with_dead), + unwind_with_dead, + ); + self.elaborator + .patch() + .patch_terminator(drop_resume_bb, TerminatorKind::Goto { target: panic_bb }); + self.elaborator + .patch() + .patch_terminator(drop_drop_bb, TerminatorKind::Goto { target: drop_pin_bb }); + + // If we are in the regular code path, `dropline_with_dead` is `Some`. + // + // In that case, the logic is reversed. Normal execution branches on `resume` from the + // `yield` terminator. To repeatedly poll the future, that `resume` branch must loop. + // When the future is dropped, the `yield` terminator branches to `drop`, which follows to + // the previous loop `drop_pin_bb`. + let succ_yield_loop = if dropline_with_dead.is_some() { + let (pin_bb, resume_bb, drop_bb) = self.build_pin_poll_yield_loop( + CTX_ARG.into(), + fut.into(), + yield_value, + // `dropline_with_dead` is `Some`, so the previous loop point to it. + succ_with_dead, + unwind_with_dead, + ); + self.elaborator + .patch() + .patch_terminator(resume_bb, TerminatorKind::Goto { target: pin_bb }); + self.elaborator + .patch() + .patch_terminator(drop_bb, TerminatorKind::Goto { target: drop_pin_bb }); + pin_bb + } else { + // We were already in the drop line, so return the loop we created for it. + drop_pin_bb + }; + + // #2:call_drop_bb >>> + // call AsyncDrop::drop(pin_obj) + // OR call async_drop_in_place(pin_obj.pointer) + let pin_adt_def = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, span)); + let pin_obj_ty = Ty::new_adt(tcx, pin_adt_def, tcx.mk_args(&[obj_ref_ty.into()])); + // Where we store the result of Pin<&drop_ty>::new_unchecked(&mut place). + let pin_obj_local = self.new_temp(pin_obj_ty); + let drop_arg = if call_destructor_only { + // `AsyncDrop::drop` takes `self: Pin<&mut Self>`. + Operand::Move(pin_obj_local.into()) + } else { + // `async_drop_in_place` takes `obj: &mut T`. + Operand::Copy(tcx.mk_place_field(pin_obj_local.into(), FieldIdx::ZERO, obj_ref_ty)) + }; + let call_drop_bb = self.new_block_with_statements( + unwind_with_dead, + vec![self.storage_live(fut)], + TerminatorKind::Call { + func: Operand::function_handle(tcx, async_drop_fn_def_id, [drop_ty.into()], span), + args: [dummy_spanned(drop_arg)].into(), + destination: fut.into(), + target: Some(succ_yield_loop), + unwind: unwind_with_dead.into_action(), + call_source: CallSource::Misc, + fn_span: self.source_info.span, + }, + ); + + // #1:pin_obj_bb >>> `call Pin::new_unchecked(&mut obj)` + let obj_ref_place = Place::from(self.new_temp(obj_ref_ty)); + let pin_obj_new_unchecked_fn = tcx.require_lang_item(LangItem::PinNewUnchecked, span); + let assign_obj_ref_place = self.assign( obj_ref_place, Rvalue::Ref( tcx.lifetimes.re_erased, @@ -302,111 +391,250 @@ where place, ), ); + self.new_block_with_statements( + unwind, + vec![assign_obj_ref_place], + TerminatorKind::Call { + func: Operand::function_handle( + tcx, + pin_obj_new_unchecked_fn, + [obj_ref_ty.into()], + span, + ), + args: [dummy_spanned(Operand::Move(obj_ref_place))].into(), + destination: pin_obj_local.into(), + target: Some(call_drop_bb), + unwind: unwind.into_action(), + call_source: CallSource::Misc, + fn_span: span, + }, + ) + } - // pin_obj_place preparation - let pin_obj_new_unchecked_fn = Ty::new_fn_def( - tcx, - tcx.require_lang_item(LangItem::PinNewUnchecked, span), - [GenericArg::from(obj_ref_ty)], - ); - let pin_obj_ty = pin_obj_new_unchecked_fn.fn_sig(tcx).output().no_bound_vars().unwrap(); - let pin_obj_place = Place::from(self.new_temp(pin_obj_ty)); - let pin_obj_new_unchecked_fn = Operand::Constant(Box::new(ConstOperand { - span, + fn build_resumed_after_drop_abort_block( + &mut self, + unwind: Unwind, + coroutine_kind: CoroutineKind, + ) -> BasicBlock { + let tcx = self.tcx(); + let panic_bb = self.new_block(unwind, TerminatorKind::Unreachable); + let msg = AssertMessage::ResumedAfterDrop(coroutine_kind); + let false_op = Operand::Constant(Box::new(ConstOperand { + span: self.source_info.span, user_ty: None, - const_: Const::zero_sized(pin_obj_new_unchecked_fn), + const_: Const::from_bool(tcx, false), })); + self.elaborator.patch().patch_terminator( + panic_bb, + TerminatorKind::Assert { + cond: false_op, + expected: true, + msg: Box::new(msg), + target: panic_bb, + unwind: unwind.into_action(), + }, + ); + panic_bb + } - // Create an intermediate block that does StorageDead(fut) then jumps to succ. - // This is necessary because `succ` may differ from `self.succ` (e.g. when - // build_async_drop is called from drop_loop, `succ` is the loop header). - // Placing StorageDead directly at `self.succ` would miss the loop-back edge, - // causing StorageLive(fut) to fire again without a preceding StorageDead. - let succ_with_dead = self.new_block_with_statements( + /// Build a small MIR loop that pins and polls a future, yielding when + /// the future returns `Poll::Pending` and continuing to `ready_target` + /// when it returns `Poll::Ready`. + /// + /// Pseudo-code: + /// ```mir + /// pin_bb: + /// let pin_fut = Pin::new_unchecked(&mut fut_place); + /// match Future::poll(pin_fut, CTX_ARG) { + /// Poll::Ready => goto succ, + /// Poll::Pending(..) => CTX_ARG = yield () [resume: resume_bb, drop: drop_bb], + /// } + /// ``` + /// + /// Returns: the tuple `(pin_bb, resume_bb, drop_bb)`. + #[instrument(level = "trace", skip(self), ret)] + fn build_pin_poll_yield_loop( + &mut self, + resume_place: Place<'tcx>, + fut_place: Place<'tcx>, + yield_value: Operand<'tcx>, + succ: BasicBlock, + unwind: Unwind, + ) -> (BasicBlock, BasicBlock, BasicBlock) { + let tcx = self.tcx(); + let source_info = self.source_info; + + let resume_arg_ty = resume_place.ty(self.elaborator.body(), tcx).ty; + let context_ref_ty = Ty::new_task_context(tcx); + + let poll_adt_def = tcx.adt_def(tcx.require_lang_item(LangItem::Poll, source_info.span)); + let poll_enum = Ty::new_adt(tcx, poll_adt_def, tcx.mk_args(&[tcx.types.unit.into()])); + + let fut_ty = self.elaborator.patch_ref().local_ty(fut_place.local); + let fut_ref_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, fut_ty); + + let pin_adt_def = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, source_info.span)); + let fut_pin_ty = Ty::new_adt(tcx, pin_adt_def, tcx.mk_args(&[fut_ref_ty.into()])); + + // Coroutine `transform_async_context` assumes that the local `resume_arg` to a yield + // is not used once, so create a special temp for it. + let yield_resume_local = self.new_temp(resume_arg_ty); + let resume_bb = self.new_block_with_statements( unwind, - vec![Statement::new(self.source_info, StatementKind::StorageDead(fut.local))], - TerminatorKind::Goto { target: succ }, + vec![ + self.assign( + resume_place, + Rvalue::Use(Operand::Move(yield_resume_local.into()), WithRetag::Yes), + ), + self.storage_dead(yield_resume_local), + ], + // This will be transformed by the caller. + TerminatorKind::Unreachable, ); - - // #3:drop_term_bb - let drop_term_bb = self.new_block( + let dropline_bb = self.new_block_with_statements( unwind, - TerminatorKind::Drop { - place, - target: succ_with_dead, - unwind: unwind.into_action(), - replace: false, - drop: dropline, - async_fut: Some(fut.local), + vec![ + self.assign( + resume_place, + Rvalue::Use(Operand::Move(yield_resume_local.into()), WithRetag::Yes), + ), + self.storage_dead(yield_resume_local), + ], + // This will be transformed by the caller. + TerminatorKind::Unreachable, + ); + let yield_bb = self.new_block_with_statements( + unwind, + vec![self.storage_live(yield_resume_local)], + TerminatorKind::Yield { + value: yield_value, + resume: resume_bb, + resume_arg: yield_resume_local.into(), + drop: Some(dropline_bb), }, ); - // #2:call_drop_bb - let mut call_statements = Vec::new(); - let drop_arg = if call_destructor_only { - pin_obj_place - } else { - let ty::Adt(adt_def, adt_args) = pin_obj_ty.kind() else { - bug!(); - }; - let unwrap_ty = - adt_def.non_enum_variant().fields[FieldIdx::ZERO].ty(tcx, adt_args).skip_norm_wip(); - let obj_ref_place = Place::from(self.new_temp(unwrap_ty)); - call_statements.push(self.assign( - obj_ref_place, - Rvalue::Use( - Operand::Copy(tcx.mk_place_field(pin_obj_place, FieldIdx::ZERO, unwrap_ty)), - WithRetag::Yes, - ), - )); - - obj_ref_place + let poll_unit_local = self.new_temp(poll_enum); + let switch_bb = { + let poll_ready_variant = + tcx.require_lang_item(LangItem::PollReady, self.source_info.span); + let poll_ready_variant_idx = poll_adt_def.variant_index_with_id(poll_ready_variant); + let poll_pending_variant = + tcx.require_lang_item(LangItem::PollPending, self.source_info.span); + let poll_pending_variant_idx = poll_adt_def.variant_index_with_id(poll_pending_variant); + + let Discr { val: poll_ready_discr, ty: poll_discr_ty } = + poll_enum.discriminant_for_variant(tcx, poll_ready_variant_idx).unwrap(); + let Discr { val: poll_pending_discr, ty: _ } = + poll_enum.discriminant_for_variant(tcx, poll_pending_variant_idx).unwrap(); + + let poll_discr_local = self.new_temp(poll_discr_ty); + let otherwise_bb = self.elaborator.patch().unreachable_no_cleanup_block(); + self.new_block_with_statements( + unwind, + vec![ + self.assign( + poll_discr_local.into(), + Rvalue::Discriminant(poll_unit_local.into()), + ), + ], + TerminatorKind::SwitchInt { + discr: Operand::Move(poll_discr_local.into()), + targets: SwitchTargets::new( + [ + // on `Ready`, exit the loop, jump to `succ` + (poll_ready_discr, succ), + // on `Pending`, yield and resume back into the loop + (poll_pending_discr, yield_bb), + ] + .into_iter(), + // otherwise: unreachable + otherwise_bb, + ), + }, + ) }; - call_statements - .push(Statement::new(self.source_info, StatementKind::StorageLive(fut.local))); - let call_drop_bb = self.new_block_with_statements( + let fut_pin_local = self.new_temp(fut_pin_ty); + let context_ref_local = self.new_temp(context_ref_ty); + + let poll_fn = tcx.require_lang_item(LangItem::FuturePoll, source_info.span); + let poll_bb = self.new_block_with_statements( unwind, - call_statements, + Vec::new(), TerminatorKind::Call { - func: Operand::function_handle(tcx, drop_fn_def_id, trait_args, span), - args: [Spanned { node: Operand::Move(drop_arg), span: DUMMY_SP }].into(), - destination: fut, - target: Some(drop_term_bb), + func: Operand::function_handle(tcx, poll_fn, [fut_ty.into()], source_info.span), + args: [ + dummy_spanned(Operand::Move(fut_pin_local.into())), + dummy_spanned(Operand::Move(context_ref_local.into())), + ] + .into(), + destination: poll_unit_local.into(), + target: Some(switch_bb), unwind: unwind.into_action(), call_source: CallSource::Misc, - fn_span: self.source_info.span, + fn_span: source_info.span, }, ); - // StorageDead(fut) in unwind block (at the begin) - if let Unwind::To(block) = unwind { - self.elaborator.patch().add_statement( - Location { block, statement_index: 0 }, - StatementKind::StorageDead(fut.local), - ); - } - // StorageDead(fut) in dropline block (at the begin) - if let Some(block) = dropline { - self.elaborator.patch().add_statement( - Location { block, statement_index: 0 }, - StatementKind::StorageDead(fut.local), - ); - } - // #1:pin_obj_bb >>> call Pin::new_unchecked(&mut obj) - self.elaborator.patch().patch_terminator( - pin_obj_bb, + let get_context_fn = tcx.require_lang_item(LangItem::GetContext, source_info.span); + let get_context_bb = { + // Coroutine `transform_async_context` assumes that the local argument to `GetContext` + // is not used once, so create a special temp for it. + let entry_resume_local = self.new_temp(resume_arg_ty); + self.new_block_with_statements( + unwind, + vec![self.assign( + entry_resume_local.into(), + Rvalue::Use(Operand::Move(resume_place), WithRetag::Yes), + )], + TerminatorKind::Call { + func: Operand::function_handle( + tcx, + get_context_fn, + [tcx.lifetimes.re_erased.into(), tcx.lifetimes.re_erased.into()], + source_info.span, + ), + args: [dummy_spanned(Operand::Move(entry_resume_local.into()))].into(), + destination: context_ref_local.into(), + target: Some(poll_bb), + unwind: unwind.into_action(), + call_source: CallSource::Misc, + fn_span: source_info.span, + }, + ) + }; + + let fut_ref_local = self.new_temp(fut_ref_ty); + let fut_pin_new_unchecked_fn = + tcx.require_lang_item(LangItem::PinNewUnchecked, source_info.span); + let pin_bb = self.new_block_with_statements( + unwind, + vec![self.assign( + fut_ref_local.into(), + Rvalue::Ref( + tcx.lifetimes.re_erased, + BorrowKind::Mut { kind: MutBorrowKind::Default }, + fut_place, + ), + )], TerminatorKind::Call { - func: pin_obj_new_unchecked_fn, - args: [dummy_spanned(Operand::Move(obj_ref_place))].into(), - destination: pin_obj_place, - target: Some(call_drop_bb), + func: Operand::function_handle( + tcx, + fut_pin_new_unchecked_fn, + [fut_ref_ty.into()], + source_info.span, + ), + args: [dummy_spanned(Operand::Move(fut_ref_local.into()))].into(), + destination: fut_pin_local.into(), + target: Some(get_context_bb), unwind: unwind.into_action(), call_source: CallSource::Misc, - fn_span: span, + fn_span: source_info.span, }, ); - pin_obj_bb + + (pin_bb, resume_bb, dropline_bb) } fn build_drop(&mut self, bb: BasicBlock) { @@ -414,15 +642,17 @@ where if !self.elaborator.patch_ref().block(self.elaborator.body(), bb).is_cleanup && self.check_if_can_async_drop(drop_ty, false) { - self.build_async_drop( + let async_drop_bb = self.build_async_drop( self.place, drop_ty, - Some(bb), self.succ, self.unwind, self.dropline, false, ); + self.elaborator + .patch() + .patch_terminator(bb, TerminatorKind::Goto { target: async_drop_bb }); } else { self.elaborator.patch().patch_terminator( bb, @@ -432,7 +662,6 @@ where unwind: self.unwind.into_action(), replace: false, drop: None, - async_fut: None, }, ); } @@ -440,6 +669,21 @@ where /// Function to check if we can generate an async drop here fn check_if_can_async_drop(&mut self, drop_ty: Ty<'tcx>, call_destructor_only: bool) -> bool { + if !self.elaborator.allow_async_drops() + || !self + .elaborator + .body() + .coroutine + .as_ref() + .is_some_and(|ck| ck.coroutine_kind.is_async_desugaring()) + { + return false; + } + + if drop_ty == self.place_ty(Local::arg(0).into()) { + return false; + } + let is_async_drop_feature_enabled = if self.tcx().features().async_drop() { true } else { @@ -454,10 +698,7 @@ where // Short-circuit before calling needs_async_drop/is_async_drop, as those // require the `async_drop` lang item to exist (which may not be present // in minimal/custom core environments like cranelift's mini_core). - if !is_async_drop_feature_enabled - || !self.elaborator.body().coroutine.is_some() - || !self.elaborator.allow_async_drops() - { + if !is_async_drop_feature_enabled { return false; } @@ -842,9 +1083,9 @@ where let mut values = Vec::with_capacity(adt.variants().len()); let mut normal_blocks = Vec::with_capacity(adt.variants().len()); let mut unwind_blocks = - if unwind.is_cleanup() { None } else { Some(Vec::with_capacity(adt.variants().len())) }; + Vec::with_capacity(if unwind.is_cleanup() { 0 } else { adt.variants().len() }); let mut dropline_blocks = - if dropline.is_none() { None } else { Some(Vec::with_capacity(adt.variants().len())) }; + Vec::with_capacity(if dropline.is_none() { 0 } else { adt.variants().len() }); let mut have_otherwise_with_drop_glue = false; let mut have_otherwise = false; @@ -880,7 +1121,6 @@ where // I want to minimize the divergence between MSVC // and non-MSVC. - let unwind_blocks = unwind_blocks.as_mut().unwrap(); let unwind_ladder = vec![Unwind::InCleanup; fields.len() + 1]; let dropline_ladder: Vec> = vec![None; fields.len() + 1]; let halfladder = @@ -890,7 +1130,7 @@ where let (normal, _, drop_bb) = self.drop_ladder(fields, succ, unwind, dropline); normal_blocks.push(normal); if dropline.is_some() { - dropline_blocks.as_mut().unwrap().push(drop_bb.unwrap()); + dropline_blocks.push(drop_bb.unwrap()); } } else { have_otherwise = true; @@ -911,28 +1151,22 @@ where } else if !have_otherwise_with_drop_glue { normal_blocks.push(self.goto_block(succ, unwind)); if let Unwind::To(unwind) = unwind { - unwind_blocks.as_mut().unwrap().push(self.goto_block(unwind, Unwind::InCleanup)); + unwind_blocks.push(self.goto_block(unwind, Unwind::InCleanup)); } } else { normal_blocks.push(self.drop_block(succ, unwind)); if let Unwind::To(unwind) = unwind { - unwind_blocks.as_mut().unwrap().push(self.drop_block(unwind, Unwind::InCleanup)); + unwind_blocks.push(self.drop_block(unwind, Unwind::InCleanup)); } } ( self.adt_switch_block(adt, normal_blocks, &values, succ, unwind), unwind.map(|unwind| { - self.adt_switch_block( - adt, - unwind_blocks.unwrap(), - &values, - unwind, - Unwind::InCleanup, - ) + self.adt_switch_block(adt, unwind_blocks, &values, unwind, Unwind::InCleanup) }), dropline.map(|dropline| { - self.adt_switch_block(adt, dropline_blocks.unwrap(), &values, dropline, unwind) + self.adt_switch_block(adt, dropline_blocks, &values, dropline, unwind) }), ) } @@ -992,8 +1226,7 @@ where )], TerminatorKind::Call { func: Operand::function_handle(tcx, drop_fn, [ty.into()], self.source_info.span), - args: [Spanned { node: Operand::Move(Place::from(ref_place)), span: DUMMY_SP }] - .into(), + args: [dummy_spanned(Operand::Move(Place::from(ref_place)))].into(), destination: unit_temp, target: Some(succ), unwind: unwind.into_action(), @@ -1012,7 +1245,7 @@ where ) -> BasicBlock { let ty = self.place_ty(self.place); if !unwind.is_cleanup() && self.check_if_can_async_drop(ty, true) { - self.build_async_drop(self.place, ty, None, succ, unwind, dropline, true) + self.build_async_drop(self.place, ty, succ, unwind, dropline, true) } else { self.destructor_call_block_sync(succ, unwind) } @@ -1074,15 +1307,11 @@ where let place = tcx.mk_place_deref(ptr); if !unwind.is_cleanup() && self.check_if_can_async_drop(ety, false) { - self.build_async_drop( - place, - ety, - Some(drop_block), - loop_block, - unwind, - dropline, - false, - ); + let async_drop_bb = + self.build_async_drop(place, ety, loop_block, unwind, dropline, false); + self.elaborator + .patch() + .patch_terminator(drop_block, TerminatorKind::Goto { target: async_drop_bb }); } else { self.elaborator.patch().patch_terminator( drop_block, @@ -1092,7 +1321,6 @@ where unwind: unwind.into_action(), replace: false, drop: None, - async_fut: None, }, ); } @@ -1328,7 +1556,6 @@ where unwind: self.unwind.into_action(), replace: false, drop: self.dropline, - async_fut: None, }, ); self.elaborate_drop(blk); @@ -1338,15 +1565,7 @@ where fn drop_block(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock { let drop_ty = self.place_ty(self.place); if !unwind.is_cleanup() && self.check_if_can_async_drop(drop_ty, false) { - self.build_async_drop( - self.place, - drop_ty, - None, - self.succ, - unwind, - self.dropline, - false, - ) + self.build_async_drop(self.place, drop_ty, self.succ, unwind, self.dropline, false) } else { self.new_block( unwind, @@ -1356,7 +1575,6 @@ where unwind: unwind.into_action(), replace: false, drop: None, - async_fut: None, }, ) } @@ -1428,4 +1646,12 @@ where fn assign(&self, lhs: Place<'tcx>, rhs: Rvalue<'tcx>) -> Statement<'tcx> { Statement::new(self.source_info, StatementKind::Assign(Box::new((lhs, rhs)))) } + + fn storage_live(&self, local: Local) -> Statement<'tcx> { + Statement::new(self.source_info, StatementKind::StorageLive(local)) + } + + fn storage_dead(&self, local: Local) -> Statement<'tcx> { + Statement::new(self.source_info, StatementKind::StorageDead(local)) + } } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 3787276919cf5..01235b1824218 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -162,10 +162,6 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> { true } - fn terminator_loc(&self, bb: BasicBlock) -> Location { - self.patch.terminator_loc(self.body, bb) - } - #[instrument(level = "debug", skip(self), ret)] fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle { let ((maybe_init, maybe_uninit), multipart) = match mode { @@ -336,8 +332,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { // This function should mirror what `collect_drop_flags` does. for (bb, data) in self.body.basic_blocks.iter_enumerated() { let terminator = data.terminator(); - let TerminatorKind::Drop { place, target, unwind, replace, drop, async_fut: _ } = - terminator.kind + let TerminatorKind::Drop { place, target, unwind, replace, drop } = terminator.kind else { continue; }; diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index fbe3a827d6394..f17ae50b7affb 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -413,14 +413,8 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> { let term = blk.terminator(); let caller_attrs = tcx.codegen_fn_attrs(self.caller_def_id()); - if let TerminatorKind::Drop { - ref place, - target, - unwind, - replace: _, - drop: _, - async_fut: _, - } = term.kind + if let TerminatorKind::Drop { ref place, target, unwind, replace: _, drop: _ } = + term.kind { work_list.push(target); diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index c354279b8ed32..0bc5704a8625d 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -137,7 +137,6 @@ impl<'a, 'mir, 'tcx> DropsReachable<'a, 'mir, 'tcx> { unwind: _, replace: _, drop: _, - async_fut: _, } = &terminator.kind && place_has_common_prefix(dropped_place, self.place) { diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs index 015bae56cf57e..da1077707baff 100644 --- a/compiler/rustc_mir_transform/src/patch.rs +++ b/compiler/rustc_mir_transform/src/patch.rs @@ -166,11 +166,6 @@ impl<'tcx> MirPatch<'tcx> { } } - pub(crate) fn terminator_loc(&self, body: &Body<'tcx>, bb: BasicBlock) -> Location { - let offset = self.block(body, bb).statements.len(); - Location { block: bb, statement_index: offset } - } - /// Queues the addition of a new temporary with additional local info. pub(crate) fn new_local_with_info( &mut self, diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 7f92199dec455..c5ef70558c88c 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -30,40 +30,6 @@ pub(super) fn provide(providers: &mut Providers) { providers.mir_shims = make_shim; } -// Replace Pin<&mut ImplCoroutine> accesses (_1.0) into Pin<&mut ProxyCoroutine> accesses -struct FixProxyFutureDropVisitor<'tcx> { - tcx: TyCtxt<'tcx>, - replace_to: Local, -} - -impl<'tcx> MutVisitor<'tcx> for FixProxyFutureDropVisitor<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn visit_place( - &mut self, - place: &mut Place<'tcx>, - _context: PlaceContext, - _location: Location, - ) { - if place.local == Local::from_u32(1) { - if place.projection.len() == 1 { - assert!(matches!( - place.projection.first(), - Some(ProjectionElem::Field(FieldIdx::ZERO, _)) - )); - *place = Place::from(self.replace_to); - } else if place.projection.len() == 2 { - assert!(matches!(place.projection[0], ProjectionElem::Field(FieldIdx::ZERO, _))); - assert!(matches!(place.projection[1], ProjectionElem::Deref)); - *place = - Place::from(self.replace_to).project_deeper(&[ProjectionElem::Deref], self.tcx); - } - } - } -} - fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<'tcx> { debug!("make_shim({:?})", instance); @@ -190,7 +156,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< // Main pass required here is StateTransform to convert sync drop ladder // into coroutine. // Others are minimal passes as for sync drop glue shim - pm::run_passes( + pm::run_passes_no_validate( tcx, &mut body, &[ @@ -201,7 +167,6 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< &crate::coroutine::StateTransform, ], Some(MirPhase::Runtime(RuntimePhase::PostCleanup)), - pm::Optimizations::Allowed, ); run_optimization_passes(tcx, &mut body); debug!("make_shim({:?}) = {:?}", instance, body); @@ -463,9 +428,6 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { self.typing_env } - fn terminator_loc(&self, bb: BasicBlock) -> Location { - self.patch.terminator_loc(self.body, bb) - } fn allow_async_drops(&self) -> bool { self.produce_async_drops } @@ -727,7 +689,6 @@ impl<'tcx> CloneShimBuilder<'tcx> { unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup), replace: false, drop: None, - async_fut: None, }, /* is_cleanup */ true, ); @@ -994,7 +955,6 @@ fn build_call_shim<'tcx>( unwind: UnwindAction::Continue, replace: false, drop: None, - async_fut: None, }, false, ); @@ -1013,7 +973,6 @@ fn build_call_shim<'tcx>( unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup), replace: false, drop: None, - async_fut: None, }, /* is_cleanup */ true, ); diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index 3a0d0ce474d77..3bd5a13ed9d17 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -9,8 +9,11 @@ use rustc_middle::mir::{ use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt, TypeVisitableExt}; use super::*; +use crate::deref_separator::deref_finder; use crate::patch::MirPatch; +const SELF_ARG: Local = Local::arg(0); + pub(super) fn build_async_destructor_ctor_shim<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, @@ -39,12 +42,12 @@ pub(super) fn build_async_destructor_ctor_shim<'tcx>( } // build_drop_shim analog for async drop glue (for generated coroutine poll function) +#[tracing::instrument(level = "trace", skip(tcx), ret)] pub(super) fn build_async_drop_shim<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, ty: Ty<'tcx>, ) -> Body<'tcx> { - debug!("build_async_drop_shim(def_id={:?}, ty={:?})", def_id, ty); let ty::Coroutine(_, parent_args) = ty.kind() else { bug!(); }; @@ -75,7 +78,7 @@ pub(super) fn build_async_drop_shim<'tcx>( let source_info = SourceInfo::outermost(span); // The first argument (index 0) which will be local 1 (after the return value). - let coroutine_layout = Place::from(Local::arg(0)); + let coroutine_layout = Place::from(SELF_ARG); let coroutine_layout_dropee = tcx.mk_place_field(coroutine_layout, FieldIdx::new(0), drop_ptr_ty); @@ -93,7 +96,6 @@ pub(super) fn build_async_drop_shim<'tcx>( unwind: UnwindAction::Continue, replace: false, drop: None, - async_fut: None, } } else { TerminatorKind::Goto { target: return_block } @@ -111,45 +113,47 @@ pub(super) fn build_async_drop_shim<'tcx>( parent_args.as_coroutine().resume_ty(), ))); body.phase = MirPhase::Runtime(RuntimePhase::Initial); - if !needs_async_drop || drop_ty.references_error() { - // Returning noop body for types without `need async drop` - // (or sync Drop in case of !`need async drop` && `need drop`). - // And also for error types. - return body; - } - - let dropee_ptr = Place::from(body.local_decls.push(LocalDecl::new(drop_ptr_ty, span))); - let st_kind = StatementKind::Assign(Box::new(( - dropee_ptr, - Rvalue::Use(Operand::Move(coroutine_layout_dropee), WithRetag::Yes), - ))); - body.basic_blocks_mut()[START_BLOCK].statements.push(Statement::new(source_info, st_kind)); - let dropline = body.basic_blocks.last_index(); - - let patch = { - let mut elaborator = DropShimElaborator { - body: &body, - patch: MirPatch::new(&body), - tcx, - typing_env, - produce_async_drops: true, + // Returning noop body for types without `need async drop` + // (or sync Drop in case of !`need async drop` && `need drop`). + // And also for error types. + if needs_async_drop && !drop_ty.references_error() { + let dropee_ptr = Place::from(body.local_decls.push(LocalDecl::new(drop_ptr_ty, span))); + let st_kind = StatementKind::Assign(Box::new(( + dropee_ptr, + Rvalue::Use(Operand::Move(coroutine_layout_dropee), WithRetag::Yes), + ))); + body.basic_blocks_mut()[START_BLOCK].statements.push(Statement::new(source_info, st_kind)); + + let dropline = body.basic_blocks.last_index(); + + let patch = { + let mut elaborator = DropShimElaborator { + body: &body, + patch: MirPatch::new(&body), + tcx, + typing_env, + produce_async_drops: true, + }; + let dropee = tcx.mk_place_deref(dropee_ptr); + let resume_block = elaborator.patch.resume_block(); + elaborate_drop( + &mut elaborator, + source_info, + dropee, + (), + return_block, + Unwind::To(resume_block), + START_BLOCK, + dropline, + ); + elaborator.patch }; - let dropee = tcx.mk_place_deref(dropee_ptr); - let resume_block = elaborator.patch.resume_block(); - elaborate_drop( - &mut elaborator, - source_info, - dropee, - (), - return_block, - Unwind::To(resume_block), - START_BLOCK, - dropline, - ); - elaborator.patch - }; - patch.apply(&mut body); + patch.apply(&mut body); + } + + // We did not bother respectig deref separation, do it here. + deref_finder(tcx, &mut body, false); body } @@ -196,87 +200,85 @@ fn build_adrop_for_coroutine_shim<'tcx>( let ty::Coroutine(coroutine_def_id, impl_args) = impl_ty.kind() else { bug!("build_adrop_for_coroutine_shim not for coroutine impl type: ({:?})", instance); }; - let proxy_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, proxy_ty); - // taking _1.0 (impl from Pin) - let pin_proxy_layout_local = Local::new(1); let source_info = SourceInfo::outermost(span); - // converting `(_1: Pin<&mut CorLayout>, _2: &mut Context<'_>) -> Poll<()>` - // into `(_1: Pin<&mut ProxyLayout>, _2: &mut Context<'_>) -> Poll<()>` - // let mut _x: &mut CorLayout = &mut *_1.0.0; - // Replace old _1.0 accesses into _x accesses; let body = tcx.optimized_mir(*coroutine_def_id).future_drop_poll().unwrap(); let mut body: Body<'tcx> = EarlyBinder::bind(body.clone()).instantiate(tcx, impl_args).skip_norm_wip(); body.source.instance = instance; body.phase = MirPhase::Runtime(RuntimePhase::Initial); body.var_debug_info.clear(); + + // converting `(_1: Pin<&mut CorLayout>, _2: &mut Context<'_>) -> Poll<()>` + // into `(_1: Pin<&mut ProxyLayout>, _2: &mut Context<'_>) -> Poll<()>` + // let mut _x: &mut CorLayout = &mut *_1.0.0; + // Replace old _1.0 accesses into _x accesses; + let proxy_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, proxy_ty); + let pin_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, span)); let args = tcx.mk_args(&[proxy_ref.into()]); let pin_proxy_ref = Ty::new_adt(tcx, pin_adt_ref, args); let cor_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, impl_ty); - - let proxy_ref_local = body.local_decls.push(LocalDecl::new(proxy_ref, span)); let cor_ref_local = body.local_decls.push(LocalDecl::new(cor_ref, span)); FixProxyFutureDropVisitor { tcx, replace_to: cor_ref_local }.visit_body(&mut body); + // Now changing first arg from Pin<&mut ImplCoroutine> to Pin<&mut ProxyCoroutine> - body.local_decls[pin_proxy_layout_local] = LocalDecl::new(pin_proxy_ref, span); - - { - let mut idx: usize = 0; - // _proxy = _1.0 : Pin<&mut ProxyLayout> ==> &mut ProxyLayout - let proxy_ref_place = Place::from(pin_proxy_layout_local) - .project_deeper(&[PlaceElem::Field(FieldIdx::ZERO, proxy_ref)], tcx); - body.basic_blocks_mut()[START_BLOCK].statements.insert( - idx, - Statement::new( - source_info, - StatementKind::Assign(Box::new(( - Place::from(proxy_ref_local), - Rvalue::Use(Operand::Copy(proxy_ref_place), WithRetag::Yes), - ))), - ), - ); - idx += 1; - - // _cor_ref_tmp = (*(*_proxy).0).0... - let mut cor_ref_tmp_local = proxy_ref_local; - proxy_ty.find_async_drop_impl_coroutine(tcx, |ty| { - if ty != proxy_ty { - let ty_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty); - let impl_ptr_place = Place::from(cor_ref_tmp_local).project_deeper( - &[PlaceElem::Deref, PlaceElem::Field(FieldIdx::ZERO, ty_ref)], - tcx, - ); - cor_ref_tmp_local = body.local_decls.push(LocalDecl::new(ty_ref, span)); - body.basic_blocks_mut()[START_BLOCK].statements.insert( - idx, - Statement::new( - source_info, - StatementKind::Assign(Box::new(( - Place::from(cor_ref_tmp_local), - Rvalue::Use(Operand::Copy(impl_ptr_place), WithRetag::Yes), - ))), - ), - ); - idx += 1; - } - }); + body.local_decls[SELF_ARG] = LocalDecl::new(pin_proxy_ref, span); - // _cor_ref = cor_ref_tmp - body.basic_blocks_mut()[START_BLOCK].statements.insert( - idx, - Statement::new( - source_info, - StatementKind::Assign(Box::new(( - Place::from(cor_ref_local), - Rvalue::Use(Operand::Move(Place::from(cor_ref_tmp_local)), WithRetag::Yes), - ))), - ), - ); + // Build the projection to assign `cor_ref_local = _1.`. + let mut pin_proxy_to_cor_projection = vec![ + // _1.0 : Pin<&mut ProxyLayout> ==> &mut ProxyLayout + PlaceElem::Field(FieldIdx::ZERO, proxy_ref), + ]; + + // _cor_ref_tmp = (*(*_proxy).0).0... + proxy_ty.find_async_drop_impl_coroutine(tcx, |ty| { + if ty != proxy_ty { + let ty_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty); + pin_proxy_to_cor_projection.push(PlaceElem::Deref); + pin_proxy_to_cor_projection.push(PlaceElem::Field(FieldIdx::ZERO, ty_ref)); + } + }); + + // _cor_ref = cor_ref_tmp + let projected_pin = Place::from(SELF_ARG).project_deeper(&pin_proxy_to_cor_projection, tcx); + body.basic_blocks_mut()[START_BLOCK].statements.insert( + 0, + Statement::new( + source_info, + StatementKind::Assign(Box::new(( + Place::from(cor_ref_local), + Rvalue::Use(Operand::Move(projected_pin), WithRetag::Yes), + ))), + ), + ); + + // We did not bother respectig deref separation, do it here. + deref_finder(tcx, &mut body, false); + + return body; + + /// Replace Pin<&mut ImplCoroutine> accesses (_1.0) into Pin<&mut ProxyCoroutine> accesses + struct FixProxyFutureDropVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + replace_to: Local, + } + + impl<'tcx> MutVisitor<'tcx> for FixProxyFutureDropVisitor<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext, _: Location) { + if place.local == SELF_ARG + && let Some((first, rest)) = place.projection.split_first() + { + assert!(matches!(first, ProjectionElem::Field(FieldIdx::ZERO, _))); + *place = Place::from(self.replace_to).project_deeper(rest, self.tcx); + } + } } - body } // When dropping async drop coroutine, we continue its execution. @@ -291,9 +293,8 @@ fn build_adrop_for_adrop_shim<'tcx>( let source_info = SourceInfo::outermost(span); let proxy_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, proxy_ty); // taking _1.0 (impl from Pin) - let pin_proxy_layout_local = Local::new(1); - let proxy_ref_place = Place::from(pin_proxy_layout_local) - .project_deeper(&[PlaceElem::Field(FieldIdx::ZERO, proxy_ref)], tcx); + let proxy_ref_place = + Place::from(SELF_ARG).project_deeper(&[PlaceElem::Field(FieldIdx::ZERO, proxy_ref)], tcx); let cor_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, impl_ty); // ret_ty = `Poll<()>` diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 132dea85e4372..07709051f8ccc 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -372,6 +372,12 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.check_unwind_edge(location, *unwind); if let Some(drop) = drop { self.check_edge(location, *drop, EdgeKind::Normal); + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { + self.fail( + location, + "`async drop` should have been removed after drop elaboration", + ); + } } } TerminatorKind::Call { func, args, .. } diff --git a/compiler/rustc_public/src/unstable/convert/stable/mir.rs b/compiler/rustc_public/src/unstable/convert/stable/mir.rs index 7e76d5a91ac66..d126304af8cde 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/mir.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/mir.rs @@ -726,18 +726,13 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { mir::TerminatorKind::UnwindTerminate(_) => TerminatorKind::Abort, mir::TerminatorKind::Return => TerminatorKind::Return, mir::TerminatorKind::Unreachable => TerminatorKind::Unreachable, - mir::TerminatorKind::Drop { - place, - target, - unwind, - replace: _, - drop: _, - async_fut: _, - } => TerminatorKind::Drop { - place: place.stable(tables, cx), - target: target.as_usize(), - unwind: unwind.stable(tables, cx), - }, + mir::TerminatorKind::Drop { place, target, unwind, replace: _, drop: _ } => { + TerminatorKind::Drop { + place: place.stable(tables, cx), + target: target.as_usize(), + unwind: unwind.stable(tables, cx), + } + } mir::TerminatorKind::Call { func, args, diff --git a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir deleted file mode 100644 index 0a1cab37427c8..0000000000000 --- a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir +++ /dev/null @@ -1,100 +0,0 @@ -// MIR for `a::{closure#0}` 0 coroutine_drop_async - -fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { - debug _task_context => _2; - debug x => ((*_19).0: T); - let mut _0: std::task::Poll<()>; - let _3: T; - let mut _4: impl std::future::Future; - let mut _5: &mut T; - let mut _6: std::pin::Pin<&mut T>; - let mut _7: &mut T; - let mut _8: std::task::Poll<()>; - let mut _9: &mut std::task::Context<'_>; - let mut _10: &mut impl std::future::Future; - let mut _11: std::pin::Pin<&mut impl std::future::Future>; - let mut _12: isize; - let mut _13: &mut std::task::Context<'_>; - let mut _14: &mut impl std::future::Future; - let mut _15: std::pin::Pin<&mut impl std::future::Future>; - let mut _16: isize; - let mut _17: (); - let mut _18: u32; - let mut _19: &mut {async fn body of a()}; - scope 1 { - debug x => (((*_19) as variant#4).0: T); - } - - bb0: { - _19 = copy (_1.0: &mut {async fn body of a()}); - _18 = discriminant((*_19)); - switchInt(move _18) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14]; - } - - bb1: { - nop; - nop; - goto -> bb2; - } - - bb2: { - _0 = Poll::<()>::Ready(const ()); - return; - } - - bb3: { - _0 = Poll::<()>::Pending; - discriminant((*_19)) = 4; - return; - } - - bb4: { - StorageLive(_15); - _14 = &mut (((*_19) as variant#4).1: impl std::future::Future); - _15 = Pin::<&mut impl Future>::new_unchecked(move _14) -> [return: bb7, unwind unreachable]; - } - - bb5: { - unreachable; - } - - bb6: { - StorageDead(_15); - _16 = discriminant(_8); - switchInt(move _16) -> [0: bb1, 1: bb3, otherwise: bb5]; - } - - bb7: { - _8 = as Future>::poll(move _15, move _13) -> [return: bb6, unwind unreachable]; - } - - bb8: { - _0 = Poll::<()>::Ready(const ()); - return; - } - - bb9: { - goto -> bb11; - } - - bb10: { - goto -> bb8; - } - - bb11: { - drop(((*_19).0: T)) -> [return: bb10, unwind unreachable]; - } - - bb12: { - goto -> bb4; - } - - bb13: { - goto -> bb4; - } - - bb14: { - _0 = Poll::<()>::Ready(const ()); - return; - } -} diff --git a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir deleted file mode 100644 index 62fbf10356558..0000000000000 --- a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir +++ /dev/null @@ -1,123 +0,0 @@ -// MIR for `a::{closure#0}` 0 coroutine_drop_async - -fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { - debug _task_context => _2; - debug x => ((*_19).0: T); - let mut _0: std::task::Poll<()>; - let _3: T; - let mut _4: impl std::future::Future; - let mut _5: &mut T; - let mut _6: std::pin::Pin<&mut T>; - let mut _7: &mut T; - let mut _8: std::task::Poll<()>; - let mut _9: &mut std::task::Context<'_>; - let mut _10: &mut impl std::future::Future; - let mut _11: std::pin::Pin<&mut impl std::future::Future>; - let mut _12: isize; - let mut _13: &mut std::task::Context<'_>; - let mut _14: &mut impl std::future::Future; - let mut _15: std::pin::Pin<&mut impl std::future::Future>; - let mut _16: isize; - let mut _17: (); - let mut _18: u32; - let mut _19: &mut {async fn body of a()}; - scope 1 { - debug x => (((*_19) as variant#4).0: T); - } - - bb0: { - _19 = copy (_1.0: &mut {async fn body of a()}); - _18 = discriminant((*_19)); - switchInt(move _18) -> [0: bb12, 2: bb18, 3: bb16, 4: bb17, otherwise: bb19]; - } - - bb1: { - nop; - nop; - goto -> bb2; - } - - bb2: { - _0 = Poll::<()>::Ready(const ()); - return; - } - - bb3 (cleanup): { - nop; - nop; - goto -> bb5; - } - - bb4 (cleanup): { - goto -> bb15; - } - - bb5 (cleanup): { - goto -> bb4; - } - - bb6: { - _0 = Poll::<()>::Pending; - discriminant((*_19)) = 4; - return; - } - - bb7: { - StorageLive(_15); - _14 = &mut (((*_19) as variant#4).1: impl std::future::Future); - _15 = Pin::<&mut impl Future>::new_unchecked(move _14) -> [return: bb10, unwind: bb15]; - } - - bb8: { - unreachable; - } - - bb9: { - StorageDead(_15); - _16 = discriminant(_8); - switchInt(move _16) -> [0: bb1, 1: bb6, otherwise: bb8]; - } - - bb10: { - _8 = as Future>::poll(move _15, move _13) -> [return: bb9, unwind: bb3]; - } - - bb11: { - _0 = Poll::<()>::Ready(const ()); - return; - } - - bb12: { - goto -> bb14; - } - - bb13: { - goto -> bb11; - } - - bb14: { - drop(((*_19).0: T)) -> [return: bb13, unwind: bb4]; - } - - bb15 (cleanup): { - discriminant((*_19)) = 2; - resume; - } - - bb16: { - goto -> bb7; - } - - bb17: { - goto -> bb7; - } - - bb18: { - assert(const false, "`async fn` resumed after panicking") -> [success: bb18, unwind continue]; - } - - bb19: { - _0 = Poll::<()>::Ready(const ()); - return; - } -} diff --git a/tests/mir-opt/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir b/tests/mir-opt/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir deleted file mode 100644 index d83a51141bd40..0000000000000 --- a/tests/mir-opt/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir +++ /dev/null @@ -1,123 +0,0 @@ -// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems - -fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<[Foo; 1]>()}, _2: std::future::ResumeTy) -> () -yields () - { - let mut _0: (); - let mut _3: &mut [Foo; 1]; - let mut _4: *mut [Foo; 1]; - let mut _5: *mut [Foo]; - let mut _6: usize; - let mut _7: usize; - let mut _8: *mut Foo; - let mut _9: bool; - let mut _10: *mut Foo; - let mut _11: bool; - let mut _12: impl std::future::Future; - let mut _13: &mut Foo; - let mut _14: std::pin::Pin<&mut Foo>; - let mut _15: &mut Foo; - let mut _16: *mut Foo; - let mut _17: bool; - let mut _18: impl std::future::Future; - let mut _19: &mut Foo; - let mut _20: std::pin::Pin<&mut Foo>; - let mut _21: &mut Foo; - - bb0: { - _3 = move (_1.0: &mut [Foo; 1]); - goto -> bb17; - } - - bb1: { - return; - } - - bb2 (cleanup): { - resume; - } - - bb3 (cleanup): { - _8 = &raw mut (*_5)[_7]; - _7 = Add(move _7, const 1_usize); - drop((*_8)) -> [return: bb4, unwind terminate(cleanup)]; - } - - bb4 (cleanup): { - StorageDead(_12); - StorageDead(_18); - _9 = Eq(copy _7, copy _6); - switchInt(move _9) -> [0: bb3, otherwise: bb2]; - } - - bb5: { - _10 = &raw mut (*_5)[_7]; - _7 = Add(move _7, const 1_usize); - _13 = &mut (*_10); - _14 = Pin::<&mut Foo>::new_unchecked(move _13) -> [return: bb9, unwind: bb4]; - } - - bb6: { - StorageDead(_18); - _11 = Eq(copy _7, copy _6); - switchInt(move _11) -> [0: bb5, otherwise: bb1]; - } - - bb7: { - StorageDead(_12); - goto -> bb6; - } - - bb8: { - async drop((*_10); poll=_12) -> [return: bb7, unwind: bb4]; - } - - bb9: { - _15 = copy (_14.0: &mut Foo); - StorageLive(_12); - _12 = async_drop_in_place::(move _15) -> [return: bb8, unwind: bb4]; - } - - bb10: { - _16 = &raw mut (*_5)[_7]; - _7 = Add(move _7, const 1_usize); - _19 = &mut (*_16); - _20 = Pin::<&mut Foo>::new_unchecked(move _19) -> [return: bb14, unwind: bb4]; - } - - bb11: { - _17 = Eq(copy _7, copy _6); - switchInt(move _17) -> [0: bb10, otherwise: bb1]; - } - - bb12: { - StorageDead(_18); - goto -> bb11; - } - - bb13: { - async drop((*_16); poll=_18) -> [return: bb12, unwind: bb4, drop: bb6]; - } - - bb14: { - _21 = copy (_20.0: &mut Foo); - StorageLive(_18); - _18 = async_drop_in_place::(move _21) -> [return: bb13, unwind: bb4]; - } - - bb15: { - _6 = PtrMetadata(copy _5); - _7 = const 0_usize; - goto -> bb11; - } - - bb16: { - goto -> bb15; - } - - bb17: { - _4 = &raw mut (*_3); - _5 = move _4 as *mut [Foo] (PointerCoercion(Unsize, Implicit)); - goto -> bb16; - } -} diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir index 6cad5b105d3e3..18cab220cfa90 100644 --- a/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.a-{closure#0}.coroutine_resume.0.mir @@ -1,15 +1,14 @@ // MIR for `a::{closure#0}` 0 coroutine_resume -/* coroutine_layout = CoroutineLayout { - field_tys: {}, - variant_fields: { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - }, - storage_conflicts: BitMatrix(0x0) {}, -} */ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + } + storage_conflicts = BitMatrix(0x0) {} + } debug _task_context => _2; let mut _0: std::task::Poll<()>; let mut _3: (); diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 96ee37185db16..1dc7dc6da4d5c 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -1,56 +1,21 @@ // MIR for `b::{closure#0}` 0 coroutine_resume -/* coroutine_layout = CoroutineLayout { - field_tys: { - _s0: CoroutineSavedTy { - ty: Coroutine( - DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), - [ - (), - std::future::ResumeTy, - (), - (), - (), - ], - ), - source_info: SourceInfo { - span: $DIR/async_await.rs:16:5: 16:14 (#9), - scope: scope[0], - }, - ignore_for_traits: false, - }, - _s1: CoroutineSavedTy { - ty: Coroutine( - DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), - [ - (), - std::future::ResumeTy, - (), - (), - (), - ], - ), - source_info: SourceInfo { - span: $DIR/async_await.rs:17:5: 17:14 (#11), - scope: scope[0], - }, - ignore_for_traits: false, - }, - }, - variant_fields: { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - Suspend0 (3): [_s0], - Suspend1 (4): [_s1], - }, - storage_conflicts: BitMatrix(2x2) { - (_s0, _s0), - (_s1, _s1), - }, -} */ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + field _s0: {async fn body of a()}; + field _s1: {async fn body of a()}; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0], + Suspend1 (4): [_s1], + } + storage_conflicts = BitMatrix(2x2) {(_s0, _s0), (_s1, _s1)} + } debug _task_context => _2; + coroutine debug __awaitee => _s0; + coroutine debug __awaitee => _s1; let mut _0: std::task::Poll<()>; let _3: (); let mut _4: {async fn body of a()}; diff --git a/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir b/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir index b61215dc28cb4..e307e385d109a 100644 --- a/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir +++ b/tests/mir-opt/building/coroutine.main-{closure#0}.StateTransform.after.mir @@ -1,29 +1,19 @@ // MIR for `main::{closure#0}` after StateTransform -/* coroutine_layout = CoroutineLayout { - field_tys: { - _s0: CoroutineSavedTy { - ty: std::string::String, - source_info: SourceInfo { - span: $DIR/coroutine.rs:18:6: 18:9 (#0), - scope: scope[0], - }, - ignore_for_traits: false, - }, - }, - variant_fields: { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - Suspend0 (3): [_s0], - Suspend1 (4): [_s0], - }, - storage_conflicts: BitMatrix(1x1) { - (_s0, _s0), - }, -} */ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> { + coroutine layout { + field _s0: String; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0], + Suspend1 (4): [_s0], + } + storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} + } debug arg => (((*_18) as variant#4).0: std::string::String); + coroutine debug arg => _s0; let mut _0: std::ops::CoroutineState<(&str, std::string::String, &std::panic::Location<'_>), ()>; let _3: std::string::String; let mut _4: (&str, std::string::String, &std::panic::Location<'_>); diff --git a/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir b/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir index aac028a9e6c0e..5944c15e1883f 100644 --- a/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir +++ b/tests/mir-opt/building/coroutine.main-{closure#1}.StateTransform.after.mir @@ -1,29 +1,19 @@ // MIR for `main::{closure#1}` after StateTransform -/* coroutine_layout = CoroutineLayout { - field_tys: { - _s0: CoroutineSavedTy { - ty: std::string::String, - source_info: SourceInfo { - span: $DIR/coroutine.rs:25:6: 25:9 (#0), - scope: scope[0], - }, - ignore_for_traits: false, - }, - }, - variant_fields: { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - Suspend0 (3): [_s0], - Suspend1 (4): [_s0], - }, - storage_conflicts: BitMatrix(1x1) { - (_s0, _s0), - }, -} */ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2: String) -> CoroutineState<(&str, String, &Location<'_>), ()> { + coroutine layout { + field _s0: String; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0], + Suspend1 (4): [_s0], + } + storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} + } debug arg => (((*_18) as variant#4).0: std::string::String); + coroutine debug arg => _s0; let mut _0: std::ops::CoroutineState<(&str, std::string::String, &std::panic::Location<'_>), ()>; let _3: std::string::String; let mut _4: (&str, std::string::String, &std::panic::Location<'_>); diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir b/tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir similarity index 100% rename from tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir rename to tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir b/tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir similarity index 100% rename from tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir rename to tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.rs b/tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.rs similarity index 100% rename from tests/mir-opt/async_closure_fake_read_for_by_move.rs rename to tests/mir-opt/coroutine/async_closure_fake_read_for_by_move.rs diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir b/tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir similarity index 100% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir rename to tests/mir-opt/coroutine/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/coroutine/async_closure_shims.rs similarity index 100% rename from tests/mir-opt/async_closure_shims.rs rename to tests/mir-opt/coroutine/async_closure_shims.rs diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.MentionedItems.after.mir new file mode 100644 index 0000000000000..d0a63ff192e77 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.MentionedItems.after.mir @@ -0,0 +1,377 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems + +fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place()}, _2: std::future::ResumeTy) -> () +yields () + { + let mut _0: (); + let mut _3: &mut AsyncEnum; + let mut _4: impl std::future::Future; + let mut _5: std::future::ResumeTy; + let mut _6: std::task::Poll<()>; + let mut _7: isize; + let mut _8: std::pin::Pin<&mut impl std::future::Future>; + let mut _9: &mut std::task::Context<'_>; + let mut _10: std::future::ResumeTy; + let mut _11: &mut impl std::future::Future; + let mut _12: std::pin::Pin<&mut AsyncInt>; + let mut _13: &mut AsyncInt; + let mut _14: impl std::future::Future; + let mut _15: std::future::ResumeTy; + let mut _16: std::task::Poll<()>; + let mut _17: isize; + let mut _18: std::pin::Pin<&mut impl std::future::Future>; + let mut _19: &mut std::task::Context<'_>; + let mut _20: std::future::ResumeTy; + let mut _21: &mut impl std::future::Future; + let mut _22: std::future::ResumeTy; + let mut _23: std::task::Poll<()>; + let mut _24: isize; + let mut _25: std::pin::Pin<&mut impl std::future::Future>; + let mut _26: &mut std::task::Context<'_>; + let mut _27: std::future::ResumeTy; + let mut _28: &mut impl std::future::Future; + let mut _29: std::pin::Pin<&mut AsyncInt>; + let mut _30: &mut AsyncInt; + let mut _31: isize; + let mut _32: isize; + let mut _33: isize; + let mut _34: impl std::future::Future; + let mut _35: std::future::ResumeTy; + let mut _36: std::task::Poll<()>; + let mut _37: isize; + let mut _38: std::pin::Pin<&mut impl std::future::Future>; + let mut _39: &mut std::task::Context<'_>; + let mut _40: std::future::ResumeTy; + let mut _41: &mut impl std::future::Future; + let mut _42: std::future::ResumeTy; + let mut _43: std::task::Poll<()>; + let mut _44: isize; + let mut _45: std::pin::Pin<&mut impl std::future::Future>; + let mut _46: &mut std::task::Context<'_>; + let mut _47: std::future::ResumeTy; + let mut _48: &mut impl std::future::Future; + let mut _49: std::pin::Pin<&mut AsyncEnum>; + let mut _50: &mut AsyncEnum; + + bb0: { + _3 = move (_1.0: &mut AsyncEnum); + goto -> bb65; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { + goto -> bb1; + } + + bb4 (cleanup): { + drop((((*_3) as A).0: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)]; + } + + bb5 (cleanup): { + drop((((*_3) as A).0: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)]; + } + + bb6: { + StorageDead(_4); + goto -> bb1; + } + + bb7 (cleanup): { + StorageDead(_4); + goto -> bb2; + } + + bb8: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb8, unwind: bb7]; + } + + bb9: { + _2 = move _5; + StorageDead(_5); + goto -> bb8; + } + + bb10: { + _2 = move _5; + StorageDead(_5); + goto -> bb16; + } + + bb11: { + StorageLive(_5); + _5 = yield(const ()) -> [resume: bb9, drop: bb10]; + } + + bb12: { + unreachable; + } + + bb13: { + _7 = discriminant(_6); + switchInt(move _7) -> [0: bb6, 1: bb11, otherwise: bb12]; + } + + bb14: { + _6 = as Future>::poll(move _8, move _9) -> [return: bb13, unwind: bb7]; + } + + bb15: { + _10 = move _2; + _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb14, unwind: bb7]; + } + + bb16: { + _11 = &mut _4; + _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb15, unwind: bb7]; + } + + bb17: { + StorageLive(_4); + _4 = async_drop_in_place::(copy (_12.0: &mut AsyncInt)) -> [return: bb16, unwind: bb7]; + } + + bb18: { + _13 = &mut (((*_3) as A).0: AsyncInt); + _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb17, unwind: bb2]; + } + + bb19: { + StorageDead(_14); + goto -> bb3; + } + + bb20: { + StorageDead(_14); + goto -> bb1; + } + + bb21 (cleanup): { + StorageDead(_14); + goto -> bb2; + } + + bb22: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb22, unwind: bb21]; + } + + bb23: { + _2 = move _15; + StorageDead(_15); + goto -> bb22; + } + + bb24: { + _2 = move _15; + StorageDead(_15); + goto -> bb29; + } + + bb25: { + StorageLive(_15); + _15 = yield(const ()) -> [resume: bb23, drop: bb24]; + } + + bb26: { + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb20, 1: bb25, otherwise: bb12]; + } + + bb27: { + _16 = as Future>::poll(move _18, move _19) -> [return: bb26, unwind: bb21]; + } + + bb28: { + _20 = move _2; + _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb27, unwind: bb21]; + } + + bb29: { + _21 = &mut _14; + _18 = Pin::<&mut impl Future>::new_unchecked(move _21) -> [return: bb28, unwind: bb21]; + } + + bb30: { + _2 = move _22; + StorageDead(_22); + goto -> bb36; + } + + bb31: { + _2 = move _22; + StorageDead(_22); + goto -> bb29; + } + + bb32: { + StorageLive(_22); + _22 = yield(const ()) -> [resume: bb30, drop: bb31]; + } + + bb33: { + _24 = discriminant(_23); + switchInt(move _24) -> [0: bb19, 1: bb32, otherwise: bb12]; + } + + bb34: { + _23 = as Future>::poll(move _25, move _26) -> [return: bb33, unwind: bb21]; + } + + bb35: { + _27 = move _2; + _26 = std::future::get_context::<'_, '_>(move _27) -> [return: bb34, unwind: bb21]; + } + + bb36: { + _28 = &mut _14; + _25 = Pin::<&mut impl Future>::new_unchecked(move _28) -> [return: bb35, unwind: bb21]; + } + + bb37: { + StorageLive(_14); + _14 = async_drop_in_place::(copy (_29.0: &mut AsyncInt)) -> [return: bb36, unwind: bb21]; + } + + bb38: { + _30 = &mut (((*_3) as A).0: AsyncInt); + _29 = Pin::<&mut AsyncInt>::new_unchecked(move _30) -> [return: bb37, unwind: bb2]; + } + + bb39 (cleanup): { + drop((((*_3) as B).0: SyncInt)) -> [return: bb2, unwind terminate(cleanup)]; + } + + bb40 (cleanup): { + drop((((*_3) as B).0: SyncInt)) -> [return: bb2, unwind terminate(cleanup)]; + } + + bb41: { + drop((((*_3) as B).0: SyncInt)) -> [return: bb1, unwind: bb2]; + } + + bb42: { + drop((((*_3) as B).0: SyncInt)) -> [return: bb3, unwind: bb2]; + } + + bb43: { + _31 = discriminant((*_3)); + switchInt(move _31) -> [0: bb38, otherwise: bb42]; + } + + bb44 (cleanup): { + _32 = discriminant((*_3)); + switchInt(move _32) -> [0: bb4, otherwise: bb39]; + } + + bb45: { + _33 = discriminant((*_3)); + switchInt(move _33) -> [0: bb18, otherwise: bb41]; + } + + bb46: { + StorageDead(_34); + goto -> bb43; + } + + bb47: { + StorageDead(_34); + goto -> bb45; + } + + bb48 (cleanup): { + StorageDead(_34); + goto -> bb44; + } + + bb49: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb49, unwind: bb48]; + } + + bb50: { + _2 = move _35; + StorageDead(_35); + goto -> bb49; + } + + bb51: { + _2 = move _35; + StorageDead(_35); + goto -> bb56; + } + + bb52: { + StorageLive(_35); + _35 = yield(const ()) -> [resume: bb50, drop: bb51]; + } + + bb53: { + _37 = discriminant(_36); + switchInt(move _37) -> [0: bb47, 1: bb52, otherwise: bb12]; + } + + bb54: { + _36 = as Future>::poll(move _38, move _39) -> [return: bb53, unwind: bb48]; + } + + bb55: { + _40 = move _2; + _39 = std::future::get_context::<'_, '_>(move _40) -> [return: bb54, unwind: bb48]; + } + + bb56: { + _41 = &mut _34; + _38 = Pin::<&mut impl Future>::new_unchecked(move _41) -> [return: bb55, unwind: bb48]; + } + + bb57: { + _2 = move _42; + StorageDead(_42); + goto -> bb63; + } + + bb58: { + _2 = move _42; + StorageDead(_42); + goto -> bb56; + } + + bb59: { + StorageLive(_42); + _42 = yield(const ()) -> [resume: bb57, drop: bb58]; + } + + bb60: { + _44 = discriminant(_43); + switchInt(move _44) -> [0: bb46, 1: bb59, otherwise: bb12]; + } + + bb61: { + _43 = as Future>::poll(move _45, move _46) -> [return: bb60, unwind: bb48]; + } + + bb62: { + _47 = move _2; + _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb61, unwind: bb48]; + } + + bb63: { + _48 = &mut _34; + _45 = Pin::<&mut impl Future>::new_unchecked(move _48) -> [return: bb62, unwind: bb48]; + } + + bb64: { + StorageLive(_34); + _34 = ::drop(move _49) -> [return: bb63, unwind: bb48]; + } + + bb65: { + _50 = &mut (*_3); + _49 = Pin::<&mut AsyncEnum>::new_unchecked(move _50) -> [return: bb64, unwind: bb44]; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.StateTransform.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.StateTransform.after.mir new file mode 100644 index 0000000000000..0a02f57c14df9 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.StateTransform.after.mir @@ -0,0 +1,313 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform + +fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + field _s0: &mut AsyncEnum; + field _s1: impl Future; + field _s2: impl Future; + field _s3: impl Future; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s1], + Suspend1 (4): [_s2], + Suspend2 (5): [_s2], + Suspend3 (6): [_s0, _s3], + Suspend4 (7): [_s0, _s3], + } + storage_conflicts = BitMatrix(4x4) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s1, _s0), (_s1, _s1), (_s2, _s0), (_s2, _s2), (_s3, _s0), (_s3, _s3)} + } + let mut _0: std::task::Poll<()>; + let mut _3: &mut AsyncEnum; + let mut _4: impl std::future::Future; + let mut _5: &mut std::task::Context<'_>; + let mut _6: std::task::Poll<()>; + let mut _7: isize; + let mut _8: std::pin::Pin<&mut impl std::future::Future>; + let mut _9: &mut std::task::Context<'_>; + let mut _10: &mut std::task::Context<'_>; + let mut _11: &mut impl std::future::Future; + let mut _12: std::pin::Pin<&mut AsyncInt>; + let mut _13: &mut AsyncInt; + let mut _14: impl std::future::Future; + let mut _15: &mut std::task::Context<'_>; + let mut _16: std::task::Poll<()>; + let mut _17: isize; + let mut _18: std::pin::Pin<&mut impl std::future::Future>; + let mut _19: &mut std::task::Context<'_>; + let mut _20: &mut std::task::Context<'_>; + let mut _21: &mut impl std::future::Future; + let mut _22: &mut std::task::Context<'_>; + let mut _23: std::task::Poll<()>; + let mut _24: isize; + let mut _25: std::pin::Pin<&mut impl std::future::Future>; + let mut _26: &mut std::task::Context<'_>; + let mut _27: &mut std::task::Context<'_>; + let mut _28: &mut impl std::future::Future; + let mut _29: std::pin::Pin<&mut AsyncInt>; + let mut _30: &mut AsyncInt; + let mut _31: isize; + let mut _32: isize; + let mut _33: isize; + let mut _34: impl std::future::Future; + let mut _35: &mut std::task::Context<'_>; + let mut _36: std::task::Poll<()>; + let mut _37: isize; + let mut _38: std::pin::Pin<&mut impl std::future::Future>; + let mut _39: &mut std::task::Context<'_>; + let mut _40: &mut std::task::Context<'_>; + let mut _41: &mut impl std::future::Future; + let mut _42: &mut std::task::Context<'_>; + let mut _43: std::task::Poll<()>; + let mut _44: isize; + let mut _45: std::pin::Pin<&mut impl std::future::Future>; + let mut _46: &mut std::task::Context<'_>; + let mut _47: &mut std::task::Context<'_>; + let mut _48: &mut impl std::future::Future; + let mut _49: std::pin::Pin<&mut AsyncEnum>; + let mut _50: &mut AsyncEnum; + let mut _51: (); + let mut _52: u32; + let mut _53: &mut {async fn body of std::future::async_drop_in_place()}; + let mut _54: &mut AsyncEnum; + let mut _55: &mut AsyncEnum; + let mut _56: &mut AsyncEnum; + let mut _57: &mut AsyncEnum; + let mut _58: &mut AsyncEnum; + let mut _59: &mut AsyncEnum; + let mut _60: &mut AsyncEnum; + + bb0: { + _53 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place()}); + _52 = discriminant((*_53)); + switchInt(move _52) -> [0: bb1, 1: bb42, 2: bb41, 3: bb36, 4: bb37, 5: bb38, 6: bb39, 7: bb40, otherwise: bb8]; + } + + bb1: { + (((*_53) as variant#7).0: &mut AsyncEnum) = move ((*_53).0: &mut AsyncEnum); + _54 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum); + _50 = &mut (*_54); + _49 = Pin::<&mut AsyncEnum>::new_unchecked(move _50) -> [return: bb34, unwind: bb23]; + } + + bb2: { + _0 = Poll::<()>::Ready(move _51); + discriminant((*_53)) = 1; + return; + } + + bb3 (cleanup): { + goto -> bb35; + } + + bb4 (cleanup): { + _55 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum); + drop((((*_55) as A).0: AsyncInt)) -> [return: bb3, unwind terminate(cleanup)]; + } + + bb5 (cleanup): { + nop; + goto -> bb3; + } + + bb6: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb6, unwind: bb5]; + } + + bb7: { + _2 = move _5; + StorageDead(_5); + goto -> bb6; + } + + bb8: { + unreachable; + } + + bb9: { + nop; + goto -> bb2; + } + + bb10 (cleanup): { + nop; + goto -> bb3; + } + + bb11: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb11, unwind: bb10]; + } + + bb12: { + _2 = move _15; + StorageDead(_15); + goto -> bb11; + } + + bb13: { + _2 = move _22; + StorageDead(_22); + goto -> bb18; + } + + bb14: { + StorageLive(_22); + _0 = Poll::<()>::Pending; + StorageDead(_22); + discriminant((*_53)) = 5; + return; + } + + bb15: { + _24 = discriminant(_23); + switchInt(move _24) -> [0: bb9, 1: bb14, otherwise: bb8]; + } + + bb16: { + _23 = as Future>::poll(move _25, move _26) -> [return: bb15, unwind: bb10]; + } + + bb17: { + _27 = move _2; + _26 = move _27; + goto -> bb16; + } + + bb18: { + _28 = &mut (((*_53) as variant#5).0: impl std::future::Future); + _25 = Pin::<&mut impl Future>::new_unchecked(move _28) -> [return: bb17, unwind: bb10]; + } + + bb19: { + nop; + (((*_53) as variant#5).0: impl std::future::Future) = async_drop_in_place::(copy (_29.0: &mut AsyncInt)) -> [return: bb18, unwind: bb10]; + } + + bb20: { + _56 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum); + _30 = &mut (((*_56) as A).0: AsyncInt); + _29 = Pin::<&mut AsyncInt>::new_unchecked(move _30) -> [return: bb19, unwind: bb3]; + } + + bb21 (cleanup): { + _57 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum); + drop((((*_57) as B).0: SyncInt)) -> [return: bb3, unwind terminate(cleanup)]; + } + + bb22: { + _58 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum); + drop((((*_58) as B).0: SyncInt)) -> [return: bb2, unwind: bb3]; + } + + bb23 (cleanup): { + _59 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum); + _32 = discriminant((*_59)); + switchInt(move _32) -> [0: bb4, otherwise: bb21]; + } + + bb24: { + nop; + _60 = no_retag copy (((*_53) as variant#7).0: &mut AsyncEnum); + _31 = discriminant((*_60)); + switchInt(move _31) -> [0: bb20, otherwise: bb22]; + } + + bb25 (cleanup): { + nop; + goto -> bb23; + } + + bb26: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb26, unwind: bb25]; + } + + bb27: { + _2 = move _35; + StorageDead(_35); + goto -> bb26; + } + + bb28: { + _2 = move _42; + StorageDead(_42); + goto -> bb33; + } + + bb29: { + StorageLive(_42); + _0 = Poll::<()>::Pending; + StorageDead(_42); + discriminant((*_53)) = 7; + return; + } + + bb30: { + _44 = discriminant(_43); + switchInt(move _44) -> [0: bb24, 1: bb29, otherwise: bb8]; + } + + bb31: { + _43 = as Future>::poll(move _45, move _46) -> [return: bb30, unwind: bb25]; + } + + bb32: { + _47 = move _2; + _46 = move _47; + goto -> bb31; + } + + bb33: { + _48 = &mut (((*_53) as variant#7).1: impl std::future::Future); + _45 = Pin::<&mut impl Future>::new_unchecked(move _48) -> [return: bb32, unwind: bb25]; + } + + bb34: { + nop; + (((*_53) as variant#7).1: impl std::future::Future) = ::drop(move _49) -> [return: bb33, unwind: bb25]; + } + + bb35 (cleanup): { + discriminant((*_53)) = 2; + resume; + } + + bb36: { + StorageLive(_5); + _5 = move _2; + goto -> bb7; + } + + bb37: { + StorageLive(_15); + _15 = move _2; + goto -> bb12; + } + + bb38: { + StorageLive(_22); + _22 = move _2; + goto -> bb13; + } + + bb39: { + StorageLive(_35); + _35 = move _2; + goto -> bb27; + } + + bb40: { + StorageLive(_42); + _42 = move _2; + goto -> bb28; + } + + bb41: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb41, unwind continue]; + } + + bb42: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.MentionedItems.after.mir new file mode 100644 index 0000000000000..da6f0f8015be8 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.MentionedItems.after.mir @@ -0,0 +1,147 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems + +fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place()}, _2: std::future::ResumeTy) -> () +yields () + { + let mut _0: (); + let mut _3: &mut AsyncInt; + let mut _4: impl std::future::Future; + let mut _5: std::future::ResumeTy; + let mut _6: std::task::Poll<()>; + let mut _7: isize; + let mut _8: std::pin::Pin<&mut impl std::future::Future>; + let mut _9: &mut std::task::Context<'_>; + let mut _10: std::future::ResumeTy; + let mut _11: &mut impl std::future::Future; + let mut _12: std::future::ResumeTy; + let mut _13: std::task::Poll<()>; + let mut _14: isize; + let mut _15: std::pin::Pin<&mut impl std::future::Future>; + let mut _16: &mut std::task::Context<'_>; + let mut _17: std::future::ResumeTy; + let mut _18: &mut impl std::future::Future; + let mut _19: std::pin::Pin<&mut AsyncInt>; + let mut _20: &mut AsyncInt; + + bb0: { + _3 = move (_1.0: &mut AsyncInt); + goto -> bb24; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { + goto -> bb1; + } + + bb4: { + StorageDead(_4); + goto -> bb3; + } + + bb5: { + StorageDead(_4); + goto -> bb1; + } + + bb6 (cleanup): { + StorageDead(_4); + goto -> bb2; + } + + bb7: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb7, unwind: bb6]; + } + + bb8: { + _2 = move _5; + StorageDead(_5); + goto -> bb7; + } + + bb9: { + _2 = move _5; + StorageDead(_5); + goto -> bb15; + } + + bb10: { + StorageLive(_5); + _5 = yield(const ()) -> [resume: bb8, drop: bb9]; + } + + bb11: { + unreachable; + } + + bb12: { + _7 = discriminant(_6); + switchInt(move _7) -> [0: bb5, 1: bb10, otherwise: bb11]; + } + + bb13: { + _6 = as Future>::poll(move _8, move _9) -> [return: bb12, unwind: bb6]; + } + + bb14: { + _10 = move _2; + _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb13, unwind: bb6]; + } + + bb15: { + _11 = &mut _4; + _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb14, unwind: bb6]; + } + + bb16: { + _2 = move _12; + StorageDead(_12); + goto -> bb22; + } + + bb17: { + _2 = move _12; + StorageDead(_12); + goto -> bb15; + } + + bb18: { + StorageLive(_12); + _12 = yield(const ()) -> [resume: bb16, drop: bb17]; + } + + bb19: { + _14 = discriminant(_13); + switchInt(move _14) -> [0: bb4, 1: bb18, otherwise: bb11]; + } + + bb20: { + _13 = as Future>::poll(move _15, move _16) -> [return: bb19, unwind: bb6]; + } + + bb21: { + _17 = move _2; + _16 = std::future::get_context::<'_, '_>(move _17) -> [return: bb20, unwind: bb6]; + } + + bb22: { + _18 = &mut _4; + _15 = Pin::<&mut impl Future>::new_unchecked(move _18) -> [return: bb21, unwind: bb6]; + } + + bb23: { + StorageLive(_4); + _4 = ::drop(move _19) -> [return: bb22, unwind: bb6]; + } + + bb24: { + _20 = &mut (*_3); + _19 = Pin::<&mut AsyncInt>::new_unchecked(move _20) -> [return: bb23, unwind: bb2]; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.StateTransform.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.StateTransform.after.mir new file mode 100644 index 0000000000000..49b8b1e3cd369 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.StateTransform.after.mir @@ -0,0 +1,148 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform + +fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + field _s0: impl Future; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0], + Suspend1 (4): [_s0], + } + storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} + } + let mut _0: std::task::Poll<()>; + let mut _3: &mut AsyncInt; + let mut _4: impl std::future::Future; + let mut _5: &mut std::task::Context<'_>; + let mut _6: std::task::Poll<()>; + let mut _7: isize; + let mut _8: std::pin::Pin<&mut impl std::future::Future>; + let mut _9: &mut std::task::Context<'_>; + let mut _10: &mut std::task::Context<'_>; + let mut _11: &mut impl std::future::Future; + let mut _12: &mut std::task::Context<'_>; + let mut _13: std::task::Poll<()>; + let mut _14: isize; + let mut _15: std::pin::Pin<&mut impl std::future::Future>; + let mut _16: &mut std::task::Context<'_>; + let mut _17: &mut std::task::Context<'_>; + let mut _18: &mut impl std::future::Future; + let mut _19: std::pin::Pin<&mut AsyncInt>; + let mut _20: &mut AsyncInt; + let mut _21: (); + let mut _22: u32; + let mut _23: &mut {async fn body of std::future::async_drop_in_place()}; + + bb0: { + _23 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place()}); + _22 = discriminant((*_23)); + switchInt(move _22) -> [0: bb1, 1: bb20, 2: bb19, 3: bb17, 4: bb18, otherwise: bb8]; + } + + bb1: { + _3 = move ((*_23).0: &mut AsyncInt); + _20 = &mut (*_3); + _19 = Pin::<&mut AsyncInt>::new_unchecked(move _20) -> [return: bb15, unwind: bb3]; + } + + bb2: { + _0 = Poll::<()>::Ready(move _21); + discriminant((*_23)) = 1; + return; + } + + bb3 (cleanup): { + goto -> bb16; + } + + bb4: { + nop; + goto -> bb2; + } + + bb5 (cleanup): { + nop; + goto -> bb3; + } + + bb6: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb6, unwind: bb5]; + } + + bb7: { + _2 = move _5; + StorageDead(_5); + goto -> bb6; + } + + bb8: { + unreachable; + } + + bb9: { + _2 = move _12; + StorageDead(_12); + goto -> bb14; + } + + bb10: { + StorageLive(_12); + _0 = Poll::<()>::Pending; + StorageDead(_12); + discriminant((*_23)) = 4; + return; + } + + bb11: { + _14 = discriminant(_13); + switchInt(move _14) -> [0: bb4, 1: bb10, otherwise: bb8]; + } + + bb12: { + _13 = as Future>::poll(move _15, move _16) -> [return: bb11, unwind: bb5]; + } + + bb13: { + _17 = move _2; + _16 = move _17; + goto -> bb12; + } + + bb14: { + _18 = &mut (((*_23) as variant#4).0: impl std::future::Future); + _15 = Pin::<&mut impl Future>::new_unchecked(move _18) -> [return: bb13, unwind: bb5]; + } + + bb15: { + nop; + (((*_23) as variant#4).0: impl std::future::Future) = ::drop(move _19) -> [return: bb14, unwind: bb5]; + } + + bb16 (cleanup): { + discriminant((*_23)) = 2; + resume; + } + + bb17: { + StorageLive(_5); + _5 = move _2; + goto -> bb7; + } + + bb18: { + StorageLive(_12); + _12 = move _2; + goto -> bb9; + } + + bb19: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb19, unwind continue]; + } + + bb20: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.MentionedItems.after.mir new file mode 100644 index 0000000000000..bfb1aed61659a --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.MentionedItems.after.mir @@ -0,0 +1,147 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems + +fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place>()}, _2: std::future::ResumeTy) -> () +yields () + { + let mut _0: (); + let mut _3: &mut AsyncReference<'_>; + let mut _4: impl std::future::Future; + let mut _5: std::future::ResumeTy; + let mut _6: std::task::Poll<()>; + let mut _7: isize; + let mut _8: std::pin::Pin<&mut impl std::future::Future>; + let mut _9: &mut std::task::Context<'_>; + let mut _10: std::future::ResumeTy; + let mut _11: &mut impl std::future::Future; + let mut _12: std::future::ResumeTy; + let mut _13: std::task::Poll<()>; + let mut _14: isize; + let mut _15: std::pin::Pin<&mut impl std::future::Future>; + let mut _16: &mut std::task::Context<'_>; + let mut _17: std::future::ResumeTy; + let mut _18: &mut impl std::future::Future; + let mut _19: std::pin::Pin<&mut AsyncReference<'_>>; + let mut _20: &mut AsyncReference<'_>; + + bb0: { + _3 = move (_1.0: &mut AsyncReference<'_>); + goto -> bb24; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { + goto -> bb1; + } + + bb4: { + StorageDead(_4); + goto -> bb3; + } + + bb5: { + StorageDead(_4); + goto -> bb1; + } + + bb6 (cleanup): { + StorageDead(_4); + goto -> bb2; + } + + bb7: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb7, unwind: bb6]; + } + + bb8: { + _2 = move _5; + StorageDead(_5); + goto -> bb7; + } + + bb9: { + _2 = move _5; + StorageDead(_5); + goto -> bb15; + } + + bb10: { + StorageLive(_5); + _5 = yield(const ()) -> [resume: bb8, drop: bb9]; + } + + bb11: { + unreachable; + } + + bb12: { + _7 = discriminant(_6); + switchInt(move _7) -> [0: bb5, 1: bb10, otherwise: bb11]; + } + + bb13: { + _6 = as Future>::poll(move _8, move _9) -> [return: bb12, unwind: bb6]; + } + + bb14: { + _10 = move _2; + _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb13, unwind: bb6]; + } + + bb15: { + _11 = &mut _4; + _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb14, unwind: bb6]; + } + + bb16: { + _2 = move _12; + StorageDead(_12); + goto -> bb22; + } + + bb17: { + _2 = move _12; + StorageDead(_12); + goto -> bb15; + } + + bb18: { + StorageLive(_12); + _12 = yield(const ()) -> [resume: bb16, drop: bb17]; + } + + bb19: { + _14 = discriminant(_13); + switchInt(move _14) -> [0: bb4, 1: bb18, otherwise: bb11]; + } + + bb20: { + _13 = as Future>::poll(move _15, move _16) -> [return: bb19, unwind: bb6]; + } + + bb21: { + _17 = move _2; + _16 = std::future::get_context::<'_, '_>(move _17) -> [return: bb20, unwind: bb6]; + } + + bb22: { + _18 = &mut _4; + _15 = Pin::<&mut impl Future>::new_unchecked(move _18) -> [return: bb21, unwind: bb6]; + } + + bb23: { + StorageLive(_4); + _4 = as AsyncDrop>::drop(move _19) -> [return: bb22, unwind: bb6]; + } + + bb24: { + _20 = &mut (*_3); + _19 = Pin::<&mut AsyncReference<'_>>::new_unchecked(move _20) -> [return: bb23, unwind: bb2]; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.StateTransform.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.StateTransform.after.mir new file mode 100644 index 0000000000000..bca20e944ab55 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.StateTransform.after.mir @@ -0,0 +1,148 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform + +fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place>()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + field _s0: impl Future; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0], + Suspend1 (4): [_s0], + } + storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} + } + let mut _0: std::task::Poll<()>; + let mut _3: &mut AsyncReference<'_>; + let mut _4: impl std::future::Future; + let mut _5: &mut std::task::Context<'_>; + let mut _6: std::task::Poll<()>; + let mut _7: isize; + let mut _8: std::pin::Pin<&mut impl std::future::Future>; + let mut _9: &mut std::task::Context<'_>; + let mut _10: &mut std::task::Context<'_>; + let mut _11: &mut impl std::future::Future; + let mut _12: &mut std::task::Context<'_>; + let mut _13: std::task::Poll<()>; + let mut _14: isize; + let mut _15: std::pin::Pin<&mut impl std::future::Future>; + let mut _16: &mut std::task::Context<'_>; + let mut _17: &mut std::task::Context<'_>; + let mut _18: &mut impl std::future::Future; + let mut _19: std::pin::Pin<&mut AsyncReference<'_>>; + let mut _20: &mut AsyncReference<'_>; + let mut _21: (); + let mut _22: u32; + let mut _23: &mut {async fn body of std::future::async_drop_in_place>()}; + + bb0: { + _23 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place>()}); + _22 = discriminant((*_23)); + switchInt(move _22) -> [0: bb1, 1: bb20, 2: bb19, 3: bb17, 4: bb18, otherwise: bb8]; + } + + bb1: { + _3 = move ((*_23).0: &mut AsyncReference<'_>); + _20 = &mut (*_3); + _19 = Pin::<&mut AsyncReference<'_>>::new_unchecked(move _20) -> [return: bb15, unwind: bb3]; + } + + bb2: { + _0 = Poll::<()>::Ready(move _21); + discriminant((*_23)) = 1; + return; + } + + bb3 (cleanup): { + goto -> bb16; + } + + bb4: { + nop; + goto -> bb2; + } + + bb5 (cleanup): { + nop; + goto -> bb3; + } + + bb6: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb6, unwind: bb5]; + } + + bb7: { + _2 = move _5; + StorageDead(_5); + goto -> bb6; + } + + bb8: { + unreachable; + } + + bb9: { + _2 = move _12; + StorageDead(_12); + goto -> bb14; + } + + bb10: { + StorageLive(_12); + _0 = Poll::<()>::Pending; + StorageDead(_12); + discriminant((*_23)) = 4; + return; + } + + bb11: { + _14 = discriminant(_13); + switchInt(move _14) -> [0: bb4, 1: bb10, otherwise: bb8]; + } + + bb12: { + _13 = as Future>::poll(move _15, move _16) -> [return: bb11, unwind: bb5]; + } + + bb13: { + _17 = move _2; + _16 = move _17; + goto -> bb12; + } + + bb14: { + _18 = &mut (((*_23) as variant#4).0: impl std::future::Future); + _15 = Pin::<&mut impl Future>::new_unchecked(move _18) -> [return: bb13, unwind: bb5]; + } + + bb15: { + nop; + (((*_23) as variant#4).0: impl std::future::Future) = as AsyncDrop>::drop(move _19) -> [return: bb14, unwind: bb5]; + } + + bb16 (cleanup): { + discriminant((*_23)) = 2; + resume; + } + + bb17: { + StorageLive(_5); + _5 = move _2; + goto -> bb7; + } + + bb18: { + StorageLive(_12); + _12 = move _2; + goto -> bb9; + } + + bb19: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb19, unwind continue]; + } + + bb20: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.MentionedItems.after.mir new file mode 100644 index 0000000000000..3a42ae5a1534e --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.MentionedItems.after.mir @@ -0,0 +1,531 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems + +fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place()}, _2: std::future::ResumeTy) -> () +yields () + { + let mut _0: (); + let mut _3: &mut AsyncStruct; + let mut _4: impl std::future::Future; + let mut _5: std::future::ResumeTy; + let mut _6: std::task::Poll<()>; + let mut _7: isize; + let mut _8: std::pin::Pin<&mut impl std::future::Future>; + let mut _9: &mut std::task::Context<'_>; + let mut _10: std::future::ResumeTy; + let mut _11: &mut impl std::future::Future; + let mut _12: std::pin::Pin<&mut AsyncInt>; + let mut _13: &mut AsyncInt; + let mut _14: impl std::future::Future; + let mut _15: std::future::ResumeTy; + let mut _16: std::task::Poll<()>; + let mut _17: isize; + let mut _18: std::pin::Pin<&mut impl std::future::Future>; + let mut _19: &mut std::task::Context<'_>; + let mut _20: std::future::ResumeTy; + let mut _21: &mut impl std::future::Future; + let mut _22: std::pin::Pin<&mut AsyncInt>; + let mut _23: &mut AsyncInt; + let mut _24: impl std::future::Future; + let mut _25: std::future::ResumeTy; + let mut _26: std::task::Poll<()>; + let mut _27: isize; + let mut _28: std::pin::Pin<&mut impl std::future::Future>; + let mut _29: &mut std::task::Context<'_>; + let mut _30: std::future::ResumeTy; + let mut _31: &mut impl std::future::Future; + let mut _32: std::future::ResumeTy; + let mut _33: std::task::Poll<()>; + let mut _34: isize; + let mut _35: std::pin::Pin<&mut impl std::future::Future>; + let mut _36: &mut std::task::Context<'_>; + let mut _37: std::future::ResumeTy; + let mut _38: &mut impl std::future::Future; + let mut _39: std::pin::Pin<&mut AsyncInt>; + let mut _40: &mut AsyncInt; + let mut _41: impl std::future::Future; + let mut _42: std::future::ResumeTy; + let mut _43: std::task::Poll<()>; + let mut _44: isize; + let mut _45: std::pin::Pin<&mut impl std::future::Future>; + let mut _46: &mut std::task::Context<'_>; + let mut _47: std::future::ResumeTy; + let mut _48: &mut impl std::future::Future; + let mut _49: std::future::ResumeTy; + let mut _50: std::task::Poll<()>; + let mut _51: isize; + let mut _52: std::pin::Pin<&mut impl std::future::Future>; + let mut _53: &mut std::task::Context<'_>; + let mut _54: std::future::ResumeTy; + let mut _55: &mut impl std::future::Future; + let mut _56: std::pin::Pin<&mut AsyncInt>; + let mut _57: &mut AsyncInt; + let mut _58: impl std::future::Future; + let mut _59: std::future::ResumeTy; + let mut _60: std::task::Poll<()>; + let mut _61: isize; + let mut _62: std::pin::Pin<&mut impl std::future::Future>; + let mut _63: &mut std::task::Context<'_>; + let mut _64: std::future::ResumeTy; + let mut _65: &mut impl std::future::Future; + let mut _66: std::future::ResumeTy; + let mut _67: std::task::Poll<()>; + let mut _68: isize; + let mut _69: std::pin::Pin<&mut impl std::future::Future>; + let mut _70: &mut std::task::Context<'_>; + let mut _71: std::future::ResumeTy; + let mut _72: &mut impl std::future::Future; + let mut _73: std::pin::Pin<&mut AsyncStruct>; + let mut _74: &mut AsyncStruct; + + bb0: { + _3 = move (_1.0: &mut AsyncStruct); + goto -> bb90; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { + goto -> bb1; + } + + bb4 (cleanup): { + drop(((*_3).2: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)]; + } + + bb5 (cleanup): { + drop(((*_3).1: AsyncInt)) -> [return: bb4, unwind terminate(cleanup)]; + } + + bb6: { + StorageDead(_4); + goto -> bb1; + } + + bb7 (cleanup): { + StorageDead(_4); + goto -> bb2; + } + + bb8: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb8, unwind: bb7]; + } + + bb9: { + _2 = move _5; + StorageDead(_5); + goto -> bb8; + } + + bb10: { + _2 = move _5; + StorageDead(_5); + goto -> bb16; + } + + bb11: { + StorageLive(_5); + _5 = yield(const ()) -> [resume: bb9, drop: bb10]; + } + + bb12: { + unreachable; + } + + bb13: { + _7 = discriminant(_6); + switchInt(move _7) -> [0: bb6, 1: bb11, otherwise: bb12]; + } + + bb14: { + _6 = as Future>::poll(move _8, move _9) -> [return: bb13, unwind: bb7]; + } + + bb15: { + _10 = move _2; + _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb14, unwind: bb7]; + } + + bb16: { + _11 = &mut _4; + _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb15, unwind: bb7]; + } + + bb17: { + StorageLive(_4); + _4 = async_drop_in_place::(copy (_12.0: &mut AsyncInt)) -> [return: bb16, unwind: bb7]; + } + + bb18: { + _13 = &mut ((*_3).2: AsyncInt); + _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb17, unwind: bb2]; + } + + bb19: { + StorageDead(_14); + goto -> bb18; + } + + bb20 (cleanup): { + StorageDead(_14); + goto -> bb4; + } + + bb21: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb21, unwind: bb20]; + } + + bb22: { + _2 = move _15; + StorageDead(_15); + goto -> bb21; + } + + bb23: { + _2 = move _15; + StorageDead(_15); + goto -> bb28; + } + + bb24: { + StorageLive(_15); + _15 = yield(const ()) -> [resume: bb22, drop: bb23]; + } + + bb25: { + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb19, 1: bb24, otherwise: bb12]; + } + + bb26: { + _16 = as Future>::poll(move _18, move _19) -> [return: bb25, unwind: bb20]; + } + + bb27: { + _20 = move _2; + _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb26, unwind: bb20]; + } + + bb28: { + _21 = &mut _14; + _18 = Pin::<&mut impl Future>::new_unchecked(move _21) -> [return: bb27, unwind: bb20]; + } + + bb29: { + StorageLive(_14); + _14 = async_drop_in_place::(copy (_22.0: &mut AsyncInt)) -> [return: bb28, unwind: bb20]; + } + + bb30: { + _23 = &mut ((*_3).1: AsyncInt); + _22 = Pin::<&mut AsyncInt>::new_unchecked(move _23) -> [return: bb29, unwind: bb4]; + } + + bb31: { + StorageDead(_24); + goto -> bb3; + } + + bb32: { + StorageDead(_24); + goto -> bb1; + } + + bb33 (cleanup): { + StorageDead(_24); + goto -> bb2; + } + + bb34: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb34, unwind: bb33]; + } + + bb35: { + _2 = move _25; + StorageDead(_25); + goto -> bb34; + } + + bb36: { + _2 = move _25; + StorageDead(_25); + goto -> bb41; + } + + bb37: { + StorageLive(_25); + _25 = yield(const ()) -> [resume: bb35, drop: bb36]; + } + + bb38: { + _27 = discriminant(_26); + switchInt(move _27) -> [0: bb32, 1: bb37, otherwise: bb12]; + } + + bb39: { + _26 = as Future>::poll(move _28, move _29) -> [return: bb38, unwind: bb33]; + } + + bb40: { + _30 = move _2; + _29 = std::future::get_context::<'_, '_>(move _30) -> [return: bb39, unwind: bb33]; + } + + bb41: { + _31 = &mut _24; + _28 = Pin::<&mut impl Future>::new_unchecked(move _31) -> [return: bb40, unwind: bb33]; + } + + bb42: { + _2 = move _32; + StorageDead(_32); + goto -> bb48; + } + + bb43: { + _2 = move _32; + StorageDead(_32); + goto -> bb41; + } + + bb44: { + StorageLive(_32); + _32 = yield(const ()) -> [resume: bb42, drop: bb43]; + } + + bb45: { + _34 = discriminant(_33); + switchInt(move _34) -> [0: bb31, 1: bb44, otherwise: bb12]; + } + + bb46: { + _33 = as Future>::poll(move _35, move _36) -> [return: bb45, unwind: bb33]; + } + + bb47: { + _37 = move _2; + _36 = std::future::get_context::<'_, '_>(move _37) -> [return: bb46, unwind: bb33]; + } + + bb48: { + _38 = &mut _24; + _35 = Pin::<&mut impl Future>::new_unchecked(move _38) -> [return: bb47, unwind: bb33]; + } + + bb49: { + StorageLive(_24); + _24 = async_drop_in_place::(copy (_39.0: &mut AsyncInt)) -> [return: bb48, unwind: bb33]; + } + + bb50: { + _40 = &mut ((*_3).2: AsyncInt); + _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb49, unwind: bb2]; + } + + bb51: { + StorageDead(_41); + goto -> bb50; + } + + bb52: { + StorageDead(_41); + goto -> bb18; + } + + bb53 (cleanup): { + StorageDead(_41); + goto -> bb4; + } + + bb54: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb54, unwind: bb53]; + } + + bb55: { + _2 = move _42; + StorageDead(_42); + goto -> bb54; + } + + bb56: { + _2 = move _42; + StorageDead(_42); + goto -> bb61; + } + + bb57: { + StorageLive(_42); + _42 = yield(const ()) -> [resume: bb55, drop: bb56]; + } + + bb58: { + _44 = discriminant(_43); + switchInt(move _44) -> [0: bb52, 1: bb57, otherwise: bb12]; + } + + bb59: { + _43 = as Future>::poll(move _45, move _46) -> [return: bb58, unwind: bb53]; + } + + bb60: { + _47 = move _2; + _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb59, unwind: bb53]; + } + + bb61: { + _48 = &mut _41; + _45 = Pin::<&mut impl Future>::new_unchecked(move _48) -> [return: bb60, unwind: bb53]; + } + + bb62: { + _2 = move _49; + StorageDead(_49); + goto -> bb68; + } + + bb63: { + _2 = move _49; + StorageDead(_49); + goto -> bb61; + } + + bb64: { + StorageLive(_49); + _49 = yield(const ()) -> [resume: bb62, drop: bb63]; + } + + bb65: { + _51 = discriminant(_50); + switchInt(move _51) -> [0: bb51, 1: bb64, otherwise: bb12]; + } + + bb66: { + _50 = as Future>::poll(move _52, move _53) -> [return: bb65, unwind: bb53]; + } + + bb67: { + _54 = move _2; + _53 = std::future::get_context::<'_, '_>(move _54) -> [return: bb66, unwind: bb53]; + } + + bb68: { + _55 = &mut _41; + _52 = Pin::<&mut impl Future>::new_unchecked(move _55) -> [return: bb67, unwind: bb53]; + } + + bb69: { + StorageLive(_41); + _41 = async_drop_in_place::(copy (_56.0: &mut AsyncInt)) -> [return: bb68, unwind: bb53]; + } + + bb70: { + _57 = &mut ((*_3).1: AsyncInt); + _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb69, unwind: bb4]; + } + + bb71: { + StorageDead(_58); + goto -> bb70; + } + + bb72: { + StorageDead(_58); + goto -> bb30; + } + + bb73 (cleanup): { + StorageDead(_58); + goto -> bb5; + } + + bb74: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb74, unwind: bb73]; + } + + bb75: { + _2 = move _59; + StorageDead(_59); + goto -> bb74; + } + + bb76: { + _2 = move _59; + StorageDead(_59); + goto -> bb81; + } + + bb77: { + StorageLive(_59); + _59 = yield(const ()) -> [resume: bb75, drop: bb76]; + } + + bb78: { + _61 = discriminant(_60); + switchInt(move _61) -> [0: bb72, 1: bb77, otherwise: bb12]; + } + + bb79: { + _60 = as Future>::poll(move _62, move _63) -> [return: bb78, unwind: bb73]; + } + + bb80: { + _64 = move _2; + _63 = std::future::get_context::<'_, '_>(move _64) -> [return: bb79, unwind: bb73]; + } + + bb81: { + _65 = &mut _58; + _62 = Pin::<&mut impl Future>::new_unchecked(move _65) -> [return: bb80, unwind: bb73]; + } + + bb82: { + _2 = move _66; + StorageDead(_66); + goto -> bb88; + } + + bb83: { + _2 = move _66; + StorageDead(_66); + goto -> bb81; + } + + bb84: { + StorageLive(_66); + _66 = yield(const ()) -> [resume: bb82, drop: bb83]; + } + + bb85: { + _68 = discriminant(_67); + switchInt(move _68) -> [0: bb71, 1: bb84, otherwise: bb12]; + } + + bb86: { + _67 = as Future>::poll(move _69, move _70) -> [return: bb85, unwind: bb73]; + } + + bb87: { + _71 = move _2; + _70 = std::future::get_context::<'_, '_>(move _71) -> [return: bb86, unwind: bb73]; + } + + bb88: { + _72 = &mut _58; + _69 = Pin::<&mut impl Future>::new_unchecked(move _72) -> [return: bb87, unwind: bb73]; + } + + bb89: { + StorageLive(_58); + _58 = ::drop(move _73) -> [return: bb88, unwind: bb73]; + } + + bb90: { + _74 = &mut (*_3); + _73 = Pin::<&mut AsyncStruct>::new_unchecked(move _74) -> [return: bb89, unwind: bb5]; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.StateTransform.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.StateTransform.after.mir new file mode 100644 index 0000000000000..e2d269b70e333 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.StateTransform.after.mir @@ -0,0 +1,417 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform + +fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + field _s0: &mut AsyncStruct; + field _s1: impl Future; + field _s2: impl Future; + field _s3: impl Future; + field _s4: impl Future; + field _s5: impl Future; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s1], + Suspend1 (4): [_s0, _s2], + Suspend2 (5): [_s3], + Suspend3 (6): [_s3], + Suspend4 (7): [_s0, _s4], + Suspend5 (8): [_s0, _s4], + Suspend6 (9): [_s0, _s5], + Suspend7 (10): [_s0, _s5], + } + storage_conflicts = BitMatrix(6x6) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s0, _s4), (_s0, _s5), (_s1, _s0), (_s1, _s1), (_s2, _s0), (_s2, _s2), (_s3, _s0), (_s3, _s3), (_s4, _s0), (_s4, _s4), (_s5, _s0), (_s5, _s5)} + } + let mut _0: std::task::Poll<()>; + let mut _3: &mut AsyncStruct; + let mut _4: impl std::future::Future; + let mut _5: &mut std::task::Context<'_>; + let mut _6: std::task::Poll<()>; + let mut _7: isize; + let mut _8: std::pin::Pin<&mut impl std::future::Future>; + let mut _9: &mut std::task::Context<'_>; + let mut _10: &mut std::task::Context<'_>; + let mut _11: &mut impl std::future::Future; + let mut _12: std::pin::Pin<&mut AsyncInt>; + let mut _13: &mut AsyncInt; + let mut _14: impl std::future::Future; + let mut _15: &mut std::task::Context<'_>; + let mut _16: std::task::Poll<()>; + let mut _17: isize; + let mut _18: std::pin::Pin<&mut impl std::future::Future>; + let mut _19: &mut std::task::Context<'_>; + let mut _20: &mut std::task::Context<'_>; + let mut _21: &mut impl std::future::Future; + let mut _22: std::pin::Pin<&mut AsyncInt>; + let mut _23: &mut AsyncInt; + let mut _24: impl std::future::Future; + let mut _25: &mut std::task::Context<'_>; + let mut _26: std::task::Poll<()>; + let mut _27: isize; + let mut _28: std::pin::Pin<&mut impl std::future::Future>; + let mut _29: &mut std::task::Context<'_>; + let mut _30: &mut std::task::Context<'_>; + let mut _31: &mut impl std::future::Future; + let mut _32: &mut std::task::Context<'_>; + let mut _33: std::task::Poll<()>; + let mut _34: isize; + let mut _35: std::pin::Pin<&mut impl std::future::Future>; + let mut _36: &mut std::task::Context<'_>; + let mut _37: &mut std::task::Context<'_>; + let mut _38: &mut impl std::future::Future; + let mut _39: std::pin::Pin<&mut AsyncInt>; + let mut _40: &mut AsyncInt; + let mut _41: impl std::future::Future; + let mut _42: &mut std::task::Context<'_>; + let mut _43: std::task::Poll<()>; + let mut _44: isize; + let mut _45: std::pin::Pin<&mut impl std::future::Future>; + let mut _46: &mut std::task::Context<'_>; + let mut _47: &mut std::task::Context<'_>; + let mut _48: &mut impl std::future::Future; + let mut _49: &mut std::task::Context<'_>; + let mut _50: std::task::Poll<()>; + let mut _51: isize; + let mut _52: std::pin::Pin<&mut impl std::future::Future>; + let mut _53: &mut std::task::Context<'_>; + let mut _54: &mut std::task::Context<'_>; + let mut _55: &mut impl std::future::Future; + let mut _56: std::pin::Pin<&mut AsyncInt>; + let mut _57: &mut AsyncInt; + let mut _58: impl std::future::Future; + let mut _59: &mut std::task::Context<'_>; + let mut _60: std::task::Poll<()>; + let mut _61: isize; + let mut _62: std::pin::Pin<&mut impl std::future::Future>; + let mut _63: &mut std::task::Context<'_>; + let mut _64: &mut std::task::Context<'_>; + let mut _65: &mut impl std::future::Future; + let mut _66: &mut std::task::Context<'_>; + let mut _67: std::task::Poll<()>; + let mut _68: isize; + let mut _69: std::pin::Pin<&mut impl std::future::Future>; + let mut _70: &mut std::task::Context<'_>; + let mut _71: &mut std::task::Context<'_>; + let mut _72: &mut impl std::future::Future; + let mut _73: std::pin::Pin<&mut AsyncStruct>; + let mut _74: &mut AsyncStruct; + let mut _75: (); + let mut _76: u32; + let mut _77: &mut {async fn body of std::future::async_drop_in_place()}; + let mut _78: &mut AsyncStruct; + let mut _79: &mut AsyncStruct; + let mut _80: &mut AsyncStruct; + let mut _81: &mut AsyncStruct; + let mut _82: &mut AsyncStruct; + + bb0: { + _77 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place()}); + _76 = discriminant((*_77)); + switchInt(move _76) -> [0: bb1, 1: bb56, 2: bb55, 3: bb47, 4: bb48, 5: bb49, 6: bb50, 7: bb51, 8: bb52, 9: bb53, 10: bb54, otherwise: bb9]; + } + + bb1: { + (((*_77) as variant#10).0: &mut AsyncStruct) = move ((*_77).0: &mut AsyncStruct); + _78 = no_retag copy (((*_77) as variant#10).0: &mut AsyncStruct); + _74 = &mut (*_78); + _73 = Pin::<&mut AsyncStruct>::new_unchecked(move _74) -> [return: bb45, unwind: bb5]; + } + + bb2: { + _0 = Poll::<()>::Ready(move _75); + discriminant((*_77)) = 1; + return; + } + + bb3 (cleanup): { + goto -> bb46; + } + + bb4 (cleanup): { + _79 = no_retag copy (((*_77) as variant#10).0: &mut AsyncStruct); + drop(((*_79).2: AsyncInt)) -> [return: bb3, unwind terminate(cleanup)]; + } + + bb5 (cleanup): { + _80 = no_retag copy (((*_77) as variant#10).0: &mut AsyncStruct); + drop(((*_80).1: AsyncInt)) -> [return: bb4, unwind terminate(cleanup)]; + } + + bb6 (cleanup): { + nop; + goto -> bb3; + } + + bb7: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb7, unwind: bb6]; + } + + bb8: { + _2 = move _5; + StorageDead(_5); + goto -> bb7; + } + + bb9: { + unreachable; + } + + bb10 (cleanup): { + nop; + goto -> bb4; + } + + bb11: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb11, unwind: bb10]; + } + + bb12: { + _2 = move _15; + StorageDead(_15); + goto -> bb11; + } + + bb13: { + nop; + goto -> bb2; + } + + bb14 (cleanup): { + nop; + goto -> bb3; + } + + bb15: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb15, unwind: bb14]; + } + + bb16: { + _2 = move _25; + StorageDead(_25); + goto -> bb15; + } + + bb17: { + _2 = move _32; + StorageDead(_32); + goto -> bb22; + } + + bb18: { + StorageLive(_32); + _0 = Poll::<()>::Pending; + StorageDead(_32); + discriminant((*_77)) = 6; + return; + } + + bb19: { + _34 = discriminant(_33); + switchInt(move _34) -> [0: bb13, 1: bb18, otherwise: bb9]; + } + + bb20: { + _33 = as Future>::poll(move _35, move _36) -> [return: bb19, unwind: bb14]; + } + + bb21: { + _37 = move _2; + _36 = move _37; + goto -> bb20; + } + + bb22: { + _38 = &mut (((*_77) as variant#6).0: impl std::future::Future); + _35 = Pin::<&mut impl Future>::new_unchecked(move _38) -> [return: bb21, unwind: bb14]; + } + + bb23: { + nop; + (((*_77) as variant#6).0: impl std::future::Future) = async_drop_in_place::(copy (_39.0: &mut AsyncInt)) -> [return: bb22, unwind: bb14]; + } + + bb24: { + nop; + _81 = no_retag copy (((*_77) as variant#10).0: &mut AsyncStruct); + _40 = &mut ((*_81).2: AsyncInt); + _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb23, unwind: bb3]; + } + + bb25 (cleanup): { + nop; + goto -> bb4; + } + + bb26: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb26, unwind: bb25]; + } + + bb27: { + _2 = move _42; + StorageDead(_42); + goto -> bb26; + } + + bb28: { + _2 = move _49; + StorageDead(_49); + goto -> bb33; + } + + bb29: { + StorageLive(_49); + _0 = Poll::<()>::Pending; + StorageDead(_49); + discriminant((*_77)) = 8; + return; + } + + bb30: { + _51 = discriminant(_50); + switchInt(move _51) -> [0: bb24, 1: bb29, otherwise: bb9]; + } + + bb31: { + _50 = as Future>::poll(move _52, move _53) -> [return: bb30, unwind: bb25]; + } + + bb32: { + _54 = move _2; + _53 = move _54; + goto -> bb31; + } + + bb33: { + _55 = &mut (((*_77) as variant#8).1: impl std::future::Future); + _52 = Pin::<&mut impl Future>::new_unchecked(move _55) -> [return: bb32, unwind: bb25]; + } + + bb34: { + nop; + (((*_77) as variant#8).1: impl std::future::Future) = async_drop_in_place::(copy (_56.0: &mut AsyncInt)) -> [return: bb33, unwind: bb25]; + } + + bb35: { + nop; + _82 = no_retag copy (((*_77) as variant#10).0: &mut AsyncStruct); + _57 = &mut ((*_82).1: AsyncInt); + _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb34, unwind: bb4]; + } + + bb36 (cleanup): { + nop; + goto -> bb5; + } + + bb37: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb37, unwind: bb36]; + } + + bb38: { + _2 = move _59; + StorageDead(_59); + goto -> bb37; + } + + bb39: { + _2 = move _66; + StorageDead(_66); + goto -> bb44; + } + + bb40: { + StorageLive(_66); + _0 = Poll::<()>::Pending; + StorageDead(_66); + discriminant((*_77)) = 10; + return; + } + + bb41: { + _68 = discriminant(_67); + switchInt(move _68) -> [0: bb35, 1: bb40, otherwise: bb9]; + } + + bb42: { + _67 = as Future>::poll(move _69, move _70) -> [return: bb41, unwind: bb36]; + } + + bb43: { + _71 = move _2; + _70 = move _71; + goto -> bb42; + } + + bb44: { + _72 = &mut (((*_77) as variant#10).1: impl std::future::Future); + _69 = Pin::<&mut impl Future>::new_unchecked(move _72) -> [return: bb43, unwind: bb36]; + } + + bb45: { + nop; + (((*_77) as variant#10).1: impl std::future::Future) = ::drop(move _73) -> [return: bb44, unwind: bb36]; + } + + bb46 (cleanup): { + discriminant((*_77)) = 2; + resume; + } + + bb47: { + StorageLive(_5); + _5 = move _2; + goto -> bb8; + } + + bb48: { + StorageLive(_15); + _15 = move _2; + goto -> bb12; + } + + bb49: { + StorageLive(_25); + _25 = move _2; + goto -> bb16; + } + + bb50: { + StorageLive(_32); + _32 = move _2; + goto -> bb17; + } + + bb51: { + StorageLive(_42); + _42 = move _2; + goto -> bb27; + } + + bb52: { + StorageLive(_49); + _49 = move _2; + goto -> bb28; + } + + bb53: { + StorageLive(_59); + _59 = move _2; + goto -> bb38; + } + + bb54: { + StorageLive(_66); + _66 = move _2; + goto -> bb39; + } + + bb55: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb55, unwind continue]; + } + + bb56: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.Int.MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.Int.MentionedItems.after.mir new file mode 100644 index 0000000000000..7823a862bbded --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.Int.MentionedItems.after.mir @@ -0,0 +1,15 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems + +fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place()}, _2: std::future::ResumeTy) -> () +yields () + { + let mut _0: (); + + bb0: { + goto -> bb1; + } + + bb1: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.Int.StateTransform.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.Int.StateTransform.after.mir new file mode 100644 index 0000000000000..ac0e8e4360efe --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.Int.StateTransform.after.mir @@ -0,0 +1,37 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform + +fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + } + storage_conflicts = BitMatrix(0x0) {} + } + let mut _0: std::task::Poll<()>; + let mut _3: (); + let mut _4: u32; + let mut _5: &mut {async fn body of std::future::async_drop_in_place()}; + + bb0: { + _5 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place()}); + _4 = discriminant((*_5)); + switchInt(move _4) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + + bb1: { + _0 = Poll::<()>::Ready(move _3); + discriminant((*_5)) = 1; + return; + } + + bb2: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb3: { + unreachable; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncInt.MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncInt.MentionedItems.after.mir new file mode 100644 index 0000000000000..b958b843c6df0 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncInt.MentionedItems.after.mir @@ -0,0 +1,17 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems + +fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place()}, _2: std::future::ResumeTy) -> () +yields () + { + let mut _0: (); + let mut _3: &mut SyncInt; + + bb0: { + _3 = no_retag copy (_1.0: &mut SyncInt); + drop((*_3)) -> [return: bb1, unwind continue]; + } + + bb1: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncInt.StateTransform.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncInt.StateTransform.after.mir new file mode 100644 index 0000000000000..749a7cfb2082b --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncInt.StateTransform.after.mir @@ -0,0 +1,52 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform + +fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + } + storage_conflicts = BitMatrix(0x0) {} + } + let mut _0: std::task::Poll<()>; + let mut _3: &mut SyncInt; + let mut _4: (); + let mut _5: u32; + let mut _6: &mut {async fn body of std::future::async_drop_in_place()}; + + bb0: { + _6 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place()}); + _5 = discriminant((*_6)); + switchInt(move _5) -> [0: bb1, 1: bb5, 2: bb4, otherwise: bb6]; + } + + bb1: { + _3 = no_retag copy ((*_6).0: &mut SyncInt); + drop((*_3)) -> [return: bb2, unwind: bb3]; + } + + bb2: { + _0 = Poll::<()>::Ready(move _4); + discriminant((*_6)) = 1; + return; + } + + bb3 (cleanup): { + discriminant((*_6)) = 2; + resume; + } + + bb4: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb4, unwind continue]; + } + + bb5: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb6: { + unreachable; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.MentionedItems.after.mir new file mode 100644 index 0000000000000..b5d451bbdc4a1 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.MentionedItems.after.mir @@ -0,0 +1,432 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems + +fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place()}, _2: std::future::ResumeTy) -> () +yields () + { + let mut _0: (); + let mut _3: &mut SyncThenAsync; + let mut _4: impl std::future::Future; + let mut _5: std::future::ResumeTy; + let mut _6: std::task::Poll<()>; + let mut _7: isize; + let mut _8: std::pin::Pin<&mut impl std::future::Future>; + let mut _9: &mut std::task::Context<'_>; + let mut _10: std::future::ResumeTy; + let mut _11: &mut impl std::future::Future; + let mut _12: std::pin::Pin<&mut AsyncInt>; + let mut _13: &mut AsyncInt; + let mut _14: impl std::future::Future; + let mut _15: std::future::ResumeTy; + let mut _16: std::task::Poll<()>; + let mut _17: isize; + let mut _18: std::pin::Pin<&mut impl std::future::Future>; + let mut _19: &mut std::task::Context<'_>; + let mut _20: std::future::ResumeTy; + let mut _21: &mut impl std::future::Future; + let mut _22: std::pin::Pin<&mut AsyncInt>; + let mut _23: &mut AsyncInt; + let mut _24: impl std::future::Future; + let mut _25: std::future::ResumeTy; + let mut _26: std::task::Poll<()>; + let mut _27: isize; + let mut _28: std::pin::Pin<&mut impl std::future::Future>; + let mut _29: &mut std::task::Context<'_>; + let mut _30: std::future::ResumeTy; + let mut _31: &mut impl std::future::Future; + let mut _32: std::future::ResumeTy; + let mut _33: std::task::Poll<()>; + let mut _34: isize; + let mut _35: std::pin::Pin<&mut impl std::future::Future>; + let mut _36: &mut std::task::Context<'_>; + let mut _37: std::future::ResumeTy; + let mut _38: &mut impl std::future::Future; + let mut _39: std::pin::Pin<&mut AsyncInt>; + let mut _40: &mut AsyncInt; + let mut _41: impl std::future::Future; + let mut _42: std::future::ResumeTy; + let mut _43: std::task::Poll<()>; + let mut _44: isize; + let mut _45: std::pin::Pin<&mut impl std::future::Future>; + let mut _46: &mut std::task::Context<'_>; + let mut _47: std::future::ResumeTy; + let mut _48: &mut impl std::future::Future; + let mut _49: std::future::ResumeTy; + let mut _50: std::task::Poll<()>; + let mut _51: isize; + let mut _52: std::pin::Pin<&mut impl std::future::Future>; + let mut _53: &mut std::task::Context<'_>; + let mut _54: std::future::ResumeTy; + let mut _55: &mut impl std::future::Future; + let mut _56: std::pin::Pin<&mut AsyncInt>; + let mut _57: &mut AsyncInt; + let mut _58: &mut SyncThenAsync; + let mut _59: (); + + bb0: { + _3 = move (_1.0: &mut SyncThenAsync); + goto -> bb74; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { + goto -> bb1; + } + + bb4 (cleanup): { + drop(((*_3).3: AsyncInt)) -> [return: bb2, unwind terminate(cleanup)]; + } + + bb5 (cleanup): { + drop(((*_3).2: SyncInt)) -> [return: bb4, unwind terminate(cleanup)]; + } + + bb6 (cleanup): { + drop(((*_3).1: AsyncInt)) -> [return: bb5, unwind terminate(cleanup)]; + } + + bb7: { + StorageDead(_4); + goto -> bb1; + } + + bb8 (cleanup): { + StorageDead(_4); + goto -> bb2; + } + + bb9: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb9, unwind: bb8]; + } + + bb10: { + _2 = move _5; + StorageDead(_5); + goto -> bb9; + } + + bb11: { + _2 = move _5; + StorageDead(_5); + goto -> bb17; + } + + bb12: { + StorageLive(_5); + _5 = yield(const ()) -> [resume: bb10, drop: bb11]; + } + + bb13: { + unreachable; + } + + bb14: { + _7 = discriminant(_6); + switchInt(move _7) -> [0: bb7, 1: bb12, otherwise: bb13]; + } + + bb15: { + _6 = as Future>::poll(move _8, move _9) -> [return: bb14, unwind: bb8]; + } + + bb16: { + _10 = move _2; + _9 = std::future::get_context::<'_, '_>(move _10) -> [return: bb15, unwind: bb8]; + } + + bb17: { + _11 = &mut _4; + _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb16, unwind: bb8]; + } + + bb18: { + StorageLive(_4); + _4 = async_drop_in_place::(copy (_12.0: &mut AsyncInt)) -> [return: bb17, unwind: bb8]; + } + + bb19: { + _13 = &mut ((*_3).3: AsyncInt); + _12 = Pin::<&mut AsyncInt>::new_unchecked(move _13) -> [return: bb18, unwind: bb2]; + } + + bb20: { + drop(((*_3).2: SyncInt)) -> [return: bb19, unwind: bb4]; + } + + bb21: { + StorageDead(_14); + goto -> bb20; + } + + bb22 (cleanup): { + StorageDead(_14); + goto -> bb5; + } + + bb23: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb23, unwind: bb22]; + } + + bb24: { + _2 = move _15; + StorageDead(_15); + goto -> bb23; + } + + bb25: { + _2 = move _15; + StorageDead(_15); + goto -> bb30; + } + + bb26: { + StorageLive(_15); + _15 = yield(const ()) -> [resume: bb24, drop: bb25]; + } + + bb27: { + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb21, 1: bb26, otherwise: bb13]; + } + + bb28: { + _16 = as Future>::poll(move _18, move _19) -> [return: bb27, unwind: bb22]; + } + + bb29: { + _20 = move _2; + _19 = std::future::get_context::<'_, '_>(move _20) -> [return: bb28, unwind: bb22]; + } + + bb30: { + _21 = &mut _14; + _18 = Pin::<&mut impl Future>::new_unchecked(move _21) -> [return: bb29, unwind: bb22]; + } + + bb31: { + StorageLive(_14); + _14 = async_drop_in_place::(copy (_22.0: &mut AsyncInt)) -> [return: bb30, unwind: bb22]; + } + + bb32: { + _23 = &mut ((*_3).1: AsyncInt); + _22 = Pin::<&mut AsyncInt>::new_unchecked(move _23) -> [return: bb31, unwind: bb5]; + } + + bb33: { + StorageDead(_24); + goto -> bb3; + } + + bb34: { + StorageDead(_24); + goto -> bb1; + } + + bb35 (cleanup): { + StorageDead(_24); + goto -> bb2; + } + + bb36: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb36, unwind: bb35]; + } + + bb37: { + _2 = move _25; + StorageDead(_25); + goto -> bb36; + } + + bb38: { + _2 = move _25; + StorageDead(_25); + goto -> bb43; + } + + bb39: { + StorageLive(_25); + _25 = yield(const ()) -> [resume: bb37, drop: bb38]; + } + + bb40: { + _27 = discriminant(_26); + switchInt(move _27) -> [0: bb34, 1: bb39, otherwise: bb13]; + } + + bb41: { + _26 = as Future>::poll(move _28, move _29) -> [return: bb40, unwind: bb35]; + } + + bb42: { + _30 = move _2; + _29 = std::future::get_context::<'_, '_>(move _30) -> [return: bb41, unwind: bb35]; + } + + bb43: { + _31 = &mut _24; + _28 = Pin::<&mut impl Future>::new_unchecked(move _31) -> [return: bb42, unwind: bb35]; + } + + bb44: { + _2 = move _32; + StorageDead(_32); + goto -> bb50; + } + + bb45: { + _2 = move _32; + StorageDead(_32); + goto -> bb43; + } + + bb46: { + StorageLive(_32); + _32 = yield(const ()) -> [resume: bb44, drop: bb45]; + } + + bb47: { + _34 = discriminant(_33); + switchInt(move _34) -> [0: bb33, 1: bb46, otherwise: bb13]; + } + + bb48: { + _33 = as Future>::poll(move _35, move _36) -> [return: bb47, unwind: bb35]; + } + + bb49: { + _37 = move _2; + _36 = std::future::get_context::<'_, '_>(move _37) -> [return: bb48, unwind: bb35]; + } + + bb50: { + _38 = &mut _24; + _35 = Pin::<&mut impl Future>::new_unchecked(move _38) -> [return: bb49, unwind: bb35]; + } + + bb51: { + StorageLive(_24); + _24 = async_drop_in_place::(copy (_39.0: &mut AsyncInt)) -> [return: bb50, unwind: bb35]; + } + + bb52: { + _40 = &mut ((*_3).3: AsyncInt); + _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb51, unwind: bb2]; + } + + bb53: { + drop(((*_3).2: SyncInt)) -> [return: bb52, unwind: bb4]; + } + + bb54: { + StorageDead(_41); + goto -> bb53; + } + + bb55: { + StorageDead(_41); + goto -> bb20; + } + + bb56 (cleanup): { + StorageDead(_41); + goto -> bb5; + } + + bb57: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb57, unwind: bb56]; + } + + bb58: { + _2 = move _42; + StorageDead(_42); + goto -> bb57; + } + + bb59: { + _2 = move _42; + StorageDead(_42); + goto -> bb64; + } + + bb60: { + StorageLive(_42); + _42 = yield(const ()) -> [resume: bb58, drop: bb59]; + } + + bb61: { + _44 = discriminant(_43); + switchInt(move _44) -> [0: bb55, 1: bb60, otherwise: bb13]; + } + + bb62: { + _43 = as Future>::poll(move _45, move _46) -> [return: bb61, unwind: bb56]; + } + + bb63: { + _47 = move _2; + _46 = std::future::get_context::<'_, '_>(move _47) -> [return: bb62, unwind: bb56]; + } + + bb64: { + _48 = &mut _41; + _45 = Pin::<&mut impl Future>::new_unchecked(move _48) -> [return: bb63, unwind: bb56]; + } + + bb65: { + _2 = move _49; + StorageDead(_49); + goto -> bb71; + } + + bb66: { + _2 = move _49; + StorageDead(_49); + goto -> bb64; + } + + bb67: { + StorageLive(_49); + _49 = yield(const ()) -> [resume: bb65, drop: bb66]; + } + + bb68: { + _51 = discriminant(_50); + switchInt(move _51) -> [0: bb54, 1: bb67, otherwise: bb13]; + } + + bb69: { + _50 = as Future>::poll(move _52, move _53) -> [return: bb68, unwind: bb56]; + } + + bb70: { + _54 = move _2; + _53 = std::future::get_context::<'_, '_>(move _54) -> [return: bb69, unwind: bb56]; + } + + bb71: { + _55 = &mut _41; + _52 = Pin::<&mut impl Future>::new_unchecked(move _55) -> [return: bb70, unwind: bb56]; + } + + bb72: { + StorageLive(_41); + _41 = async_drop_in_place::(copy (_56.0: &mut AsyncInt)) -> [return: bb71, unwind: bb56]; + } + + bb73: { + _57 = &mut ((*_3).1: AsyncInt); + _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb72, unwind: bb5]; + } + + bb74: { + _58 = &mut (*_3); + _59 = ::drop(move _58) -> [return: bb73, unwind: bb6]; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.StateTransform.after.mir b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.StateTransform.after.mir new file mode 100644 index 0000000000000..b7a59a0d985f2 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.StateTransform.after.mir @@ -0,0 +1,321 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after StateTransform + +fn async_drop_in_place::{closure#0}(_1: Pin<&mut {async fn body of async_drop_in_place()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + field _s0: &mut SyncThenAsync; + field _s1: impl Future; + field _s2: impl Future; + field _s3: impl Future; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s1], + Suspend1 (4): [_s2], + Suspend2 (5): [_s2], + Suspend3 (6): [_s0, _s3], + Suspend4 (7): [_s0, _s3], + } + storage_conflicts = BitMatrix(4x4) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s1, _s0), (_s1, _s1), (_s2, _s0), (_s2, _s2), (_s3, _s0), (_s3, _s3)} + } + let mut _0: std::task::Poll<()>; + let mut _3: &mut SyncThenAsync; + let mut _4: impl std::future::Future; + let mut _5: &mut std::task::Context<'_>; + let mut _6: std::task::Poll<()>; + let mut _7: isize; + let mut _8: std::pin::Pin<&mut impl std::future::Future>; + let mut _9: &mut std::task::Context<'_>; + let mut _10: &mut std::task::Context<'_>; + let mut _11: &mut impl std::future::Future; + let mut _12: std::pin::Pin<&mut AsyncInt>; + let mut _13: &mut AsyncInt; + let mut _14: impl std::future::Future; + let mut _15: std::future::ResumeTy; + let mut _16: std::task::Poll<()>; + let mut _17: isize; + let mut _18: std::pin::Pin<&mut impl std::future::Future>; + let mut _19: &mut std::task::Context<'_>; + let mut _20: std::future::ResumeTy; + let mut _21: &mut impl std::future::Future; + let mut _22: std::pin::Pin<&mut AsyncInt>; + let mut _23: &mut AsyncInt; + let mut _24: impl std::future::Future; + let mut _25: &mut std::task::Context<'_>; + let mut _26: std::task::Poll<()>; + let mut _27: isize; + let mut _28: std::pin::Pin<&mut impl std::future::Future>; + let mut _29: &mut std::task::Context<'_>; + let mut _30: &mut std::task::Context<'_>; + let mut _31: &mut impl std::future::Future; + let mut _32: &mut std::task::Context<'_>; + let mut _33: std::task::Poll<()>; + let mut _34: isize; + let mut _35: std::pin::Pin<&mut impl std::future::Future>; + let mut _36: &mut std::task::Context<'_>; + let mut _37: &mut std::task::Context<'_>; + let mut _38: &mut impl std::future::Future; + let mut _39: std::pin::Pin<&mut AsyncInt>; + let mut _40: &mut AsyncInt; + let mut _41: impl std::future::Future; + let mut _42: &mut std::task::Context<'_>; + let mut _43: std::task::Poll<()>; + let mut _44: isize; + let mut _45: std::pin::Pin<&mut impl std::future::Future>; + let mut _46: &mut std::task::Context<'_>; + let mut _47: &mut std::task::Context<'_>; + let mut _48: &mut impl std::future::Future; + let mut _49: &mut std::task::Context<'_>; + let mut _50: std::task::Poll<()>; + let mut _51: isize; + let mut _52: std::pin::Pin<&mut impl std::future::Future>; + let mut _53: &mut std::task::Context<'_>; + let mut _54: &mut std::task::Context<'_>; + let mut _55: &mut impl std::future::Future; + let mut _56: std::pin::Pin<&mut AsyncInt>; + let mut _57: &mut AsyncInt; + let mut _58: &mut SyncThenAsync; + let mut _59: (); + let mut _60: (); + let mut _61: u32; + let mut _62: &mut {async fn body of std::future::async_drop_in_place()}; + let mut _63: &mut SyncThenAsync; + let mut _64: &mut SyncThenAsync; + let mut _65: &mut SyncThenAsync; + let mut _66: &mut SyncThenAsync; + let mut _67: &mut SyncThenAsync; + let mut _68: &mut SyncThenAsync; + let mut _69: &mut SyncThenAsync; + + bb0: { + _62 = copy (_1.0: &mut {async fn body of std::future::async_drop_in_place()}); + _61 = discriminant((*_62)); + switchInt(move _61) -> [0: bb1, 1: bb42, 2: bb41, 3: bb36, 4: bb37, 5: bb38, 6: bb39, 7: bb40, otherwise: bb10]; + } + + bb1: { + (((*_62) as variant#7).0: &mut SyncThenAsync) = move ((*_62).0: &mut SyncThenAsync); + _63 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync); + _58 = &mut (*_63); + _59 = ::drop(move _58) -> [return: bb34, unwind: bb6]; + } + + bb2: { + _0 = Poll::<()>::Ready(move _60); + discriminant((*_62)) = 1; + return; + } + + bb3 (cleanup): { + goto -> bb35; + } + + bb4 (cleanup): { + _64 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync); + drop(((*_64).3: AsyncInt)) -> [return: bb3, unwind terminate(cleanup)]; + } + + bb5 (cleanup): { + _65 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync); + drop(((*_65).2: SyncInt)) -> [return: bb4, unwind terminate(cleanup)]; + } + + bb6 (cleanup): { + _66 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync); + drop(((*_66).1: AsyncInt)) -> [return: bb5, unwind terminate(cleanup)]; + } + + bb7 (cleanup): { + nop; + goto -> bb3; + } + + bb8: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb8, unwind: bb7]; + } + + bb9: { + _2 = move _5; + StorageDead(_5); + goto -> bb8; + } + + bb10: { + unreachable; + } + + bb11: { + nop; + goto -> bb2; + } + + bb12 (cleanup): { + nop; + goto -> bb3; + } + + bb13: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb13, unwind: bb12]; + } + + bb14: { + _2 = move _25; + StorageDead(_25); + goto -> bb13; + } + + bb15: { + _2 = move _32; + StorageDead(_32); + goto -> bb20; + } + + bb16: { + StorageLive(_32); + _0 = Poll::<()>::Pending; + StorageDead(_32); + discriminant((*_62)) = 5; + return; + } + + bb17: { + _34 = discriminant(_33); + switchInt(move _34) -> [0: bb11, 1: bb16, otherwise: bb10]; + } + + bb18: { + _33 = as Future>::poll(move _35, move _36) -> [return: bb17, unwind: bb12]; + } + + bb19: { + _37 = move _2; + _36 = move _37; + goto -> bb18; + } + + bb20: { + _38 = &mut (((*_62) as variant#5).0: impl std::future::Future); + _35 = Pin::<&mut impl Future>::new_unchecked(move _38) -> [return: bb19, unwind: bb12]; + } + + bb21: { + nop; + (((*_62) as variant#5).0: impl std::future::Future) = async_drop_in_place::(copy (_39.0: &mut AsyncInt)) -> [return: bb20, unwind: bb12]; + } + + bb22: { + _67 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync); + _40 = &mut ((*_67).3: AsyncInt); + _39 = Pin::<&mut AsyncInt>::new_unchecked(move _40) -> [return: bb21, unwind: bb3]; + } + + bb23: { + nop; + _68 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync); + drop(((*_68).2: SyncInt)) -> [return: bb22, unwind: bb4]; + } + + bb24 (cleanup): { + nop; + goto -> bb5; + } + + bb25: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb25, unwind: bb24]; + } + + bb26: { + _2 = move _42; + StorageDead(_42); + goto -> bb25; + } + + bb27: { + _2 = move _49; + StorageDead(_49); + goto -> bb32; + } + + bb28: { + StorageLive(_49); + _0 = Poll::<()>::Pending; + StorageDead(_49); + discriminant((*_62)) = 7; + return; + } + + bb29: { + _51 = discriminant(_50); + switchInt(move _51) -> [0: bb23, 1: bb28, otherwise: bb10]; + } + + bb30: { + _50 = as Future>::poll(move _52, move _53) -> [return: bb29, unwind: bb24]; + } + + bb31: { + _54 = move _2; + _53 = move _54; + goto -> bb30; + } + + bb32: { + _55 = &mut (((*_62) as variant#7).1: impl std::future::Future); + _52 = Pin::<&mut impl Future>::new_unchecked(move _55) -> [return: bb31, unwind: bb24]; + } + + bb33: { + nop; + (((*_62) as variant#7).1: impl std::future::Future) = async_drop_in_place::(copy (_56.0: &mut AsyncInt)) -> [return: bb32, unwind: bb24]; + } + + bb34: { + _69 = no_retag copy (((*_62) as variant#7).0: &mut SyncThenAsync); + _57 = &mut ((*_69).1: AsyncInt); + _56 = Pin::<&mut AsyncInt>::new_unchecked(move _57) -> [return: bb33, unwind: bb5]; + } + + bb35 (cleanup): { + discriminant((*_62)) = 2; + resume; + } + + bb36: { + StorageLive(_5); + _5 = move _2; + goto -> bb9; + } + + bb37: { + StorageLive(_25); + _25 = move _2; + goto -> bb14; + } + + bb38: { + StorageLive(_32); + _32 = move _2; + goto -> bb15; + } + + bb39: { + StorageLive(_42); + _42 = move _2; + goto -> bb26; + } + + bb40: { + StorageLive(_49); + _49 = move _2; + goto -> bb27; + } + + bb41: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb41, unwind continue]; + } + + bb42: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.double-{closure#0}.ElaborateDrops.diff b/tests/mir-opt/coroutine/async_drop.double-{closure#0}.ElaborateDrops.diff new file mode 100644 index 0000000000000..b11d65b4da8b8 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.double-{closure#0}.ElaborateDrops.diff @@ -0,0 +1,348 @@ +- // MIR for `double::{closure#0}` before ElaborateDrops ++ // MIR for `double::{closure#0}` after ElaborateDrops + + fn double::{closure#0}(_1: {async fn body of double()}, _2: std::future::ResumeTy) -> () + yields () + { + debug _task_context => _2; + let mut _0: (); + let _3: SyncInt; ++ let mut _6: impl std::future::Future; ++ let mut _7: std::future::ResumeTy; ++ let mut _8: std::task::Poll<()>; ++ let mut _9: isize; ++ let mut _10: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _11: &mut std::task::Context<'_>; ++ let mut _12: std::future::ResumeTy; ++ let mut _13: &mut impl std::future::Future; ++ let mut _14: std::future::ResumeTy; ++ let mut _15: std::task::Poll<()>; ++ let mut _16: isize; ++ let mut _17: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _18: &mut std::task::Context<'_>; ++ let mut _19: std::future::ResumeTy; ++ let mut _20: &mut impl std::future::Future; ++ let mut _21: std::pin::Pin<&mut AsyncInt>; ++ let mut _22: &mut AsyncInt; ++ let mut _23: impl std::future::Future; ++ let mut _24: std::future::ResumeTy; ++ let mut _25: std::task::Poll<()>; ++ let mut _26: isize; ++ let mut _27: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _28: &mut std::task::Context<'_>; ++ let mut _29: std::future::ResumeTy; ++ let mut _30: &mut impl std::future::Future; ++ let mut _31: std::future::ResumeTy; ++ let mut _32: std::task::Poll<()>; ++ let mut _33: isize; ++ let mut _34: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _35: &mut std::task::Context<'_>; ++ let mut _36: std::future::ResumeTy; ++ let mut _37: &mut impl std::future::Future; ++ let mut _38: std::pin::Pin<&mut AsyncInt>; ++ let mut _39: &mut AsyncInt; + scope 1 { + debug sync_int => _3; + let _4: AsyncInt; + scope 2 { + debug async_int => _4; + let _5: AsyncInt; + scope 3 { + debug async_int_again => _5; + } + } + } + + bb0: { + StorageLive(_3); + _3 = SyncInt(const 0_i32); + StorageLive(_4); + _4 = AsyncInt(const 0_i32); + StorageLive(_5); + _5 = AsyncInt(const 0_i32); + _0 = const (); +- drop(_5) -> [return: bb1, unwind: bb9, drop: bb5]; ++ goto -> bb35; + } + + bb1: { + StorageDead(_5); +- drop(_4) -> [return: bb2, unwind: bb10, drop: bb6]; ++ goto -> bb55; + } + + bb2: { + StorageDead(_4); + drop(_3) -> [return: bb3, unwind: bb11]; + } + + bb3: { + StorageDead(_3); +- drop(_1) -> [return: bb4, drop: bb8, unwind continue]; ++ drop(_1) -> [return: bb4, unwind: bb12]; + } + + bb4: { + return; + } + + bb5: { + StorageDead(_5); +- drop(_4) -> [return: bb6, unwind: bb13]; ++ goto -> bb6; + } + + bb6: { + StorageDead(_4); +- drop(_3) -> [return: bb7, unwind: bb14]; ++ goto -> bb7; + } + + bb7: { + StorageDead(_3); +- drop(_1) -> [return: bb8, unwind continue]; ++ goto -> bb8; + } + + bb8: { + coroutine_drop; + } + + bb9 (cleanup): { + StorageDead(_5); + drop(_4) -> [return: bb10, unwind terminate(cleanup)]; + } + + bb10 (cleanup): { + StorageDead(_4); + drop(_3) -> [return: bb11, unwind terminate(cleanup)]; + } + + bb11 (cleanup): { + StorageDead(_3); + drop(_1) -> [return: bb12, unwind terminate(cleanup)]; + } + + bb12 (cleanup): { + resume; + } + + bb13 (cleanup): { + StorageDead(_4); +- drop(_3) -> [return: bb14, unwind terminate(cleanup)]; ++ goto -> bb14; + } + + bb14 (cleanup): { + StorageDead(_3); +- drop(_1) -> [return: bb12, unwind terminate(cleanup)]; ++ goto -> bb12; ++ } ++ ++ bb15: { ++ StorageDead(_6); ++ goto -> bb1; ++ } ++ ++ bb16: { ++ StorageDead(_6); ++ goto -> bb5; ++ } ++ ++ bb17 (cleanup): { ++ StorageDead(_6); ++ goto -> bb9; ++ } ++ ++ bb18: { ++ assert(const false, "`async fn` resumed after async drop") -> [success: bb18, unwind: bb17]; ++ } ++ ++ bb19: { ++ _2 = move _7; ++ StorageDead(_7); ++ goto -> bb18; ++ } ++ ++ bb20: { ++ _2 = move _7; ++ StorageDead(_7); ++ goto -> bb26; ++ } ++ ++ bb21: { ++ StorageLive(_7); ++ _7 = yield(const ()) -> [resume: bb19, drop: bb20]; ++ } ++ ++ bb22: { ++ unreachable; ++ } ++ ++ bb23: { ++ _9 = discriminant(_8); ++ switchInt(move _9) -> [0: bb16, 1: bb21, otherwise: bb22]; ++ } ++ ++ bb24: { ++ _8 = as Future>::poll(move _10, move _11) -> [return: bb23, unwind: bb17]; ++ } ++ ++ bb25: { ++ _12 = move _2; ++ _11 = std::future::get_context::<'_, '_>(move _12) -> [return: bb24, unwind: bb17]; ++ } ++ ++ bb26: { ++ _13 = &mut _6; ++ _10 = Pin::<&mut impl Future>::new_unchecked(move _13) -> [return: bb25, unwind: bb17]; ++ } ++ ++ bb27: { ++ _2 = move _14; ++ StorageDead(_14); ++ goto -> bb33; ++ } ++ ++ bb28: { ++ _2 = move _14; ++ StorageDead(_14); ++ goto -> bb26; ++ } ++ ++ bb29: { ++ StorageLive(_14); ++ _14 = yield(const ()) -> [resume: bb27, drop: bb28]; ++ } ++ ++ bb30: { ++ _16 = discriminant(_15); ++ switchInt(move _16) -> [0: bb15, 1: bb29, otherwise: bb22]; ++ } ++ ++ bb31: { ++ _15 = as Future>::poll(move _17, move _18) -> [return: bb30, unwind: bb17]; ++ } ++ ++ bb32: { ++ _19 = move _2; ++ _18 = std::future::get_context::<'_, '_>(move _19) -> [return: bb31, unwind: bb17]; ++ } ++ ++ bb33: { ++ _20 = &mut _6; ++ _17 = Pin::<&mut impl Future>::new_unchecked(move _20) -> [return: bb32, unwind: bb17]; ++ } ++ ++ bb34: { ++ StorageLive(_6); ++ _6 = async_drop_in_place::(copy (_21.0: &mut AsyncInt)) -> [return: bb33, unwind: bb17]; ++ } ++ ++ bb35: { ++ _22 = &mut _5; ++ _21 = Pin::<&mut AsyncInt>::new_unchecked(move _22) -> [return: bb34, unwind: bb9]; ++ } ++ ++ bb36: { ++ StorageDead(_23); ++ goto -> bb2; ++ } ++ ++ bb37: { ++ StorageDead(_23); ++ goto -> bb6; ++ } ++ ++ bb38 (cleanup): { ++ StorageDead(_23); ++ goto -> bb10; ++ } ++ ++ bb39: { ++ assert(const false, "`async fn` resumed after async drop") -> [success: bb39, unwind: bb38]; ++ } ++ ++ bb40: { ++ _2 = move _24; ++ StorageDead(_24); ++ goto -> bb39; ++ } ++ ++ bb41: { ++ _2 = move _24; ++ StorageDead(_24); ++ goto -> bb46; ++ } ++ ++ bb42: { ++ StorageLive(_24); ++ _24 = yield(const ()) -> [resume: bb40, drop: bb41]; ++ } ++ ++ bb43: { ++ _26 = discriminant(_25); ++ switchInt(move _26) -> [0: bb37, 1: bb42, otherwise: bb22]; ++ } ++ ++ bb44: { ++ _25 = as Future>::poll(move _27, move _28) -> [return: bb43, unwind: bb38]; ++ } ++ ++ bb45: { ++ _29 = move _2; ++ _28 = std::future::get_context::<'_, '_>(move _29) -> [return: bb44, unwind: bb38]; ++ } ++ ++ bb46: { ++ _30 = &mut _23; ++ _27 = Pin::<&mut impl Future>::new_unchecked(move _30) -> [return: bb45, unwind: bb38]; ++ } ++ ++ bb47: { ++ _2 = move _31; ++ StorageDead(_31); ++ goto -> bb53; ++ } ++ ++ bb48: { ++ _2 = move _31; ++ StorageDead(_31); ++ goto -> bb46; ++ } ++ ++ bb49: { ++ StorageLive(_31); ++ _31 = yield(const ()) -> [resume: bb47, drop: bb48]; ++ } ++ ++ bb50: { ++ _33 = discriminant(_32); ++ switchInt(move _33) -> [0: bb36, 1: bb49, otherwise: bb22]; ++ } ++ ++ bb51: { ++ _32 = as Future>::poll(move _34, move _35) -> [return: bb50, unwind: bb38]; ++ } ++ ++ bb52: { ++ _36 = move _2; ++ _35 = std::future::get_context::<'_, '_>(move _36) -> [return: bb51, unwind: bb38]; ++ } ++ ++ bb53: { ++ _37 = &mut _23; ++ _34 = Pin::<&mut impl Future>::new_unchecked(move _37) -> [return: bb52, unwind: bb38]; ++ } ++ ++ bb54: { ++ StorageLive(_23); ++ _23 = async_drop_in_place::(copy (_38.0: &mut AsyncInt)) -> [return: bb53, unwind: bb38]; ++ } ++ ++ bb55: { ++ _39 = &mut _4; ++ _38 = Pin::<&mut AsyncInt>::new_unchecked(move _39) -> [return: bb54, unwind: bb10]; + } + } + diff --git a/tests/mir-opt/coroutine/async_drop.double-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_drop.double-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..e296c552851ab --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.double-{closure#0}.StateTransform.after.mir @@ -0,0 +1,306 @@ +// MIR for `double::{closure#0}` after StateTransform + +fn double::{closure#0}(_1: Pin<&mut {async fn body of double()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + field _s0: (); + field _s1: SyncInt; + field _s2: AsyncInt; + field _s3: AsyncInt; + field _s4: impl Future; + field _s5: impl Future; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s1, _s2, _s3, _s4], + Suspend1 (4): [_s0, _s1, _s2, _s3, _s4], + Suspend2 (5): [_s1, _s2, _s5], + Suspend3 (6): [_s0, _s1, _s2, _s5], + } + storage_conflicts = BitMatrix(6x6) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s0, _s4), (_s0, _s5), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s1, _s3), (_s1, _s4), (_s1, _s5), (_s2, _s0), (_s2, _s1), (_s2, _s2), (_s2, _s3), (_s2, _s4), (_s2, _s5), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3), (_s3, _s4), (_s4, _s0), (_s4, _s1), (_s4, _s2), (_s4, _s3), (_s4, _s4), (_s5, _s0), (_s5, _s1), (_s5, _s2), (_s5, _s5)} + } + debug _task_context => _2; + coroutine debug sync_int => _s1; + let mut _0: std::task::Poll<()>; + let _3: SyncInt; + let mut _6: impl std::future::Future; + let mut _7: &mut std::task::Context<'_>; + let mut _8: std::task::Poll<()>; + let mut _9: isize; + let mut _10: std::pin::Pin<&mut impl std::future::Future>; + let mut _11: &mut std::task::Context<'_>; + let mut _12: &mut std::task::Context<'_>; + let mut _13: &mut impl std::future::Future; + let mut _14: &mut std::task::Context<'_>; + let mut _15: std::task::Poll<()>; + let mut _16: isize; + let mut _17: std::pin::Pin<&mut impl std::future::Future>; + let mut _18: &mut std::task::Context<'_>; + let mut _19: &mut std::task::Context<'_>; + let mut _20: &mut impl std::future::Future; + let mut _21: std::pin::Pin<&mut AsyncInt>; + let mut _22: &mut AsyncInt; + let mut _23: impl std::future::Future; + let mut _24: &mut std::task::Context<'_>; + let mut _25: std::task::Poll<()>; + let mut _26: isize; + let mut _27: std::pin::Pin<&mut impl std::future::Future>; + let mut _28: &mut std::task::Context<'_>; + let mut _29: &mut std::task::Context<'_>; + let mut _30: &mut impl std::future::Future; + let mut _31: &mut std::task::Context<'_>; + let mut _32: std::task::Poll<()>; + let mut _33: isize; + let mut _34: std::pin::Pin<&mut impl std::future::Future>; + let mut _35: &mut std::task::Context<'_>; + let mut _36: &mut std::task::Context<'_>; + let mut _37: &mut impl std::future::Future; + let mut _38: std::pin::Pin<&mut AsyncInt>; + let mut _39: &mut AsyncInt; + let mut _40: (); + let mut _41: u32; + let mut _42: &mut {async fn body of double()}; + scope 1 { + debug sync_int => (((*_42) as variant#6).1: SyncInt); + coroutine debug async_int => _s2; + let _4: AsyncInt; + scope 2 { + debug async_int => (((*_42) as variant#6).2: AsyncInt); + coroutine debug async_int_again => _s3; + let _5: AsyncInt; + scope 3 { + debug async_int_again => (((*_42) as variant#4).3: AsyncInt); + } + } + } + + bb0: { + _42 = copy (_1.0: &mut {async fn body of double()}); + _41 = discriminant((*_42)); + switchInt(move _41) -> [0: bb1, 1: bb42, 2: bb41, 3: bb37, 4: bb38, 5: bb39, 6: bb40, otherwise: bb14]; + } + + bb1: { + nop; + (((*_42) as variant#6).1: SyncInt) = SyncInt(const 0_i32); + nop; + (((*_42) as variant#6).2: AsyncInt) = AsyncInt(const 0_i32); + nop; + (((*_42) as variant#4).3: AsyncInt) = AsyncInt(const 0_i32); + (((*_42) as variant#6).0: ()) = const (); + goto -> bb22; + } + + bb2: { + nop; + goto -> bb34; + } + + bb3: { + nop; + drop((((*_42) as variant#6).1: SyncInt)) -> [return: bb4, unwind: bb8]; + } + + bb4: { + nop; + goto -> bb35; + } + + bb5: { + _0 = Poll::<()>::Ready(move (((*_42) as variant#6).0: ())); + discriminant((*_42)) = 1; + return; + } + + bb6 (cleanup): { + nop; + drop((((*_42) as variant#6).2: AsyncInt)) -> [return: bb7, unwind terminate(cleanup)]; + } + + bb7 (cleanup): { + nop; + drop((((*_42) as variant#6).1: SyncInt)) -> [return: bb8, unwind terminate(cleanup)]; + } + + bb8 (cleanup): { + nop; + goto -> bb9; + } + + bb9 (cleanup): { + goto -> bb36; + } + + bb10: { + nop; + goto -> bb2; + } + + bb11 (cleanup): { + nop; + goto -> bb6; + } + + bb12: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb12, unwind: bb11]; + } + + bb13: { + _2 = move _7; + StorageDead(_7); + goto -> bb12; + } + + bb14: { + unreachable; + } + + bb15: { + _2 = move _14; + StorageDead(_14); + goto -> bb20; + } + + bb16: { + StorageLive(_14); + _0 = Poll::<()>::Pending; + StorageDead(_14); + discriminant((*_42)) = 4; + return; + } + + bb17: { + _16 = discriminant(_15); + switchInt(move _16) -> [0: bb10, 1: bb16, otherwise: bb14]; + } + + bb18: { + _15 = as Future>::poll(move _17, move _18) -> [return: bb17, unwind: bb11]; + } + + bb19: { + _19 = move _2; + _18 = move _19; + goto -> bb18; + } + + bb20: { + _20 = &mut (((*_42) as variant#4).4: impl std::future::Future); + _17 = Pin::<&mut impl Future>::new_unchecked(move _20) -> [return: bb19, unwind: bb11]; + } + + bb21: { + nop; + (((*_42) as variant#4).4: impl std::future::Future) = async_drop_in_place::(copy (_21.0: &mut AsyncInt)) -> [return: bb20, unwind: bb11]; + } + + bb22: { + _22 = &mut (((*_42) as variant#4).3: AsyncInt); + _21 = Pin::<&mut AsyncInt>::new_unchecked(move _22) -> [return: bb21, unwind: bb6]; + } + + bb23: { + nop; + goto -> bb3; + } + + bb24 (cleanup): { + nop; + goto -> bb7; + } + + bb25: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb25, unwind: bb24]; + } + + bb26: { + _2 = move _24; + StorageDead(_24); + goto -> bb25; + } + + bb27: { + _2 = move _31; + StorageDead(_31); + goto -> bb32; + } + + bb28: { + StorageLive(_31); + _0 = Poll::<()>::Pending; + StorageDead(_31); + discriminant((*_42)) = 6; + return; + } + + bb29: { + _33 = discriminant(_32); + switchInt(move _33) -> [0: bb23, 1: bb28, otherwise: bb14]; + } + + bb30: { + _32 = as Future>::poll(move _34, move _35) -> [return: bb29, unwind: bb24]; + } + + bb31: { + _36 = move _2; + _35 = move _36; + goto -> bb30; + } + + bb32: { + _37 = &mut (((*_42) as variant#6).3: impl std::future::Future); + _34 = Pin::<&mut impl Future>::new_unchecked(move _37) -> [return: bb31, unwind: bb24]; + } + + bb33: { + nop; + (((*_42) as variant#6).3: impl std::future::Future) = async_drop_in_place::(copy (_38.0: &mut AsyncInt)) -> [return: bb32, unwind: bb24]; + } + + bb34: { + _39 = &mut (((*_42) as variant#6).2: AsyncInt); + _38 = Pin::<&mut AsyncInt>::new_unchecked(move _39) -> [return: bb33, unwind: bb7]; + } + + bb35: { + goto -> bb5; + } + + bb36 (cleanup): { + discriminant((*_42)) = 2; + resume; + } + + bb37: { + StorageLive(_7); + _7 = move _2; + goto -> bb13; + } + + bb38: { + StorageLive(_14); + _14 = move _2; + goto -> bb15; + } + + bb39: { + StorageLive(_24); + _24 = move _2; + goto -> bb26; + } + + bb40: { + StorageLive(_31); + _31 = move _2; + goto -> bb27; + } + + bb41: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb41, unwind continue]; + } + + bb42: { + assert(const false, "`async fn` resumed after completion") -> [success: bb42, unwind continue]; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.double-{closure#0}.coroutine_drop_async.0.mir b/tests/mir-opt/coroutine/async_drop.double-{closure#0}.coroutine_drop_async.0.mir new file mode 100644 index 0000000000000..96603c3ada31a --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.double-{closure#0}.coroutine_drop_async.0.mir @@ -0,0 +1,251 @@ +// MIR for `double::{closure#0}` 0 coroutine_drop_async + +fn double::{closure#0}(_1: Pin<&mut {async fn body of double()}>, _2: &mut Context<'_>) -> Poll<()> { + debug _task_context => _2; + let mut _0: std::task::Poll<()>; + let _3: SyncInt; + let mut _6: impl std::future::Future; + let mut _7: &mut std::task::Context<'_>; + let mut _8: std::task::Poll<()>; + let mut _9: isize; + let mut _10: std::pin::Pin<&mut impl std::future::Future>; + let mut _11: &mut std::task::Context<'_>; + let mut _12: &mut std::task::Context<'_>; + let mut _13: &mut impl std::future::Future; + let mut _14: &mut std::task::Context<'_>; + let mut _15: std::task::Poll<()>; + let mut _16: isize; + let mut _17: std::pin::Pin<&mut impl std::future::Future>; + let mut _18: &mut std::task::Context<'_>; + let mut _19: &mut std::task::Context<'_>; + let mut _20: &mut impl std::future::Future; + let mut _21: std::pin::Pin<&mut AsyncInt>; + let mut _22: &mut AsyncInt; + let mut _23: impl std::future::Future; + let mut _24: &mut std::task::Context<'_>; + let mut _25: std::task::Poll<()>; + let mut _26: isize; + let mut _27: std::pin::Pin<&mut impl std::future::Future>; + let mut _28: &mut std::task::Context<'_>; + let mut _29: &mut std::task::Context<'_>; + let mut _30: &mut impl std::future::Future; + let mut _31: &mut std::task::Context<'_>; + let mut _32: std::task::Poll<()>; + let mut _33: isize; + let mut _34: std::pin::Pin<&mut impl std::future::Future>; + let mut _35: &mut std::task::Context<'_>; + let mut _36: &mut std::task::Context<'_>; + let mut _37: &mut impl std::future::Future; + let mut _38: std::pin::Pin<&mut AsyncInt>; + let mut _39: &mut AsyncInt; + let mut _40: (); + let mut _41: u32; + let mut _42: &mut {async fn body of double()}; + scope 1 { + debug sync_int => (((*_42) as variant#6).1: SyncInt); + let _4: AsyncInt; + scope 2 { + debug async_int => (((*_42) as variant#6).2: AsyncInt); + let _5: AsyncInt; + scope 3 { + debug async_int_again => (((*_42) as variant#4).3: AsyncInt); + } + } + } + + bb0: { + _42 = copy (_1.0: &mut {async fn body of double()}); + _41 = discriminant((*_42)); + switchInt(move _41) -> [0: bb29, 2: bb36, 3: bb32, 4: bb33, 5: bb34, 6: bb35, otherwise: bb37]; + } + + bb1: { + nop; + goto -> bb2; + } + + bb2: { + nop; + goto -> bb3; + } + + bb3: { + nop; + goto -> bb4; + } + + bb4: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb5 (cleanup): { + nop; + drop((((*_42) as variant#6).2: AsyncInt)) -> [return: bb6, unwind terminate(cleanup)]; + } + + bb6 (cleanup): { + nop; + drop((((*_42) as variant#6).1: SyncInt)) -> [return: bb7, unwind terminate(cleanup)]; + } + + bb7 (cleanup): { + nop; + goto -> bb8; + } + + bb8 (cleanup): { + goto -> bb31; + } + + bb9: { + nop; + goto -> bb1; + } + + bb10 (cleanup): { + nop; + goto -> bb5; + } + + bb11: { + _2 = move _7; + StorageDead(_7); + goto -> bb17; + } + + bb12: { + StorageLive(_7); + _0 = Poll::<()>::Pending; + StorageDead(_7); + discriminant((*_42)) = 3; + return; + } + + bb13: { + unreachable; + } + + bb14: { + _9 = discriminant(_8); + switchInt(move _9) -> [0: bb9, 1: bb12, otherwise: bb13]; + } + + bb15: { + _8 = as Future>::poll(move _10, move _11) -> [return: bb14, unwind: bb10]; + } + + bb16: { + _12 = move _2; + _11 = move _12; + goto -> bb15; + } + + bb17: { + _13 = &mut (((*_42) as variant#4).4: impl std::future::Future); + _10 = Pin::<&mut impl Future>::new_unchecked(move _13) -> [return: bb16, unwind: bb10]; + } + + bb18: { + _2 = move _14; + StorageDead(_14); + goto -> bb17; + } + + bb19: { + nop; + goto -> bb2; + } + + bb20 (cleanup): { + nop; + goto -> bb6; + } + + bb21: { + _2 = move _24; + StorageDead(_24); + goto -> bb26; + } + + bb22: { + StorageLive(_24); + _0 = Poll::<()>::Pending; + StorageDead(_24); + discriminant((*_42)) = 5; + return; + } + + bb23: { + _26 = discriminant(_25); + switchInt(move _26) -> [0: bb19, 1: bb22, otherwise: bb13]; + } + + bb24: { + _25 = as Future>::poll(move _27, move _28) -> [return: bb23, unwind: bb20]; + } + + bb25: { + _29 = move _2; + _28 = move _29; + goto -> bb24; + } + + bb26: { + _30 = &mut (((*_42) as variant#6).3: impl std::future::Future); + _27 = Pin::<&mut impl Future>::new_unchecked(move _30) -> [return: bb25, unwind: bb20]; + } + + bb27: { + _2 = move _31; + StorageDead(_31); + goto -> bb26; + } + + bb28: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb29: { + goto -> bb30; + } + + bb30: { + goto -> bb28; + } + + bb31 (cleanup): { + discriminant((*_42)) = 2; + resume; + } + + bb32: { + StorageLive(_7); + goto -> bb11; + } + + bb33: { + StorageLive(_14); + goto -> bb18; + } + + bb34: { + StorageLive(_24); + goto -> bb21; + } + + bb35: { + StorageLive(_31); + goto -> bb27; + } + + bb36: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb36, unwind continue]; + } + + bb37: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.elaborate_drops-{closure#0}.ElaborateDrops.diff b/tests/mir-opt/coroutine/async_drop.elaborate_drops-{closure#0}.ElaborateDrops.diff new file mode 100644 index 0000000000000..dd65409f0db13 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.elaborate_drops-{closure#0}.ElaborateDrops.diff @@ -0,0 +1,1657 @@ +- // MIR for `elaborate_drops::{closure#0}` before ElaborateDrops ++ // MIR for `elaborate_drops::{closure#0}` after ElaborateDrops + + fn elaborate_drops::{closure#0}(_1: {async fn body of elaborate_drops()}, _2: std::future::ResumeTy) -> () + yields () + { + debug _task_context => _2; + let mut _0: (); + let _3: SyncInt; + let mut _6: AsyncInt; + let mut _7: AsyncInt; + let mut _9: AsyncInt; + let mut _10: AsyncInt; + let mut _12: AsyncInt; + let mut _13: SyncInt; + let mut _14: AsyncInt; + let mut _16: AsyncInt; + let mut _18: AsyncInt; + let mut _21: &AsyncInt; + let _22: &AsyncInt; ++ let mut _27: impl std::future::Future; ++ let mut _28: std::future::ResumeTy; ++ let mut _29: std::task::Poll<()>; ++ let mut _30: isize; ++ let mut _31: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _32: &mut std::task::Context<'_>; ++ let mut _33: std::future::ResumeTy; ++ let mut _34: &mut impl std::future::Future; ++ let mut _35: std::future::ResumeTy; ++ let mut _36: std::task::Poll<()>; ++ let mut _37: isize; ++ let mut _38: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _39: &mut std::task::Context<'_>; ++ let mut _40: std::future::ResumeTy; ++ let mut _41: &mut impl std::future::Future; ++ let mut _42: std::pin::Pin<&mut {async closure@$DIR/async_drop.rs:78:27: 78:35}>; ++ let mut _43: &mut {async closure@$DIR/async_drop.rs:78:27: 78:35}; ++ let mut _44: impl std::future::Future; ++ let mut _45: std::future::ResumeTy; ++ let mut _46: std::task::Poll<()>; ++ let mut _47: isize; ++ let mut _48: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _49: &mut std::task::Context<'_>; ++ let mut _50: std::future::ResumeTy; ++ let mut _51: &mut impl std::future::Future; ++ let mut _52: std::future::ResumeTy; ++ let mut _53: std::task::Poll<()>; ++ let mut _54: isize; ++ let mut _55: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _56: &mut std::task::Context<'_>; ++ let mut _57: std::future::ResumeTy; ++ let mut _58: &mut impl std::future::Future; ++ let mut _59: std::pin::Pin<&mut {closure@$DIR/async_drop.rs:70:25: 70:27}>; ++ let mut _60: &mut {closure@$DIR/async_drop.rs:70:25: 70:27}; ++ let mut _61: impl std::future::Future; ++ let mut _62: std::future::ResumeTy; ++ let mut _63: std::task::Poll<()>; ++ let mut _64: isize; ++ let mut _65: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _66: &mut std::task::Context<'_>; ++ let mut _67: std::future::ResumeTy; ++ let mut _68: &mut impl std::future::Future; ++ let mut _69: std::future::ResumeTy; ++ let mut _70: std::task::Poll<()>; ++ let mut _71: isize; ++ let mut _72: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _73: &mut std::task::Context<'_>; ++ let mut _74: std::future::ResumeTy; ++ let mut _75: &mut impl std::future::Future; ++ let mut _76: std::pin::Pin<&mut AsyncReference<'_>>; ++ let mut _77: &mut AsyncReference<'_>; ++ let mut _78: impl std::future::Future; ++ let mut _79: std::future::ResumeTy; ++ let mut _80: std::task::Poll<()>; ++ let mut _81: isize; ++ let mut _82: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _83: &mut std::task::Context<'_>; ++ let mut _84: std::future::ResumeTy; ++ let mut _85: &mut impl std::future::Future; ++ let mut _86: std::future::ResumeTy; ++ let mut _87: std::task::Poll<()>; ++ let mut _88: isize; ++ let mut _89: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _90: &mut std::task::Context<'_>; ++ let mut _91: std::future::ResumeTy; ++ let mut _92: &mut impl std::future::Future; ++ let mut _93: std::pin::Pin<&mut AsyncInt>; ++ let mut _94: &mut AsyncInt; ++ let mut _95: impl std::future::Future; ++ let mut _96: std::future::ResumeTy; ++ let mut _97: std::task::Poll<()>; ++ let mut _98: isize; ++ let mut _99: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _100: &mut std::task::Context<'_>; ++ let mut _101: std::future::ResumeTy; ++ let mut _102: &mut impl std::future::Future; ++ let mut _103: std::future::ResumeTy; ++ let mut _104: std::task::Poll<()>; ++ let mut _105: isize; ++ let mut _106: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _107: &mut std::task::Context<'_>; ++ let mut _108: std::future::ResumeTy; ++ let mut _109: &mut impl std::future::Future; ++ let mut _110: std::pin::Pin<&mut AsyncEnum>; ++ let mut _111: &mut AsyncEnum; ++ let mut _112: impl std::future::Future; ++ let mut _113: std::future::ResumeTy; ++ let mut _114: std::task::Poll<()>; ++ let mut _115: isize; ++ let mut _116: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _117: &mut std::task::Context<'_>; ++ let mut _118: std::future::ResumeTy; ++ let mut _119: &mut impl std::future::Future; ++ let mut _120: std::future::ResumeTy; ++ let mut _121: std::task::Poll<()>; ++ let mut _122: isize; ++ let mut _123: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _124: &mut std::task::Context<'_>; ++ let mut _125: std::future::ResumeTy; ++ let mut _126: &mut impl std::future::Future; ++ let mut _127: std::pin::Pin<&mut SyncThenAsync>; ++ let mut _128: &mut SyncThenAsync; ++ let mut _129: impl std::future::Future; ++ let mut _130: std::future::ResumeTy; ++ let mut _131: std::task::Poll<()>; ++ let mut _132: isize; ++ let mut _133: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _134: &mut std::task::Context<'_>; ++ let mut _135: std::future::ResumeTy; ++ let mut _136: &mut impl std::future::Future; ++ let mut _137: std::future::ResumeTy; ++ let mut _138: std::task::Poll<()>; ++ let mut _139: isize; ++ let mut _140: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _141: &mut std::task::Context<'_>; ++ let mut _142: std::future::ResumeTy; ++ let mut _143: &mut impl std::future::Future; ++ let mut _144: std::pin::Pin<&mut AsyncStruct>; ++ let mut _145: &mut AsyncStruct; ++ let mut _146: impl std::future::Future; ++ let mut _147: std::future::ResumeTy; ++ let mut _148: std::task::Poll<()>; ++ let mut _149: isize; ++ let mut _150: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _151: &mut std::task::Context<'_>; ++ let mut _152: std::future::ResumeTy; ++ let mut _153: &mut impl std::future::Future; ++ let mut _154: std::future::ResumeTy; ++ let mut _155: std::task::Poll<()>; ++ let mut _156: isize; ++ let mut _157: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _158: &mut std::task::Context<'_>; ++ let mut _159: std::future::ResumeTy; ++ let mut _160: &mut impl std::future::Future; ++ let mut _161: std::pin::Pin<&mut [AsyncInt; 2]>; ++ let mut _162: &mut [AsyncInt; 2]; ++ let mut _163: impl std::future::Future; ++ let mut _164: std::future::ResumeTy; ++ let mut _165: std::task::Poll<()>; ++ let mut _166: isize; ++ let mut _167: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _168: &mut std::task::Context<'_>; ++ let mut _169: std::future::ResumeTy; ++ let mut _170: &mut impl std::future::Future; ++ let mut _171: std::future::ResumeTy; ++ let mut _172: std::task::Poll<()>; ++ let mut _173: isize; ++ let mut _174: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _175: &mut std::task::Context<'_>; ++ let mut _176: std::future::ResumeTy; ++ let mut _177: &mut impl std::future::Future; ++ let mut _178: std::pin::Pin<&mut AsyncInt>; ++ let mut _179: &mut AsyncInt; + scope 1 { + debug sync_int => _3; + let _4: AsyncInt; + scope 2 { + debug async_int => _4; + let _5: [AsyncInt; 2]; + scope 3 { + debug tuple => _5; + let _8: AsyncStruct; + scope 4 { + debug async_struct => _8; + let _11: SyncThenAsync; + scope 5 { + debug async_struct_mix => _11; + let _15: AsyncEnum; + scope 6 { + debug async_enum => _15; + let _17: std::mem::ManuallyDrop; + scope 7 { + debug manually_drop_async_int => _17; + let _19: AsyncInt; + scope 8 { + debug foo => _19; + let _20: AsyncReference<'_>; + scope 9 { + debug async_ref => _20; + let _23: AsyncInt; + scope 10 { + debug foo => _23; + let _24: {closure@$DIR/async_drop.rs:70:25: 70:27}; + scope 11 { + debug async_closure => _24; + let _25: AsyncInt; + scope 12 { + debug foo => _25; + let _26: {async closure@$DIR/async_drop.rs:78:27: 78:35}; + scope 13 { + debug async_coroutine => _26; + } + } + } + } + } + } + } + } + } + } + } + } + } + + bb0: { + StorageLive(_3); + _3 = SyncInt(const 0_i32); + StorageLive(_4); + _4 = AsyncInt(const 0_i32); + StorageLive(_5); + StorageLive(_6); + _6 = AsyncInt(const 1_i32); + StorageLive(_7); + _7 = AsyncInt(const 2_i32); + _5 = [move _6, move _7]; +- drop(_7) -> [return: bb1, unwind: bb62, drop: bb38]; ++ goto -> bb1; + } + + bb1: { + StorageDead(_7); +- drop(_6) -> [return: bb2, unwind: bb63, drop: bb39]; ++ goto -> bb2; + } + + bb2: { + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = AsyncInt(const 5_i32); + StorageLive(_10); + _10 = AsyncInt(const 4_i32); + _8 = AsyncStruct { i: const 3_i32, a: move _10, b: move _9 }; +- drop(_10) -> [return: bb3, unwind: bb59, drop: bb35]; ++ goto -> bb3; + } + + bb3: { + StorageDead(_10); +- drop(_9) -> [return: bb4, unwind: bb60, drop: bb36]; ++ goto -> bb4; + } + + bb4: { + StorageDead(_9); + StorageLive(_11); + StorageLive(_12); + _12 = AsyncInt(const 7_i32); + StorageLive(_13); + _13 = SyncInt(const 8_i32); + StorageLive(_14); + _14 = AsyncInt(const 9_i32); + _11 = SyncThenAsync { i: const 6_i32, a: move _12, b: move _13, c: move _14 }; +- drop(_14) -> [return: bb5, unwind: bb55, drop: bb31]; ++ goto -> bb5; + } + + bb5: { + StorageDead(_14); +- drop(_13) -> [return: bb6, unwind: bb56]; ++ goto -> bb6; + } + + bb6: { + StorageDead(_13); +- drop(_12) -> [return: bb7, unwind: bb57, drop: bb33]; ++ goto -> bb7; + } + + bb7: { + StorageDead(_12); + StorageLive(_15); + StorageLive(_16); + _16 = AsyncInt(const 10_i32); + _15 = AsyncEnum::A(move _16); +- drop(_16) -> [return: bb8, unwind: bb53, drop: bb29]; ++ goto -> bb8; + } + + bb8: { + StorageDead(_16); + StorageLive(_17); + StorageLive(_18); + _18 = AsyncInt(const 11_i32); + _17 = ManuallyDrop::::new(move _18) -> [return: bb9, unwind: bb50]; + } + + bb9: { + StorageDead(_18); + StorageLive(_19); + _19 = AsyncInt(const 12_i32); + StorageLive(_20); + StorageLive(_21); + StorageLive(_22); + _22 = &_19; + _21 = &(*_22); + _20 = AsyncReference::<'_> { foo: move _21 }; + StorageDead(_21); + StorageDead(_22); + StorageLive(_23); + _23 = AsyncInt(const 14_i32); + StorageLive(_24); + _24 = {closure@$DIR/async_drop.rs:70:25: 70:27} { foo: move _23 }; + StorageLive(_25); + _25 = AsyncInt(const 15_i32); + StorageLive(_26); + _26 = {closure@$DIR/async_drop.rs:78:27: 78:35} { foo: move _25 }; + _0 = const (); +- drop(_26) -> [return: bb10, unwind: bb44, drop: bb23]; ++ goto -> bb103; + } + + bb10: { + StorageDead(_26); +- drop(_25) -> [return: bb11, unwind: bb45, drop: bb24]; ++ goto -> bb11; + } + + bb11: { + StorageDead(_25); +- drop(_24) -> [return: bb12, unwind: bb46, drop: bb25]; ++ goto -> bb123; + } + + bb12: { + StorageDead(_24); +- drop(_23) -> [return: bb13, unwind: bb47, drop: bb26]; ++ goto -> bb13; + } + + bb13: { + StorageDead(_23); +- drop(_20) -> [return: bb14, unwind: bb48, drop: bb27]; ++ goto -> bb143; + } + + bb14: { + StorageDead(_20); +- drop(_19) -> [return: bb15, unwind: bb49, drop: bb28]; ++ goto -> bb163; + } + + bb15: { + StorageDead(_19); + StorageDead(_17); +- drop(_15) -> [return: bb16, unwind: bb54, drop: bb30]; ++ goto -> bb183; + } + + bb16: { + StorageDead(_15); +- drop(_11) -> [return: bb17, unwind: bb58, drop: bb34]; ++ goto -> bb203; + } + + bb17: { + StorageDead(_11); +- drop(_8) -> [return: bb18, unwind: bb61, drop: bb37]; ++ goto -> bb223; + } + + bb18: { + StorageDead(_8); +- drop(_5) -> [return: bb19, unwind: bb64, drop: bb40]; ++ goto -> bb243; + } + + bb19: { + StorageDead(_5); +- drop(_4) -> [return: bb20, unwind: bb65, drop: bb41]; ++ goto -> bb263; + } + + bb20: { + StorageDead(_4); + drop(_3) -> [return: bb21, unwind: bb66]; + } + + bb21: { + StorageDead(_3); +- drop(_1) -> [return: bb22, drop: bb43, unwind continue]; ++ drop(_1) -> [return: bb22, unwind: bb67]; + } + + bb22: { + return; + } + + bb23: { + StorageDead(_26); +- drop(_25) -> [return: bb24, unwind: bb68]; ++ goto -> bb24; + } + + bb24: { + StorageDead(_25); +- drop(_24) -> [return: bb25, unwind: bb69]; ++ goto -> bb25; + } + + bb25: { + StorageDead(_24); +- drop(_23) -> [return: bb26, unwind: bb70]; ++ goto -> bb26; + } + + bb26: { + StorageDead(_23); +- drop(_20) -> [return: bb27, unwind: bb71]; ++ goto -> bb27; + } + + bb27: { + StorageDead(_20); +- drop(_19) -> [return: bb28, unwind: bb72]; ++ goto -> bb28; + } + + bb28: { + StorageDead(_19); + StorageDead(_17); +- drop(_15) -> [return: bb30, unwind: bb73]; ++ goto -> bb30; + } + + bb29: { + StorageDead(_16); + goto -> bb30; + } + + bb30: { + StorageDead(_15); +- drop(_11) -> [return: bb34, unwind: bb76]; ++ goto -> bb34; + } + + bb31: { + StorageDead(_14); +- drop(_13) -> [return: bb32, unwind: bb74]; ++ goto -> bb32; + } + + bb32: { + StorageDead(_13); +- drop(_12) -> [return: bb33, unwind: bb75]; ++ goto -> bb33; + } + + bb33: { + StorageDead(_12); + goto -> bb34; + } + + bb34: { + StorageDead(_11); +- drop(_8) -> [return: bb37, unwind: bb78]; ++ goto -> bb37; + } + + bb35: { + StorageDead(_10); +- drop(_9) -> [return: bb36, unwind: bb77]; ++ goto -> bb36; + } + + bb36: { + StorageDead(_9); + goto -> bb37; + } + + bb37: { + StorageDead(_8); +- drop(_5) -> [return: bb40, unwind: bb80]; ++ goto -> bb40; + } + + bb38: { + StorageDead(_7); +- drop(_6) -> [return: bb39, unwind: bb79]; ++ goto -> bb39; + } + + bb39: { + StorageDead(_6); + goto -> bb40; + } + + bb40: { + StorageDead(_5); +- drop(_4) -> [return: bb41, unwind: bb81]; ++ goto -> bb41; + } + + bb41: { + StorageDead(_4); +- drop(_3) -> [return: bb42, unwind: bb82]; ++ goto -> bb42; + } + + bb42: { + StorageDead(_3); +- drop(_1) -> [return: bb43, unwind continue]; ++ goto -> bb43; + } + + bb43: { + coroutine_drop; + } + + bb44 (cleanup): { + StorageDead(_26); +- drop(_25) -> [return: bb45, unwind terminate(cleanup)]; ++ goto -> bb45; + } + + bb45 (cleanup): { + StorageDead(_25); + drop(_24) -> [return: bb46, unwind terminate(cleanup)]; + } + + bb46 (cleanup): { + StorageDead(_24); +- drop(_23) -> [return: bb47, unwind terminate(cleanup)]; ++ goto -> bb47; + } + + bb47 (cleanup): { + StorageDead(_23); + drop(_20) -> [return: bb48, unwind terminate(cleanup)]; + } + + bb48 (cleanup): { + StorageDead(_20); + drop(_19) -> [return: bb49, unwind terminate(cleanup)]; + } + + bb49 (cleanup): { + StorageDead(_19); + goto -> bb52; + } + + bb50 (cleanup): { +- drop(_18) -> [return: bb51, unwind terminate(cleanup)]; ++ goto -> bb51; + } + + bb51 (cleanup): { + StorageDead(_18); + goto -> bb52; + } + + bb52 (cleanup): { + StorageDead(_17); + drop(_15) -> [return: bb54, unwind terminate(cleanup)]; + } + + bb53 (cleanup): { + StorageDead(_16); + goto -> bb54; + } + + bb54 (cleanup): { + StorageDead(_15); + drop(_11) -> [return: bb58, unwind terminate(cleanup)]; + } + + bb55 (cleanup): { + StorageDead(_14); +- drop(_13) -> [return: bb56, unwind terminate(cleanup)]; ++ goto -> bb56; + } + + bb56 (cleanup): { + StorageDead(_13); +- drop(_12) -> [return: bb57, unwind terminate(cleanup)]; ++ goto -> bb57; + } + + bb57 (cleanup): { + StorageDead(_12); + goto -> bb58; + } + + bb58 (cleanup): { + StorageDead(_11); + drop(_8) -> [return: bb61, unwind terminate(cleanup)]; + } + + bb59 (cleanup): { + StorageDead(_10); +- drop(_9) -> [return: bb60, unwind terminate(cleanup)]; ++ goto -> bb60; + } + + bb60 (cleanup): { + StorageDead(_9); + goto -> bb61; + } + + bb61 (cleanup): { + StorageDead(_8); + drop(_5) -> [return: bb64, unwind terminate(cleanup)]; + } + + bb62 (cleanup): { + StorageDead(_7); +- drop(_6) -> [return: bb63, unwind terminate(cleanup)]; ++ goto -> bb63; + } + + bb63 (cleanup): { + StorageDead(_6); + goto -> bb64; + } + + bb64 (cleanup): { + StorageDead(_5); + drop(_4) -> [return: bb65, unwind terminate(cleanup)]; + } + + bb65 (cleanup): { + StorageDead(_4); + drop(_3) -> [return: bb66, unwind terminate(cleanup)]; + } + + bb66 (cleanup): { + StorageDead(_3); + drop(_1) -> [return: bb67, unwind terminate(cleanup)]; + } + + bb67 (cleanup): { + resume; + } + + bb68 (cleanup): { + StorageDead(_25); +- drop(_24) -> [return: bb69, unwind terminate(cleanup)]; ++ goto -> bb69; + } + + bb69 (cleanup): { + StorageDead(_24); +- drop(_23) -> [return: bb70, unwind terminate(cleanup)]; ++ goto -> bb70; + } + + bb70 (cleanup): { + StorageDead(_23); +- drop(_20) -> [return: bb71, unwind terminate(cleanup)]; ++ goto -> bb71; + } + + bb71 (cleanup): { + StorageDead(_20); +- drop(_19) -> [return: bb72, unwind terminate(cleanup)]; ++ goto -> bb72; + } + + bb72 (cleanup): { + StorageDead(_19); + StorageDead(_17); +- drop(_15) -> [return: bb73, unwind terminate(cleanup)]; ++ goto -> bb73; + } + + bb73 (cleanup): { + StorageDead(_15); +- drop(_11) -> [return: bb76, unwind terminate(cleanup)]; ++ goto -> bb76; + } + + bb74 (cleanup): { + StorageDead(_13); +- drop(_12) -> [return: bb75, unwind terminate(cleanup)]; ++ goto -> bb75; + } + + bb75 (cleanup): { + StorageDead(_12); + goto -> bb76; + } + + bb76 (cleanup): { + StorageDead(_11); +- drop(_8) -> [return: bb78, unwind terminate(cleanup)]; ++ goto -> bb78; + } + + bb77 (cleanup): { + StorageDead(_9); + goto -> bb78; + } + + bb78 (cleanup): { + StorageDead(_8); +- drop(_5) -> [return: bb80, unwind terminate(cleanup)]; ++ goto -> bb80; + } + + bb79 (cleanup): { + StorageDead(_6); + goto -> bb80; + } + + bb80 (cleanup): { + StorageDead(_5); +- drop(_4) -> [return: bb81, unwind terminate(cleanup)]; ++ goto -> bb81; + } + + bb81 (cleanup): { + StorageDead(_4); +- drop(_3) -> [return: bb82, unwind terminate(cleanup)]; ++ goto -> bb82; + } + + bb82 (cleanup): { + StorageDead(_3); +- drop(_1) -> [return: bb67, unwind terminate(cleanup)]; ++ goto -> bb67; ++ } ++ ++ bb83: { ++ StorageDead(_27); ++ goto -> bb10; ++ } ++ ++ bb84: { ++ StorageDead(_27); ++ goto -> bb23; ++ } ++ ++ bb85 (cleanup): { ++ StorageDead(_27); ++ goto -> bb44; ++ } ++ ++ bb86: { ++ assert(const false, "`async fn` resumed after async drop") -> [success: bb86, unwind: bb85]; ++ } ++ ++ bb87: { ++ _2 = move _28; ++ StorageDead(_28); ++ goto -> bb86; ++ } ++ ++ bb88: { ++ _2 = move _28; ++ StorageDead(_28); ++ goto -> bb94; ++ } ++ ++ bb89: { ++ StorageLive(_28); ++ _28 = yield(const ()) -> [resume: bb87, drop: bb88]; ++ } ++ ++ bb90: { ++ unreachable; ++ } ++ ++ bb91: { ++ _30 = discriminant(_29); ++ switchInt(move _30) -> [0: bb84, 1: bb89, otherwise: bb90]; ++ } ++ ++ bb92: { ++ _29 = as Future>::poll(move _31, move _32) -> [return: bb91, unwind: bb85]; ++ } ++ ++ bb93: { ++ _33 = move _2; ++ _32 = std::future::get_context::<'_, '_>(move _33) -> [return: bb92, unwind: bb85]; ++ } ++ ++ bb94: { ++ _34 = &mut _27; ++ _31 = Pin::<&mut impl Future>::new_unchecked(move _34) -> [return: bb93, unwind: bb85]; ++ } ++ ++ bb95: { ++ _2 = move _35; ++ StorageDead(_35); ++ goto -> bb101; ++ } ++ ++ bb96: { ++ _2 = move _35; ++ StorageDead(_35); ++ goto -> bb94; ++ } ++ ++ bb97: { ++ StorageLive(_35); ++ _35 = yield(const ()) -> [resume: bb95, drop: bb96]; ++ } ++ ++ bb98: { ++ _37 = discriminant(_36); ++ switchInt(move _37) -> [0: bb83, 1: bb97, otherwise: bb90]; ++ } ++ ++ bb99: { ++ _36 = as Future>::poll(move _38, move _39) -> [return: bb98, unwind: bb85]; ++ } ++ ++ bb100: { ++ _40 = move _2; ++ _39 = std::future::get_context::<'_, '_>(move _40) -> [return: bb99, unwind: bb85]; ++ } ++ ++ bb101: { ++ _41 = &mut _27; ++ _38 = Pin::<&mut impl Future>::new_unchecked(move _41) -> [return: bb100, unwind: bb85]; ++ } ++ ++ bb102: { ++ StorageLive(_27); ++ _27 = async_drop_in_place::<{async closure@$DIR/async_drop.rs:78:27: 78:35}>(copy (_42.0: &mut {async closure@$DIR/async_drop.rs:78:27: 78:35})) -> [return: bb101, unwind: bb85]; ++ } ++ ++ bb103: { ++ _43 = &mut _26; ++ _42 = Pin::<&mut {async closure@$DIR/async_drop.rs:78:27: 78:35}>::new_unchecked(move _43) -> [return: bb102, unwind: bb44]; ++ } ++ ++ bb104: { ++ StorageDead(_44); ++ goto -> bb12; ++ } ++ ++ bb105: { ++ StorageDead(_44); ++ goto -> bb25; ++ } ++ ++ bb106 (cleanup): { ++ StorageDead(_44); ++ goto -> bb46; ++ } ++ ++ bb107: { ++ assert(const false, "`async fn` resumed after async drop") -> [success: bb107, unwind: bb106]; ++ } ++ ++ bb108: { ++ _2 = move _45; ++ StorageDead(_45); ++ goto -> bb107; ++ } ++ ++ bb109: { ++ _2 = move _45; ++ StorageDead(_45); ++ goto -> bb114; ++ } ++ ++ bb110: { ++ StorageLive(_45); ++ _45 = yield(const ()) -> [resume: bb108, drop: bb109]; ++ } ++ ++ bb111: { ++ _47 = discriminant(_46); ++ switchInt(move _47) -> [0: bb105, 1: bb110, otherwise: bb90]; ++ } ++ ++ bb112: { ++ _46 = as Future>::poll(move _48, move _49) -> [return: bb111, unwind: bb106]; ++ } ++ ++ bb113: { ++ _50 = move _2; ++ _49 = std::future::get_context::<'_, '_>(move _50) -> [return: bb112, unwind: bb106]; ++ } ++ ++ bb114: { ++ _51 = &mut _44; ++ _48 = Pin::<&mut impl Future>::new_unchecked(move _51) -> [return: bb113, unwind: bb106]; ++ } ++ ++ bb115: { ++ _2 = move _52; ++ StorageDead(_52); ++ goto -> bb121; ++ } ++ ++ bb116: { ++ _2 = move _52; ++ StorageDead(_52); ++ goto -> bb114; ++ } ++ ++ bb117: { ++ StorageLive(_52); ++ _52 = yield(const ()) -> [resume: bb115, drop: bb116]; ++ } ++ ++ bb118: { ++ _54 = discriminant(_53); ++ switchInt(move _54) -> [0: bb104, 1: bb117, otherwise: bb90]; ++ } ++ ++ bb119: { ++ _53 = as Future>::poll(move _55, move _56) -> [return: bb118, unwind: bb106]; ++ } ++ ++ bb120: { ++ _57 = move _2; ++ _56 = std::future::get_context::<'_, '_>(move _57) -> [return: bb119, unwind: bb106]; ++ } ++ ++ bb121: { ++ _58 = &mut _44; ++ _55 = Pin::<&mut impl Future>::new_unchecked(move _58) -> [return: bb120, unwind: bb106]; ++ } ++ ++ bb122: { ++ StorageLive(_44); ++ _44 = async_drop_in_place::<{closure@$DIR/async_drop.rs:70:25: 70:27}>(copy (_59.0: &mut {closure@$DIR/async_drop.rs:70:25: 70:27})) -> [return: bb121, unwind: bb106]; ++ } ++ ++ bb123: { ++ _60 = &mut _24; ++ _59 = Pin::<&mut {closure@$DIR/async_drop.rs:70:25: 70:27}>::new_unchecked(move _60) -> [return: bb122, unwind: bb46]; ++ } ++ ++ bb124: { ++ StorageDead(_61); ++ goto -> bb14; ++ } ++ ++ bb125: { ++ StorageDead(_61); ++ goto -> bb27; ++ } ++ ++ bb126 (cleanup): { ++ StorageDead(_61); ++ goto -> bb48; ++ } ++ ++ bb127: { ++ assert(const false, "`async fn` resumed after async drop") -> [success: bb127, unwind: bb126]; ++ } ++ ++ bb128: { ++ _2 = move _62; ++ StorageDead(_62); ++ goto -> bb127; ++ } ++ ++ bb129: { ++ _2 = move _62; ++ StorageDead(_62); ++ goto -> bb134; ++ } ++ ++ bb130: { ++ StorageLive(_62); ++ _62 = yield(const ()) -> [resume: bb128, drop: bb129]; ++ } ++ ++ bb131: { ++ _64 = discriminant(_63); ++ switchInt(move _64) -> [0: bb125, 1: bb130, otherwise: bb90]; ++ } ++ ++ bb132: { ++ _63 = as Future>::poll(move _65, move _66) -> [return: bb131, unwind: bb126]; ++ } ++ ++ bb133: { ++ _67 = move _2; ++ _66 = std::future::get_context::<'_, '_>(move _67) -> [return: bb132, unwind: bb126]; ++ } ++ ++ bb134: { ++ _68 = &mut _61; ++ _65 = Pin::<&mut impl Future>::new_unchecked(move _68) -> [return: bb133, unwind: bb126]; ++ } ++ ++ bb135: { ++ _2 = move _69; ++ StorageDead(_69); ++ goto -> bb141; ++ } ++ ++ bb136: { ++ _2 = move _69; ++ StorageDead(_69); ++ goto -> bb134; ++ } ++ ++ bb137: { ++ StorageLive(_69); ++ _69 = yield(const ()) -> [resume: bb135, drop: bb136]; ++ } ++ ++ bb138: { ++ _71 = discriminant(_70); ++ switchInt(move _71) -> [0: bb124, 1: bb137, otherwise: bb90]; ++ } ++ ++ bb139: { ++ _70 = as Future>::poll(move _72, move _73) -> [return: bb138, unwind: bb126]; ++ } ++ ++ bb140: { ++ _74 = move _2; ++ _73 = std::future::get_context::<'_, '_>(move _74) -> [return: bb139, unwind: bb126]; ++ } ++ ++ bb141: { ++ _75 = &mut _61; ++ _72 = Pin::<&mut impl Future>::new_unchecked(move _75) -> [return: bb140, unwind: bb126]; ++ } ++ ++ bb142: { ++ StorageLive(_61); ++ _61 = async_drop_in_place::>(copy (_76.0: &mut AsyncReference<'_>)) -> [return: bb141, unwind: bb126]; ++ } ++ ++ bb143: { ++ _77 = &mut _20; ++ _76 = Pin::<&mut AsyncReference<'_>>::new_unchecked(move _77) -> [return: bb142, unwind: bb48]; ++ } ++ ++ bb144: { ++ StorageDead(_78); ++ goto -> bb15; ++ } ++ ++ bb145: { ++ StorageDead(_78); ++ goto -> bb28; ++ } ++ ++ bb146 (cleanup): { ++ StorageDead(_78); ++ goto -> bb49; ++ } ++ ++ bb147: { ++ assert(const false, "`async fn` resumed after async drop") -> [success: bb147, unwind: bb146]; ++ } ++ ++ bb148: { ++ _2 = move _79; ++ StorageDead(_79); ++ goto -> bb147; ++ } ++ ++ bb149: { ++ _2 = move _79; ++ StorageDead(_79); ++ goto -> bb154; ++ } ++ ++ bb150: { ++ StorageLive(_79); ++ _79 = yield(const ()) -> [resume: bb148, drop: bb149]; ++ } ++ ++ bb151: { ++ _81 = discriminant(_80); ++ switchInt(move _81) -> [0: bb145, 1: bb150, otherwise: bb90]; ++ } ++ ++ bb152: { ++ _80 = as Future>::poll(move _82, move _83) -> [return: bb151, unwind: bb146]; ++ } ++ ++ bb153: { ++ _84 = move _2; ++ _83 = std::future::get_context::<'_, '_>(move _84) -> [return: bb152, unwind: bb146]; ++ } ++ ++ bb154: { ++ _85 = &mut _78; ++ _82 = Pin::<&mut impl Future>::new_unchecked(move _85) -> [return: bb153, unwind: bb146]; ++ } ++ ++ bb155: { ++ _2 = move _86; ++ StorageDead(_86); ++ goto -> bb161; ++ } ++ ++ bb156: { ++ _2 = move _86; ++ StorageDead(_86); ++ goto -> bb154; ++ } ++ ++ bb157: { ++ StorageLive(_86); ++ _86 = yield(const ()) -> [resume: bb155, drop: bb156]; ++ } ++ ++ bb158: { ++ _88 = discriminant(_87); ++ switchInt(move _88) -> [0: bb144, 1: bb157, otherwise: bb90]; ++ } ++ ++ bb159: { ++ _87 = as Future>::poll(move _89, move _90) -> [return: bb158, unwind: bb146]; ++ } ++ ++ bb160: { ++ _91 = move _2; ++ _90 = std::future::get_context::<'_, '_>(move _91) -> [return: bb159, unwind: bb146]; ++ } ++ ++ bb161: { ++ _92 = &mut _78; ++ _89 = Pin::<&mut impl Future>::new_unchecked(move _92) -> [return: bb160, unwind: bb146]; ++ } ++ ++ bb162: { ++ StorageLive(_78); ++ _78 = async_drop_in_place::(copy (_93.0: &mut AsyncInt)) -> [return: bb161, unwind: bb146]; ++ } ++ ++ bb163: { ++ _94 = &mut _19; ++ _93 = Pin::<&mut AsyncInt>::new_unchecked(move _94) -> [return: bb162, unwind: bb49]; ++ } ++ ++ bb164: { ++ StorageDead(_95); ++ goto -> bb16; ++ } ++ ++ bb165: { ++ StorageDead(_95); ++ goto -> bb30; ++ } ++ ++ bb166 (cleanup): { ++ StorageDead(_95); ++ goto -> bb54; ++ } ++ ++ bb167: { ++ assert(const false, "`async fn` resumed after async drop") -> [success: bb167, unwind: bb166]; ++ } ++ ++ bb168: { ++ _2 = move _96; ++ StorageDead(_96); ++ goto -> bb167; ++ } ++ ++ bb169: { ++ _2 = move _96; ++ StorageDead(_96); ++ goto -> bb174; ++ } ++ ++ bb170: { ++ StorageLive(_96); ++ _96 = yield(const ()) -> [resume: bb168, drop: bb169]; ++ } ++ ++ bb171: { ++ _98 = discriminant(_97); ++ switchInt(move _98) -> [0: bb165, 1: bb170, otherwise: bb90]; ++ } ++ ++ bb172: { ++ _97 = as Future>::poll(move _99, move _100) -> [return: bb171, unwind: bb166]; ++ } ++ ++ bb173: { ++ _101 = move _2; ++ _100 = std::future::get_context::<'_, '_>(move _101) -> [return: bb172, unwind: bb166]; ++ } ++ ++ bb174: { ++ _102 = &mut _95; ++ _99 = Pin::<&mut impl Future>::new_unchecked(move _102) -> [return: bb173, unwind: bb166]; ++ } ++ ++ bb175: { ++ _2 = move _103; ++ StorageDead(_103); ++ goto -> bb181; ++ } ++ ++ bb176: { ++ _2 = move _103; ++ StorageDead(_103); ++ goto -> bb174; ++ } ++ ++ bb177: { ++ StorageLive(_103); ++ _103 = yield(const ()) -> [resume: bb175, drop: bb176]; ++ } ++ ++ bb178: { ++ _105 = discriminant(_104); ++ switchInt(move _105) -> [0: bb164, 1: bb177, otherwise: bb90]; ++ } ++ ++ bb179: { ++ _104 = as Future>::poll(move _106, move _107) -> [return: bb178, unwind: bb166]; ++ } ++ ++ bb180: { ++ _108 = move _2; ++ _107 = std::future::get_context::<'_, '_>(move _108) -> [return: bb179, unwind: bb166]; ++ } ++ ++ bb181: { ++ _109 = &mut _95; ++ _106 = Pin::<&mut impl Future>::new_unchecked(move _109) -> [return: bb180, unwind: bb166]; ++ } ++ ++ bb182: { ++ StorageLive(_95); ++ _95 = async_drop_in_place::(copy (_110.0: &mut AsyncEnum)) -> [return: bb181, unwind: bb166]; ++ } ++ ++ bb183: { ++ _111 = &mut _15; ++ _110 = Pin::<&mut AsyncEnum>::new_unchecked(move _111) -> [return: bb182, unwind: bb54]; ++ } ++ ++ bb184: { ++ StorageDead(_112); ++ goto -> bb17; ++ } ++ ++ bb185: { ++ StorageDead(_112); ++ goto -> bb34; ++ } ++ ++ bb186 (cleanup): { ++ StorageDead(_112); ++ goto -> bb58; ++ } ++ ++ bb187: { ++ assert(const false, "`async fn` resumed after async drop") -> [success: bb187, unwind: bb186]; ++ } ++ ++ bb188: { ++ _2 = move _113; ++ StorageDead(_113); ++ goto -> bb187; ++ } ++ ++ bb189: { ++ _2 = move _113; ++ StorageDead(_113); ++ goto -> bb194; ++ } ++ ++ bb190: { ++ StorageLive(_113); ++ _113 = yield(const ()) -> [resume: bb188, drop: bb189]; ++ } ++ ++ bb191: { ++ _115 = discriminant(_114); ++ switchInt(move _115) -> [0: bb185, 1: bb190, otherwise: bb90]; ++ } ++ ++ bb192: { ++ _114 = as Future>::poll(move _116, move _117) -> [return: bb191, unwind: bb186]; ++ } ++ ++ bb193: { ++ _118 = move _2; ++ _117 = std::future::get_context::<'_, '_>(move _118) -> [return: bb192, unwind: bb186]; ++ } ++ ++ bb194: { ++ _119 = &mut _112; ++ _116 = Pin::<&mut impl Future>::new_unchecked(move _119) -> [return: bb193, unwind: bb186]; ++ } ++ ++ bb195: { ++ _2 = move _120; ++ StorageDead(_120); ++ goto -> bb201; ++ } ++ ++ bb196: { ++ _2 = move _120; ++ StorageDead(_120); ++ goto -> bb194; ++ } ++ ++ bb197: { ++ StorageLive(_120); ++ _120 = yield(const ()) -> [resume: bb195, drop: bb196]; ++ } ++ ++ bb198: { ++ _122 = discriminant(_121); ++ switchInt(move _122) -> [0: bb184, 1: bb197, otherwise: bb90]; ++ } ++ ++ bb199: { ++ _121 = as Future>::poll(move _123, move _124) -> [return: bb198, unwind: bb186]; ++ } ++ ++ bb200: { ++ _125 = move _2; ++ _124 = std::future::get_context::<'_, '_>(move _125) -> [return: bb199, unwind: bb186]; ++ } ++ ++ bb201: { ++ _126 = &mut _112; ++ _123 = Pin::<&mut impl Future>::new_unchecked(move _126) -> [return: bb200, unwind: bb186]; ++ } ++ ++ bb202: { ++ StorageLive(_112); ++ _112 = async_drop_in_place::(copy (_127.0: &mut SyncThenAsync)) -> [return: bb201, unwind: bb186]; ++ } ++ ++ bb203: { ++ _128 = &mut _11; ++ _127 = Pin::<&mut SyncThenAsync>::new_unchecked(move _128) -> [return: bb202, unwind: bb58]; ++ } ++ ++ bb204: { ++ StorageDead(_129); ++ goto -> bb18; ++ } ++ ++ bb205: { ++ StorageDead(_129); ++ goto -> bb37; ++ } ++ ++ bb206 (cleanup): { ++ StorageDead(_129); ++ goto -> bb61; ++ } ++ ++ bb207: { ++ assert(const false, "`async fn` resumed after async drop") -> [success: bb207, unwind: bb206]; ++ } ++ ++ bb208: { ++ _2 = move _130; ++ StorageDead(_130); ++ goto -> bb207; ++ } ++ ++ bb209: { ++ _2 = move _130; ++ StorageDead(_130); ++ goto -> bb214; ++ } ++ ++ bb210: { ++ StorageLive(_130); ++ _130 = yield(const ()) -> [resume: bb208, drop: bb209]; ++ } ++ ++ bb211: { ++ _132 = discriminant(_131); ++ switchInt(move _132) -> [0: bb205, 1: bb210, otherwise: bb90]; ++ } ++ ++ bb212: { ++ _131 = as Future>::poll(move _133, move _134) -> [return: bb211, unwind: bb206]; ++ } ++ ++ bb213: { ++ _135 = move _2; ++ _134 = std::future::get_context::<'_, '_>(move _135) -> [return: bb212, unwind: bb206]; ++ } ++ ++ bb214: { ++ _136 = &mut _129; ++ _133 = Pin::<&mut impl Future>::new_unchecked(move _136) -> [return: bb213, unwind: bb206]; ++ } ++ ++ bb215: { ++ _2 = move _137; ++ StorageDead(_137); ++ goto -> bb221; ++ } ++ ++ bb216: { ++ _2 = move _137; ++ StorageDead(_137); ++ goto -> bb214; ++ } ++ ++ bb217: { ++ StorageLive(_137); ++ _137 = yield(const ()) -> [resume: bb215, drop: bb216]; ++ } ++ ++ bb218: { ++ _139 = discriminant(_138); ++ switchInt(move _139) -> [0: bb204, 1: bb217, otherwise: bb90]; ++ } ++ ++ bb219: { ++ _138 = as Future>::poll(move _140, move _141) -> [return: bb218, unwind: bb206]; ++ } ++ ++ bb220: { ++ _142 = move _2; ++ _141 = std::future::get_context::<'_, '_>(move _142) -> [return: bb219, unwind: bb206]; ++ } ++ ++ bb221: { ++ _143 = &mut _129; ++ _140 = Pin::<&mut impl Future>::new_unchecked(move _143) -> [return: bb220, unwind: bb206]; ++ } ++ ++ bb222: { ++ StorageLive(_129); ++ _129 = async_drop_in_place::(copy (_144.0: &mut AsyncStruct)) -> [return: bb221, unwind: bb206]; ++ } ++ ++ bb223: { ++ _145 = &mut _8; ++ _144 = Pin::<&mut AsyncStruct>::new_unchecked(move _145) -> [return: bb222, unwind: bb61]; ++ } ++ ++ bb224: { ++ StorageDead(_146); ++ goto -> bb19; ++ } ++ ++ bb225: { ++ StorageDead(_146); ++ goto -> bb40; ++ } ++ ++ bb226 (cleanup): { ++ StorageDead(_146); ++ goto -> bb64; ++ } ++ ++ bb227: { ++ assert(const false, "`async fn` resumed after async drop") -> [success: bb227, unwind: bb226]; ++ } ++ ++ bb228: { ++ _2 = move _147; ++ StorageDead(_147); ++ goto -> bb227; ++ } ++ ++ bb229: { ++ _2 = move _147; ++ StorageDead(_147); ++ goto -> bb234; ++ } ++ ++ bb230: { ++ StorageLive(_147); ++ _147 = yield(const ()) -> [resume: bb228, drop: bb229]; ++ } ++ ++ bb231: { ++ _149 = discriminant(_148); ++ switchInt(move _149) -> [0: bb225, 1: bb230, otherwise: bb90]; ++ } ++ ++ bb232: { ++ _148 = as Future>::poll(move _150, move _151) -> [return: bb231, unwind: bb226]; ++ } ++ ++ bb233: { ++ _152 = move _2; ++ _151 = std::future::get_context::<'_, '_>(move _152) -> [return: bb232, unwind: bb226]; ++ } ++ ++ bb234: { ++ _153 = &mut _146; ++ _150 = Pin::<&mut impl Future>::new_unchecked(move _153) -> [return: bb233, unwind: bb226]; ++ } ++ ++ bb235: { ++ _2 = move _154; ++ StorageDead(_154); ++ goto -> bb241; ++ } ++ ++ bb236: { ++ _2 = move _154; ++ StorageDead(_154); ++ goto -> bb234; ++ } ++ ++ bb237: { ++ StorageLive(_154); ++ _154 = yield(const ()) -> [resume: bb235, drop: bb236]; ++ } ++ ++ bb238: { ++ _156 = discriminant(_155); ++ switchInt(move _156) -> [0: bb224, 1: bb237, otherwise: bb90]; ++ } ++ ++ bb239: { ++ _155 = as Future>::poll(move _157, move _158) -> [return: bb238, unwind: bb226]; ++ } ++ ++ bb240: { ++ _159 = move _2; ++ _158 = std::future::get_context::<'_, '_>(move _159) -> [return: bb239, unwind: bb226]; ++ } ++ ++ bb241: { ++ _160 = &mut _146; ++ _157 = Pin::<&mut impl Future>::new_unchecked(move _160) -> [return: bb240, unwind: bb226]; ++ } ++ ++ bb242: { ++ StorageLive(_146); ++ _146 = async_drop_in_place::<[AsyncInt; 2]>(copy (_161.0: &mut [AsyncInt; 2])) -> [return: bb241, unwind: bb226]; ++ } ++ ++ bb243: { ++ _162 = &mut _5; ++ _161 = Pin::<&mut [AsyncInt; 2]>::new_unchecked(move _162) -> [return: bb242, unwind: bb64]; ++ } ++ ++ bb244: { ++ StorageDead(_163); ++ goto -> bb20; ++ } ++ ++ bb245: { ++ StorageDead(_163); ++ goto -> bb41; ++ } ++ ++ bb246 (cleanup): { ++ StorageDead(_163); ++ goto -> bb65; ++ } ++ ++ bb247: { ++ assert(const false, "`async fn` resumed after async drop") -> [success: bb247, unwind: bb246]; ++ } ++ ++ bb248: { ++ _2 = move _164; ++ StorageDead(_164); ++ goto -> bb247; ++ } ++ ++ bb249: { ++ _2 = move _164; ++ StorageDead(_164); ++ goto -> bb254; ++ } ++ ++ bb250: { ++ StorageLive(_164); ++ _164 = yield(const ()) -> [resume: bb248, drop: bb249]; ++ } ++ ++ bb251: { ++ _166 = discriminant(_165); ++ switchInt(move _166) -> [0: bb245, 1: bb250, otherwise: bb90]; ++ } ++ ++ bb252: { ++ _165 = as Future>::poll(move _167, move _168) -> [return: bb251, unwind: bb246]; ++ } ++ ++ bb253: { ++ _169 = move _2; ++ _168 = std::future::get_context::<'_, '_>(move _169) -> [return: bb252, unwind: bb246]; ++ } ++ ++ bb254: { ++ _170 = &mut _163; ++ _167 = Pin::<&mut impl Future>::new_unchecked(move _170) -> [return: bb253, unwind: bb246]; ++ } ++ ++ bb255: { ++ _2 = move _171; ++ StorageDead(_171); ++ goto -> bb261; ++ } ++ ++ bb256: { ++ _2 = move _171; ++ StorageDead(_171); ++ goto -> bb254; ++ } ++ ++ bb257: { ++ StorageLive(_171); ++ _171 = yield(const ()) -> [resume: bb255, drop: bb256]; ++ } ++ ++ bb258: { ++ _173 = discriminant(_172); ++ switchInt(move _173) -> [0: bb244, 1: bb257, otherwise: bb90]; ++ } ++ ++ bb259: { ++ _172 = as Future>::poll(move _174, move _175) -> [return: bb258, unwind: bb246]; ++ } ++ ++ bb260: { ++ _176 = move _2; ++ _175 = std::future::get_context::<'_, '_>(move _176) -> [return: bb259, unwind: bb246]; ++ } ++ ++ bb261: { ++ _177 = &mut _163; ++ _174 = Pin::<&mut impl Future>::new_unchecked(move _177) -> [return: bb260, unwind: bb246]; ++ } ++ ++ bb262: { ++ StorageLive(_163); ++ _163 = async_drop_in_place::(copy (_178.0: &mut AsyncInt)) -> [return: bb261, unwind: bb246]; ++ } ++ ++ bb263: { ++ _179 = &mut _4; ++ _178 = Pin::<&mut AsyncInt>::new_unchecked(move _179) -> [return: bb262, unwind: bb65]; + } + } + diff --git a/tests/mir-opt/coroutine/async_drop.elaborate_drops-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_drop.elaborate_drops-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..69b40c979a9f5 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.elaborate_drops-{closure#0}.StateTransform.after.mir @@ -0,0 +1,1257 @@ +// MIR for `elaborate_drops::{closure#0}` after StateTransform + +fn elaborate_drops::{closure#0}(_1: Pin<&mut {async fn body of elaborate_drops()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + field _s0: (); + field _s1: SyncInt; + field _s2: AsyncInt; + field _s3: [AsyncInt; 2]; + field _s4: AsyncStruct; + field _s5: SyncThenAsync; + field _s6: AsyncEnum; + field _s7: AsyncInt; + field _s8: AsyncReference<'_>; + field _s9: {closure@$DIR/async_drop.rs:70:25: 70:27}; + field _s10: {async closure@$DIR/async_drop.rs:78:27: 78:35}; + field _s11: impl Future; + field _s12: impl Future; + field _s13: impl Future; + field _s14: impl Future; + field _s15: impl Future; + field _s16: impl Future; + field _s17: impl Future; + field _s18: impl Future; + field _s19: impl Future; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11], + Suspend1 (4): [_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11], + Suspend2 (5): [_s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s12], + Suspend3 (6): [_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s12], + Suspend4 (7): [_s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s13], + Suspend5 (8): [_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s13], + Suspend6 (9): [_s1, _s2, _s3, _s4, _s5, _s6, _s7, _s14], + Suspend7 (10): [_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s14], + Suspend8 (11): [_s1, _s2, _s3, _s4, _s5, _s6, _s15], + Suspend9 (12): [_s0, _s1, _s2, _s3, _s4, _s5, _s6, _s15], + Suspend10(13): [_s1, _s2, _s3, _s4, _s5, _s16], + Suspend11(14): [_s0, _s1, _s2, _s3, _s4, _s5, _s16], + Suspend12(15): [_s1, _s2, _s3, _s4, _s17], + Suspend13(16): [_s0, _s1, _s2, _s3, _s4, _s17], + Suspend14(17): [_s1, _s2, _s3, _s18], + Suspend15(18): [_s0, _s1, _s2, _s3, _s18], + Suspend16(19): [_s1, _s2, _s19], + Suspend17(20): [_s0, _s1, _s2, _s19], + } + storage_conflicts = BitMatrix(20x20) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s0, _s4), (_s0, _s5), (_s0, _s6), (_s0, _s7), (_s0, _s8), (_s0, _s9), (_s0, _s10), (_s0, _s11), (_s0, _s12), (_s0, _s13), (_s0, _s14), (_s0, _s15), (_s0, _s16), (_s0, _s17), (_s0, _s18), (_s0, _s19), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s1, _s3), (_s1, _s4), (_s1, _s5), (_s1, _s6), (_s1, _s7), (_s1, _s8), (_s1, _s9), (_s1, _s10), (_s1, _s11), (_s1, _s12), (_s1, _s13), (_s1, _s14), (_s1, _s15), (_s1, _s16), (_s1, _s17), (_s1, _s18), (_s1, _s19), (_s2, _s0), (_s2, _s1), (_s2, _s2), (_s2, _s3), (_s2, _s4), (_s2, _s5), (_s2, _s6), (_s2, _s7), (_s2, _s8), (_s2, _s9), (_s2, _s10), (_s2, _s11), (_s2, _s12), (_s2, _s13), (_s2, _s14), (_s2, _s15), (_s2, _s16), (_s2, _s17), (_s2, _s18), (_s2, _s19), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3), (_s3, _s4), (_s3, _s5), (_s3, _s6), (_s3, _s7), (_s3, _s8), (_s3, _s9), (_s3, _s10), (_s3, _s11), (_s3, _s12), (_s3, _s13), (_s3, _s14), (_s3, _s15), (_s3, _s16), (_s3, _s17), (_s3, _s18), (_s4, _s0), (_s4, _s1), (_s4, _s2), (_s4, _s3), (_s4, _s4), (_s4, _s5), (_s4, _s6), (_s4, _s7), (_s4, _s8), (_s4, _s9), (_s4, _s10), (_s4, _s11), (_s4, _s12), (_s4, _s13), (_s4, _s14), (_s4, _s15), (_s4, _s16), (_s4, _s17), (_s5, _s0), (_s5, _s1), (_s5, _s2), (_s5, _s3), (_s5, _s4), (_s5, _s5), (_s5, _s6), (_s5, _s7), (_s5, _s8), (_s5, _s9), (_s5, _s10), (_s5, _s11), (_s5, _s12), (_s5, _s13), (_s5, _s14), (_s5, _s15), (_s5, _s16), (_s6, _s0), (_s6, _s1), (_s6, _s2), (_s6, _s3), (_s6, _s4), (_s6, _s5), (_s6, _s6), (_s6, _s7), (_s6, _s8), (_s6, _s9), (_s6, _s10), (_s6, _s11), (_s6, _s12), (_s6, _s13), (_s6, _s14), (_s6, _s15), (_s7, _s0), (_s7, _s1), (_s7, _s2), (_s7, _s3), (_s7, _s4), (_s7, _s5), (_s7, _s6), (_s7, _s7), (_s7, _s8), (_s7, _s9), (_s7, _s10), (_s7, _s11), (_s7, _s12), (_s7, _s13), (_s7, _s14), (_s8, _s0), (_s8, _s1), (_s8, _s2), (_s8, _s3), (_s8, _s4), (_s8, _s5), (_s8, _s6), (_s8, _s7), (_s8, _s8), (_s8, _s9), (_s8, _s10), (_s8, _s11), (_s8, _s12), (_s8, _s13), (_s9, _s0), (_s9, _s1), (_s9, _s2), (_s9, _s3), (_s9, _s4), (_s9, _s5), (_s9, _s6), (_s9, _s7), (_s9, _s8), (_s9, _s9), (_s9, _s10), (_s9, _s11), (_s9, _s12), (_s10, _s0), (_s10, _s1), (_s10, _s2), (_s10, _s3), (_s10, _s4), (_s10, _s5), (_s10, _s6), (_s10, _s7), (_s10, _s8), (_s10, _s9), (_s10, _s10), (_s10, _s11), (_s11, _s0), (_s11, _s1), (_s11, _s2), (_s11, _s3), (_s11, _s4), (_s11, _s5), (_s11, _s6), (_s11, _s7), (_s11, _s8), (_s11, _s9), (_s11, _s10), (_s11, _s11), (_s12, _s0), (_s12, _s1), (_s12, _s2), (_s12, _s3), (_s12, _s4), (_s12, _s5), (_s12, _s6), (_s12, _s7), (_s12, _s8), (_s12, _s9), (_s12, _s12), (_s13, _s0), (_s13, _s1), (_s13, _s2), (_s13, _s3), (_s13, _s4), (_s13, _s5), (_s13, _s6), (_s13, _s7), (_s13, _s8), (_s13, _s13), (_s14, _s0), (_s14, _s1), (_s14, _s2), (_s14, _s3), (_s14, _s4), (_s14, _s5), (_s14, _s6), (_s14, _s7), (_s14, _s14), (_s15, _s0), (_s15, _s1), (_s15, _s2), (_s15, _s3), (_s15, _s4), (_s15, _s5), (_s15, _s6), (_s15, _s15), (_s16, _s0), (_s16, _s1), (_s16, _s2), (_s16, _s3), (_s16, _s4), (_s16, _s5), (_s16, _s16), (_s17, _s0), (_s17, _s1), (_s17, _s2), (_s17, _s3), (_s17, _s4), (_s17, _s17), (_s18, _s0), (_s18, _s1), (_s18, _s2), (_s18, _s3), (_s18, _s18), (_s19, _s0), (_s19, _s1), (_s19, _s2), (_s19, _s19)} + } + debug _task_context => _2; + coroutine debug sync_int => _s1; + let mut _0: std::task::Poll<()>; + let _3: SyncInt; + let mut _6: AsyncInt; + let mut _7: AsyncInt; + let mut _9: AsyncInt; + let mut _10: AsyncInt; + let mut _12: AsyncInt; + let mut _13: SyncInt; + let mut _14: AsyncInt; + let mut _16: AsyncInt; + let mut _18: AsyncInt; + let mut _21: &AsyncInt; + let _22: &AsyncInt; + let mut _27: impl std::future::Future; + let mut _28: &mut std::task::Context<'_>; + let mut _29: std::task::Poll<()>; + let mut _30: isize; + let mut _31: std::pin::Pin<&mut impl std::future::Future>; + let mut _32: &mut std::task::Context<'_>; + let mut _33: &mut std::task::Context<'_>; + let mut _34: &mut impl std::future::Future; + let mut _35: &mut std::task::Context<'_>; + let mut _36: std::task::Poll<()>; + let mut _37: isize; + let mut _38: std::pin::Pin<&mut impl std::future::Future>; + let mut _39: &mut std::task::Context<'_>; + let mut _40: &mut std::task::Context<'_>; + let mut _41: &mut impl std::future::Future; + let mut _42: std::pin::Pin<&mut {async closure@$DIR/async_drop.rs:78:27: 78:35}>; + let mut _43: &mut {async closure@$DIR/async_drop.rs:78:27: 78:35}; + let mut _44: impl std::future::Future; + let mut _45: &mut std::task::Context<'_>; + let mut _46: std::task::Poll<()>; + let mut _47: isize; + let mut _48: std::pin::Pin<&mut impl std::future::Future>; + let mut _49: &mut std::task::Context<'_>; + let mut _50: &mut std::task::Context<'_>; + let mut _51: &mut impl std::future::Future; + let mut _52: &mut std::task::Context<'_>; + let mut _53: std::task::Poll<()>; + let mut _54: isize; + let mut _55: std::pin::Pin<&mut impl std::future::Future>; + let mut _56: &mut std::task::Context<'_>; + let mut _57: &mut std::task::Context<'_>; + let mut _58: &mut impl std::future::Future; + let mut _59: std::pin::Pin<&mut {closure@$DIR/async_drop.rs:70:25: 70:27}>; + let mut _60: &mut {closure@$DIR/async_drop.rs:70:25: 70:27}; + let mut _61: impl std::future::Future; + let mut _62: &mut std::task::Context<'_>; + let mut _63: std::task::Poll<()>; + let mut _64: isize; + let mut _65: std::pin::Pin<&mut impl std::future::Future>; + let mut _66: &mut std::task::Context<'_>; + let mut _67: &mut std::task::Context<'_>; + let mut _68: &mut impl std::future::Future; + let mut _69: &mut std::task::Context<'_>; + let mut _70: std::task::Poll<()>; + let mut _71: isize; + let mut _72: std::pin::Pin<&mut impl std::future::Future>; + let mut _73: &mut std::task::Context<'_>; + let mut _74: &mut std::task::Context<'_>; + let mut _75: &mut impl std::future::Future; + let mut _76: std::pin::Pin<&mut AsyncReference<'_>>; + let mut _77: &mut AsyncReference<'_>; + let mut _78: impl std::future::Future; + let mut _79: &mut std::task::Context<'_>; + let mut _80: std::task::Poll<()>; + let mut _81: isize; + let mut _82: std::pin::Pin<&mut impl std::future::Future>; + let mut _83: &mut std::task::Context<'_>; + let mut _84: &mut std::task::Context<'_>; + let mut _85: &mut impl std::future::Future; + let mut _86: &mut std::task::Context<'_>; + let mut _87: std::task::Poll<()>; + let mut _88: isize; + let mut _89: std::pin::Pin<&mut impl std::future::Future>; + let mut _90: &mut std::task::Context<'_>; + let mut _91: &mut std::task::Context<'_>; + let mut _92: &mut impl std::future::Future; + let mut _93: std::pin::Pin<&mut AsyncInt>; + let mut _94: &mut AsyncInt; + let mut _95: impl std::future::Future; + let mut _96: &mut std::task::Context<'_>; + let mut _97: std::task::Poll<()>; + let mut _98: isize; + let mut _99: std::pin::Pin<&mut impl std::future::Future>; + let mut _100: &mut std::task::Context<'_>; + let mut _101: &mut std::task::Context<'_>; + let mut _102: &mut impl std::future::Future; + let mut _103: &mut std::task::Context<'_>; + let mut _104: std::task::Poll<()>; + let mut _105: isize; + let mut _106: std::pin::Pin<&mut impl std::future::Future>; + let mut _107: &mut std::task::Context<'_>; + let mut _108: &mut std::task::Context<'_>; + let mut _109: &mut impl std::future::Future; + let mut _110: std::pin::Pin<&mut AsyncEnum>; + let mut _111: &mut AsyncEnum; + let mut _112: impl std::future::Future; + let mut _113: &mut std::task::Context<'_>; + let mut _114: std::task::Poll<()>; + let mut _115: isize; + let mut _116: std::pin::Pin<&mut impl std::future::Future>; + let mut _117: &mut std::task::Context<'_>; + let mut _118: &mut std::task::Context<'_>; + let mut _119: &mut impl std::future::Future; + let mut _120: &mut std::task::Context<'_>; + let mut _121: std::task::Poll<()>; + let mut _122: isize; + let mut _123: std::pin::Pin<&mut impl std::future::Future>; + let mut _124: &mut std::task::Context<'_>; + let mut _125: &mut std::task::Context<'_>; + let mut _126: &mut impl std::future::Future; + let mut _127: std::pin::Pin<&mut SyncThenAsync>; + let mut _128: &mut SyncThenAsync; + let mut _129: impl std::future::Future; + let mut _130: &mut std::task::Context<'_>; + let mut _131: std::task::Poll<()>; + let mut _132: isize; + let mut _133: std::pin::Pin<&mut impl std::future::Future>; + let mut _134: &mut std::task::Context<'_>; + let mut _135: &mut std::task::Context<'_>; + let mut _136: &mut impl std::future::Future; + let mut _137: &mut std::task::Context<'_>; + let mut _138: std::task::Poll<()>; + let mut _139: isize; + let mut _140: std::pin::Pin<&mut impl std::future::Future>; + let mut _141: &mut std::task::Context<'_>; + let mut _142: &mut std::task::Context<'_>; + let mut _143: &mut impl std::future::Future; + let mut _144: std::pin::Pin<&mut AsyncStruct>; + let mut _145: &mut AsyncStruct; + let mut _146: impl std::future::Future; + let mut _147: &mut std::task::Context<'_>; + let mut _148: std::task::Poll<()>; + let mut _149: isize; + let mut _150: std::pin::Pin<&mut impl std::future::Future>; + let mut _151: &mut std::task::Context<'_>; + let mut _152: &mut std::task::Context<'_>; + let mut _153: &mut impl std::future::Future; + let mut _154: &mut std::task::Context<'_>; + let mut _155: std::task::Poll<()>; + let mut _156: isize; + let mut _157: std::pin::Pin<&mut impl std::future::Future>; + let mut _158: &mut std::task::Context<'_>; + let mut _159: &mut std::task::Context<'_>; + let mut _160: &mut impl std::future::Future; + let mut _161: std::pin::Pin<&mut [AsyncInt; 2]>; + let mut _162: &mut [AsyncInt; 2]; + let mut _163: impl std::future::Future; + let mut _164: &mut std::task::Context<'_>; + let mut _165: std::task::Poll<()>; + let mut _166: isize; + let mut _167: std::pin::Pin<&mut impl std::future::Future>; + let mut _168: &mut std::task::Context<'_>; + let mut _169: &mut std::task::Context<'_>; + let mut _170: &mut impl std::future::Future; + let mut _171: &mut std::task::Context<'_>; + let mut _172: std::task::Poll<()>; + let mut _173: isize; + let mut _174: std::pin::Pin<&mut impl std::future::Future>; + let mut _175: &mut std::task::Context<'_>; + let mut _176: &mut std::task::Context<'_>; + let mut _177: &mut impl std::future::Future; + let mut _178: std::pin::Pin<&mut AsyncInt>; + let mut _179: &mut AsyncInt; + let mut _180: (); + let mut _181: u32; + let mut _182: &mut {async fn body of elaborate_drops()}; + scope 1 { + debug sync_int => (((*_182) as variant#20).1: SyncInt); + coroutine debug async_int => _s2; + let _4: AsyncInt; + scope 2 { + debug async_int => (((*_182) as variant#20).2: AsyncInt); + coroutine debug tuple => _s3; + let _5: [AsyncInt; 2]; + scope 3 { + debug tuple => (((*_182) as variant#18).3: [AsyncInt; 2]); + coroutine debug async_struct => _s4; + let _8: AsyncStruct; + scope 4 { + debug async_struct => (((*_182) as variant#16).4: AsyncStruct); + coroutine debug async_struct_mix => _s5; + let _11: SyncThenAsync; + scope 5 { + debug async_struct_mix => (((*_182) as variant#14).5: SyncThenAsync); + coroutine debug async_enum => _s6; + let _15: AsyncEnum; + scope 6 { + debug async_enum => (((*_182) as variant#12).6: AsyncEnum); + let _17: std::mem::ManuallyDrop; + scope 7 { + debug manually_drop_async_int => _17; + coroutine debug foo => _s7; + let _19: AsyncInt; + scope 8 { + debug foo => (((*_182) as variant#10).7: AsyncInt); + coroutine debug async_ref => _s8; + let _20: AsyncReference<'_>; + scope 9 { + debug async_ref => (((*_182) as variant#8).8: AsyncReference<'_>); + let _23: AsyncInt; + scope 10 { + debug foo => _23; + coroutine debug async_closure => _s9; + let _24: {closure@$DIR/async_drop.rs:70:25: 70:27}; + scope 11 { + debug async_closure => (((*_182) as variant#6).9: {closure@$DIR/async_drop.rs:70:25: 70:27}); + let _25: AsyncInt; + scope 12 { + debug foo => _25; + coroutine debug async_coroutine => _s10; + let _26: {async closure@$DIR/async_drop.rs:78:27: 78:35}; + scope 13 { + debug async_coroutine => (((*_182) as variant#4).10: {async closure@$DIR/async_drop.rs:78:27: 78:35}); + } + } + } + } + } + } + } + } + } + } + } + } + } + + bb0: { + _182 = copy (_1.0: &mut {async fn body of elaborate_drops()}); + _181 = discriminant((*_182)); + switchInt(move _181) -> [0: bb1, 1: bb170, 2: bb169, 3: bb151, 4: bb152, 5: bb153, 6: bb154, 7: bb155, 8: bb156, 9: bb157, 10: bb158, 11: bb159, 12: bb160, 13: bb161, 14: bb162, 15: bb163, 16: bb164, 17: bb165, 18: bb166, 19: bb167, 20: bb168, otherwise: bb44]; + } + + bb1: { + nop; + (((*_182) as variant#20).1: SyncInt) = SyncInt(const 0_i32); + nop; + (((*_182) as variant#20).2: AsyncInt) = AsyncInt(const 0_i32); + nop; + StorageLive(_6); + _6 = AsyncInt(const 1_i32); + StorageLive(_7); + _7 = AsyncInt(const 2_i32); + (((*_182) as variant#18).3: [AsyncInt; 2]) = [move _6, move _7]; + goto -> bb2; + } + + bb2: { + StorageDead(_7); + goto -> bb3; + } + + bb3: { + StorageDead(_6); + nop; + StorageLive(_9); + _9 = AsyncInt(const 5_i32); + StorageLive(_10); + _10 = AsyncInt(const 4_i32); + (((*_182) as variant#16).4: AsyncStruct) = AsyncStruct { i: const 3_i32, a: move _10, b: move _9 }; + goto -> bb4; + } + + bb4: { + StorageDead(_10); + goto -> bb5; + } + + bb5: { + StorageDead(_9); + nop; + StorageLive(_12); + _12 = AsyncInt(const 7_i32); + StorageLive(_13); + _13 = SyncInt(const 8_i32); + StorageLive(_14); + _14 = AsyncInt(const 9_i32); + (((*_182) as variant#14).5: SyncThenAsync) = SyncThenAsync { i: const 6_i32, a: move _12, b: move _13, c: move _14 }; + goto -> bb6; + } + + bb6: { + StorageDead(_14); + goto -> bb7; + } + + bb7: { + StorageDead(_13); + goto -> bb8; + } + + bb8: { + StorageDead(_12); + nop; + StorageLive(_16); + _16 = AsyncInt(const 10_i32); + (((*_182) as variant#12).6: AsyncEnum) = AsyncEnum::A(move _16); + goto -> bb9; + } + + bb9: { + StorageDead(_16); + StorageLive(_17); + StorageLive(_18); + _18 = AsyncInt(const 11_i32); + _17 = ManuallyDrop::::new(move _18) -> [return: bb10, unwind: bb30]; + } + + bb10: { + StorageDead(_18); + nop; + (((*_182) as variant#10).7: AsyncInt) = AsyncInt(const 12_i32); + nop; + StorageLive(_21); + StorageLive(_22); + _22 = &(((*_182) as variant#10).7: AsyncInt); + _21 = &(*_22); + (((*_182) as variant#8).8: AsyncReference<'_>) = AsyncReference::<'_> { foo: move _21 }; + StorageDead(_21); + StorageDead(_22); + StorageLive(_23); + _23 = AsyncInt(const 14_i32); + nop; + (((*_182) as variant#6).9: {closure@$DIR/async_drop.rs:70:25: 70:27}) = {closure@$DIR/async_drop.rs:70:25: 70:27} { foo: move _23 }; + StorageLive(_25); + _25 = AsyncInt(const 15_i32); + nop; + (((*_182) as variant#4).10: {async closure@$DIR/async_drop.rs:78:27: 78:35}) = {closure@$DIR/async_drop.rs:78:27: 78:35} { foo: move _25 }; + (((*_182) as variant#20).0: ()) = const (); + goto -> bb52; + } + + bb11: { + nop; + goto -> bb12; + } + + bb12: { + StorageDead(_25); + goto -> bb64; + } + + bb13: { + nop; + goto -> bb14; + } + + bb14: { + StorageDead(_23); + goto -> bb76; + } + + bb15: { + nop; + goto -> bb88; + } + + bb16: { + nop; + StorageDead(_17); + goto -> bb100; + } + + bb17: { + nop; + goto -> bb112; + } + + bb18: { + nop; + goto -> bb124; + } + + bb19: { + nop; + goto -> bb136; + } + + bb20: { + nop; + goto -> bb148; + } + + bb21: { + nop; + drop((((*_182) as variant#20).1: SyncInt)) -> [return: bb22, unwind: bb38]; + } + + bb22: { + nop; + goto -> bb149; + } + + bb23: { + _0 = Poll::<()>::Ready(move (((*_182) as variant#20).0: ())); + discriminant((*_182)) = 1; + return; + } + + bb24 (cleanup): { + nop; + goto -> bb25; + } + + bb25 (cleanup): { + StorageDead(_25); + drop((((*_182) as variant#6).9: {closure@$DIR/async_drop.rs:70:25: 70:27})) -> [return: bb26, unwind terminate(cleanup)]; + } + + bb26 (cleanup): { + nop; + goto -> bb27; + } + + bb27 (cleanup): { + StorageDead(_23); + drop((((*_182) as variant#8).8: AsyncReference<'_>)) -> [return: bb28, unwind terminate(cleanup)]; + } + + bb28 (cleanup): { + nop; + drop((((*_182) as variant#10).7: AsyncInt)) -> [return: bb29, unwind terminate(cleanup)]; + } + + bb29 (cleanup): { + nop; + goto -> bb32; + } + + bb30 (cleanup): { + goto -> bb31; + } + + bb31 (cleanup): { + StorageDead(_18); + goto -> bb32; + } + + bb32 (cleanup): { + StorageDead(_17); + drop((((*_182) as variant#12).6: AsyncEnum)) -> [return: bb33, unwind terminate(cleanup)]; + } + + bb33 (cleanup): { + nop; + drop((((*_182) as variant#14).5: SyncThenAsync)) -> [return: bb34, unwind terminate(cleanup)]; + } + + bb34 (cleanup): { + nop; + drop((((*_182) as variant#16).4: AsyncStruct)) -> [return: bb35, unwind terminate(cleanup)]; + } + + bb35 (cleanup): { + nop; + drop((((*_182) as variant#18).3: [AsyncInt; 2])) -> [return: bb36, unwind terminate(cleanup)]; + } + + bb36 (cleanup): { + nop; + drop((((*_182) as variant#20).2: AsyncInt)) -> [return: bb37, unwind terminate(cleanup)]; + } + + bb37 (cleanup): { + nop; + drop((((*_182) as variant#20).1: SyncInt)) -> [return: bb38, unwind terminate(cleanup)]; + } + + bb38 (cleanup): { + nop; + goto -> bb39; + } + + bb39 (cleanup): { + goto -> bb150; + } + + bb40: { + nop; + goto -> bb11; + } + + bb41 (cleanup): { + nop; + goto -> bb24; + } + + bb42: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb42, unwind: bb41]; + } + + bb43: { + _2 = move _28; + StorageDead(_28); + goto -> bb42; + } + + bb44: { + unreachable; + } + + bb45: { + _2 = move _35; + StorageDead(_35); + goto -> bb50; + } + + bb46: { + StorageLive(_35); + _0 = Poll::<()>::Pending; + StorageDead(_17); + StorageDead(_23); + StorageDead(_25); + StorageDead(_35); + discriminant((*_182)) = 4; + return; + } + + bb47: { + _37 = discriminant(_36); + switchInt(move _37) -> [0: bb40, 1: bb46, otherwise: bb44]; + } + + bb48: { + _36 = as Future>::poll(move _38, move _39) -> [return: bb47, unwind: bb41]; + } + + bb49: { + _40 = move _2; + _39 = move _40; + goto -> bb48; + } + + bb50: { + _41 = &mut (((*_182) as variant#4).11: impl std::future::Future); + _38 = Pin::<&mut impl Future>::new_unchecked(move _41) -> [return: bb49, unwind: bb41]; + } + + bb51: { + nop; + (((*_182) as variant#4).11: impl std::future::Future) = async_drop_in_place::<{async closure@$DIR/async_drop.rs:78:27: 78:35}>(copy (_42.0: &mut {async closure@$DIR/async_drop.rs:78:27: 78:35})) -> [return: bb50, unwind: bb41]; + } + + bb52: { + _43 = &mut (((*_182) as variant#4).10: {async closure@$DIR/async_drop.rs:78:27: 78:35}); + _42 = Pin::<&mut {async closure@$DIR/async_drop.rs:78:27: 78:35}>::new_unchecked(move _43) -> [return: bb51, unwind: bb24]; + } + + bb53: { + nop; + goto -> bb13; + } + + bb54 (cleanup): { + nop; + goto -> bb26; + } + + bb55: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb55, unwind: bb54]; + } + + bb56: { + _2 = move _45; + StorageDead(_45); + goto -> bb55; + } + + bb57: { + _2 = move _52; + StorageDead(_52); + goto -> bb62; + } + + bb58: { + StorageLive(_52); + _0 = Poll::<()>::Pending; + StorageDead(_17); + StorageDead(_23); + StorageDead(_52); + discriminant((*_182)) = 6; + return; + } + + bb59: { + _54 = discriminant(_53); + switchInt(move _54) -> [0: bb53, 1: bb58, otherwise: bb44]; + } + + bb60: { + _53 = as Future>::poll(move _55, move _56) -> [return: bb59, unwind: bb54]; + } + + bb61: { + _57 = move _2; + _56 = move _57; + goto -> bb60; + } + + bb62: { + _58 = &mut (((*_182) as variant#6).10: impl std::future::Future); + _55 = Pin::<&mut impl Future>::new_unchecked(move _58) -> [return: bb61, unwind: bb54]; + } + + bb63: { + nop; + (((*_182) as variant#6).10: impl std::future::Future) = async_drop_in_place::<{closure@$DIR/async_drop.rs:70:25: 70:27}>(copy (_59.0: &mut {closure@$DIR/async_drop.rs:70:25: 70:27})) -> [return: bb62, unwind: bb54]; + } + + bb64: { + _60 = &mut (((*_182) as variant#6).9: {closure@$DIR/async_drop.rs:70:25: 70:27}); + _59 = Pin::<&mut {closure@$DIR/async_drop.rs:70:25: 70:27}>::new_unchecked(move _60) -> [return: bb63, unwind: bb26]; + } + + bb65: { + nop; + goto -> bb15; + } + + bb66 (cleanup): { + nop; + goto -> bb28; + } + + bb67: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb67, unwind: bb66]; + } + + bb68: { + _2 = move _62; + StorageDead(_62); + goto -> bb67; + } + + bb69: { + _2 = move _69; + StorageDead(_69); + goto -> bb74; + } + + bb70: { + StorageLive(_69); + _0 = Poll::<()>::Pending; + StorageDead(_17); + StorageDead(_69); + discriminant((*_182)) = 8; + return; + } + + bb71: { + _71 = discriminant(_70); + switchInt(move _71) -> [0: bb65, 1: bb70, otherwise: bb44]; + } + + bb72: { + _70 = as Future>::poll(move _72, move _73) -> [return: bb71, unwind: bb66]; + } + + bb73: { + _74 = move _2; + _73 = move _74; + goto -> bb72; + } + + bb74: { + _75 = &mut (((*_182) as variant#8).9: impl std::future::Future); + _72 = Pin::<&mut impl Future>::new_unchecked(move _75) -> [return: bb73, unwind: bb66]; + } + + bb75: { + nop; + (((*_182) as variant#8).9: impl std::future::Future) = async_drop_in_place::>(copy (_76.0: &mut AsyncReference<'_>)) -> [return: bb74, unwind: bb66]; + } + + bb76: { + _77 = &mut (((*_182) as variant#8).8: AsyncReference<'_>); + _76 = Pin::<&mut AsyncReference<'_>>::new_unchecked(move _77) -> [return: bb75, unwind: bb28]; + } + + bb77: { + nop; + goto -> bb16; + } + + bb78 (cleanup): { + nop; + goto -> bb29; + } + + bb79: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb79, unwind: bb78]; + } + + bb80: { + _2 = move _79; + StorageDead(_79); + goto -> bb79; + } + + bb81: { + _2 = move _86; + StorageDead(_86); + goto -> bb86; + } + + bb82: { + StorageLive(_86); + _0 = Poll::<()>::Pending; + StorageDead(_17); + StorageDead(_86); + discriminant((*_182)) = 10; + return; + } + + bb83: { + _88 = discriminant(_87); + switchInt(move _88) -> [0: bb77, 1: bb82, otherwise: bb44]; + } + + bb84: { + _87 = as Future>::poll(move _89, move _90) -> [return: bb83, unwind: bb78]; + } + + bb85: { + _91 = move _2; + _90 = move _91; + goto -> bb84; + } + + bb86: { + _92 = &mut (((*_182) as variant#10).8: impl std::future::Future); + _89 = Pin::<&mut impl Future>::new_unchecked(move _92) -> [return: bb85, unwind: bb78]; + } + + bb87: { + nop; + (((*_182) as variant#10).8: impl std::future::Future) = async_drop_in_place::(copy (_93.0: &mut AsyncInt)) -> [return: bb86, unwind: bb78]; + } + + bb88: { + _94 = &mut (((*_182) as variant#10).7: AsyncInt); + _93 = Pin::<&mut AsyncInt>::new_unchecked(move _94) -> [return: bb87, unwind: bb29]; + } + + bb89: { + nop; + goto -> bb17; + } + + bb90 (cleanup): { + nop; + goto -> bb33; + } + + bb91: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb91, unwind: bb90]; + } + + bb92: { + _2 = move _96; + StorageDead(_96); + goto -> bb91; + } + + bb93: { + _2 = move _103; + StorageDead(_103); + goto -> bb98; + } + + bb94: { + StorageLive(_103); + _0 = Poll::<()>::Pending; + StorageDead(_103); + discriminant((*_182)) = 12; + return; + } + + bb95: { + _105 = discriminant(_104); + switchInt(move _105) -> [0: bb89, 1: bb94, otherwise: bb44]; + } + + bb96: { + _104 = as Future>::poll(move _106, move _107) -> [return: bb95, unwind: bb90]; + } + + bb97: { + _108 = move _2; + _107 = move _108; + goto -> bb96; + } + + bb98: { + _109 = &mut (((*_182) as variant#12).7: impl std::future::Future); + _106 = Pin::<&mut impl Future>::new_unchecked(move _109) -> [return: bb97, unwind: bb90]; + } + + bb99: { + nop; + (((*_182) as variant#12).7: impl std::future::Future) = async_drop_in_place::(copy (_110.0: &mut AsyncEnum)) -> [return: bb98, unwind: bb90]; + } + + bb100: { + _111 = &mut (((*_182) as variant#12).6: AsyncEnum); + _110 = Pin::<&mut AsyncEnum>::new_unchecked(move _111) -> [return: bb99, unwind: bb33]; + } + + bb101: { + nop; + goto -> bb18; + } + + bb102 (cleanup): { + nop; + goto -> bb34; + } + + bb103: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb103, unwind: bb102]; + } + + bb104: { + _2 = move _113; + StorageDead(_113); + goto -> bb103; + } + + bb105: { + _2 = move _120; + StorageDead(_120); + goto -> bb110; + } + + bb106: { + StorageLive(_120); + _0 = Poll::<()>::Pending; + StorageDead(_120); + discriminant((*_182)) = 14; + return; + } + + bb107: { + _122 = discriminant(_121); + switchInt(move _122) -> [0: bb101, 1: bb106, otherwise: bb44]; + } + + bb108: { + _121 = as Future>::poll(move _123, move _124) -> [return: bb107, unwind: bb102]; + } + + bb109: { + _125 = move _2; + _124 = move _125; + goto -> bb108; + } + + bb110: { + _126 = &mut (((*_182) as variant#14).6: impl std::future::Future); + _123 = Pin::<&mut impl Future>::new_unchecked(move _126) -> [return: bb109, unwind: bb102]; + } + + bb111: { + nop; + (((*_182) as variant#14).6: impl std::future::Future) = async_drop_in_place::(copy (_127.0: &mut SyncThenAsync)) -> [return: bb110, unwind: bb102]; + } + + bb112: { + _128 = &mut (((*_182) as variant#14).5: SyncThenAsync); + _127 = Pin::<&mut SyncThenAsync>::new_unchecked(move _128) -> [return: bb111, unwind: bb34]; + } + + bb113: { + nop; + goto -> bb19; + } + + bb114 (cleanup): { + nop; + goto -> bb35; + } + + bb115: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb115, unwind: bb114]; + } + + bb116: { + _2 = move _130; + StorageDead(_130); + goto -> bb115; + } + + bb117: { + _2 = move _137; + StorageDead(_137); + goto -> bb122; + } + + bb118: { + StorageLive(_137); + _0 = Poll::<()>::Pending; + StorageDead(_137); + discriminant((*_182)) = 16; + return; + } + + bb119: { + _139 = discriminant(_138); + switchInt(move _139) -> [0: bb113, 1: bb118, otherwise: bb44]; + } + + bb120: { + _138 = as Future>::poll(move _140, move _141) -> [return: bb119, unwind: bb114]; + } + + bb121: { + _142 = move _2; + _141 = move _142; + goto -> bb120; + } + + bb122: { + _143 = &mut (((*_182) as variant#16).5: impl std::future::Future); + _140 = Pin::<&mut impl Future>::new_unchecked(move _143) -> [return: bb121, unwind: bb114]; + } + + bb123: { + nop; + (((*_182) as variant#16).5: impl std::future::Future) = async_drop_in_place::(copy (_144.0: &mut AsyncStruct)) -> [return: bb122, unwind: bb114]; + } + + bb124: { + _145 = &mut (((*_182) as variant#16).4: AsyncStruct); + _144 = Pin::<&mut AsyncStruct>::new_unchecked(move _145) -> [return: bb123, unwind: bb35]; + } + + bb125: { + nop; + goto -> bb20; + } + + bb126 (cleanup): { + nop; + goto -> bb36; + } + + bb127: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb127, unwind: bb126]; + } + + bb128: { + _2 = move _147; + StorageDead(_147); + goto -> bb127; + } + + bb129: { + _2 = move _154; + StorageDead(_154); + goto -> bb134; + } + + bb130: { + StorageLive(_154); + _0 = Poll::<()>::Pending; + StorageDead(_154); + discriminant((*_182)) = 18; + return; + } + + bb131: { + _156 = discriminant(_155); + switchInt(move _156) -> [0: bb125, 1: bb130, otherwise: bb44]; + } + + bb132: { + _155 = as Future>::poll(move _157, move _158) -> [return: bb131, unwind: bb126]; + } + + bb133: { + _159 = move _2; + _158 = move _159; + goto -> bb132; + } + + bb134: { + _160 = &mut (((*_182) as variant#18).4: impl std::future::Future); + _157 = Pin::<&mut impl Future>::new_unchecked(move _160) -> [return: bb133, unwind: bb126]; + } + + bb135: { + nop; + (((*_182) as variant#18).4: impl std::future::Future) = async_drop_in_place::<[AsyncInt; 2]>(copy (_161.0: &mut [AsyncInt; 2])) -> [return: bb134, unwind: bb126]; + } + + bb136: { + _162 = &mut (((*_182) as variant#18).3: [AsyncInt; 2]); + _161 = Pin::<&mut [AsyncInt; 2]>::new_unchecked(move _162) -> [return: bb135, unwind: bb36]; + } + + bb137: { + nop; + goto -> bb21; + } + + bb138 (cleanup): { + nop; + goto -> bb37; + } + + bb139: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb139, unwind: bb138]; + } + + bb140: { + _2 = move _164; + StorageDead(_164); + goto -> bb139; + } + + bb141: { + _2 = move _171; + StorageDead(_171); + goto -> bb146; + } + + bb142: { + StorageLive(_171); + _0 = Poll::<()>::Pending; + StorageDead(_171); + discriminant((*_182)) = 20; + return; + } + + bb143: { + _173 = discriminant(_172); + switchInt(move _173) -> [0: bb137, 1: bb142, otherwise: bb44]; + } + + bb144: { + _172 = as Future>::poll(move _174, move _175) -> [return: bb143, unwind: bb138]; + } + + bb145: { + _176 = move _2; + _175 = move _176; + goto -> bb144; + } + + bb146: { + _177 = &mut (((*_182) as variant#20).3: impl std::future::Future); + _174 = Pin::<&mut impl Future>::new_unchecked(move _177) -> [return: bb145, unwind: bb138]; + } + + bb147: { + nop; + (((*_182) as variant#20).3: impl std::future::Future) = async_drop_in_place::(copy (_178.0: &mut AsyncInt)) -> [return: bb146, unwind: bb138]; + } + + bb148: { + _179 = &mut (((*_182) as variant#20).2: AsyncInt); + _178 = Pin::<&mut AsyncInt>::new_unchecked(move _179) -> [return: bb147, unwind: bb37]; + } + + bb149: { + goto -> bb23; + } + + bb150 (cleanup): { + discriminant((*_182)) = 2; + resume; + } + + bb151: { + StorageLive(_17); + StorageLive(_23); + StorageLive(_25); + StorageLive(_28); + _28 = move _2; + goto -> bb43; + } + + bb152: { + StorageLive(_17); + StorageLive(_23); + StorageLive(_25); + StorageLive(_35); + _35 = move _2; + goto -> bb45; + } + + bb153: { + StorageLive(_17); + StorageLive(_23); + StorageLive(_45); + _45 = move _2; + goto -> bb56; + } + + bb154: { + StorageLive(_17); + StorageLive(_23); + StorageLive(_52); + _52 = move _2; + goto -> bb57; + } + + bb155: { + StorageLive(_17); + StorageLive(_62); + _62 = move _2; + goto -> bb68; + } + + bb156: { + StorageLive(_17); + StorageLive(_69); + _69 = move _2; + goto -> bb69; + } + + bb157: { + StorageLive(_17); + StorageLive(_79); + _79 = move _2; + goto -> bb80; + } + + bb158: { + StorageLive(_17); + StorageLive(_86); + _86 = move _2; + goto -> bb81; + } + + bb159: { + StorageLive(_96); + _96 = move _2; + goto -> bb92; + } + + bb160: { + StorageLive(_103); + _103 = move _2; + goto -> bb93; + } + + bb161: { + StorageLive(_113); + _113 = move _2; + goto -> bb104; + } + + bb162: { + StorageLive(_120); + _120 = move _2; + goto -> bb105; + } + + bb163: { + StorageLive(_130); + _130 = move _2; + goto -> bb116; + } + + bb164: { + StorageLive(_137); + _137 = move _2; + goto -> bb117; + } + + bb165: { + StorageLive(_147); + _147 = move _2; + goto -> bb128; + } + + bb166: { + StorageLive(_154); + _154 = move _2; + goto -> bb129; + } + + bb167: { + StorageLive(_164); + _164 = move _2; + goto -> bb140; + } + + bb168: { + StorageLive(_171); + _171 = move _2; + goto -> bb141; + } + + bb169: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb169, unwind continue]; + } + + bb170: { + assert(const false, "`async fn` resumed after completion") -> [success: bb170, unwind continue]; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.rs b/tests/mir-opt/coroutine/async_drop.rs new file mode 100644 index 0000000000000..a6cfa381b5a7e --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.rs @@ -0,0 +1,258 @@ +//@ skip-filecheck +//@ compile-flags: -Zmir-opt-level=0 +//@ needs-unwind +//@ edition: 2024 + +// WARNING: If you would ever want to modify this test, +// please consider modifying rustc's async drop test at +// `tests/ui/async-await/async-drop/async-drop-initial.rs`. + +#![feature(async_drop, impl_trait_in_assoc_type)] +#![allow(incomplete_features, dead_code, unused_variables)] + +// FIXME(zetanumbers): consider AsyncDestruct::async_drop cleanup tests +use core::future::{AsyncDrop, Future, async_drop_in_place}; +use core::hint::black_box; +use core::mem::{self, ManuallyDrop}; +use core::pin::{Pin, pin}; +use core::task::{Context, Poll, Waker}; + +async fn test_async_drop(x: T) { + let mut x = mem::MaybeUninit::new(x); + let dtor = pin!(unsafe { async_drop_in_place(&mut *x.as_mut_ptr()) }); + test_idempotency(dtor).await; +} + +fn test_idempotency(mut x: Pin<&mut T>) -> impl Future + '_ +where + T: Future, +{ + core::future::poll_fn(move |cx| { + assert_eq!(x.as_mut().poll(cx), Poll::Ready(())); + assert_eq!(x.as_mut().poll(cx), Poll::Ready(())); + Poll::Ready(()) + }) +} + +// EMIT_MIR async_drop.simple-{closure#0}.ElaborateDrops.diff +// EMIT_MIR async_drop.simple-{closure#0}.StateTransform.after.mir +// EMIT_MIR async_drop.simple-{closure#0}.coroutine_drop_async.0.mir +async fn simple() { + let sync_int = SyncInt(0); + let async_int = AsyncInt(0); +} + +// EMIT_MIR async_drop.double-{closure#0}.ElaborateDrops.diff +// EMIT_MIR async_drop.double-{closure#0}.StateTransform.after.mir +// EMIT_MIR async_drop.double-{closure#0}.coroutine_drop_async.0.mir +async fn double() { + let sync_int = SyncInt(0); + let async_int = AsyncInt(0); + let async_int_again = AsyncInt(0); +} + +// EMIT_MIR async_drop.elaborate_drops-{closure#0}.ElaborateDrops.diff +// EMIT_MIR async_drop.elaborate_drops-{closure#0}.StateTransform.after.mir +async fn elaborate_drops() { + let sync_int = SyncInt(0); + let async_int = AsyncInt(0); + let tuple = [AsyncInt(1), AsyncInt(2)]; + + let async_struct = AsyncStruct { b: AsyncInt(5), a: AsyncInt(4), i: 3 }; + let async_struct_mix = SyncThenAsync { i: 6, a: AsyncInt(7), b: SyncInt(8), c: AsyncInt(9) }; + let async_enum = AsyncEnum::A(AsyncInt(10)); + + let manually_drop_async_int = ManuallyDrop::new(AsyncInt(11)); + let foo = AsyncInt(12); + let async_ref = AsyncReference { foo: &foo }; + + let foo = AsyncInt(14); + let async_closure = || { + black_box(foo); + let foo = AsyncInt(13); + foo + }; + + // We test dropping the coroutine, not running it. + let foo = AsyncInt(15); + let async_coroutine = async || { + black_box(foo); + let foo = AsyncInt(16); + // Await point there, but this is async closure so it's fine + black_box(core::future::ready(())).await; + foo + }; +} + +fn main() { + let waker = Waker::noop(); + let mut cx = Context::from_waker(&waker); + + let i = 13; + let fut = pin!(async { + elaborate_drops().await; + + test_async_drop(Int(0)).await; + test_async_drop(AsyncInt(0)).await; + test_async_drop([AsyncInt(1), AsyncInt(2)]).await; + test_async_drop((AsyncInt(3), AsyncInt(4))).await; + test_async_drop(5).await; + let j = 42; + test_async_drop(&i).await; + test_async_drop(&j).await; + test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }).await; + test_async_drop(ManuallyDrop::new(AsyncInt(9))).await; + + let foo = AsyncInt(10); + test_async_drop(AsyncReference { foo: &foo }).await; + + let foo = AsyncInt(11); + test_async_drop(|| { + black_box(foo); + let foo = AsyncInt(10); + foo + }) + .await; + + test_async_drop(AsyncEnum::A(AsyncInt(12))).await; + test_async_drop(AsyncEnum::B(SyncInt(13))).await; + + test_async_drop(SyncInt(14)).await; + test_async_drop(SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) }) + .await; + + let mut ptr19 = mem::MaybeUninit::new(AsyncInt(19)); + let async_drop_fut = pin!(unsafe { async_drop_in_place(&mut *ptr19.as_mut_ptr()) }); + test_idempotency(async_drop_fut).await; + + let foo = AsyncInt(20); + test_async_drop(async || { + black_box(foo); + let foo = AsyncInt(19); + // Await point there, but this is async closure so it's fine + black_box(core::future::ready(())).await; + foo + }) + .await; + }); + let res = fut.poll(&mut cx); + assert_eq!(res, Poll::Ready(())); +} + +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.MentionedItems.after.mir +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncInt.StateTransform.after.mir +struct AsyncInt(i32); + +impl Drop for AsyncInt { + fn drop(&mut self) { + println!("AsyncInt::drop: {}", self.0); + } +} +impl AsyncDrop for AsyncInt { + async fn drop(self: Pin<&mut Self>) { + println!("AsyncInt::async_drop: {}", self.0); + } +} + +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.SyncInt.MentionedItems.after.mir +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.SyncInt.StateTransform.after.mir +struct SyncInt(i32); + +impl Drop for SyncInt { + fn drop(&mut self) { + println!("SyncInt::drop: {}", self.0); + } +} + +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.MentionedItems.after.mir +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.SyncThenAsync.StateTransform.after.mir +struct SyncThenAsync { + i: i32, + a: AsyncInt, + b: SyncInt, + c: AsyncInt, +} + +impl Drop for SyncThenAsync { + fn drop(&mut self) { + println!("SyncThenAsync::drop: {}", self.i); + } +} + +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.MentionedItems.after.mir +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncReference_'__.StateTransform.after.mir +struct AsyncReference<'a> { + foo: &'a AsyncInt, +} + +impl Drop for AsyncReference<'_> { + fn drop(&mut self) { + println!("AsyncReference::drop: {}", self.foo.0); + } +} +impl AsyncDrop for AsyncReference<'_> { + async fn drop(self: Pin<&mut Self>) { + println!("AsyncReference::async_drop: {}", self.foo.0); + } +} + +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.Int.MentionedItems.after.mir +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.Int.StateTransform.after.mir +struct Int(i32); + +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.MentionedItems.after.mir +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncStruct.StateTransform.after.mir +struct AsyncStruct { + i: i32, + a: AsyncInt, + b: AsyncInt, +} + +impl Drop for AsyncStruct { + fn drop(&mut self) { + println!("AsyncStruct::drop: {}", self.i); + } +} +impl AsyncDrop for AsyncStruct { + async fn drop(self: Pin<&mut Self>) { + println!("AsyncStruct::async_drop: {}", self.i); + } +} + +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.MentionedItems.after.mir +// EMIT_MIR core.future-async_drop-async_drop_in_place-{closure#0}.AsyncEnum.StateTransform.after.mir +enum AsyncEnum { + A(AsyncInt), + B(SyncInt), +} + +impl Drop for AsyncEnum { + fn drop(&mut self) { + let new_self = match self { + AsyncEnum::A(foo) => { + println!("AsyncEnum(A)::drop: {}", foo.0); + AsyncEnum::B(SyncInt(foo.0)) + } + AsyncEnum::B(foo) => { + println!("AsyncEnum(B)::drop: {}", foo.0); + AsyncEnum::A(AsyncInt(foo.0)) + } + }; + mem::forget(mem::replace(&mut *self, new_self)); + } +} +impl AsyncDrop for AsyncEnum { + async fn drop(mut self: Pin<&mut Self>) { + let new_self = match &*self { + AsyncEnum::A(foo) => { + println!("AsyncEnum(A)::async_drop: {}", foo.0); + AsyncEnum::B(SyncInt(foo.0)) + } + AsyncEnum::B(foo) => { + println!("AsyncEnum(B)::async_drop: {}", foo.0); + AsyncEnum::A(AsyncInt(foo.0)) + } + }; + mem::forget(mem::replace(&mut *self, new_self)); + } +} diff --git a/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.ElaborateDrops.diff b/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.ElaborateDrops.diff new file mode 100644 index 0000000000000..0e18ddf5ad2dd --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.ElaborateDrops.diff @@ -0,0 +1,201 @@ +- // MIR for `simple::{closure#0}` before ElaborateDrops ++ // MIR for `simple::{closure#0}` after ElaborateDrops + + fn simple::{closure#0}(_1: {async fn body of simple()}, _2: std::future::ResumeTy) -> () + yields () + { + debug _task_context => _2; + let mut _0: (); + let _3: SyncInt; ++ let mut _5: impl std::future::Future; ++ let mut _6: std::future::ResumeTy; ++ let mut _7: std::task::Poll<()>; ++ let mut _8: isize; ++ let mut _9: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _10: &mut std::task::Context<'_>; ++ let mut _11: std::future::ResumeTy; ++ let mut _12: &mut impl std::future::Future; ++ let mut _13: std::future::ResumeTy; ++ let mut _14: std::task::Poll<()>; ++ let mut _15: isize; ++ let mut _16: std::pin::Pin<&mut impl std::future::Future>; ++ let mut _17: &mut std::task::Context<'_>; ++ let mut _18: std::future::ResumeTy; ++ let mut _19: &mut impl std::future::Future; ++ let mut _20: std::pin::Pin<&mut AsyncInt>; ++ let mut _21: &mut AsyncInt; + scope 1 { + debug sync_int => _3; + let _4: AsyncInt; + scope 2 { + debug async_int => _4; + } + } + + bb0: { + StorageLive(_3); + _3 = SyncInt(const 0_i32); + StorageLive(_4); + _4 = AsyncInt(const 0_i32); + _0 = const (); +- drop(_4) -> [return: bb1, unwind: bb7, drop: bb4]; ++ goto -> bb31; + } + + bb1: { + StorageDead(_4); + drop(_3) -> [return: bb2, unwind: bb8]; + } + + bb2: { + StorageDead(_3); +- drop(_1) -> [return: bb3, drop: bb6, unwind continue]; ++ drop(_1) -> [return: bb3, unwind: bb9]; + } + + bb3: { + return; + } + + bb4: { + StorageDead(_4); +- drop(_3) -> [return: bb5, unwind: bb10]; ++ goto -> bb5; + } + + bb5: { + StorageDead(_3); +- drop(_1) -> [return: bb6, unwind continue]; ++ goto -> bb6; + } + + bb6: { + coroutine_drop; + } + + bb7 (cleanup): { + StorageDead(_4); + drop(_3) -> [return: bb8, unwind terminate(cleanup)]; + } + + bb8 (cleanup): { + StorageDead(_3); + drop(_1) -> [return: bb9, unwind terminate(cleanup)]; + } + + bb9 (cleanup): { + resume; + } + + bb10 (cleanup): { + StorageDead(_3); +- drop(_1) -> [return: bb9, unwind terminate(cleanup)]; ++ goto -> bb9; ++ } ++ ++ bb11: { ++ StorageDead(_5); ++ goto -> bb1; ++ } ++ ++ bb12: { ++ StorageDead(_5); ++ goto -> bb4; ++ } ++ ++ bb13 (cleanup): { ++ StorageDead(_5); ++ goto -> bb7; ++ } ++ ++ bb14: { ++ assert(const false, "`async fn` resumed after async drop") -> [success: bb14, unwind: bb13]; ++ } ++ ++ bb15: { ++ _2 = move _6; ++ StorageDead(_6); ++ goto -> bb14; ++ } ++ ++ bb16: { ++ _2 = move _6; ++ StorageDead(_6); ++ goto -> bb22; ++ } ++ ++ bb17: { ++ StorageLive(_6); ++ _6 = yield(const ()) -> [resume: bb15, drop: bb16]; ++ } ++ ++ bb18: { ++ unreachable; ++ } ++ ++ bb19: { ++ _8 = discriminant(_7); ++ switchInt(move _8) -> [0: bb12, 1: bb17, otherwise: bb18]; ++ } ++ ++ bb20: { ++ _7 = as Future>::poll(move _9, move _10) -> [return: bb19, unwind: bb13]; ++ } ++ ++ bb21: { ++ _11 = move _2; ++ _10 = std::future::get_context::<'_, '_>(move _11) -> [return: bb20, unwind: bb13]; ++ } ++ ++ bb22: { ++ _12 = &mut _5; ++ _9 = Pin::<&mut impl Future>::new_unchecked(move _12) -> [return: bb21, unwind: bb13]; ++ } ++ ++ bb23: { ++ _2 = move _13; ++ StorageDead(_13); ++ goto -> bb29; ++ } ++ ++ bb24: { ++ _2 = move _13; ++ StorageDead(_13); ++ goto -> bb22; ++ } ++ ++ bb25: { ++ StorageLive(_13); ++ _13 = yield(const ()) -> [resume: bb23, drop: bb24]; ++ } ++ ++ bb26: { ++ _15 = discriminant(_14); ++ switchInt(move _15) -> [0: bb11, 1: bb25, otherwise: bb18]; ++ } ++ ++ bb27: { ++ _14 = as Future>::poll(move _16, move _17) -> [return: bb26, unwind: bb13]; ++ } ++ ++ bb28: { ++ _18 = move _2; ++ _17 = std::future::get_context::<'_, '_>(move _18) -> [return: bb27, unwind: bb13]; ++ } ++ ++ bb29: { ++ _19 = &mut _5; ++ _16 = Pin::<&mut impl Future>::new_unchecked(move _19) -> [return: bb28, unwind: bb13]; ++ } ++ ++ bb30: { ++ StorageLive(_5); ++ _5 = async_drop_in_place::(copy (_20.0: &mut AsyncInt)) -> [return: bb29, unwind: bb13]; ++ } ++ ++ bb31: { ++ _21 = &mut _4; ++ _20 = Pin::<&mut AsyncInt>::new_unchecked(move _21) -> [return: bb30, unwind: bb7]; + } + } + diff --git a/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..a592e4c8f4245 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.StateTransform.after.mir @@ -0,0 +1,192 @@ +// MIR for `simple::{closure#0}` after StateTransform + +fn simple::{closure#0}(_1: Pin<&mut {async fn body of simple()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + field _s0: (); + field _s1: SyncInt; + field _s2: AsyncInt; + field _s3: impl Future; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s1, _s2, _s3], + Suspend1 (4): [_s0, _s1, _s2, _s3], + } + storage_conflicts = BitMatrix(4x4) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s1, _s3), (_s2, _s0), (_s2, _s1), (_s2, _s2), (_s2, _s3), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3)} + } + debug _task_context => _2; + coroutine debug sync_int => _s1; + let mut _0: std::task::Poll<()>; + let _3: SyncInt; + let mut _5: impl std::future::Future; + let mut _6: &mut std::task::Context<'_>; + let mut _7: std::task::Poll<()>; + let mut _8: isize; + let mut _9: std::pin::Pin<&mut impl std::future::Future>; + let mut _10: &mut std::task::Context<'_>; + let mut _11: &mut std::task::Context<'_>; + let mut _12: &mut impl std::future::Future; + let mut _13: &mut std::task::Context<'_>; + let mut _14: std::task::Poll<()>; + let mut _15: isize; + let mut _16: std::pin::Pin<&mut impl std::future::Future>; + let mut _17: &mut std::task::Context<'_>; + let mut _18: &mut std::task::Context<'_>; + let mut _19: &mut impl std::future::Future; + let mut _20: std::pin::Pin<&mut AsyncInt>; + let mut _21: &mut AsyncInt; + let mut _22: (); + let mut _23: u32; + let mut _24: &mut {async fn body of simple()}; + scope 1 { + debug sync_int => (((*_24) as variant#4).1: SyncInt); + coroutine debug async_int => _s2; + let _4: AsyncInt; + scope 2 { + debug async_int => (((*_24) as variant#4).2: AsyncInt); + } + } + + bb0: { + _24 = copy (_1.0: &mut {async fn body of simple()}); + _23 = discriminant((*_24)); + switchInt(move _23) -> [0: bb1, 1: bb26, 2: bb25, 3: bb23, 4: bb24, otherwise: bb12]; + } + + bb1: { + nop; + (((*_24) as variant#4).1: SyncInt) = SyncInt(const 0_i32); + nop; + (((*_24) as variant#4).2: AsyncInt) = AsyncInt(const 0_i32); + (((*_24) as variant#4).0: ()) = const (); + goto -> bb20; + } + + bb2: { + nop; + drop((((*_24) as variant#4).1: SyncInt)) -> [return: bb3, unwind: bb6]; + } + + bb3: { + nop; + goto -> bb21; + } + + bb4: { + _0 = Poll::<()>::Ready(move (((*_24) as variant#4).0: ())); + discriminant((*_24)) = 1; + return; + } + + bb5 (cleanup): { + nop; + drop((((*_24) as variant#4).1: SyncInt)) -> [return: bb6, unwind terminate(cleanup)]; + } + + bb6 (cleanup): { + nop; + goto -> bb7; + } + + bb7 (cleanup): { + goto -> bb22; + } + + bb8: { + nop; + goto -> bb2; + } + + bb9 (cleanup): { + nop; + goto -> bb5; + } + + bb10: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb10, unwind: bb9]; + } + + bb11: { + _2 = move _6; + StorageDead(_6); + goto -> bb10; + } + + bb12: { + unreachable; + } + + bb13: { + _2 = move _13; + StorageDead(_13); + goto -> bb18; + } + + bb14: { + StorageLive(_13); + _0 = Poll::<()>::Pending; + StorageDead(_13); + discriminant((*_24)) = 4; + return; + } + + bb15: { + _15 = discriminant(_14); + switchInt(move _15) -> [0: bb8, 1: bb14, otherwise: bb12]; + } + + bb16: { + _14 = as Future>::poll(move _16, move _17) -> [return: bb15, unwind: bb9]; + } + + bb17: { + _18 = move _2; + _17 = move _18; + goto -> bb16; + } + + bb18: { + _19 = &mut (((*_24) as variant#4).3: impl std::future::Future); + _16 = Pin::<&mut impl Future>::new_unchecked(move _19) -> [return: bb17, unwind: bb9]; + } + + bb19: { + nop; + (((*_24) as variant#4).3: impl std::future::Future) = async_drop_in_place::(copy (_20.0: &mut AsyncInt)) -> [return: bb18, unwind: bb9]; + } + + bb20: { + _21 = &mut (((*_24) as variant#4).2: AsyncInt); + _20 = Pin::<&mut AsyncInt>::new_unchecked(move _21) -> [return: bb19, unwind: bb5]; + } + + bb21: { + goto -> bb4; + } + + bb22 (cleanup): { + discriminant((*_24)) = 2; + resume; + } + + bb23: { + StorageLive(_6); + _6 = move _2; + goto -> bb11; + } + + bb24: { + StorageLive(_13); + _13 = move _2; + goto -> bb13; + } + + bb25: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb25, unwind continue]; + } + + bb26: { + assert(const false, "`async fn` resumed after completion") -> [success: bb26, unwind continue]; + } +} diff --git a/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.coroutine_drop_async.0.mir b/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.coroutine_drop_async.0.mir new file mode 100644 index 0000000000000..575ddd4416306 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop.simple-{closure#0}.coroutine_drop_async.0.mir @@ -0,0 +1,160 @@ +// MIR for `simple::{closure#0}` 0 coroutine_drop_async + +fn simple::{closure#0}(_1: Pin<&mut {async fn body of simple()}>, _2: &mut Context<'_>) -> Poll<()> { + debug _task_context => _2; + let mut _0: std::task::Poll<()>; + let _3: SyncInt; + let mut _5: impl std::future::Future; + let mut _6: &mut std::task::Context<'_>; + let mut _7: std::task::Poll<()>; + let mut _8: isize; + let mut _9: std::pin::Pin<&mut impl std::future::Future>; + let mut _10: &mut std::task::Context<'_>; + let mut _11: &mut std::task::Context<'_>; + let mut _12: &mut impl std::future::Future; + let mut _13: &mut std::task::Context<'_>; + let mut _14: std::task::Poll<()>; + let mut _15: isize; + let mut _16: std::pin::Pin<&mut impl std::future::Future>; + let mut _17: &mut std::task::Context<'_>; + let mut _18: &mut std::task::Context<'_>; + let mut _19: &mut impl std::future::Future; + let mut _20: std::pin::Pin<&mut AsyncInt>; + let mut _21: &mut AsyncInt; + let mut _22: (); + let mut _23: u32; + let mut _24: &mut {async fn body of simple()}; + scope 1 { + debug sync_int => (((*_24) as variant#4).1: SyncInt); + let _4: AsyncInt; + scope 2 { + debug async_int => (((*_24) as variant#4).2: AsyncInt); + } + } + + bb0: { + _24 = copy (_1.0: &mut {async fn body of simple()}); + _23 = discriminant((*_24)); + switchInt(move _23) -> [0: bb18, 2: bb23, 3: bb21, 4: bb22, otherwise: bb24]; + } + + bb1: { + nop; + goto -> bb2; + } + + bb2: { + nop; + goto -> bb3; + } + + bb3: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb4 (cleanup): { + nop; + drop((((*_24) as variant#4).1: SyncInt)) -> [return: bb5, unwind terminate(cleanup)]; + } + + bb5 (cleanup): { + nop; + goto -> bb6; + } + + bb6 (cleanup): { + goto -> bb20; + } + + bb7: { + nop; + goto -> bb1; + } + + bb8 (cleanup): { + nop; + goto -> bb4; + } + + bb9: { + _2 = move _6; + StorageDead(_6); + goto -> bb15; + } + + bb10: { + StorageLive(_6); + _0 = Poll::<()>::Pending; + StorageDead(_6); + discriminant((*_24)) = 3; + return; + } + + bb11: { + unreachable; + } + + bb12: { + _8 = discriminant(_7); + switchInt(move _8) -> [0: bb7, 1: bb10, otherwise: bb11]; + } + + bb13: { + _7 = as Future>::poll(move _9, move _10) -> [return: bb12, unwind: bb8]; + } + + bb14: { + _11 = move _2; + _10 = move _11; + goto -> bb13; + } + + bb15: { + _12 = &mut (((*_24) as variant#4).3: impl std::future::Future); + _9 = Pin::<&mut impl Future>::new_unchecked(move _12) -> [return: bb14, unwind: bb8]; + } + + bb16: { + _2 = move _13; + StorageDead(_13); + goto -> bb15; + } + + bb17: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb18: { + goto -> bb19; + } + + bb19: { + goto -> bb17; + } + + bb20 (cleanup): { + discriminant((*_24)) = 2; + resume; + } + + bb21: { + StorageLive(_6); + goto -> bb9; + } + + bb22: { + StorageLive(_13); + goto -> bb16; + } + + bb23: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb23, unwind continue]; + } + + bb24: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir new file mode 100644 index 0000000000000..2802e3585b867 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir @@ -0,0 +1,128 @@ +// MIR for `a::{closure#0}` 0 coroutine_drop_async + +fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { + debug _task_context => _2; + debug x => ((*_23).0: T); + let mut _0: std::task::Poll<()>; + let _3: T; + let mut _4: impl std::future::Future; + let mut _5: &mut std::task::Context<'_>; + let mut _6: std::task::Poll<()>; + let mut _7: isize; + let mut _8: std::pin::Pin<&mut impl std::future::Future>; + let mut _9: &mut std::task::Context<'_>; + let mut _10: &mut std::task::Context<'_>; + let mut _11: &mut impl std::future::Future; + let mut _12: &mut std::task::Context<'_>; + let mut _13: std::task::Poll<()>; + let mut _14: isize; + let mut _15: std::pin::Pin<&mut impl std::future::Future>; + let mut _16: &mut std::task::Context<'_>; + let mut _17: &mut std::task::Context<'_>; + let mut _18: &mut impl std::future::Future; + let mut _19: std::pin::Pin<&mut T>; + let mut _20: &mut T; + let mut _21: (); + let mut _22: u32; + let mut _23: &mut {async fn body of a()}; + scope 1 { + debug x => (((*_23) as variant#4).1: T); + } + + bb0: { + _23 = copy (_1.0: &mut {async fn body of a()}); + _22 = discriminant((*_23)); + switchInt(move _22) -> [0: bb13, 3: bb16, 4: bb17, otherwise: bb18]; + } + + bb1: { + nop; + goto -> bb2; + } + + bb2: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb3: { + nop; + goto -> bb1; + } + + bb4: { + _2 = move _5; + StorageDead(_5); + goto -> bb10; + } + + bb5: { + StorageLive(_5); + _0 = Poll::<()>::Pending; + StorageDead(_5); + discriminant((*_23)) = 3; + return; + } + + bb6: { + unreachable; + } + + bb7: { + _7 = discriminant(_6); + switchInt(move _7) -> [0: bb3, 1: bb5, otherwise: bb6]; + } + + bb8: { + _6 = as Future>::poll(move _8, move _9) -> [return: bb7, unwind unreachable]; + } + + bb9: { + _10 = move _2; + _9 = move _10; + goto -> bb8; + } + + bb10: { + _11 = &mut (((*_23) as variant#4).2: impl std::future::Future); + _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb9, unwind unreachable]; + } + + bb11: { + _2 = move _12; + StorageDead(_12); + goto -> bb10; + } + + bb12: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb13: { + goto -> bb15; + } + + bb14: { + goto -> bb12; + } + + bb15: { + drop(((*_23).0: T)) -> [return: bb14, unwind unreachable]; + } + + bb16: { + StorageLive(_5); + goto -> bb4; + } + + bb17: { + StorageLive(_12); + goto -> bb11; + } + + bb18: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir new file mode 100644 index 0000000000000..a767f97bcba4f --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir @@ -0,0 +1,155 @@ +// MIR for `a::{closure#0}` 0 coroutine_drop_async + +fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { + debug _task_context => _2; + debug x => ((*_23).0: T); + let mut _0: std::task::Poll<()>; + let _3: T; + let mut _4: impl std::future::Future; + let mut _5: &mut std::task::Context<'_>; + let mut _6: std::task::Poll<()>; + let mut _7: isize; + let mut _8: std::pin::Pin<&mut impl std::future::Future>; + let mut _9: &mut std::task::Context<'_>; + let mut _10: &mut std::task::Context<'_>; + let mut _11: &mut impl std::future::Future; + let mut _12: &mut std::task::Context<'_>; + let mut _13: std::task::Poll<()>; + let mut _14: isize; + let mut _15: std::pin::Pin<&mut impl std::future::Future>; + let mut _16: &mut std::task::Context<'_>; + let mut _17: &mut std::task::Context<'_>; + let mut _18: &mut impl std::future::Future; + let mut _19: std::pin::Pin<&mut T>; + let mut _20: &mut T; + let mut _21: (); + let mut _22: u32; + let mut _23: &mut {async fn body of a()}; + scope 1 { + debug x => (((*_23) as variant#4).1: T); + } + + bb0: { + _23 = copy (_1.0: &mut {async fn body of a()}); + _22 = discriminant((*_23)); + switchInt(move _22) -> [0: bb17, 2: bb23, 3: bb21, 4: bb22, otherwise: bb24]; + } + + bb1: { + nop; + goto -> bb2; + } + + bb2: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb3 (cleanup): { + nop; + goto -> bb15; + } + + bb4 (cleanup): { + goto -> bb20; + } + + bb5: { + nop; + goto -> bb1; + } + + bb6 (cleanup): { + nop; + goto -> bb3; + } + + bb7: { + _2 = move _5; + StorageDead(_5); + goto -> bb13; + } + + bb8: { + StorageLive(_5); + _0 = Poll::<()>::Pending; + StorageDead(_5); + discriminant((*_23)) = 3; + return; + } + + bb9: { + unreachable; + } + + bb10: { + _7 = discriminant(_6); + switchInt(move _7) -> [0: bb5, 1: bb8, otherwise: bb9]; + } + + bb11: { + _6 = as Future>::poll(move _8, move _9) -> [return: bb10, unwind: bb6]; + } + + bb12: { + _10 = move _2; + _9 = move _10; + goto -> bb11; + } + + bb13: { + _11 = &mut (((*_23) as variant#4).2: impl std::future::Future); + _8 = Pin::<&mut impl Future>::new_unchecked(move _11) -> [return: bb12, unwind: bb6]; + } + + bb14: { + _2 = move _12; + StorageDead(_12); + goto -> bb13; + } + + bb15 (cleanup): { + goto -> bb4; + } + + bb16: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb17: { + goto -> bb19; + } + + bb18: { + goto -> bb16; + } + + bb19: { + drop(((*_23).0: T)) -> [return: bb18, unwind: bb4]; + } + + bb20 (cleanup): { + discriminant((*_23)) = 2; + resume; + } + + bb21: { + StorageLive(_5); + goto -> bb7; + } + + bb22: { + StorageLive(_12); + goto -> bb14; + } + + bb23: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb23, unwind continue]; + } + + bb24: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/async_drop_live_dead.rs b/tests/mir-opt/coroutine/async_drop_live_dead.rs similarity index 100% rename from tests/mir-opt/async_drop_live_dead.rs rename to tests/mir-opt/coroutine/async_drop_live_dead.rs diff --git a/tests/mir-opt/coroutine/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir b/tests/mir-opt/coroutine/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir new file mode 100644 index 0000000000000..3d1ee14cc0740 --- /dev/null +++ b/tests/mir-opt/coroutine/async_drop_mir_pin.core.future-async_drop-async_drop_in_place-{closure#0}.[Foo;1].MentionedItems.after.mir @@ -0,0 +1,272 @@ +// MIR for `std::future::async_drop_in_place::{closure#0}` after MentionedItems + +fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<[Foo; 1]>()}, _2: std::future::ResumeTy) -> () +yields () + { + let mut _0: (); + let mut _3: &mut [Foo; 1]; + let mut _4: *mut [Foo; 1]; + let mut _5: *mut [Foo]; + let mut _6: usize; + let mut _7: usize; + let mut _8: *mut Foo; + let mut _9: bool; + let mut _10: *mut Foo; + let mut _11: bool; + let mut _12: impl std::future::Future; + let mut _13: std::future::ResumeTy; + let mut _14: std::task::Poll<()>; + let mut _15: isize; + let mut _16: std::pin::Pin<&mut impl std::future::Future>; + let mut _17: &mut std::task::Context<'_>; + let mut _18: std::future::ResumeTy; + let mut _19: &mut impl std::future::Future; + let mut _20: std::pin::Pin<&mut Foo>; + let mut _21: &mut Foo; + let mut _22: *mut Foo; + let mut _23: bool; + let mut _24: impl std::future::Future; + let mut _25: std::future::ResumeTy; + let mut _26: std::task::Poll<()>; + let mut _27: isize; + let mut _28: std::pin::Pin<&mut impl std::future::Future>; + let mut _29: &mut std::task::Context<'_>; + let mut _30: std::future::ResumeTy; + let mut _31: &mut impl std::future::Future; + let mut _32: std::future::ResumeTy; + let mut _33: std::task::Poll<()>; + let mut _34: isize; + let mut _35: std::pin::Pin<&mut impl std::future::Future>; + let mut _36: &mut std::task::Context<'_>; + let mut _37: std::future::ResumeTy; + let mut _38: &mut impl std::future::Future; + let mut _39: std::pin::Pin<&mut Foo>; + let mut _40: &mut Foo; + + bb0: { + _3 = move (_1.0: &mut [Foo; 1]); + goto -> bb44; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } + + bb3 (cleanup): { + _8 = &raw mut (*_5)[_7]; + _7 = Add(move _7, const 1_usize); + drop((*_8)) -> [return: bb4, unwind terminate(cleanup)]; + } + + bb4 (cleanup): { + _9 = Eq(copy _7, copy _6); + switchInt(move _9) -> [0: bb3, otherwise: bb2]; + } + + bb5: { + _10 = &raw mut (*_5)[_7]; + _7 = Add(move _7, const 1_usize); + goto -> bb19; + } + + bb6: { + _11 = Eq(copy _7, copy _6); + switchInt(move _11) -> [0: bb5, otherwise: bb1]; + } + + bb7: { + StorageDead(_12); + goto -> bb6; + } + + bb8 (cleanup): { + StorageDead(_12); + goto -> bb4; + } + + bb9: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb9, unwind: bb8]; + } + + bb10: { + _2 = move _13; + StorageDead(_13); + goto -> bb9; + } + + bb11: { + _2 = move _13; + StorageDead(_13); + goto -> bb17; + } + + bb12: { + StorageLive(_13); + _13 = yield(const ()) -> [resume: bb10, drop: bb11]; + } + + bb13: { + unreachable; + } + + bb14: { + _15 = discriminant(_14); + switchInt(move _15) -> [0: bb7, 1: bb12, otherwise: bb13]; + } + + bb15: { + _14 = as Future>::poll(move _16, move _17) -> [return: bb14, unwind: bb8]; + } + + bb16: { + _18 = move _2; + _17 = std::future::get_context::<'_, '_>(move _18) -> [return: bb15, unwind: bb8]; + } + + bb17: { + _19 = &mut _12; + _16 = Pin::<&mut impl Future>::new_unchecked(move _19) -> [return: bb16, unwind: bb8]; + } + + bb18: { + StorageLive(_12); + _12 = async_drop_in_place::(copy (_20.0: &mut Foo)) -> [return: bb17, unwind: bb8]; + } + + bb19: { + _21 = &mut (*_10); + _20 = Pin::<&mut Foo>::new_unchecked(move _21) -> [return: bb18, unwind: bb4]; + } + + bb20: { + _22 = &raw mut (*_5)[_7]; + _7 = Add(move _7, const 1_usize); + goto -> bb41; + } + + bb21: { + _23 = Eq(copy _7, copy _6); + switchInt(move _23) -> [0: bb20, otherwise: bb1]; + } + + bb22: { + StorageDead(_24); + goto -> bb21; + } + + bb23: { + StorageDead(_24); + goto -> bb6; + } + + bb24 (cleanup): { + StorageDead(_24); + goto -> bb4; + } + + bb25: { + assert(const false, "`async fn` resumed after async drop") -> [success: bb25, unwind: bb24]; + } + + bb26: { + _2 = move _25; + StorageDead(_25); + goto -> bb25; + } + + bb27: { + _2 = move _25; + StorageDead(_25); + goto -> bb32; + } + + bb28: { + StorageLive(_25); + _25 = yield(const ()) -> [resume: bb26, drop: bb27]; + } + + bb29: { + _27 = discriminant(_26); + switchInt(move _27) -> [0: bb23, 1: bb28, otherwise: bb13]; + } + + bb30: { + _26 = as Future>::poll(move _28, move _29) -> [return: bb29, unwind: bb24]; + } + + bb31: { + _30 = move _2; + _29 = std::future::get_context::<'_, '_>(move _30) -> [return: bb30, unwind: bb24]; + } + + bb32: { + _31 = &mut _24; + _28 = Pin::<&mut impl Future>::new_unchecked(move _31) -> [return: bb31, unwind: bb24]; + } + + bb33: { + _2 = move _32; + StorageDead(_32); + goto -> bb39; + } + + bb34: { + _2 = move _32; + StorageDead(_32); + goto -> bb32; + } + + bb35: { + StorageLive(_32); + _32 = yield(const ()) -> [resume: bb33, drop: bb34]; + } + + bb36: { + _34 = discriminant(_33); + switchInt(move _34) -> [0: bb22, 1: bb35, otherwise: bb13]; + } + + bb37: { + _33 = as Future>::poll(move _35, move _36) -> [return: bb36, unwind: bb24]; + } + + bb38: { + _37 = move _2; + _36 = std::future::get_context::<'_, '_>(move _37) -> [return: bb37, unwind: bb24]; + } + + bb39: { + _38 = &mut _24; + _35 = Pin::<&mut impl Future>::new_unchecked(move _38) -> [return: bb38, unwind: bb24]; + } + + bb40: { + StorageLive(_24); + _24 = async_drop_in_place::(copy (_39.0: &mut Foo)) -> [return: bb39, unwind: bb24]; + } + + bb41: { + _40 = &mut (*_22); + _39 = Pin::<&mut Foo>::new_unchecked(move _40) -> [return: bb40, unwind: bb4]; + } + + bb42: { + _6 = PtrMetadata(copy _5); + _7 = const 0_usize; + goto -> bb21; + } + + bb43: { + goto -> bb42; + } + + bb44: { + _4 = &raw mut (*_3); + _5 = move _4 as *mut [Foo] (PointerCoercion(Unsize, Implicit)); + goto -> bb43; + } +} diff --git a/tests/mir-opt/async_drop_mir_pin.rs b/tests/mir-opt/coroutine/async_drop_mir_pin.rs similarity index 100% rename from tests/mir-opt/async_drop_mir_pin.rs rename to tests/mir-opt/coroutine/async_drop_mir_pin.rs diff --git a/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..b0c9a3e0de118 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.StateTransform.after.mir @@ -0,0 +1,60 @@ +// MIR for `add::{closure#0}::{closure#0}` after StateTransform + +fn add::{closure#0}::{closure#0}(_1: Pin<&mut {async block@$DIR/async_fn.rs:34:13: 34:18}>, _2: &mut Context<'_>) -> Poll { + coroutine layout { + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + } + storage_conflicts = BitMatrix(0x0) {} + } + debug _task_context => _2; + debug x => (*((*_9).0: &u32)); + debug y => (*((*_9).1: &u32)); + let mut _0: std::task::Poll; + let mut _3: u32; + let mut _4: u32; + let mut _5: &u32; + let mut _6: &u32; + let mut _7: u32; + let mut _8: u32; + let mut _9: &mut {async block@$DIR/async_fn.rs:34:13: 34:18}; + + bb0: { + _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:34:13: 34:18}); + _8 = discriminant((*_9)); + switchInt(move _8) -> [0: bb1, 1: bb4, otherwise: bb5]; + } + + bb1: { + StorageLive(_3); + _5 = no_retag copy ((*_9).0: &u32); + _3 = copy (*_5); + StorageLive(_4); + _6 = no_retag copy ((*_9).1: &u32); + _4 = copy (*_6); + _7 = Add(move _3, move _4); + StorageDead(_4); + StorageDead(_3); + goto -> bb3; + } + + bb2: { + _0 = Poll::::Ready(move _7); + discriminant((*_9)) = 1; + return; + } + + bb3: { + goto -> bb2; + } + + bb4: { + assert(const false, "`async fn` resumed after completion") -> [success: bb4, unwind continue]; + } + + bb5: { + unreachable; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.coroutine_drop.0.mir new file mode 100644 index 0000000000000..0439d4c682755 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.coroutine_drop.0.mir @@ -0,0 +1,36 @@ +// MIR for `add::{closure#0}::{closure#0}` 0 coroutine_drop + +fn add::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs:34:13: 34:18}) -> () { + debug _task_context => _2; + debug x => (*((*_1).0: &u32)); + debug y => (*((*_1).1: &u32)); + let mut _0: (); + let mut _2: &mut std::task::Context<'_>; + let mut _3: u32; + let mut _4: u32; + let mut _5: &u32; + let mut _6: &u32; + let mut _7: u32; + let mut _8: u32; + + bb0: { + _8 = discriminant((*_1)); + switchInt(move _8) -> [0: bb2, otherwise: bb4]; + } + + bb1: { + return; + } + + bb2: { + goto -> bb3; + } + + bb3: { + goto -> bb1; + } + + bb4: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir b/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir new file mode 100644 index 0000000000000..0c8f25df081aa --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.add-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir @@ -0,0 +1,14 @@ +// MIR for `add::{closure#0}::{closure#0}` 0 coroutine_drop_proxy_async + +fn add::{closure#0}::{closure#0}(_1: {async block@$DIR/async_fn.rs:34:13: 34:18}, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: std::task::Poll<()>; + + bb0: { + drop(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.add-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_fn.add-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..d79a22b1f63c8 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.add-{closure#0}.StateTransform.after.mir @@ -0,0 +1,269 @@ +// MIR for `add::{closure#0}` after StateTransform + +fn add::{closure#0}(_1: Pin<&mut {async fn body of add()}>, _2: &mut Context<'_>) -> Poll { + coroutine layout { + field _s0: u32; + field _s1: u32; + field _s2: {async block@$DIR/async_fn.rs:34:13: 34:18}; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0, _s1, _s2], + } + storage_conflicts = BitMatrix(3x3) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s2, _s0), (_s2, _s1), (_s2, _s2)} + } + debug _task_context => _2; + debug x => ((*_27).0: u32); + debug y => ((*_27).1: u32); + coroutine debug x => _s0; + let mut _0: std::task::Poll; + let _3: u32; + let mut _6: &u32; + let mut _7: &u32; + let mut _8: {async block@$DIR/async_fn.rs:34:13: 34:18}; + let mut _9: {async block@$DIR/async_fn.rs:34:13: 34:18}; + let mut _11: (); + let _12: (); + let mut _13: std::task::Poll; + let mut _14: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:34:13: 34:18}>; + let mut _15: &mut {async block@$DIR/async_fn.rs:34:13: 34:18}; + let mut _16: &mut {async block@$DIR/async_fn.rs:34:13: 34:18}; + let mut _17: &mut std::task::Context<'_>; + let mut _18: &mut std::task::Context<'_>; + let mut _19: &mut std::task::Context<'_>; + let mut _20: isize; + let mut _22: !; + let mut _23: &mut std::task::Context<'_>; + let mut _24: (); + let mut _25: u32; + let mut _26: u32; + let mut _27: &mut {async fn body of add()}; + scope 1 { + debug x => (((*_27) as variant#3).0: u32); + coroutine debug y => _s1; + let _4: u32; + scope 2 { + debug y => (((*_27) as variant#3).1: u32); + let _5: {async block@$DIR/async_fn.rs:34:13: 34:18}; + scope 3 { + debug a => _5; + coroutine debug __awaitee => _s2; + let mut _10: {async block@$DIR/async_fn.rs:34:13: 34:18}; + scope 4 { + debug __awaitee => (((*_27) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18}); + let _21: u32; + scope 5 { + debug result => _21; + } + } + } + } + } + + bb0: { + _27 = copy (_1.0: &mut {async fn body of add()}); + _26 = discriminant((*_27)); + switchInt(move _26) -> [0: bb1, 1: bb28, 2: bb27, 3: bb26, otherwise: bb7]; + } + + bb1: { + nop; + (((*_27) as variant#3).0: u32) = copy ((*_27).0: u32); + nop; + (((*_27) as variant#3).1: u32) = copy ((*_27).1: u32); + StorageLive(_5); + StorageLive(_6); + _6 = &(((*_27) as variant#3).0: u32); + StorageLive(_7); + _7 = &(((*_27) as variant#3).1: u32); + _5 = {coroutine@$DIR/async_fn.rs:34:13: 34:18 (#0)} { x: move _6, y: move _7 }; + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = move _5; + _8 = <{async block@$DIR/async_fn.rs:34:13: 34:18} as IntoFuture>::into_future(move _9) -> [return: bb2, unwind: bb19]; + } + + bb2: { + StorageDead(_9); + PlaceMention(_8); + nop; + (((*_27) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18}) = move _8; + goto -> bb3; + } + + bb3: { + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); + StorageLive(_15); + StorageLive(_16); + _16 = &mut (((*_27) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18}); + _15 = &mut (*_16); + _14 = Pin::<&mut {async block@$DIR/async_fn.rs:34:13: 34:18}>::new_unchecked(move _15) -> [return: bb4, unwind: bb16]; + } + + bb4: { + StorageDead(_15); + StorageLive(_17); + StorageLive(_18); + StorageLive(_19); + _19 = copy _2; + _18 = move _19; + goto -> bb5; + } + + bb5: { + _17 = &mut (*_18); + StorageDead(_19); + _13 = <{async block@$DIR/async_fn.rs:34:13: 34:18} as Future>::poll(move _14, move _17) -> [return: bb6, unwind: bb15]; + } + + bb6: { + StorageDead(_18); + StorageDead(_17); + StorageDead(_16); + StorageDead(_14); + PlaceMention(_13); + _20 = discriminant(_13); + switchInt(move _20) -> [0: bb9, 1: bb8, otherwise: bb7]; + } + + bb7: { + unreachable; + } + + bb8: { + _12 = const (); + StorageDead(_13); + StorageDead(_12); + StorageLive(_23); + StorageLive(_24); + _24 = (); + _0 = Poll::::Pending; + StorageDead(_5); + StorageDead(_8); + StorageDead(_23); + StorageDead(_24); + discriminant((*_27)) = 3; + return; + } + + bb9: { + StorageLive(_21); + _21 = copy ((_13 as Ready).0: u32); + _25 = copy _21; + StorageDead(_21); + StorageDead(_13); + StorageDead(_12); + drop((((*_27) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18})) -> [return: bb11, unwind: bb18]; + } + + bb10: { + StorageDead(_24); + _2 = move _23; + StorageDead(_23); + _11 = const (); + goto -> bb3; + } + + bb11: { + nop; + goto -> bb12; + } + + bb12: { + StorageDead(_8); + goto -> bb13; + } + + bb13: { + StorageDead(_5); + nop; + nop; + goto -> bb24; + } + + bb14: { + _0 = Poll::::Ready(move _25); + discriminant((*_27)) = 1; + return; + } + + bb15 (cleanup): { + StorageDead(_18); + StorageDead(_17); + goto -> bb17; + } + + bb16 (cleanup): { + StorageDead(_15); + goto -> bb17; + } + + bb17 (cleanup): { + StorageDead(_16); + StorageDead(_14); + StorageDead(_13); + StorageDead(_12); + drop((((*_27) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18})) -> [return: bb18, unwind terminate(cleanup)]; + } + + bb18 (cleanup): { + nop; + goto -> bb21; + } + + bb19 (cleanup): { + goto -> bb20; + } + + bb20 (cleanup): { + StorageDead(_9); + goto -> bb21; + } + + bb21 (cleanup): { + StorageDead(_8); + goto -> bb22; + } + + bb22 (cleanup): { + StorageDead(_5); + nop; + nop; + goto -> bb23; + } + + bb23 (cleanup): { + goto -> bb25; + } + + bb24: { + goto -> bb14; + } + + bb25 (cleanup): { + discriminant((*_27)) = 2; + resume; + } + + bb26: { + StorageLive(_5); + StorageLive(_8); + StorageLive(_23); + StorageLive(_24); + _23 = move _2; + goto -> bb10; + } + + bb27: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb27, unwind continue]; + } + + bb28: { + assert(const false, "`async fn` resumed after completion") -> [success: bb28, unwind continue]; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.add-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.add-{closure#0}.coroutine_drop.0.mir new file mode 100644 index 0000000000000..ecff837e4436f --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.add-{closure#0}.coroutine_drop.0.mir @@ -0,0 +1,129 @@ +// MIR for `add::{closure#0}` 0 coroutine_drop + +fn add::{closure#0}(_1: &mut {async fn body of add()}) -> () { + debug _task_context => _2; + debug x => ((*_1).0: u32); + debug y => ((*_1).1: u32); + let mut _0: (); + let mut _2: &mut std::task::Context<'_>; + let _3: u32; + let mut _6: &u32; + let mut _7: &u32; + let mut _8: {async block@$DIR/async_fn.rs:34:13: 34:18}; + let mut _9: {async block@$DIR/async_fn.rs:34:13: 34:18}; + let mut _11: (); + let _12: (); + let mut _13: std::task::Poll; + let mut _14: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:34:13: 34:18}>; + let mut _15: &mut {async block@$DIR/async_fn.rs:34:13: 34:18}; + let mut _16: &mut {async block@$DIR/async_fn.rs:34:13: 34:18}; + let mut _17: &mut std::task::Context<'_>; + let mut _18: &mut std::task::Context<'_>; + let mut _19: &mut std::task::Context<'_>; + let mut _20: isize; + let mut _22: !; + let mut _23: &mut std::task::Context<'_>; + let mut _24: (); + let mut _25: u32; + let mut _26: u32; + scope 1 { + debug x => (((*_1) as variant#3).0: u32); + let _4: u32; + scope 2 { + debug y => (((*_1) as variant#3).1: u32); + let _5: {async block@$DIR/async_fn.rs:34:13: 34:18}; + scope 3 { + debug a => _5; + let mut _10: {async block@$DIR/async_fn.rs:34:13: 34:18}; + scope 4 { + debug __awaitee => (((*_1) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18}); + let _21: u32; + scope 5 { + debug result => _21; + } + } + } + } + } + + bb0: { + _26 = discriminant((*_1)); + switchInt(move _26) -> [0: bb11, 3: bb14, otherwise: bb15]; + } + + bb1: { + StorageDead(_24); + StorageDead(_23); + drop((((*_1) as variant#3).2: {async block@$DIR/async_fn.rs:34:13: 34:18})) -> [return: bb2, unwind: bb7]; + } + + bb2: { + nop; + goto -> bb3; + } + + bb3: { + StorageDead(_8); + goto -> bb4; + } + + bb4: { + StorageDead(_5); + nop; + nop; + goto -> bb12; + } + + bb5: { + return; + } + + bb6 (cleanup): { + resume; + } + + bb7 (cleanup): { + nop; + goto -> bb8; + } + + bb8 (cleanup): { + StorageDead(_8); + goto -> bb9; + } + + bb9 (cleanup): { + StorageDead(_5); + nop; + nop; + goto -> bb6; + } + + bb10: { + return; + } + + bb11: { + goto -> bb13; + } + + bb12: { + goto -> bb5; + } + + bb13: { + goto -> bb10; + } + + bb14: { + StorageLive(_5); + StorageLive(_8); + StorageLive(_23); + StorageLive(_24); + goto -> bb1; + } + + bb15: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.add-{closure#0}.coroutine_drop_proxy_async.0.mir b/tests/mir-opt/coroutine/async_fn.add-{closure#0}.coroutine_drop_proxy_async.0.mir new file mode 100644 index 0000000000000..c86391c4f729e --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.add-{closure#0}.coroutine_drop_proxy_async.0.mir @@ -0,0 +1,24 @@ +// MIR for `add::{closure#0}` 0 coroutine_drop_proxy_async + +fn add::{closure#0}(_1: {async fn body of add()}, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: std::task::Poll<()>; + scope 1 { + scope 2 { + scope 3 { + scope 4 { + scope 5 { + } + } + } + } + } + + bb0: { + drop(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..9015bbc939792 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.StateTransform.after.mir @@ -0,0 +1,507 @@ +// MIR for `build_aggregate::{closure#0}` after StateTransform + +fn build_aggregate::{closure#0}(_1: Pin<&mut {async fn body of build_aggregate()}>, _2: &mut Context<'_>) -> Poll { + coroutine layout { + field _s0: u32; + field _s1: u32; + field _s2: u32; + field _s3: {async fn body of add()}; + field _s4: {async fn body of add()}; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0, _s1, _s3], + Suspend1 (4): [_s2, _s4], + } + storage_conflicts = BitMatrix(5x5) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s0, _s4), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s1, _s3), (_s1, _s4), (_s2, _s0), (_s2, _s1), (_s2, _s2), (_s2, _s3), (_s2, _s4), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3), (_s4, _s0), (_s4, _s1), (_s4, _s2), (_s4, _s4)} + } + debug _task_context => _2; + debug a => ((*_51).0: u32); + debug b => ((*_51).1: u32); + debug c => ((*_51).2: u32); + debug d => ((*_51).3: u32); + let mut _0: std::task::Poll; + let _3: u32; + let mut _8: u32; + let mut _9: {async fn body of add()}; + let mut _10: {async fn body of add()}; + let mut _11: u32; + let mut _12: u32; + let mut _14: (); + let _15: (); + let mut _16: std::task::Poll; + let mut _17: std::pin::Pin<&mut {async fn body of add()}>; + let mut _18: &mut {async fn body of add()}; + let mut _19: &mut {async fn body of add()}; + let mut _20: &mut std::task::Context<'_>; + let mut _21: &mut std::task::Context<'_>; + let mut _22: &mut std::task::Context<'_>; + let mut _23: isize; + let mut _25: !; + let mut _26: &mut std::task::Context<'_>; + let mut _27: (); + let mut _28: u32; + let mut _29: {async fn body of add()}; + let mut _30: {async fn body of add()}; + let mut _31: u32; + let mut _32: u32; + let _34: (); + let mut _35: std::task::Poll; + let mut _36: std::pin::Pin<&mut {async fn body of add()}>; + let mut _37: &mut {async fn body of add()}; + let mut _38: &mut {async fn body of add()}; + let mut _39: &mut std::task::Context<'_>; + let mut _40: &mut std::task::Context<'_>; + let mut _41: &mut std::task::Context<'_>; + let mut _42: isize; + let mut _44: !; + let mut _45: &mut std::task::Context<'_>; + let mut _46: (); + let mut _47: u32; + let mut _48: u32; + let mut _49: u32; + let mut _50: u32; + let mut _51: &mut {async fn body of build_aggregate()}; + scope 1 { + debug a => _3; + let _4: u32; + scope 2 { + debug b => _4; + coroutine debug c => _s0; + let _5: u32; + scope 3 { + debug c => (((*_51) as variant#3).0: u32); + coroutine debug d => _s1; + let _6: u32; + scope 4 { + debug d => (((*_51) as variant#3).1: u32); + coroutine debug __awaitee => _s3; + coroutine debug __awaitee => _s4; + let _7: (u32, u32); + let mut _13: {async fn body of add()}; + let mut _33: {async fn body of add()}; + scope 5 { + debug x => _7; + } + scope 6 { + debug __awaitee => (((*_51) as variant#3).2: {async fn body of add()}); + let _24: u32; + scope 7 { + debug result => _24; + } + } + scope 8 { + debug __awaitee => (((*_51) as variant#4).1: {async fn body of add()}); + let _43: u32; + scope 9 { + debug result => _43; + } + } + } + } + } + } + + bb0: { + _51 = copy (_1.0: &mut {async fn body of build_aggregate()}); + _50 = discriminant((*_51)); + switchInt(move _50) -> [0: bb1, 1: bb49, 2: bb48, 3: bb46, 4: bb47, otherwise: bb8]; + } + + bb1: { + StorageLive(_3); + _3 = copy ((*_51).0: u32); + StorageLive(_4); + _4 = copy ((*_51).1: u32); + nop; + (((*_51) as variant#3).0: u32) = copy ((*_51).2: u32); + nop; + (((*_51) as variant#3).1: u32) = copy ((*_51).3: u32); + StorageLive(_7); + nop; + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _11 = copy _3; + StorageLive(_12); + _12 = copy _4; + _10 = add(move _11, move _12) -> [return: bb2, unwind: bb40]; + } + + bb2: { + StorageDead(_12); + StorageDead(_11); + _9 = <{async fn body of add()} as IntoFuture>::into_future(move _10) -> [return: bb3, unwind: bb39]; + } + + bb3: { + StorageDead(_10); + PlaceMention(_9); + nop; + (((*_51) as variant#3).2: {async fn body of add()}) = move _9; + goto -> bb4; + } + + bb4: { + StorageLive(_15); + StorageLive(_16); + StorageLive(_17); + StorageLive(_18); + StorageLive(_19); + _19 = &mut (((*_51) as variant#3).2: {async fn body of add()}); + _18 = &mut (*_19); + _17 = Pin::<&mut {async fn body of add()}>::new_unchecked(move _18) -> [return: bb5, unwind: bb35]; + } + + bb5: { + StorageDead(_18); + StorageLive(_20); + StorageLive(_21); + StorageLive(_22); + _22 = copy _2; + _21 = move _22; + goto -> bb6; + } + + bb6: { + _20 = &mut (*_21); + StorageDead(_22); + _16 = <{async fn body of add()} as Future>::poll(move _17, move _20) -> [return: bb7, unwind: bb34]; + } + + bb7: { + StorageDead(_21); + StorageDead(_20); + StorageDead(_19); + StorageDead(_17); + PlaceMention(_16); + _23 = discriminant(_16); + switchInt(move _23) -> [0: bb10, 1: bb9, otherwise: bb8]; + } + + bb8: { + unreachable; + } + + bb9: { + _15 = const (); + StorageDead(_16); + StorageDead(_15); + StorageLive(_26); + StorageLive(_27); + _27 = (); + _0 = Poll::::Pending; + StorageDead(_3); + StorageDead(_4); + StorageDead(_7); + StorageDead(_9); + StorageDead(_26); + StorageDead(_27); + discriminant((*_51)) = 3; + return; + } + + bb10: { + StorageLive(_24); + _24 = copy ((_16 as Ready).0: u32); + (((*_51) as variant#4).0: u32) = copy _24; + StorageDead(_24); + StorageDead(_16); + StorageDead(_15); + drop((((*_51) as variant#3).2: {async fn body of add()})) -> [return: bb12, unwind: bb37]; + } + + bb11: { + StorageDead(_27); + _2 = move _26; + StorageDead(_26); + _14 = const (); + goto -> bb4; + } + + bb12: { + nop; + StorageLive(_28); + StorageLive(_29); + StorageLive(_30); + StorageLive(_31); + _31 = copy (((*_51) as variant#3).0: u32); + StorageLive(_32); + _32 = copy (((*_51) as variant#3).1: u32); + _30 = add(move _31, move _32) -> [return: bb13, unwind: bb31]; + } + + bb13: { + StorageDead(_32); + StorageDead(_31); + _29 = <{async fn body of add()} as IntoFuture>::into_future(move _30) -> [return: bb14, unwind: bb30]; + } + + bb14: { + StorageDead(_30); + PlaceMention(_29); + nop; + (((*_51) as variant#4).1: {async fn body of add()}) = move _29; + goto -> bb15; + } + + bb15: { + StorageLive(_34); + StorageLive(_35); + StorageLive(_36); + StorageLive(_37); + StorageLive(_38); + _38 = &mut (((*_51) as variant#4).1: {async fn body of add()}); + _37 = &mut (*_38); + _36 = Pin::<&mut {async fn body of add()}>::new_unchecked(move _37) -> [return: bb16, unwind: bb27]; + } + + bb16: { + StorageDead(_37); + StorageLive(_39); + StorageLive(_40); + StorageLive(_41); + _41 = copy _2; + _40 = move _41; + goto -> bb17; + } + + bb17: { + _39 = &mut (*_40); + StorageDead(_41); + _35 = <{async fn body of add()} as Future>::poll(move _36, move _39) -> [return: bb18, unwind: bb26]; + } + + bb18: { + StorageDead(_40); + StorageDead(_39); + StorageDead(_38); + StorageDead(_36); + PlaceMention(_35); + _42 = discriminant(_35); + switchInt(move _42) -> [0: bb20, 1: bb19, otherwise: bb8]; + } + + bb19: { + _34 = const (); + StorageDead(_35); + StorageDead(_34); + StorageLive(_45); + StorageLive(_46); + _46 = (); + _0 = Poll::::Pending; + StorageDead(_3); + StorageDead(_4); + StorageDead(_7); + StorageDead(_9); + StorageDead(_28); + StorageDead(_29); + StorageDead(_45); + StorageDead(_46); + discriminant((*_51)) = 4; + return; + } + + bb20: { + StorageLive(_43); + _43 = copy ((_35 as Ready).0: u32); + _28 = copy _43; + StorageDead(_43); + StorageDead(_35); + StorageDead(_34); + drop((((*_51) as variant#4).1: {async fn body of add()})) -> [return: bb22, unwind: bb29]; + } + + bb21: { + StorageDead(_46); + _2 = move _45; + StorageDead(_45); + _14 = const (); + goto -> bb15; + } + + bb22: { + nop; + _7 = (move (((*_51) as variant#4).0: u32), move _28); + StorageDead(_28); + nop; + goto -> bb23; + } + + bb23: { + StorageDead(_29); + goto -> bb24; + } + + bb24: { + StorageDead(_9); + StorageLive(_47); + _47 = copy (_7.0: u32); + StorageLive(_48); + _48 = copy (_7.1: u32); + _49 = Add(move _47, move _48); + StorageDead(_48); + StorageDead(_47); + StorageDead(_7); + nop; + nop; + StorageDead(_4); + StorageDead(_3); + goto -> bb44; + } + + bb25: { + _0 = Poll::::Ready(move _49); + discriminant((*_51)) = 1; + return; + } + + bb26 (cleanup): { + StorageDead(_40); + StorageDead(_39); + goto -> bb28; + } + + bb27 (cleanup): { + StorageDead(_37); + goto -> bb28; + } + + bb28 (cleanup): { + StorageDead(_38); + StorageDead(_36); + StorageDead(_35); + StorageDead(_34); + drop((((*_51) as variant#4).1: {async fn body of add()})) -> [return: bb29, unwind terminate(cleanup)]; + } + + bb29 (cleanup): { + nop; + StorageDead(_28); + nop; + goto -> bb33; + } + + bb30 (cleanup): { + goto -> bb32; + } + + bb31 (cleanup): { + StorageDead(_32); + StorageDead(_31); + goto -> bb32; + } + + bb32 (cleanup): { + StorageDead(_30); + StorageDead(_28); + nop; + goto -> bb33; + } + + bb33 (cleanup): { + StorageDead(_29); + goto -> bb38; + } + + bb34 (cleanup): { + StorageDead(_21); + StorageDead(_20); + goto -> bb36; + } + + bb35 (cleanup): { + StorageDead(_18); + goto -> bb36; + } + + bb36 (cleanup): { + StorageDead(_19); + StorageDead(_17); + StorageDead(_16); + StorageDead(_15); + drop((((*_51) as variant#3).2: {async fn body of add()})) -> [return: bb37, unwind terminate(cleanup)]; + } + + bb37 (cleanup): { + nop; + nop; + goto -> bb38; + } + + bb38 (cleanup): { + goto -> bb42; + } + + bb39 (cleanup): { + goto -> bb41; + } + + bb40 (cleanup): { + StorageDead(_12); + StorageDead(_11); + goto -> bb41; + } + + bb41 (cleanup): { + StorageDead(_10); + nop; + goto -> bb42; + } + + bb42 (cleanup): { + StorageDead(_9); + StorageDead(_7); + nop; + nop; + StorageDead(_4); + StorageDead(_3); + goto -> bb43; + } + + bb43 (cleanup): { + goto -> bb45; + } + + bb44: { + goto -> bb25; + } + + bb45 (cleanup): { + discriminant((*_51)) = 2; + resume; + } + + bb46: { + StorageLive(_3); + StorageLive(_4); + StorageLive(_7); + StorageLive(_9); + StorageLive(_26); + StorageLive(_27); + _26 = move _2; + goto -> bb11; + } + + bb47: { + StorageLive(_3); + StorageLive(_4); + StorageLive(_7); + StorageLive(_9); + StorageLive(_28); + StorageLive(_29); + StorageLive(_45); + StorageLive(_46); + _45 = move _2; + goto -> bb21; + } + + bb48: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb48, unwind continue]; + } + + bb49: { + assert(const false, "`async fn` resumed after completion") -> [success: bb49, unwind continue]; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.coroutine_drop.0.mir new file mode 100644 index 0000000000000..bd5fea383b50d --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.coroutine_drop.0.mir @@ -0,0 +1,217 @@ +// MIR for `build_aggregate::{closure#0}` 0 coroutine_drop + +fn build_aggregate::{closure#0}(_1: &mut {async fn body of build_aggregate()}) -> () { + debug _task_context => _2; + debug a => ((*_1).0: u32); + debug b => ((*_1).1: u32); + debug c => ((*_1).2: u32); + debug d => ((*_1).3: u32); + let mut _0: (); + let mut _2: &mut std::task::Context<'_>; + let _3: u32; + let mut _8: u32; + let mut _9: {async fn body of add()}; + let mut _10: {async fn body of add()}; + let mut _11: u32; + let mut _12: u32; + let mut _14: (); + let _15: (); + let mut _16: std::task::Poll; + let mut _17: std::pin::Pin<&mut {async fn body of add()}>; + let mut _18: &mut {async fn body of add()}; + let mut _19: &mut {async fn body of add()}; + let mut _20: &mut std::task::Context<'_>; + let mut _21: &mut std::task::Context<'_>; + let mut _22: &mut std::task::Context<'_>; + let mut _23: isize; + let mut _25: !; + let mut _26: &mut std::task::Context<'_>; + let mut _27: (); + let mut _28: u32; + let mut _29: {async fn body of add()}; + let mut _30: {async fn body of add()}; + let mut _31: u32; + let mut _32: u32; + let _34: (); + let mut _35: std::task::Poll; + let mut _36: std::pin::Pin<&mut {async fn body of add()}>; + let mut _37: &mut {async fn body of add()}; + let mut _38: &mut {async fn body of add()}; + let mut _39: &mut std::task::Context<'_>; + let mut _40: &mut std::task::Context<'_>; + let mut _41: &mut std::task::Context<'_>; + let mut _42: isize; + let mut _44: !; + let mut _45: &mut std::task::Context<'_>; + let mut _46: (); + let mut _47: u32; + let mut _48: u32; + let mut _49: u32; + let mut _50: u32; + scope 1 { + debug a => _3; + let _4: u32; + scope 2 { + debug b => _4; + let _5: u32; + scope 3 { + debug c => (((*_1) as variant#3).0: u32); + let _6: u32; + scope 4 { + debug d => (((*_1) as variant#3).1: u32); + let _7: (u32, u32); + let mut _13: {async fn body of add()}; + let mut _33: {async fn body of add()}; + scope 5 { + debug x => _7; + } + scope 6 { + debug __awaitee => (((*_1) as variant#3).2: {async fn body of add()}); + let _24: u32; + scope 7 { + debug result => _24; + } + } + scope 8 { + debug __awaitee => (((*_1) as variant#4).1: {async fn body of add()}); + let _43: u32; + scope 9 { + debug result => _43; + } + } + } + } + } + } + + bb0: { + _50 = discriminant((*_1)); + switchInt(move _50) -> [0: bb16, 3: bb19, 4: bb20, otherwise: bb21]; + } + + bb1: { + StorageDead(_46); + StorageDead(_45); + drop((((*_1) as variant#4).1: {async fn body of add()})) -> [return: bb2, unwind: bb10]; + } + + bb2: { + nop; + StorageDead(_28); + nop; + goto -> bb3; + } + + bb3: { + StorageDead(_29); + goto -> bb6; + } + + bb4: { + StorageDead(_27); + StorageDead(_26); + drop((((*_1) as variant#3).2: {async fn body of add()})) -> [return: bb5, unwind: bb12]; + } + + bb5: { + nop; + nop; + goto -> bb6; + } + + bb6: { + goto -> bb7; + } + + bb7: { + StorageDead(_9); + StorageDead(_7); + nop; + nop; + StorageDead(_4); + StorageDead(_3); + goto -> bb17; + } + + bb8: { + return; + } + + bb9 (cleanup): { + resume; + } + + bb10 (cleanup): { + nop; + StorageDead(_28); + nop; + goto -> bb11; + } + + bb11 (cleanup): { + StorageDead(_29); + goto -> bb13; + } + + bb12 (cleanup): { + nop; + nop; + goto -> bb13; + } + + bb13 (cleanup): { + goto -> bb14; + } + + bb14 (cleanup): { + StorageDead(_9); + StorageDead(_7); + nop; + nop; + StorageDead(_4); + StorageDead(_3); + goto -> bb9; + } + + bb15: { + return; + } + + bb16: { + goto -> bb18; + } + + bb17: { + goto -> bb8; + } + + bb18: { + goto -> bb15; + } + + bb19: { + StorageLive(_3); + StorageLive(_4); + StorageLive(_7); + StorageLive(_9); + StorageLive(_26); + StorageLive(_27); + goto -> bb4; + } + + bb20: { + StorageLive(_3); + StorageLive(_4); + StorageLive(_7); + StorageLive(_9); + StorageLive(_28); + StorageLive(_29); + StorageLive(_45); + StorageLive(_46); + goto -> bb1; + } + + bb21: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.coroutine_drop_proxy_async.0.mir b/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.coroutine_drop_proxy_async.0.mir new file mode 100644 index 0000000000000..9f06ae9272bad --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.build_aggregate-{closure#0}.coroutine_drop_proxy_async.0.mir @@ -0,0 +1,32 @@ +// MIR for `build_aggregate::{closure#0}` 0 coroutine_drop_proxy_async + +fn build_aggregate::{closure#0}(_1: {async fn body of build_aggregate()}, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: std::task::Poll<()>; + scope 1 { + scope 2 { + scope 3 { + scope 4 { + scope 5 { + } + scope 6 { + scope 7 { + } + } + scope 8 { + scope 9 { + } + } + } + } + } + } + + bb0: { + drop(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..f4ed33f4d8661 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.StateTransform.after.mir @@ -0,0 +1,60 @@ +// MIR for `foo::{closure#0}::{closure#0}` after StateTransform + +fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async block@$DIR/async_fn.rs:21:13: 21:18}>, _2: &mut Context<'_>) -> Poll { + coroutine layout { + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + } + storage_conflicts = BitMatrix(0x0) {} + } + debug _task_context => _2; + debug y => (*((*_9).0: &u32)); + debug z => (*((*_9).1: &u32)); + let mut _0: std::task::Poll; + let mut _3: u32; + let mut _4: u32; + let mut _5: &u32; + let mut _6: &u32; + let mut _7: u32; + let mut _8: u32; + let mut _9: &mut {async block@$DIR/async_fn.rs:21:13: 21:18}; + + bb0: { + _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:21:13: 21:18}); + _8 = discriminant((*_9)); + switchInt(move _8) -> [0: bb1, 1: bb4, otherwise: bb5]; + } + + bb1: { + StorageLive(_3); + _5 = no_retag copy ((*_9).0: &u32); + _3 = copy (*_5); + StorageLive(_4); + _6 = no_retag copy ((*_9).1: &u32); + _4 = copy (*_6); + _7 = Add(move _3, move _4); + StorageDead(_4); + StorageDead(_3); + goto -> bb3; + } + + bb2: { + _0 = Poll::::Ready(move _7); + discriminant((*_9)) = 1; + return; + } + + bb3: { + goto -> bb2; + } + + bb4: { + assert(const false, "`async fn` resumed after completion") -> [success: bb4, unwind continue]; + } + + bb5: { + unreachable; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.coroutine_drop.0.mir new file mode 100644 index 0000000000000..c22d1ca1ca132 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.coroutine_drop.0.mir @@ -0,0 +1,36 @@ +// MIR for `foo::{closure#0}::{closure#0}` 0 coroutine_drop + +fn foo::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs:21:13: 21:18}) -> () { + debug _task_context => _2; + debug y => (*((*_1).0: &u32)); + debug z => (*((*_1).1: &u32)); + let mut _0: (); + let mut _2: &mut std::task::Context<'_>; + let mut _3: u32; + let mut _4: u32; + let mut _5: &u32; + let mut _6: &u32; + let mut _7: u32; + let mut _8: u32; + + bb0: { + _8 = discriminant((*_1)); + switchInt(move _8) -> [0: bb2, otherwise: bb4]; + } + + bb1: { + return; + } + + bb2: { + goto -> bb3; + } + + bb3: { + goto -> bb1; + } + + bb4: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir new file mode 100644 index 0000000000000..19fe75de78cb5 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir @@ -0,0 +1,14 @@ +// MIR for `foo::{closure#0}::{closure#0}` 0 coroutine_drop_proxy_async + +fn foo::{closure#0}::{closure#0}(_1: {async block@$DIR/async_fn.rs:21:13: 21:18}, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: std::task::Poll<()>; + + bb0: { + drop(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..e29f0a174c0e2 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.StateTransform.after.mir @@ -0,0 +1,323 @@ +// MIR for `foo::{closure#0}` after StateTransform + +fn foo::{closure#0}(_1: Pin<&mut {async fn body of foo()}>, _2: &mut Context<'_>) -> Poll { + coroutine layout { + field _s0: &u32; + field _s1: u32; + field _s2: u32; + field _s3: {async block@$DIR/async_fn.rs:21:13: 21:18}; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0, _s1, _s2, _s3], + } + storage_conflicts = BitMatrix(4x4) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s1, _s3), (_s2, _s0), (_s2, _s1), (_s2, _s2), (_s2, _s3), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3)} + } + debug _task_context => _2; + debug x => ((*_36).0: &u32); + debug y => ((*_36).1: u32); + coroutine debug x => _s0; + let mut _0: std::task::Poll; + let _3: &u32; + let mut _9: {async block@$DIR/async_fn.rs:21:13: 21:18}; + let mut _10: {async block@$DIR/async_fn.rs:21:13: 21:18}; + let mut _11: &u32; + let mut _12: &u32; + let mut _14: (); + let _15: (); + let mut _16: std::task::Poll; + let mut _17: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:21:13: 21:18}>; + let mut _18: &mut {async block@$DIR/async_fn.rs:21:13: 21:18}; + let mut _19: &mut {async block@$DIR/async_fn.rs:21:13: 21:18}; + let mut _20: &mut std::task::Context<'_>; + let mut _21: &mut std::task::Context<'_>; + let mut _22: &mut std::task::Context<'_>; + let mut _23: isize; + let mut _25: !; + let mut _26: &mut std::task::Context<'_>; + let mut _27: (); + let mut _30: u32; + let mut _31: u32; + let mut _32: u32; + let mut _33: u32; + let mut _34: u32; + let mut _35: u32; + let mut _36: &mut {async fn body of foo()}; + let mut _37: &u32; + scope 1 { + debug x => (((*_36) as variant#3).0: &u32); + coroutine debug y => _s1; + let _4: u32; + scope 2 { + debug y => (((*_36) as variant#3).1: u32); + let _5: &u32; + scope 3 { + debug y => _5; + coroutine debug z => _s2; + let _6: u32; + scope 4 { + debug z => (((*_36) as variant#3).2: u32); + let _7: &u32; + scope 5 { + debug z => _7; + coroutine debug __awaitee => _s3; + let _8: u32; + let mut _13: {async block@$DIR/async_fn.rs:21:13: 21:18}; + scope 6 { + debug y => _8; + let _28: u32; + scope 9 { + debug a => _28; + let _29: &u32; + scope 10 { + debug a => _29; + } + } + } + scope 7 { + debug __awaitee => (((*_36) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18}); + let _24: u32; + scope 8 { + debug result => _24; + } + } + } + } + } + } + } + + bb0: { + _36 = copy (_1.0: &mut {async fn body of foo()}); + _35 = discriminant((*_36)); + switchInt(move _35) -> [0: bb1, 1: bb26, 2: bb25, 3: bb24, otherwise: bb7]; + } + + bb1: { + nop; + (((*_36) as variant#3).0: &u32) = copy ((*_36).0: &u32); + nop; + (((*_36) as variant#3).1: u32) = copy ((*_36).1: u32); + StorageLive(_5); + _5 = &(((*_36) as variant#3).1: u32); + nop; + (((*_36) as variant#3).2: u32) = const 9_u32; + StorageLive(_7); + _7 = &(((*_36) as variant#3).2: u32); + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _11 = &(*_5); + StorageLive(_12); + _12 = &(*_7); + _10 = {coroutine@$DIR/async_fn.rs:21:13: 21:18 (#0)} { y: move _11, z: move _12 }; + StorageDead(_12); + StorageDead(_11); + _9 = <{async block@$DIR/async_fn.rs:21:13: 21:18} as IntoFuture>::into_future(move _10) -> [return: bb2, unwind: bb18]; + } + + bb2: { + StorageDead(_10); + PlaceMention(_9); + nop; + (((*_36) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18}) = move _9; + goto -> bb3; + } + + bb3: { + StorageLive(_15); + StorageLive(_16); + StorageLive(_17); + StorageLive(_18); + StorageLive(_19); + _19 = &mut (((*_36) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18}); + _18 = &mut (*_19); + _17 = Pin::<&mut {async block@$DIR/async_fn.rs:21:13: 21:18}>::new_unchecked(move _18) -> [return: bb4, unwind: bb15]; + } + + bb4: { + StorageDead(_18); + StorageLive(_20); + StorageLive(_21); + StorageLive(_22); + _22 = copy _2; + _21 = move _22; + goto -> bb5; + } + + bb5: { + _20 = &mut (*_21); + StorageDead(_22); + _16 = <{async block@$DIR/async_fn.rs:21:13: 21:18} as Future>::poll(move _17, move _20) -> [return: bb6, unwind: bb14]; + } + + bb6: { + StorageDead(_21); + StorageDead(_20); + StorageDead(_19); + StorageDead(_17); + PlaceMention(_16); + _23 = discriminant(_16); + switchInt(move _23) -> [0: bb9, 1: bb8, otherwise: bb7]; + } + + bb7: { + unreachable; + } + + bb8: { + _15 = const (); + StorageDead(_16); + StorageDead(_15); + StorageLive(_26); + StorageLive(_27); + _27 = (); + _0 = Poll::::Pending; + StorageDead(_5); + StorageDead(_7); + StorageDead(_8); + StorageDead(_9); + StorageDead(_26); + StorageDead(_27); + discriminant((*_36)) = 3; + return; + } + + bb9: { + StorageLive(_24); + _24 = copy ((_16 as Ready).0: u32); + _8 = copy _24; + StorageDead(_24); + StorageDead(_16); + StorageDead(_15); + drop((((*_36) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18})) -> [return: bb11, unwind: bb17]; + } + + bb10: { + StorageDead(_27); + _2 = move _26; + StorageDead(_26); + _14 = const (); + goto -> bb3; + } + + bb11: { + nop; + goto -> bb12; + } + + bb12: { + StorageDead(_9); + StorageLive(_28); + _28 = const 10_u32; + StorageLive(_29); + _29 = &_28; + StorageLive(_30); + StorageLive(_31); + _37 = no_retag copy (((*_36) as variant#3).0: &u32); + _31 = copy (*_37); + StorageLive(_32); + _32 = copy _8; + _30 = Add(move _31, move _32); + StorageDead(_32); + StorageDead(_31); + StorageLive(_33); + _33 = copy (*_29); + _34 = Add(move _30, move _33); + StorageDead(_33); + StorageDead(_30); + StorageDead(_29); + StorageDead(_28); + StorageDead(_8); + StorageDead(_7); + nop; + StorageDead(_5); + nop; + nop; + goto -> bb22; + } + + bb13: { + _0 = Poll::::Ready(move _34); + discriminant((*_36)) = 1; + return; + } + + bb14 (cleanup): { + StorageDead(_21); + StorageDead(_20); + goto -> bb16; + } + + bb15 (cleanup): { + StorageDead(_18); + goto -> bb16; + } + + bb16 (cleanup): { + StorageDead(_19); + StorageDead(_17); + StorageDead(_16); + StorageDead(_15); + drop((((*_36) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18})) -> [return: bb17, unwind terminate(cleanup)]; + } + + bb17 (cleanup): { + nop; + goto -> bb20; + } + + bb18 (cleanup): { + goto -> bb19; + } + + bb19 (cleanup): { + StorageDead(_10); + goto -> bb20; + } + + bb20 (cleanup): { + StorageDead(_9); + StorageDead(_8); + StorageDead(_7); + nop; + StorageDead(_5); + nop; + nop; + goto -> bb21; + } + + bb21 (cleanup): { + goto -> bb23; + } + + bb22: { + goto -> bb13; + } + + bb23 (cleanup): { + discriminant((*_36)) = 2; + resume; + } + + bb24: { + StorageLive(_5); + StorageLive(_7); + StorageLive(_8); + StorageLive(_9); + StorageLive(_26); + StorageLive(_27); + _26 = move _2; + goto -> bb10; + } + + bb25: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb25, unwind continue]; + } + + bb26: { + assert(const false, "`async fn` resumed after completion") -> [success: bb26, unwind continue]; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.coroutine_drop.0.mir new file mode 100644 index 0000000000000..1ce52d353af34 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.coroutine_drop.0.mir @@ -0,0 +1,153 @@ +// MIR for `foo::{closure#0}` 0 coroutine_drop + +fn foo::{closure#0}(_1: &mut {async fn body of foo()}) -> () { + debug _task_context => _2; + debug x => ((*_1).0: &u32); + debug y => ((*_1).1: u32); + let mut _0: (); + let mut _2: &mut std::task::Context<'_>; + let _3: &u32; + let mut _9: {async block@$DIR/async_fn.rs:21:13: 21:18}; + let mut _10: {async block@$DIR/async_fn.rs:21:13: 21:18}; + let mut _11: &u32; + let mut _12: &u32; + let mut _14: (); + let _15: (); + let mut _16: std::task::Poll; + let mut _17: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:21:13: 21:18}>; + let mut _18: &mut {async block@$DIR/async_fn.rs:21:13: 21:18}; + let mut _19: &mut {async block@$DIR/async_fn.rs:21:13: 21:18}; + let mut _20: &mut std::task::Context<'_>; + let mut _21: &mut std::task::Context<'_>; + let mut _22: &mut std::task::Context<'_>; + let mut _23: isize; + let mut _25: !; + let mut _26: &mut std::task::Context<'_>; + let mut _27: (); + let mut _30: u32; + let mut _31: u32; + let mut _32: u32; + let mut _33: u32; + let mut _34: u32; + let mut _35: u32; + scope 1 { + debug x => (((*_1) as variant#3).0: &u32); + let _4: u32; + scope 2 { + debug y => (((*_1) as variant#3).1: u32); + let _5: &u32; + scope 3 { + debug y => _5; + let _6: u32; + scope 4 { + debug z => (((*_1) as variant#3).2: u32); + let _7: &u32; + scope 5 { + debug z => _7; + let _8: u32; + let mut _13: {async block@$DIR/async_fn.rs:21:13: 21:18}; + scope 6 { + debug y => _8; + let _28: u32; + scope 9 { + debug a => _28; + let _29: &u32; + scope 10 { + debug a => _29; + } + } + } + scope 7 { + debug __awaitee => (((*_1) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18}); + let _24: u32; + scope 8 { + debug result => _24; + } + } + } + } + } + } + } + + bb0: { + _35 = discriminant((*_1)); + switchInt(move _35) -> [0: bb9, 3: bb12, otherwise: bb13]; + } + + bb1: { + StorageDead(_27); + StorageDead(_26); + drop((((*_1) as variant#3).3: {async block@$DIR/async_fn.rs:21:13: 21:18})) -> [return: bb2, unwind: bb6]; + } + + bb2: { + nop; + goto -> bb3; + } + + bb3: { + StorageDead(_9); + StorageDead(_8); + StorageDead(_7); + nop; + StorageDead(_5); + nop; + nop; + goto -> bb10; + } + + bb4: { + return; + } + + bb5 (cleanup): { + resume; + } + + bb6 (cleanup): { + nop; + goto -> bb7; + } + + bb7 (cleanup): { + StorageDead(_9); + StorageDead(_8); + StorageDead(_7); + nop; + StorageDead(_5); + nop; + nop; + goto -> bb5; + } + + bb8: { + return; + } + + bb9: { + goto -> bb11; + } + + bb10: { + goto -> bb4; + } + + bb11: { + goto -> bb8; + } + + bb12: { + StorageLive(_5); + StorageLive(_7); + StorageLive(_8); + StorageLive(_9); + StorageLive(_26); + StorageLive(_27); + goto -> bb1; + } + + bb13: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.coroutine_drop_proxy_async.0.mir b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.coroutine_drop_proxy_async.0.mir new file mode 100644 index 0000000000000..f7038fc83baad --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.foo-{closure#0}.coroutine_drop_proxy_async.0.mir @@ -0,0 +1,34 @@ +// MIR for `foo::{closure#0}` 0 coroutine_drop_proxy_async + +fn foo::{closure#0}(_1: {async fn body of foo()}, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: std::task::Poll<()>; + scope 1 { + scope 2 { + scope 3 { + scope 4 { + scope 5 { + scope 6 { + scope 9 { + scope 10 { + } + } + } + scope 7 { + scope 8 { + } + } + } + } + } + } + } + + bb0: { + drop(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..5657c5c35fa2c --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.StateTransform.after.mir @@ -0,0 +1,336 @@ +// MIR for `hello_world::{closure#0}` after StateTransform + +fn hello_world::{closure#0}(_1: Pin<&mut {async fn body of hello_world()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + field _s0: [u8; 1]; + field _s1: &[u8]; + field _s2: [u8; 1]; + field _s3: {async fn body of read_exact()}; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0, _s1, _s2, _s3], + } + storage_conflicts = BitMatrix(4x4) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s0, _s3), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s1, _s3), (_s2, _s0), (_s2, _s1), (_s2, _s2), (_s2, _s3), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3)} + } + debug _task_context => _2; + coroutine debug data => _s0; + let mut _0: std::task::Poll<()>; + let _3: [u8; 1]; + let _5: &[u8]; + let mut _6: &[u8; 1]; + let mut _7: std::ops::RangeFull; + let _9: (); + let mut _10: std::option::Option<()>; + let mut _11: {async fn body of read_exact()}; + let mut _12: {async fn body of read_exact()}; + let mut _13: &mut &[u8]; + let mut _14: &mut &[u8]; + let mut _15: &mut [u8]; + let mut _16: &mut [u8; 1]; + let mut _17: &mut [u8; 1]; + let mut _19: (); + let _20: (); + let mut _21: std::task::Poll>; + let mut _22: std::pin::Pin<&mut {async fn body of read_exact()}>; + let mut _23: &mut {async fn body of read_exact()}; + let mut _24: &mut {async fn body of read_exact()}; + let mut _25: &mut std::task::Context<'_>; + let mut _26: &mut std::task::Context<'_>; + let mut _27: &mut std::task::Context<'_>; + let mut _28: isize; + let mut _30: !; + let mut _31: &mut std::task::Context<'_>; + let mut _32: (); + let mut _33: (); + let mut _34: u32; + let mut _35: &mut {async fn body of hello_world()}; + scope 1 { + debug data => (((*_35) as variant#3).0: [u8; 1]); + coroutine debug reader => _s1; + let mut _4: &[u8]; + scope 2 { + debug reader => (((*_35) as variant#3).1: &[u8]); + coroutine debug marker => _s2; + let mut _8: [u8; 1]; + scope 3 { + debug marker => (((*_35) as variant#3).2: [u8; 1]); + coroutine debug __awaitee => _s3; + let mut _18: {async fn body of read_exact()}; + scope 4 { + debug __awaitee => (((*_35) as variant#3).3: {async fn body of read_exact()}); + let _29: std::option::Option<()>; + scope 5 { + debug result => _29; + } + } + } + } + } + + bb0: { + _35 = copy (_1.0: &mut {async fn body of hello_world()}); + _34 = discriminant((*_35)); + switchInt(move _34) -> [0: bb1, 1: bb33, 2: bb32, 3: bb31, otherwise: bb9]; + } + + bb1: { + nop; + (((*_35) as variant#3).0: [u8; 1]) = [const 0_u8; 1]; + nop; + StorageLive(_5); + StorageLive(_6); + _6 = &(((*_35) as variant#3).0: [u8; 1]); + StorageLive(_7); + _7 = RangeFull; + _5 = <[u8; 1] as Index>::index(move _6, move _7) -> [return: bb2, unwind: bb26]; + } + + bb2: { + StorageDead(_7); + StorageDead(_6); + (((*_35) as variant#3).1: &[u8]) = &(*_5); + nop; + (((*_35) as variant#3).2: [u8; 1]) = [const 0_u8; 1]; + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); + _14 = &mut (((*_35) as variant#3).1: &[u8]); + _13 = &mut (*_14); + StorageLive(_15); + StorageLive(_16); + StorageLive(_17); + _17 = &mut (((*_35) as variant#3).2: [u8; 1]); + _16 = &mut (*_17); + _15 = move _16 as &mut [u8] (PointerCoercion(Unsize, Implicit)); + StorageDead(_16); + _12 = read_exact(move _13, move _15) -> [return: bb3, unwind: bb23]; + } + + bb3: { + StorageDead(_15); + StorageDead(_13); + _11 = <{async fn body of read_exact()} as IntoFuture>::into_future(move _12) -> [return: bb4, unwind: bb22]; + } + + bb4: { + StorageDead(_12); + PlaceMention(_11); + nop; + (((*_35) as variant#3).3: {async fn body of read_exact()}) = move _11; + goto -> bb5; + } + + bb5: { + StorageLive(_20); + StorageLive(_21); + StorageLive(_22); + StorageLive(_23); + StorageLive(_24); + _24 = &mut (((*_35) as variant#3).3: {async fn body of read_exact()}); + _23 = &mut (*_24); + _22 = Pin::<&mut {async fn body of read_exact()}>::new_unchecked(move _23) -> [return: bb6, unwind: bb18]; + } + + bb6: { + StorageDead(_23); + StorageLive(_25); + StorageLive(_26); + StorageLive(_27); + _27 = copy _2; + _26 = move _27; + goto -> bb7; + } + + bb7: { + _25 = &mut (*_26); + StorageDead(_27); + _21 = <{async fn body of read_exact()} as Future>::poll(move _22, move _25) -> [return: bb8, unwind: bb17]; + } + + bb8: { + StorageDead(_26); + StorageDead(_25); + StorageDead(_24); + StorageDead(_22); + PlaceMention(_21); + _28 = discriminant(_21); + switchInt(move _28) -> [0: bb11, 1: bb10, otherwise: bb9]; + } + + bb9: { + unreachable; + } + + bb10: { + _20 = const (); + StorageDead(_21); + StorageDead(_20); + StorageLive(_31); + StorageLive(_32); + _32 = (); + _0 = Poll::<()>::Pending; + StorageDead(_5); + StorageDead(_9); + StorageDead(_10); + StorageDead(_11); + StorageDead(_14); + StorageDead(_17); + StorageDead(_31); + StorageDead(_32); + discriminant((*_35)) = 3; + return; + } + + bb11: { + StorageLive(_29); + _29 = copy ((_21 as Ready).0: std::option::Option<()>); + _10 = copy _29; + StorageDead(_29); + StorageDead(_21); + StorageDead(_20); + drop((((*_35) as variant#3).3: {async fn body of read_exact()})) -> [return: bb13, unwind: bb20]; + } + + bb12: { + StorageDead(_32); + _2 = move _31; + StorageDead(_31); + _19 = const (); + goto -> bb5; + } + + bb13: { + nop; + _9 = Option::<()>::unwrap(move _10) -> [return: bb14, unwind: bb21]; + } + + bb14: { + StorageDead(_10); + goto -> bb15; + } + + bb15: { + StorageDead(_17); + StorageDead(_14); + StorageDead(_11); + StorageDead(_9); + _33 = const (); + nop; + StorageDead(_5); + nop; + nop; + goto -> bb29; + } + + bb16: { + _0 = Poll::<()>::Ready(move _33); + discriminant((*_35)) = 1; + return; + } + + bb17 (cleanup): { + StorageDead(_26); + StorageDead(_25); + goto -> bb19; + } + + bb18 (cleanup): { + StorageDead(_23); + goto -> bb19; + } + + bb19 (cleanup): { + StorageDead(_24); + StorageDead(_22); + StorageDead(_21); + StorageDead(_20); + drop((((*_35) as variant#3).3: {async fn body of read_exact()})) -> [return: bb20, unwind terminate(cleanup)]; + } + + bb20 (cleanup): { + nop; + goto -> bb21; + } + + bb21 (cleanup): { + StorageDead(_10); + goto -> bb25; + } + + bb22 (cleanup): { + goto -> bb24; + } + + bb23 (cleanup): { + StorageDead(_15); + StorageDead(_13); + goto -> bb24; + } + + bb24 (cleanup): { + StorageDead(_12); + StorageDead(_10); + goto -> bb25; + } + + bb25 (cleanup): { + StorageDead(_17); + StorageDead(_14); + StorageDead(_11); + StorageDead(_9); + nop; + goto -> bb27; + } + + bb26 (cleanup): { + StorageDead(_7); + StorageDead(_6); + goto -> bb27; + } + + bb27 (cleanup): { + StorageDead(_5); + nop; + nop; + goto -> bb28; + } + + bb28 (cleanup): { + goto -> bb30; + } + + bb29: { + goto -> bb16; + } + + bb30 (cleanup): { + discriminant((*_35)) = 2; + resume; + } + + bb31: { + StorageLive(_5); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + StorageLive(_14); + StorageLive(_17); + StorageLive(_31); + StorageLive(_32); + _31 = move _2; + goto -> bb12; + } + + bb32: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb32, unwind continue]; + } + + bb33: { + assert(const false, "`async fn` resumed after completion") -> [success: bb33, unwind continue]; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.coroutine_drop.0.mir new file mode 100644 index 0000000000000..2fd801f42122c --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.coroutine_drop.0.mir @@ -0,0 +1,141 @@ +// MIR for `hello_world::{closure#0}` 0 coroutine_drop + +fn hello_world::{closure#0}(_1: &mut {async fn body of hello_world()}) -> () { + debug _task_context => _2; + let mut _0: (); + let mut _2: &mut std::task::Context<'_>; + let _3: [u8; 1]; + let _5: &[u8]; + let mut _6: &[u8; 1]; + let mut _7: std::ops::RangeFull; + let _9: (); + let mut _10: std::option::Option<()>; + let mut _11: {async fn body of read_exact()}; + let mut _12: {async fn body of read_exact()}; + let mut _13: &mut &[u8]; + let mut _14: &mut &[u8]; + let mut _15: &mut [u8]; + let mut _16: &mut [u8; 1]; + let mut _17: &mut [u8; 1]; + let mut _19: (); + let _20: (); + let mut _21: std::task::Poll>; + let mut _22: std::pin::Pin<&mut {async fn body of read_exact()}>; + let mut _23: &mut {async fn body of read_exact()}; + let mut _24: &mut {async fn body of read_exact()}; + let mut _25: &mut std::task::Context<'_>; + let mut _26: &mut std::task::Context<'_>; + let mut _27: &mut std::task::Context<'_>; + let mut _28: isize; + let mut _30: !; + let mut _31: &mut std::task::Context<'_>; + let mut _32: (); + let mut _33: (); + let mut _34: u32; + scope 1 { + debug data => (((*_1) as variant#3).0: [u8; 1]); + let mut _4: &[u8]; + scope 2 { + debug reader => (((*_1) as variant#3).1: &[u8]); + let mut _8: [u8; 1]; + scope 3 { + debug marker => (((*_1) as variant#3).2: [u8; 1]); + let mut _18: {async fn body of read_exact()}; + scope 4 { + debug __awaitee => (((*_1) as variant#3).3: {async fn body of read_exact()}); + let _29: std::option::Option<()>; + scope 5 { + debug result => _29; + } + } + } + } + } + + bb0: { + _34 = discriminant((*_1)); + switchInt(move _34) -> [0: bb9, 3: bb12, otherwise: bb13]; + } + + bb1: { + StorageDead(_32); + StorageDead(_31); + drop((((*_1) as variant#3).3: {async fn body of read_exact()})) -> [return: bb2, unwind: bb6]; + } + + bb2: { + nop; + StorageDead(_10); + goto -> bb3; + } + + bb3: { + StorageDead(_17); + StorageDead(_14); + StorageDead(_11); + StorageDead(_9); + nop; + StorageDead(_5); + nop; + nop; + goto -> bb10; + } + + bb4: { + return; + } + + bb5 (cleanup): { + resume; + } + + bb6 (cleanup): { + nop; + StorageDead(_10); + goto -> bb7; + } + + bb7 (cleanup): { + StorageDead(_17); + StorageDead(_14); + StorageDead(_11); + StorageDead(_9); + nop; + StorageDead(_5); + nop; + nop; + goto -> bb5; + } + + bb8: { + return; + } + + bb9: { + goto -> bb11; + } + + bb10: { + goto -> bb4; + } + + bb11: { + goto -> bb8; + } + + bb12: { + StorageLive(_5); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + StorageLive(_14); + StorageLive(_17); + StorageLive(_31); + StorageLive(_32); + goto -> bb1; + } + + bb13: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.coroutine_drop_proxy_async.0.mir b/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.coroutine_drop_proxy_async.0.mir new file mode 100644 index 0000000000000..f611658c30174 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.hello_world-{closure#0}.coroutine_drop_proxy_async.0.mir @@ -0,0 +1,24 @@ +// MIR for `hello_world::{closure#0}` 0 coroutine_drop_proxy_async + +fn hello_world::{closure#0}(_1: {async fn body of hello_world()}, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: std::task::Poll<()>; + scope 1 { + scope 2 { + scope 3 { + scope 4 { + scope 5 { + } + } + } + } + } + + bb0: { + drop(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..cb48d771ce8c5 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.StateTransform.after.mir @@ -0,0 +1,59 @@ +// MIR for `includes_never::{closure#0}::{closure#0}` after StateTransform + +fn includes_never::{closure#0}::{closure#0}(_1: Pin<&mut {async block@$DIR/async_fn.rs:61:18: 61:23}>, _2: &mut Context<'_>) -> Poll { + coroutine layout { + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + } + storage_conflicts = BitMatrix(0x0) {} + } + debug _task_context => _2; + debug x => (*((*_9).0: &u32)); + let mut _0: std::task::Poll; + let mut _3: u32; + let mut _4: u32; + let mut _5: &u32; + let mut _6: &u32; + let mut _7: u32; + let mut _8: u32; + let mut _9: &mut {async block@$DIR/async_fn.rs:61:18: 61:23}; + + bb0: { + _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:61:18: 61:23}); + _8 = discriminant((*_9)); + switchInt(move _8) -> [0: bb1, 1: bb4, otherwise: bb5]; + } + + bb1: { + StorageLive(_3); + _5 = no_retag copy ((*_9).0: &u32); + _3 = copy (*_5); + StorageLive(_4); + _6 = no_retag copy ((*_9).0: &u32); + _4 = copy (*_6); + _7 = Mul(move _3, move _4); + StorageDead(_4); + StorageDead(_3); + goto -> bb3; + } + + bb2: { + _0 = Poll::::Ready(move _7); + discriminant((*_9)) = 1; + return; + } + + bb3: { + goto -> bb2; + } + + bb4: { + assert(const false, "`async fn` resumed after completion") -> [success: bb4, unwind continue]; + } + + bb5: { + unreachable; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop.0.mir new file mode 100644 index 0000000000000..a17dbe3199dee --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop.0.mir @@ -0,0 +1,35 @@ +// MIR for `includes_never::{closure#0}::{closure#0}` 0 coroutine_drop + +fn includes_never::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs:61:18: 61:23}) -> () { + debug _task_context => _2; + debug x => (*((*_1).0: &u32)); + let mut _0: (); + let mut _2: &mut std::task::Context<'_>; + let mut _3: u32; + let mut _4: u32; + let mut _5: &u32; + let mut _6: &u32; + let mut _7: u32; + let mut _8: u32; + + bb0: { + _8 = discriminant((*_1)); + switchInt(move _8) -> [0: bb2, otherwise: bb4]; + } + + bb1: { + return; + } + + bb2: { + goto -> bb3; + } + + bb3: { + goto -> bb1; + } + + bb4: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir new file mode 100644 index 0000000000000..11fefd8e962c4 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir @@ -0,0 +1,14 @@ +// MIR for `includes_never::{closure#0}::{closure#0}` 0 coroutine_drop_proxy_async + +fn includes_never::{closure#0}::{closure#0}(_1: {async block@$DIR/async_fn.rs:61:18: 61:23}, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: std::task::Poll<()>; + + bb0: { + drop(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.StateTransform.after.mir new file mode 100644 index 0000000000000..96fd0d74c28c8 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.StateTransform.after.mir @@ -0,0 +1,59 @@ +// MIR for `includes_never::{closure#0}::{closure#1}` after StateTransform + +fn includes_never::{closure#0}::{closure#1}(_1: Pin<&mut {async block@$DIR/async_fn.rs:67:15: 67:20}>, _2: &mut Context<'_>) -> Poll { + coroutine layout { + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + } + storage_conflicts = BitMatrix(0x0) {} + } + debug _task_context => _2; + debug x => (*((*_9).0: &u32)); + let mut _0: std::task::Poll; + let mut _3: u32; + let mut _4: u32; + let mut _5: &u32; + let mut _6: &u32; + let mut _7: u32; + let mut _8: u32; + let mut _9: &mut {async block@$DIR/async_fn.rs:67:15: 67:20}; + + bb0: { + _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:67:15: 67:20}); + _8 = discriminant((*_9)); + switchInt(move _8) -> [0: bb1, 1: bb4, otherwise: bb5]; + } + + bb1: { + StorageLive(_3); + _5 = no_retag copy ((*_9).0: &u32); + _3 = copy (*_5); + StorageLive(_4); + _6 = no_retag copy ((*_9).0: &u32); + _4 = copy (*_6); + _7 = Add(move _3, move _4); + StorageDead(_4); + StorageDead(_3); + goto -> bb3; + } + + bb2: { + _0 = Poll::::Ready(move _7); + discriminant((*_9)) = 1; + return; + } + + bb3: { + goto -> bb2; + } + + bb4: { + assert(const false, "`async fn` resumed after completion") -> [success: bb4, unwind continue]; + } + + bb5: { + unreachable; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop.0.mir new file mode 100644 index 0000000000000..bf47e4c62f433 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop.0.mir @@ -0,0 +1,35 @@ +// MIR for `includes_never::{closure#0}::{closure#1}` 0 coroutine_drop + +fn includes_never::{closure#0}::{closure#1}(_1: &mut {async block@$DIR/async_fn.rs:67:15: 67:20}) -> () { + debug _task_context => _2; + debug x => (*((*_1).0: &u32)); + let mut _0: (); + let mut _2: &mut std::task::Context<'_>; + let mut _3: u32; + let mut _4: u32; + let mut _5: &u32; + let mut _6: &u32; + let mut _7: u32; + let mut _8: u32; + + bb0: { + _8 = discriminant((*_1)); + switchInt(move _8) -> [0: bb2, otherwise: bb4]; + } + + bb1: { + return; + } + + bb2: { + goto -> bb3; + } + + bb3: { + goto -> bb1; + } + + bb4: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop_proxy_async.0.mir b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop_proxy_async.0.mir new file mode 100644 index 0000000000000..8daa763583e8c --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop_proxy_async.0.mir @@ -0,0 +1,14 @@ +// MIR for `includes_never::{closure#0}::{closure#1}` 0 coroutine_drop_proxy_async + +fn includes_never::{closure#0}::{closure#1}(_1: {async block@$DIR/async_fn.rs:67:15: 67:20}, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: std::task::Poll<()>; + + bb0: { + drop(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..421472cf7b0a0 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.StateTransform.after.mir @@ -0,0 +1,318 @@ +// MIR for `includes_never::{closure#0}` after StateTransform + +fn includes_never::{closure#0}(_1: Pin<&mut {async fn body of includes_never()}>, _2: &mut Context<'_>) -> Poll { + coroutine layout { + field _s0: bool; + field _s1: u32; + field _s2: {async block@$DIR/async_fn.rs:61:18: 61:23}; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0, _s1, _s2], + } + storage_conflicts = BitMatrix(3x3) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s2, _s0), (_s2, _s1), (_s2, _s2)} + } + debug _task_context => _2; + debug crash => ((*_50).0: bool); + debug x => ((*_50).1: u32); + coroutine debug crash => _s0; + let mut _0: std::task::Poll; + let _3: bool; + let mut _6: {async block@$DIR/async_fn.rs:61:18: 61:23}; + let mut _7: {async block@$DIR/async_fn.rs:61:18: 61:23}; + let mut _8: &u32; + let mut _10: (); + let _11: (); + let mut _12: std::task::Poll; + let mut _13: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:61:18: 61:23}>; + let mut _14: &mut {async block@$DIR/async_fn.rs:61:18: 61:23}; + let mut _15: &mut {async block@$DIR/async_fn.rs:61:18: 61:23}; + let mut _16: &mut std::task::Context<'_>; + let mut _17: &mut std::task::Context<'_>; + let mut _18: &mut std::task::Context<'_>; + let mut _19: isize; + let mut _21: !; + let mut _22: &mut std::task::Context<'_>; + let mut _23: (); + let _24: (); + let mut _25: bool; + let mut _26: !; + let mut _28: u32; + let mut _29: {async block@$DIR/async_fn.rs:67:15: 67:20}; + let mut _30: {async block@$DIR/async_fn.rs:67:15: 67:20}; + let mut _31: &u32; + let _33: (); + let mut _34: std::task::Poll; + let mut _35: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:67:15: 67:20}>; + let mut _36: &mut {async block@$DIR/async_fn.rs:67:15: 67:20}; + let mut _37: &mut {async block@$DIR/async_fn.rs:67:15: 67:20}; + let mut _38: &mut std::task::Context<'_>; + let mut _39: &mut std::task::Context<'_>; + let mut _40: std::future::ResumeTy; + let mut _41: isize; + let mut _43: !; + let mut _44: std::future::ResumeTy; + let mut _45: (); + let _46: (); + let mut _47: Never; + let mut _48: u32; + let mut _49: u32; + let mut _50: &mut {async fn body of includes_never()}; + scope 1 { + debug crash => (((*_50) as variant#3).0: bool); + coroutine debug x => _s1; + let _4: u32; + scope 2 { + debug x => (((*_50) as variant#3).1: u32); + coroutine debug __awaitee => _s2; + let _5: u32; + let mut _9: {async block@$DIR/async_fn.rs:61:18: 61:23}; + scope 3 { + debug result => _5; + scope 6 { + debug bad => _27; + let mut _32: {async block@$DIR/async_fn.rs:67:15: 67:20}; + scope 8 { + debug __awaitee => _32; + let _42: u32; + scope 9 { + debug result => _42; + } + } + } + scope 7 { + let _27: Never; + } + } + scope 4 { + debug __awaitee => (((*_50) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23}); + let _20: u32; + scope 5 { + debug result => _20; + } + } + } + } + + bb0: { + _50 = copy (_1.0: &mut {async fn body of includes_never()}); + _49 = discriminant((*_50)); + switchInt(move _49) -> [0: bb1, 1: bb30, 2: bb29, 3: bb28, otherwise: bb7]; + } + + bb1: { + nop; + (((*_50) as variant#3).0: bool) = copy ((*_50).0: bool); + nop; + (((*_50) as variant#3).1: u32) = copy ((*_50).1: u32); + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); + StorageLive(_8); + _8 = &(((*_50) as variant#3).1: u32); + _7 = {coroutine@$DIR/async_fn.rs:61:18: 61:23 (#0)} { x: move _8 }; + StorageDead(_8); + _6 = <{async block@$DIR/async_fn.rs:61:18: 61:23} as IntoFuture>::into_future(move _7) -> [return: bb2, unwind: bb21]; + } + + bb2: { + StorageDead(_7); + PlaceMention(_6); + nop; + (((*_50) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23}) = move _6; + goto -> bb3; + } + + bb3: { + StorageLive(_11); + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); + StorageLive(_15); + _15 = &mut (((*_50) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23}); + _14 = &mut (*_15); + _13 = Pin::<&mut {async block@$DIR/async_fn.rs:61:18: 61:23}>::new_unchecked(move _14) -> [return: bb4, unwind: bb18]; + } + + bb4: { + StorageDead(_14); + StorageLive(_16); + StorageLive(_17); + StorageLive(_18); + _18 = copy _2; + _17 = move _18; + goto -> bb5; + } + + bb5: { + _16 = &mut (*_17); + StorageDead(_18); + _12 = <{async block@$DIR/async_fn.rs:61:18: 61:23} as Future>::poll(move _13, move _16) -> [return: bb6, unwind: bb17]; + } + + bb6: { + StorageDead(_17); + StorageDead(_16); + StorageDead(_15); + StorageDead(_13); + PlaceMention(_12); + _19 = discriminant(_12); + switchInt(move _19) -> [0: bb9, 1: bb8, otherwise: bb7]; + } + + bb7: { + unreachable; + } + + bb8: { + _11 = const (); + StorageDead(_12); + StorageDead(_11); + StorageLive(_22); + StorageLive(_23); + _23 = (); + _0 = Poll::::Pending; + StorageDead(_5); + StorageDead(_6); + StorageDead(_22); + StorageDead(_23); + discriminant((*_50)) = 3; + return; + } + + bb9: { + StorageLive(_20); + _20 = copy ((_12 as Ready).0: u32); + _5 = copy _20; + StorageDead(_20); + StorageDead(_12); + StorageDead(_11); + drop((((*_50) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23})) -> [return: bb11, unwind: bb20]; + } + + bb10: { + StorageDead(_23); + _2 = move _22; + StorageDead(_22); + _10 = const (); + goto -> bb3; + } + + bb11: { + nop; + goto -> bb12; + } + + bb12: { + StorageDead(_6); + StorageLive(_24); + StorageLive(_25); + _25 = copy (((*_50) as variant#3).0: bool); + switchInt(move _25) -> [0: bb13, otherwise: bb14]; + } + + bb13: { + _48 = copy _5; + StorageDead(_25); + StorageDead(_24); + StorageDead(_5); + nop; + nop; + goto -> bb26; + } + + bb14: { + _24 = const (); + StorageDead(_25); + StorageDead(_24); + StorageLive(_27); + _27 = never() -> bb16; + } + + bb15: { + _0 = Poll::::Ready(move _48); + discriminant((*_50)) = 1; + return; + } + + bb16 (cleanup): { + StorageDead(_27); + goto -> bb24; + } + + bb17 (cleanup): { + StorageDead(_17); + StorageDead(_16); + goto -> bb19; + } + + bb18 (cleanup): { + StorageDead(_14); + goto -> bb19; + } + + bb19 (cleanup): { + StorageDead(_15); + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); + drop((((*_50) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23})) -> [return: bb20, unwind terminate(cleanup)]; + } + + bb20 (cleanup): { + nop; + goto -> bb23; + } + + bb21 (cleanup): { + goto -> bb22; + } + + bb22 (cleanup): { + StorageDead(_7); + goto -> bb23; + } + + bb23 (cleanup): { + StorageDead(_6); + goto -> bb24; + } + + bb24 (cleanup): { + StorageDead(_5); + nop; + nop; + goto -> bb25; + } + + bb25 (cleanup): { + goto -> bb27; + } + + bb26: { + goto -> bb15; + } + + bb27 (cleanup): { + discriminant((*_50)) = 2; + resume; + } + + bb28: { + StorageLive(_5); + StorageLive(_6); + StorageLive(_22); + StorageLive(_23); + _22 = move _2; + goto -> bb10; + } + + bb29: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb29, unwind continue]; + } + + bb30: { + assert(const false, "`async fn` resumed after completion") -> [success: bb30, unwind continue]; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.coroutine_drop.0.mir new file mode 100644 index 0000000000000..a701710ebfc58 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.coroutine_drop.0.mir @@ -0,0 +1,155 @@ +// MIR for `includes_never::{closure#0}` 0 coroutine_drop + +fn includes_never::{closure#0}(_1: &mut {async fn body of includes_never()}) -> () { + debug _task_context => _2; + debug crash => ((*_1).0: bool); + debug x => ((*_1).1: u32); + let mut _0: (); + let mut _2: &mut std::task::Context<'_>; + let _3: bool; + let mut _6: {async block@$DIR/async_fn.rs:61:18: 61:23}; + let mut _7: {async block@$DIR/async_fn.rs:61:18: 61:23}; + let mut _8: &u32; + let mut _10: (); + let _11: (); + let mut _12: std::task::Poll; + let mut _13: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:61:18: 61:23}>; + let mut _14: &mut {async block@$DIR/async_fn.rs:61:18: 61:23}; + let mut _15: &mut {async block@$DIR/async_fn.rs:61:18: 61:23}; + let mut _16: &mut std::task::Context<'_>; + let mut _17: &mut std::task::Context<'_>; + let mut _18: &mut std::task::Context<'_>; + let mut _19: isize; + let mut _21: !; + let mut _22: &mut std::task::Context<'_>; + let mut _23: (); + let _24: (); + let mut _25: bool; + let mut _26: !; + let mut _28: u32; + let mut _29: {async block@$DIR/async_fn.rs:67:15: 67:20}; + let mut _30: {async block@$DIR/async_fn.rs:67:15: 67:20}; + let mut _31: &u32; + let _33: (); + let mut _34: std::task::Poll; + let mut _35: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:67:15: 67:20}>; + let mut _36: &mut {async block@$DIR/async_fn.rs:67:15: 67:20}; + let mut _37: &mut {async block@$DIR/async_fn.rs:67:15: 67:20}; + let mut _38: &mut std::task::Context<'_>; + let mut _39: &mut std::task::Context<'_>; + let mut _40: std::future::ResumeTy; + let mut _41: isize; + let mut _43: !; + let mut _44: std::future::ResumeTy; + let mut _45: (); + let _46: (); + let mut _47: Never; + let mut _48: u32; + let mut _49: u32; + scope 1 { + debug crash => (((*_1) as variant#3).0: bool); + let _4: u32; + scope 2 { + debug x => (((*_1) as variant#3).1: u32); + let _5: u32; + let mut _9: {async block@$DIR/async_fn.rs:61:18: 61:23}; + scope 3 { + debug result => _5; + scope 6 { + debug bad => _27; + let mut _32: {async block@$DIR/async_fn.rs:67:15: 67:20}; + scope 8 { + debug __awaitee => _32; + let _42: u32; + scope 9 { + debug result => _42; + } + } + } + scope 7 { + let _27: Never; + } + } + scope 4 { + debug __awaitee => (((*_1) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23}); + let _20: u32; + scope 5 { + debug result => _20; + } + } + } + } + + bb0: { + _49 = discriminant((*_1)); + switchInt(move _49) -> [0: bb9, 3: bb12, otherwise: bb13]; + } + + bb1: { + StorageDead(_23); + StorageDead(_22); + drop((((*_1) as variant#3).2: {async block@$DIR/async_fn.rs:61:18: 61:23})) -> [return: bb2, unwind: bb6]; + } + + bb2: { + nop; + goto -> bb3; + } + + bb3: { + StorageDead(_6); + StorageDead(_5); + nop; + nop; + goto -> bb10; + } + + bb4: { + return; + } + + bb5 (cleanup): { + resume; + } + + bb6 (cleanup): { + nop; + goto -> bb7; + } + + bb7 (cleanup): { + StorageDead(_6); + StorageDead(_5); + nop; + nop; + goto -> bb5; + } + + bb8: { + return; + } + + bb9: { + goto -> bb11; + } + + bb10: { + goto -> bb4; + } + + bb11: { + goto -> bb8; + } + + bb12: { + StorageLive(_5); + StorageLive(_6); + StorageLive(_22); + StorageLive(_23); + goto -> bb1; + } + + bb13: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.coroutine_drop_proxy_async.0.mir b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.coroutine_drop_proxy_async.0.mir new file mode 100644 index 0000000000000..4a6ceb7f1d4e9 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.includes_never-{closure#0}.coroutine_drop_proxy_async.0.mir @@ -0,0 +1,32 @@ +// MIR for `includes_never::{closure#0}` 0 coroutine_drop_proxy_async + +fn includes_never::{closure#0}(_1: {async fn body of includes_never()}, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: std::task::Poll<()>; + scope 1 { + scope 2 { + scope 3 { + scope 6 { + scope 8 { + scope 9 { + } + } + } + scope 7 { + } + } + scope 4 { + scope 5 { + } + } + } + } + + bb0: { + drop(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..e6eafbffe0f64 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.StateTransform.after.mir @@ -0,0 +1,59 @@ +// MIR for `partial_init::{closure#0}::{closure#0}` after StateTransform + +fn partial_init::{closure#0}::{closure#0}(_1: Pin<&mut {async block@$DIR/async_fn.rs:80:50: 80:55}>, _2: &mut Context<'_>) -> Poll { + coroutine layout { + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + } + storage_conflicts = BitMatrix(0x0) {} + } + debug _task_context => _2; + debug x => (*((*_9).0: &u32)); + let mut _0: std::task::Poll; + let mut _3: u32; + let mut _4: u32; + let mut _5: &u32; + let mut _6: &u32; + let mut _7: u32; + let mut _8: u32; + let mut _9: &mut {async block@$DIR/async_fn.rs:80:50: 80:55}; + + bb0: { + _9 = copy (_1.0: &mut {async block@$DIR/async_fn.rs:80:50: 80:55}); + _8 = discriminant((*_9)); + switchInt(move _8) -> [0: bb1, 1: bb4, otherwise: bb5]; + } + + bb1: { + StorageLive(_3); + _5 = no_retag copy ((*_9).0: &u32); + _3 = copy (*_5); + StorageLive(_4); + _6 = no_retag copy ((*_9).0: &u32); + _4 = copy (*_6); + _7 = Add(move _3, move _4); + StorageDead(_4); + StorageDead(_3); + goto -> bb3; + } + + bb2: { + _0 = Poll::::Ready(move _7); + discriminant((*_9)) = 1; + return; + } + + bb3: { + goto -> bb2; + } + + bb4: { + assert(const false, "`async fn` resumed after completion") -> [success: bb4, unwind continue]; + } + + bb5: { + unreachable; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop.0.mir new file mode 100644 index 0000000000000..0261bfd7236f2 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop.0.mir @@ -0,0 +1,35 @@ +// MIR for `partial_init::{closure#0}::{closure#0}` 0 coroutine_drop + +fn partial_init::{closure#0}::{closure#0}(_1: &mut {async block@$DIR/async_fn.rs:80:50: 80:55}) -> () { + debug _task_context => _2; + debug x => (*((*_1).0: &u32)); + let mut _0: (); + let mut _2: &mut std::task::Context<'_>; + let mut _3: u32; + let mut _4: u32; + let mut _5: &u32; + let mut _6: &u32; + let mut _7: u32; + let mut _8: u32; + + bb0: { + _8 = discriminant((*_1)); + switchInt(move _8) -> [0: bb2, otherwise: bb4]; + } + + bb1: { + return; + } + + bb2: { + goto -> bb3; + } + + bb3: { + goto -> bb1; + } + + bb4: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir new file mode 100644 index 0000000000000..3ddd757ef84e6 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir @@ -0,0 +1,14 @@ +// MIR for `partial_init::{closure#0}::{closure#0}` 0 coroutine_drop_proxy_async + +fn partial_init::{closure#0}::{closure#0}(_1: {async block@$DIR/async_fn.rs:80:50: 80:55}, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: std::task::Poll<()>; + + bb0: { + drop(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..0daea3b9ba747 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.StateTransform.after.mir @@ -0,0 +1,285 @@ +// MIR for `partial_init::{closure#0}` after StateTransform + +fn partial_init::{closure#0}(_1: Pin<&mut {async fn body of partial_init()}>, _2: &mut Context<'_>) -> Poll { + coroutine layout { + field _s0: u32; + field _s1: String; + field _s2: {async block@$DIR/async_fn.rs:80:50: 80:55}; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0, _s1, _s2], + } + storage_conflicts = BitMatrix(3x3) {(_s0, _s0), (_s0, _s1), (_s0, _s2), (_s1, _s0), (_s1, _s1), (_s1, _s2), (_s2, _s0), (_s2, _s1), (_s2, _s2)} + } + debug _task_context => _2; + debug x => ((*_28).0: u32); + coroutine debug x => _s0; + let mut _0: std::task::Poll; + let _3: u32; + let mut _4: !; + let mut _6: std::string::String; + let mut _7: !; + let mut _8: {async block@$DIR/async_fn.rs:80:50: 80:55}; + let mut _9: {async block@$DIR/async_fn.rs:80:50: 80:55}; + let mut _10: &u32; + let mut _12: (); + let _13: (); + let mut _14: std::task::Poll; + let mut _15: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:80:50: 80:55}>; + let mut _16: &mut {async block@$DIR/async_fn.rs:80:50: 80:55}; + let mut _17: &mut {async block@$DIR/async_fn.rs:80:50: 80:55}; + let mut _18: &mut std::task::Context<'_>; + let mut _19: &mut std::task::Context<'_>; + let mut _20: &mut std::task::Context<'_>; + let mut _21: isize; + let mut _23: !; + let mut _24: &mut std::task::Context<'_>; + let mut _25: (); + let mut _26: u32; + let mut _27: u32; + let mut _28: &mut {async fn body of partial_init()}; + scope 1 { + debug x => (((*_28) as variant#3).0: u32); + scope 2 { + debug _x => _5; + } + scope 3 { + coroutine debug __awaitee => _s2; + let _5: (std::string::String, !); + let mut _11: {async block@$DIR/async_fn.rs:80:50: 80:55}; + scope 4 { + debug __awaitee => (((*_28) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55}); + let _22: u32; + scope 5 { + debug result => _22; + } + } + } + } + + bb0: { + _28 = copy (_1.0: &mut {async fn body of partial_init()}); + _27 = discriminant((*_28)); + switchInt(move _27) -> [0: bb1, 1: bb32, 2: bb31, 3: bb30, otherwise: bb8]; + } + + bb1: { + nop; + (((*_28) as variant#3).0: u32) = copy ((*_28).0: u32); + StorageLive(_4); + StorageLive(_5); + nop; + (((*_28) as variant#3).1: std::string::String) = String::new() -> [return: bb2, unwind: bb25]; + } + + bb2: { + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + _10 = &(((*_28) as variant#3).0: u32); + _9 = {coroutine@$DIR/async_fn.rs:80:50: 80:55 (#0)} { x: move _10 }; + StorageDead(_10); + _8 = <{async block@$DIR/async_fn.rs:80:50: 80:55} as IntoFuture>::into_future(move _9) -> [return: bb3, unwind: bb21]; + } + + bb3: { + StorageDead(_9); + PlaceMention(_8); + nop; + (((*_28) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55}) = move _8; + goto -> bb4; + } + + bb4: { + StorageLive(_13); + StorageLive(_14); + StorageLive(_15); + StorageLive(_16); + StorageLive(_17); + _17 = &mut (((*_28) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55}); + _16 = &mut (*_17); + _15 = Pin::<&mut {async block@$DIR/async_fn.rs:80:50: 80:55}>::new_unchecked(move _16) -> [return: bb5, unwind: bb17]; + } + + bb5: { + StorageDead(_16); + StorageLive(_18); + StorageLive(_19); + StorageLive(_20); + _20 = copy _2; + _19 = move _20; + goto -> bb6; + } + + bb6: { + _18 = &mut (*_19); + StorageDead(_20); + _14 = <{async block@$DIR/async_fn.rs:80:50: 80:55} as Future>::poll(move _15, move _18) -> [return: bb7, unwind: bb16]; + } + + bb7: { + StorageDead(_19); + StorageDead(_18); + StorageDead(_17); + StorageDead(_15); + PlaceMention(_14); + _21 = discriminant(_14); + switchInt(move _21) -> [0: bb10, 1: bb9, otherwise: bb8]; + } + + bb8: { + unreachable; + } + + bb9: { + _13 = const (); + StorageDead(_14); + StorageDead(_13); + StorageLive(_24); + StorageLive(_25); + _25 = (); + _0 = Poll::::Pending; + StorageDead(_4); + StorageDead(_5); + StorageDead(_8); + StorageDead(_24); + StorageDead(_25); + discriminant((*_28)) = 3; + return; + } + + bb10: { + StorageLive(_22); + _22 = copy ((_14 as Ready).0: u32); + _26 = copy _22; + StorageDead(_22); + StorageDead(_14); + StorageDead(_13); + drop((((*_28) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55})) -> [return: bb12, unwind: bb19]; + } + + bb11: { + StorageDead(_25); + _2 = move _24; + StorageDead(_24); + _12 = const (); + goto -> bb4; + } + + bb12: { + nop; + drop((((*_28) as variant#3).1: std::string::String)) -> [return: bb13, unwind: bb20]; + } + + bb13: { + nop; + goto -> bb14; + } + + bb14: { + StorageDead(_8); + StorageDead(_5); + StorageDead(_4); + nop; + goto -> bb28; + } + + bb15: { + _0 = Poll::::Ready(move _26); + discriminant((*_28)) = 1; + return; + } + + bb16 (cleanup): { + StorageDead(_19); + StorageDead(_18); + goto -> bb18; + } + + bb17 (cleanup): { + StorageDead(_16); + goto -> bb18; + } + + bb18 (cleanup): { + StorageDead(_17); + StorageDead(_15); + StorageDead(_14); + StorageDead(_13); + drop((((*_28) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55})) -> [return: bb19, unwind terminate(cleanup)]; + } + + bb19 (cleanup): { + nop; + drop((((*_28) as variant#3).1: std::string::String)) -> [return: bb20, unwind terminate(cleanup)]; + } + + bb20 (cleanup): { + nop; + goto -> bb24; + } + + bb21 (cleanup): { + goto -> bb22; + } + + bb22 (cleanup): { + StorageDead(_9); + drop((((*_28) as variant#3).1: std::string::String)) -> [return: bb23, unwind terminate(cleanup)]; + } + + bb23 (cleanup): { + nop; + goto -> bb24; + } + + bb24 (cleanup): { + StorageDead(_8); + goto -> bb26; + } + + bb25 (cleanup): { + nop; + goto -> bb26; + } + + bb26 (cleanup): { + StorageDead(_5); + StorageDead(_4); + nop; + goto -> bb27; + } + + bb27 (cleanup): { + goto -> bb29; + } + + bb28: { + goto -> bb15; + } + + bb29 (cleanup): { + discriminant((*_28)) = 2; + resume; + } + + bb30: { + StorageLive(_4); + StorageLive(_5); + StorageLive(_8); + StorageLive(_24); + StorageLive(_25); + _24 = move _2; + goto -> bb11; + } + + bb31: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb31, unwind continue]; + } + + bb32: { + assert(const false, "`async fn` resumed after completion") -> [success: bb32, unwind continue]; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.coroutine_drop.0.mir new file mode 100644 index 0000000000000..20525a4cc712d --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.coroutine_drop.0.mir @@ -0,0 +1,131 @@ +// MIR for `partial_init::{closure#0}` 0 coroutine_drop + +fn partial_init::{closure#0}(_1: &mut {async fn body of partial_init()}) -> () { + debug _task_context => _2; + debug x => ((*_1).0: u32); + let mut _0: (); + let mut _2: &mut std::task::Context<'_>; + let _3: u32; + let mut _4: !; + let mut _6: std::string::String; + let mut _7: !; + let mut _8: {async block@$DIR/async_fn.rs:80:50: 80:55}; + let mut _9: {async block@$DIR/async_fn.rs:80:50: 80:55}; + let mut _10: &u32; + let mut _12: (); + let _13: (); + let mut _14: std::task::Poll; + let mut _15: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:80:50: 80:55}>; + let mut _16: &mut {async block@$DIR/async_fn.rs:80:50: 80:55}; + let mut _17: &mut {async block@$DIR/async_fn.rs:80:50: 80:55}; + let mut _18: &mut std::task::Context<'_>; + let mut _19: &mut std::task::Context<'_>; + let mut _20: &mut std::task::Context<'_>; + let mut _21: isize; + let mut _23: !; + let mut _24: &mut std::task::Context<'_>; + let mut _25: (); + let mut _26: u32; + let mut _27: u32; + scope 1 { + debug x => (((*_1) as variant#3).0: u32); + scope 2 { + debug _x => _5; + } + scope 3 { + let _5: (std::string::String, !); + let mut _11: {async block@$DIR/async_fn.rs:80:50: 80:55}; + scope 4 { + debug __awaitee => (((*_1) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55}); + let _22: u32; + scope 5 { + debug result => _22; + } + } + } + } + + bb0: { + _27 = discriminant((*_1)); + switchInt(move _27) -> [0: bb11, 3: bb14, otherwise: bb15]; + } + + bb1: { + StorageDead(_25); + StorageDead(_24); + drop((((*_1) as variant#3).2: {async block@$DIR/async_fn.rs:80:50: 80:55})) -> [return: bb2, unwind: bb7]; + } + + bb2: { + nop; + drop((((*_1) as variant#3).1: std::string::String)) -> [return: bb3, unwind: bb8]; + } + + bb3: { + nop; + goto -> bb4; + } + + bb4: { + StorageDead(_8); + StorageDead(_5); + StorageDead(_4); + nop; + goto -> bb12; + } + + bb5: { + return; + } + + bb6 (cleanup): { + resume; + } + + bb7 (cleanup): { + nop; + drop((((*_1) as variant#3).1: std::string::String)) -> [return: bb8, unwind terminate(cleanup)]; + } + + bb8 (cleanup): { + nop; + goto -> bb9; + } + + bb9 (cleanup): { + StorageDead(_8); + StorageDead(_5); + StorageDead(_4); + nop; + goto -> bb6; + } + + bb10: { + return; + } + + bb11: { + goto -> bb13; + } + + bb12: { + goto -> bb5; + } + + bb13: { + goto -> bb10; + } + + bb14: { + StorageLive(_4); + StorageLive(_5); + StorageLive(_8); + StorageLive(_24); + StorageLive(_25); + goto -> bb1; + } + + bb15: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.coroutine_drop_proxy_async.0.mir b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.coroutine_drop_proxy_async.0.mir new file mode 100644 index 0000000000000..1f67854bef25c --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.partial_init-{closure#0}.coroutine_drop_proxy_async.0.mir @@ -0,0 +1,24 @@ +// MIR for `partial_init::{closure#0}` 0 coroutine_drop_proxy_async + +fn partial_init::{closure#0}(_1: {async fn body of partial_init()}, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: std::task::Poll<()>; + scope 1 { + scope 2 { + } + scope 3 { + scope 4 { + scope 5 { + } + } + } + } + + bb0: { + drop(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.rs b/tests/mir-opt/coroutine/async_fn.rs new file mode 100644 index 0000000000000..97fb67acf82eb --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.rs @@ -0,0 +1,139 @@ +//@ skip-filecheck +//@ compile-flags: -Zmir-opt-level=0 +//@ needs-unwind +//@ edition: 2024 + +#![feature(never_type)] + +use std::future::Future; + +// See if we can run a basic `async fn` +// EMIT_MIR async_fn.foo-{closure#0}.StateTransform.after.mir +// EMIT_MIR async_fn.foo-{closure#0}.coroutine_drop.0.mir +// EMIT_MIR async_fn.foo-{closure#0}.coroutine_drop_proxy_async.0.mir +// EMIT_MIR async_fn.foo-{closure#0}-{closure#0}.StateTransform.after.mir +// EMIT_MIR async_fn.foo-{closure#0}-{closure#0}.coroutine_drop.0.mir +// EMIT_MIR async_fn.foo-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir +pub async fn foo(x: &u32, y: u32) -> u32 { + let y = &y; + let z = 9; + let z = &z; + let y = async { *y + *z }.await; + let a = 10; + let a = &a; + *x + y + *a +} + +// EMIT_MIR async_fn.add-{closure#0}.StateTransform.after.mir +// EMIT_MIR async_fn.add-{closure#0}.coroutine_drop.0.mir +// EMIT_MIR async_fn.add-{closure#0}.coroutine_drop_proxy_async.0.mir +// EMIT_MIR async_fn.add-{closure#0}-{closure#0}.StateTransform.after.mir +// EMIT_MIR async_fn.add-{closure#0}-{closure#0}.coroutine_drop.0.mir +// EMIT_MIR async_fn.add-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir +async fn add(x: u32, y: u32) -> u32 { + let a = async { x + y }; + a.await +} + +// EMIT_MIR async_fn.build_aggregate-{closure#0}.StateTransform.after.mir +// EMIT_MIR async_fn.build_aggregate-{closure#0}.coroutine_drop.0.mir +// EMIT_MIR async_fn.build_aggregate-{closure#0}.coroutine_drop_proxy_async.0.mir +async fn build_aggregate(a: u32, b: u32, c: u32, d: u32) -> u32 { + let x = (add(a, b).await, add(c, d).await); + x.0 + x.1 +} + +enum Never {} +fn never() -> Never { + panic!() +} + +// EMIT_MIR async_fn.includes_never-{closure#0}.StateTransform.after.mir +// EMIT_MIR async_fn.includes_never-{closure#0}.coroutine_drop.0.mir +// EMIT_MIR async_fn.includes_never-{closure#0}.coroutine_drop_proxy_async.0.mir +// EMIT_MIR async_fn.includes_never-{closure#0}-{closure#0}.StateTransform.after.mir +// EMIT_MIR async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop.0.mir +// EMIT_MIR async_fn.includes_never-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir +// EMIT_MIR async_fn.includes_never-{closure#0}-{closure#1}.StateTransform.after.mir +// EMIT_MIR async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop.0.mir +// EMIT_MIR async_fn.includes_never-{closure#0}-{closure#1}.coroutine_drop_proxy_async.0.mir +async fn includes_never(crash: bool, x: u32) -> u32 { + let result = async { x * x }.await; + if !crash { + return result; + } + #[allow(unused)] + let bad = never(); + result *= async { x + x }.await; + drop(bad); + result +} + +// EMIT_MIR async_fn.partial_init-{closure#0}.StateTransform.after.mir +// EMIT_MIR async_fn.partial_init-{closure#0}.coroutine_drop.0.mir +// EMIT_MIR async_fn.partial_init-{closure#0}.coroutine_drop_proxy_async.0.mir +// EMIT_MIR async_fn.partial_init-{closure#0}-{closure#0}.StateTransform.after.mir +// EMIT_MIR async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop.0.mir +// EMIT_MIR async_fn.partial_init-{closure#0}-{closure#0}.coroutine_drop_proxy_async.0.mir +async fn partial_init(x: u32) -> u32 { + #[allow(unreachable_code)] + let _x: (String, !) = (String::new(), return async { x + x }.await); +} + +async fn read_exact(_from: &mut &[u8], _to: &mut [u8]) -> Option<()> { + Some(()) +} + +// EMIT_MIR async_fn.hello_world-{closure#0}.StateTransform.after.mir +// EMIT_MIR async_fn.hello_world-{closure#0}.coroutine_drop.0.mir +// EMIT_MIR async_fn.hello_world-{closure#0}.coroutine_drop_proxy_async.0.mir +async fn hello_world() { + let data = [0u8; 1]; + let mut reader = &data[..]; + + let mut marker = [0u8; 1]; + read_exact(&mut reader, &mut marker).await.unwrap(); +} + +// This example comes from https://github.com/rust-lang/rust/issues/115145 +// EMIT_MIR async_fn.uninhabited_variant-{closure#0}.StateTransform.after.mir +// EMIT_MIR async_fn.uninhabited_variant-{closure#0}.coroutine_drop.0.mir +// EMIT_MIR async_fn.uninhabited_variant-{closure#0}.coroutine_drop_proxy_async.0.mir +#[allow(unreachable_patterns)] +async fn uninhabited_variant() { + async fn unreachable(_: Never) {} + + let c = async {}; + match None:: { + None => { + c.await; + } + Some(r) => { + unreachable(r).await; + } + } +} + +fn run_fut(fut: impl Future) -> T { + use std::task::{Context, Poll, Waker}; + + let mut context = Context::from_waker(Waker::noop()); + + let mut pinned = Box::pin(fut); + loop { + match pinned.as_mut().poll(&mut context) { + Poll::Pending => continue, + Poll::Ready(v) => return v, + } + } +} + +fn main() { + let x = 5; + assert_eq!(run_fut(foo(&x, 7)), 31); + assert_eq!(run_fut(build_aggregate(1, 2, 3, 4)), 10); + assert_eq!(run_fut(includes_never(false, 4)), 16); + assert_eq!(run_fut(partial_init(4)), 8); + run_fut(hello_world()); + run_fut(uninhabited_variant()); +} diff --git a/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.StateTransform.after.mir b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.StateTransform.after.mir new file mode 100644 index 0000000000000..9edc5b2fc3e6a --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.StateTransform.after.mir @@ -0,0 +1,488 @@ +// MIR for `uninhabited_variant::{closure#0}` after StateTransform + +fn uninhabited_variant::{closure#0}(_1: Pin<&mut {async fn body of uninhabited_variant()}>, _2: &mut Context<'_>) -> Poll<()> { + coroutine layout { + field _s0: {async block@$DIR/async_fn.rs:106:13: 106:18}; + field _s1: {async block@$DIR/async_fn.rs:106:13: 106:18}; + field _s2: {async fn body of uninhabited_variant::{closure#0}::unreachable()}; + field _s3: bool; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s1, _s3], + Suspend1 (4): [_s0, _s2, _s3], + } + storage_conflicts = BitMatrix(4x4) {(_s0, _s0), (_s0, _s2), (_s0, _s3), (_s1, _s1), (_s1, _s3), (_s2, _s0), (_s2, _s2), (_s2, _s3), (_s3, _s0), (_s3, _s1), (_s3, _s2), (_s3, _s3)} + } + debug _task_context => _2; + coroutine debug c => _s0; + let mut _0: std::task::Poll<()>; + let _3: {async block@$DIR/async_fn.rs:106:13: 106:18}; + let mut _4: std::option::Option; + let mut _5: isize; + let _6: (); + let mut _7: {async block@$DIR/async_fn.rs:106:13: 106:18}; + let mut _8: {async block@$DIR/async_fn.rs:106:13: 106:18}; + let mut _10: (); + let _11: (); + let mut _12: std::task::Poll<()>; + let mut _13: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:106:13: 106:18}>; + let mut _14: &mut {async block@$DIR/async_fn.rs:106:13: 106:18}; + let mut _15: &mut {async block@$DIR/async_fn.rs:106:13: 106:18}; + let mut _16: &mut std::task::Context<'_>; + let mut _17: &mut std::task::Context<'_>; + let mut _18: &mut std::task::Context<'_>; + let mut _19: isize; + let mut _21: !; + let mut _22: &mut std::task::Context<'_>; + let mut _23: (); + let _25: (); + let mut _26: {async fn body of uninhabited_variant::{closure#0}::unreachable()}; + let mut _27: {async fn body of uninhabited_variant::{closure#0}::unreachable()}; + let mut _28: Never; + let _30: (); + let mut _31: std::task::Poll<()>; + let mut _32: std::pin::Pin<&mut {async fn body of uninhabited_variant::{closure#0}::unreachable()}>; + let mut _33: &mut {async fn body of uninhabited_variant::{closure#0}::unreachable()}; + let mut _34: &mut {async fn body of uninhabited_variant::{closure#0}::unreachable()}; + let mut _35: &mut std::task::Context<'_>; + let mut _36: &mut std::task::Context<'_>; + let mut _37: &mut std::task::Context<'_>; + let mut _38: isize; + let mut _40: !; + let mut _41: &mut std::task::Context<'_>; + let mut _42: (); + let mut _43: bool; + let mut _44: (); + let mut _45: u32; + let mut _46: &mut {async fn body of uninhabited_variant()}; + scope 1 { + debug c => (((*_46) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18}); + coroutine debug __awaitee => _s1; + let mut _9: {async block@$DIR/async_fn.rs:106:13: 106:18}; + let _24: Never; + scope 2 { + debug __awaitee => (((*_46) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18}); + let _20: (); + scope 3 { + debug result => _20; + } + } + scope 4 { + debug r => _24; + coroutine debug __awaitee => _s2; + let mut _29: {async fn body of uninhabited_variant::{closure#0}::unreachable()}; + scope 5 { + debug __awaitee => (((*_46) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()}); + let _39: (); + scope 6 { + debug result => _39; + } + } + } + } + + bb0: { + _46 = copy (_1.0: &mut {async fn body of uninhabited_variant()}); + _45 = discriminant((*_46)); + switchInt(move _45) -> [0: bb1, 1: bb56, 2: bb55, 3: bb53, 4: bb54, otherwise: bb2]; + } + + bb1: { + (((*_46) as variant#4).2: bool) = const false; + nop; + (((*_46) as variant#4).2: bool) = const true; + (((*_46) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18}) = {coroutine@$DIR/async_fn.rs:106:13: 106:18 (#0)}; + StorageLive(_4); + _4 = Option::::None; + PlaceMention(_4); + _5 = discriminant(_4); + switchInt(move _5) -> [0: bb4, 1: bb3, otherwise: bb2]; + } + + bb2: { + unreachable; + } + + bb3: { + StorageLive(_24); + _24 = move ((_4 as Some).0: Never); + StorageLive(_25); + StorageLive(_26); + StorageLive(_27); + StorageLive(_28); + _28 = move _24; + _27 = uninhabited_variant::{closure#0}::unreachable(move _28) -> [return: bb15, unwind: bb34]; + } + + bb4: { + StorageLive(_6); + StorageLive(_7); + StorageLive(_8); + (((*_46) as variant#4).2: bool) = const false; + _8 = move (((*_46) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18}); + _7 = <{async block@$DIR/async_fn.rs:106:13: 106:18} as IntoFuture>::into_future(move _8) -> [return: bb5, unwind: bb41]; + } + + bb5: { + StorageDead(_8); + PlaceMention(_7); + nop; + (((*_46) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18}) = move _7; + goto -> bb6; + } + + bb6: { + StorageLive(_11); + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); + StorageLive(_15); + _15 = &mut (((*_46) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18}); + _14 = &mut (*_15); + _13 = Pin::<&mut {async block@$DIR/async_fn.rs:106:13: 106:18}>::new_unchecked(move _14) -> [return: bb7, unwind: bb38]; + } + + bb7: { + StorageDead(_14); + StorageLive(_16); + StorageLive(_17); + StorageLive(_18); + _18 = copy _2; + _17 = move _18; + goto -> bb8; + } + + bb8: { + _16 = &mut (*_17); + StorageDead(_18); + _12 = <{async block@$DIR/async_fn.rs:106:13: 106:18} as Future>::poll(move _13, move _16) -> [return: bb9, unwind: bb37]; + } + + bb9: { + StorageDead(_17); + StorageDead(_16); + StorageDead(_15); + StorageDead(_13); + PlaceMention(_12); + _19 = discriminant(_12); + switchInt(move _19) -> [0: bb11, 1: bb10, otherwise: bb2]; + } + + bb10: { + _11 = const (); + StorageDead(_12); + StorageDead(_11); + StorageLive(_22); + StorageLive(_23); + _23 = (); + _0 = Poll::<()>::Pending; + StorageDead(_4); + StorageDead(_6); + StorageDead(_7); + StorageDead(_22); + StorageDead(_23); + discriminant((*_46)) = 3; + return; + } + + bb11: { + StorageLive(_20); + _20 = copy ((_12 as Ready).0: ()); + _6 = copy _20; + StorageDead(_20); + StorageDead(_12); + StorageDead(_11); + drop((((*_46) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb13, unwind: bb40]; + } + + bb12: { + StorageDead(_23); + _2 = move _22; + StorageDead(_22); + _10 = const (); + goto -> bb6; + } + + bb13: { + nop; + goto -> bb14; + } + + bb14: { + StorageDead(_7); + StorageDead(_6); + _44 = const (); + goto -> bb26; + } + + bb15: { + StorageDead(_28); + _26 = <{async fn body of uninhabited_variant::{closure#0}::unreachable()} as IntoFuture>::into_future(move _27) -> [return: bb16, unwind: bb33]; + } + + bb16: { + StorageDead(_27); + PlaceMention(_26); + nop; + (((*_46) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()}) = move _26; + goto -> bb17; + } + + bb17: { + StorageLive(_30); + StorageLive(_31); + StorageLive(_32); + StorageLive(_33); + StorageLive(_34); + _34 = &mut (((*_46) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()}); + _33 = &mut (*_34); + _32 = Pin::<&mut {async fn body of uninhabited_variant::{closure#0}::unreachable()}>::new_unchecked(move _33) -> [return: bb18, unwind: bb30]; + } + + bb18: { + StorageDead(_33); + StorageLive(_35); + StorageLive(_36); + StorageLive(_37); + _37 = copy _2; + _36 = move _37; + goto -> bb19; + } + + bb19: { + _35 = &mut (*_36); + StorageDead(_37); + _31 = <{async fn body of uninhabited_variant::{closure#0}::unreachable()} as Future>::poll(move _32, move _35) -> [return: bb20, unwind: bb29]; + } + + bb20: { + StorageDead(_36); + StorageDead(_35); + StorageDead(_34); + StorageDead(_32); + PlaceMention(_31); + _38 = discriminant(_31); + switchInt(move _38) -> [0: bb22, 1: bb21, otherwise: bb2]; + } + + bb21: { + _30 = const (); + StorageDead(_31); + StorageDead(_30); + StorageLive(_41); + StorageLive(_42); + _42 = (); + _0 = Poll::<()>::Pending; + StorageDead(_4); + StorageDead(_24); + StorageDead(_25); + StorageDead(_26); + StorageDead(_41); + StorageDead(_42); + discriminant((*_46)) = 4; + return; + } + + bb22: { + StorageLive(_39); + _39 = copy ((_31 as Ready).0: ()); + _25 = copy _39; + StorageDead(_39); + StorageDead(_31); + StorageDead(_30); + drop((((*_46) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()})) -> [return: bb24, unwind: bb32]; + } + + bb23: { + StorageDead(_42); + _2 = move _41; + StorageDead(_41); + _10 = const (); + goto -> bb17; + } + + bb24: { + nop; + goto -> bb25; + } + + bb25: { + StorageDead(_26); + StorageDead(_25); + _44 = const (); + StorageDead(_24); + goto -> bb26; + } + + bb26: { + StorageDead(_4); + goto -> bb48; + } + + bb27: { + (((*_46) as variant#4).2: bool) = const false; + nop; + goto -> bb51; + } + + bb28: { + _0 = Poll::<()>::Ready(move _44); + discriminant((*_46)) = 1; + return; + } + + bb29 (cleanup): { + StorageDead(_36); + StorageDead(_35); + goto -> bb31; + } + + bb30 (cleanup): { + StorageDead(_33); + goto -> bb31; + } + + bb31 (cleanup): { + StorageDead(_34); + StorageDead(_32); + StorageDead(_31); + StorageDead(_30); + drop((((*_46) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()})) -> [return: bb32, unwind terminate(cleanup)]; + } + + bb32 (cleanup): { + nop; + goto -> bb36; + } + + bb33 (cleanup): { + goto -> bb35; + } + + bb34 (cleanup): { + StorageDead(_28); + goto -> bb35; + } + + bb35 (cleanup): { + StorageDead(_27); + goto -> bb36; + } + + bb36 (cleanup): { + StorageDead(_26); + StorageDead(_25); + StorageDead(_24); + goto -> bb44; + } + + bb37 (cleanup): { + StorageDead(_17); + StorageDead(_16); + goto -> bb39; + } + + bb38 (cleanup): { + StorageDead(_14); + goto -> bb39; + } + + bb39 (cleanup): { + StorageDead(_15); + StorageDead(_13); + StorageDead(_12); + StorageDead(_11); + drop((((*_46) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb40, unwind terminate(cleanup)]; + } + + bb40 (cleanup): { + nop; + goto -> bb43; + } + + bb41 (cleanup): { + goto -> bb42; + } + + bb42 (cleanup): { + StorageDead(_8); + goto -> bb43; + } + + bb43 (cleanup): { + StorageDead(_7); + StorageDead(_6); + goto -> bb44; + } + + bb44 (cleanup): { + StorageDead(_4); + goto -> bb50; + } + + bb45 (cleanup): { + (((*_46) as variant#4).2: bool) = const false; + nop; + goto -> bb46; + } + + bb46 (cleanup): { + goto -> bb52; + } + + bb47: { + drop((((*_46) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb27, unwind: bb45]; + } + + bb48: { + switchInt(copy (((*_46) as variant#4).2: bool)) -> [0: bb27, otherwise: bb47]; + } + + bb49 (cleanup): { + drop((((*_46) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb45, unwind terminate(cleanup)]; + } + + bb50 (cleanup): { + switchInt(copy (((*_46) as variant#4).2: bool)) -> [0: bb45, otherwise: bb49]; + } + + bb51: { + goto -> bb28; + } + + bb52 (cleanup): { + discriminant((*_46)) = 2; + resume; + } + + bb53: { + StorageLive(_4); + StorageLive(_6); + StorageLive(_7); + StorageLive(_22); + StorageLive(_23); + _22 = move _2; + goto -> bb12; + } + + bb54: { + StorageLive(_4); + StorageLive(_24); + StorageLive(_25); + StorageLive(_26); + StorageLive(_41); + StorageLive(_42); + _41 = move _2; + goto -> bb23; + } + + bb55: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb55, unwind continue]; + } + + bb56: { + assert(const false, "`async fn` resumed after completion") -> [success: bb56, unwind continue]; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.coroutine_drop.0.mir b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.coroutine_drop.0.mir new file mode 100644 index 0000000000000..31b418c7efad9 --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.coroutine_drop.0.mir @@ -0,0 +1,216 @@ +// MIR for `uninhabited_variant::{closure#0}` 0 coroutine_drop + +fn uninhabited_variant::{closure#0}(_1: &mut {async fn body of uninhabited_variant()}) -> () { + debug _task_context => _2; + let mut _0: (); + let mut _2: &mut std::task::Context<'_>; + let _3: {async block@$DIR/async_fn.rs:106:13: 106:18}; + let mut _4: std::option::Option; + let mut _5: isize; + let _6: (); + let mut _7: {async block@$DIR/async_fn.rs:106:13: 106:18}; + let mut _8: {async block@$DIR/async_fn.rs:106:13: 106:18}; + let mut _10: (); + let _11: (); + let mut _12: std::task::Poll<()>; + let mut _13: std::pin::Pin<&mut {async block@$DIR/async_fn.rs:106:13: 106:18}>; + let mut _14: &mut {async block@$DIR/async_fn.rs:106:13: 106:18}; + let mut _15: &mut {async block@$DIR/async_fn.rs:106:13: 106:18}; + let mut _16: &mut std::task::Context<'_>; + let mut _17: &mut std::task::Context<'_>; + let mut _18: &mut std::task::Context<'_>; + let mut _19: isize; + let mut _21: !; + let mut _22: &mut std::task::Context<'_>; + let mut _23: (); + let _25: (); + let mut _26: {async fn body of uninhabited_variant::{closure#0}::unreachable()}; + let mut _27: {async fn body of uninhabited_variant::{closure#0}::unreachable()}; + let mut _28: Never; + let _30: (); + let mut _31: std::task::Poll<()>; + let mut _32: std::pin::Pin<&mut {async fn body of uninhabited_variant::{closure#0}::unreachable()}>; + let mut _33: &mut {async fn body of uninhabited_variant::{closure#0}::unreachable()}; + let mut _34: &mut {async fn body of uninhabited_variant::{closure#0}::unreachable()}; + let mut _35: &mut std::task::Context<'_>; + let mut _36: &mut std::task::Context<'_>; + let mut _37: &mut std::task::Context<'_>; + let mut _38: isize; + let mut _40: !; + let mut _41: &mut std::task::Context<'_>; + let mut _42: (); + let mut _43: bool; + let mut _44: (); + let mut _45: u32; + scope 1 { + debug c => (((*_1) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18}); + let mut _9: {async block@$DIR/async_fn.rs:106:13: 106:18}; + let _24: Never; + scope 2 { + debug __awaitee => (((*_1) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18}); + let _20: (); + scope 3 { + debug result => _20; + } + } + scope 4 { + debug r => _24; + let mut _29: {async fn body of uninhabited_variant::{closure#0}::unreachable()}; + scope 5 { + debug __awaitee => (((*_1) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()}); + let _39: (); + scope 6 { + debug result => _39; + } + } + } + } + + bb0: { + _45 = discriminant((*_1)); + switchInt(move _45) -> [0: bb22, 3: bb25, 4: bb26, otherwise: bb27]; + } + + bb1: { + StorageDead(_42); + StorageDead(_41); + drop((((*_1) as variant#4).1: {async fn body of uninhabited_variant::{closure#0}::unreachable()})) -> [return: bb2, unwind: bb11]; + } + + bb2: { + nop; + goto -> bb3; + } + + bb3: { + StorageDead(_26); + StorageDead(_25); + StorageDead(_24); + goto -> bb7; + } + + bb4: { + StorageDead(_23); + StorageDead(_22); + drop((((*_1) as variant#3).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb5, unwind: bb13]; + } + + bb5: { + nop; + goto -> bb6; + } + + bb6: { + StorageDead(_7); + StorageDead(_6); + goto -> bb7; + } + + bb7: { + StorageDead(_4); + goto -> bb18; + } + + bb8: { + (((*_1) as variant#4).2: bool) = const false; + nop; + goto -> bb23; + } + + bb9: { + return; + } + + bb10 (cleanup): { + resume; + } + + bb11 (cleanup): { + nop; + goto -> bb12; + } + + bb12 (cleanup): { + StorageDead(_26); + StorageDead(_25); + StorageDead(_24); + goto -> bb15; + } + + bb13 (cleanup): { + nop; + goto -> bb14; + } + + bb14 (cleanup): { + StorageDead(_7); + StorageDead(_6); + goto -> bb15; + } + + bb15 (cleanup): { + StorageDead(_4); + goto -> bb20; + } + + bb16 (cleanup): { + (((*_1) as variant#4).2: bool) = const false; + nop; + goto -> bb10; + } + + bb17: { + drop((((*_1) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb8, unwind: bb16]; + } + + bb18: { + switchInt(copy (((*_1) as variant#4).2: bool)) -> [0: bb8, otherwise: bb17]; + } + + bb19 (cleanup): { + drop((((*_1) as variant#4).0: {async block@$DIR/async_fn.rs:106:13: 106:18})) -> [return: bb16, unwind terminate(cleanup)]; + } + + bb20 (cleanup): { + switchInt(copy (((*_1) as variant#4).2: bool)) -> [0: bb16, otherwise: bb19]; + } + + bb21: { + return; + } + + bb22: { + goto -> bb24; + } + + bb23: { + goto -> bb9; + } + + bb24: { + goto -> bb21; + } + + bb25: { + StorageLive(_4); + StorageLive(_6); + StorageLive(_7); + StorageLive(_22); + StorageLive(_23); + goto -> bb4; + } + + bb26: { + StorageLive(_4); + StorageLive(_24); + StorageLive(_25); + StorageLive(_26); + StorageLive(_41); + StorageLive(_42); + goto -> bb1; + } + + bb27: { + return; + } +} diff --git a/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.coroutine_drop_proxy_async.0.mir b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.coroutine_drop_proxy_async.0.mir new file mode 100644 index 0000000000000..f460d8984bacf --- /dev/null +++ b/tests/mir-opt/coroutine/async_fn.uninhabited_variant-{closure#0}.coroutine_drop_proxy_async.0.mir @@ -0,0 +1,26 @@ +// MIR for `uninhabited_variant::{closure#0}` 0 coroutine_drop_proxy_async + +fn uninhabited_variant::{closure#0}(_1: {async fn body of uninhabited_variant()}, _2: &mut Context<'_>) -> Poll<()> { + let mut _0: std::task::Poll<()>; + scope 1 { + scope 2 { + scope 3 { + } + } + scope 4 { + scope 5 { + scope 6 { + } + } + } + } + + bb0: { + drop(_1) -> [return: bb1, unwind continue]; + } + + bb1: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir b/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir similarity index 100% rename from tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir rename to tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir b/tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir similarity index 100% rename from tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir rename to tests/mir-opt/coroutine/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir diff --git a/tests/mir-opt/coroutine_drop_cleanup.rs b/tests/mir-opt/coroutine/coroutine_drop_cleanup.rs similarity index 100% rename from tests/mir-opt/coroutine_drop_cleanup.rs rename to tests/mir-opt/coroutine/coroutine_drop_cleanup.rs diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir similarity index 100% rename from tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir rename to tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir similarity index 100% rename from tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir rename to tests/mir-opt/coroutine/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.rs b/tests/mir-opt/coroutine/coroutine_storage_dead_unwind.rs similarity index 100% rename from tests/mir-opt/coroutine_storage_dead_unwind.rs rename to tests/mir-opt/coroutine/coroutine_storage_dead_unwind.rs diff --git a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir similarity index 74% rename from tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir rename to tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir index 222c7144ef07d..e5667215d54fd 100644 --- a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/coroutine/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir @@ -1,28 +1,18 @@ // MIR for `main::{closure#0}` 0 coroutine_resume -/* coroutine_layout = CoroutineLayout { - field_tys: { - _s0: CoroutineSavedTy { - ty: HasDrop, - source_info: SourceInfo { - span: $DIR/coroutine_tiny.rs:22:13: 22:15 (#0), - scope: scope[0], - }, - ignore_for_traits: false, - }, - }, - variant_fields: { - Unresumed(0): [], - Returned (1): [], - Panicked (2): [], - Suspend0 (3): [_s0], - }, - storage_conflicts: BitMatrix(1x1) { - (_s0, _s0), - }, -} */ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}>, _2: u8) -> CoroutineState<(), ()> { + coroutine layout { + field _s0: HasDrop; + variant_fields = { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_s0], + } + storage_conflicts = BitMatrix(1x1) {(_s0, _s0)} + } debug _x => _2; + coroutine debug _d => _s0; let mut _0: std::ops::CoroutineState<(), ()>; let _3: HasDrop; let mut _4: !; diff --git a/tests/mir-opt/coroutine_tiny.rs b/tests/mir-opt/coroutine/coroutine_tiny.rs similarity index 100% rename from tests/mir-opt/coroutine_tiny.rs rename to tests/mir-opt/coroutine/coroutine_tiny.rs diff --git a/tests/mir-opt/inline_coroutine_body.rs b/tests/mir-opt/coroutine/inline_coroutine_body.rs similarity index 100% rename from tests/mir-opt/inline_coroutine_body.rs rename to tests/mir-opt/coroutine/inline_coroutine_body.rs diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/coroutine/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff similarity index 100% rename from tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff rename to tests/mir-opt/coroutine/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/coroutine/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff similarity index 100% rename from tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff rename to tests/mir-opt/coroutine/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff