diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 87e1d9aa7a114..acbcee3b74755 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1036,10 +1036,13 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::LangItem::PinNewUnchecked, arena_vec![self; ref_mut_awaitee], ); - let get_context = self.expr_call_lang_item_fn_mut( + let get_context = self.expr( gen_future_span, - hir::LangItem::GetContext, - arena_vec![self; task_context], + hir::ExprKind::UnsafeBinderCast( + UnsafeBinderCastKind::Unwrap, + self.arena.alloc(task_context), + None, + ), ); let call = match await_kind { FutureKind::Future => self.expr_call_lang_item_fn( diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 60676ac6b8644..cdae794775432 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -306,6 +306,11 @@ fn place_projection_conflict<'tcx>( debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE"); Overlap::EqualOrDisjoint } + (ProjectionElem::UnwrapUnsafeBinder(_), ProjectionElem::UnwrapUnsafeBinder(_)) => { + // casts to other types may always conflict irrespective of the type being cast to. + debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE"); + Overlap::EqualOrDisjoint + } (ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => { if f1 == f2 { // same field (e.g., `a.y` vs. `a.y`) - recur. @@ -510,6 +515,7 @@ fn place_projection_conflict<'tcx>( | ProjectionElem::Index(..) | ProjectionElem::ConstantIndex { .. } | ProjectionElem::OpaqueCast { .. } + | ProjectionElem::UnwrapUnsafeBinder { .. } | ProjectionElem::Subslice { .. } | ProjectionElem::Downcast(..), _, @@ -518,9 +524,5 @@ fn place_projection_conflict<'tcx>( pi1_elem, pi2_elem ), - - (ProjectionElem::UnwrapUnsafeBinder(_), _) => { - todo!() - } } } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index bb461ccb6f370..c7e0ec29a47a9 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -991,7 +991,6 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // Nothing to check. interp_ok(true) } - ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"), // The above should be all the primitive types. The rest is compound, we // check them by visiting their fields/variants. ty::Adt(..) @@ -1002,6 +1001,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { | ty::Dynamic(..) | ty::Closure(..) | ty::Pat(..) + | ty::UnsafeBinder(_) | ty::CoroutineClosure(..) | ty::Coroutine(..) => interp_ok(false), // Some types only occur during typechecking, they have no layout. @@ -1536,6 +1536,12 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, BackendRepr::Memory { .. } => unreachable!() } } + ty::UnsafeBinder(base) => { + // First check that the base type is valid + let base = self.ecx.tcx.instantiate_bound_regions_with_erased((*base).into()); + let inner_layout = self.ecx.layout_of(base)?; + self.visit_value(&val.transmute(inner_layout, self.ecx)?)?; + } ty::Adt(adt, _) if adt.is_maybe_dangling() => { let old_may_dangle = mem::replace(&mut self.may_dangle, true); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 0569c1b986d1a..f661a85505c94 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_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 4a3615e5421fe..47cdc7c465edb 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -378,8 +378,7 @@ language_item_table! { // FIXME(swatinem): the following lang items are used for async lowering and // should become obsolete eventually. - ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None; - GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None; + ResumeTy, sym::ResumeTy, resume_ty, Target::TyAlias, GenericRequirement::None; Context, sym::Context, context, Target::Struct, GenericRequirement::None; FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9db9b1769ab9c..6e94cbc970446 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -916,6 +916,29 @@ impl<'tcx> Ty<'tcx> { Ty::new_generic_adt(tcx, def_id, ty) } + /// Creates a `unsafe<'a, 'b> &'a mut Context<'b>` [`Ty`]. + pub fn new_resume_ty(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + let context_did = tcx.require_lang_item(LangItem::Context, DUMMY_SP); + let context_adt_ref = tcx.adt_def(context_did); + + let lt = |n| { + ty::Region::new_bound( + tcx, + ty::INNERMOST, + ty::BoundRegion { var: ty::BoundVar::from_u32(n), kind: BoundRegionKind::Anon }, + ) + }; + + let context_args = tcx.mk_args(&[lt(1).into()]); + let context_ty = Ty::new_adt(tcx, context_adt_ref, context_args); + let context_mut_ref = Ty::new_mut_ref(tcx, lt(0), context_ty); + let bound_vars = tcx.mk_bound_variable_kinds(&[ + BoundVariableKind::Region(BoundRegionKind::Anon), + BoundVariableKind::Region(BoundRegionKind::Anon), + ]); + Ty::new_unsafe_binder(tcx, ty::Binder::bind_with_vars(context_mut_ref, bound_vars)) + } + /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes. pub fn new_task_context(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { let context_did = tcx.require_lang_item(LangItem::Context, DUMMY_SP); diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 4ae6e9a8885d1..0509e24aaab6b 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -563,20 +563,13 @@ fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body ); } -/// Transforms the `body` of the coroutine applying the following transforms: +/// Transforms the `body` of the coroutine replacing `CTX_ARG: ResumeTy` types with +/// `CTX_ARG: &mut Context<'_>` (`context_mut_ref`), and making all users wrap/unwrap +/// into a `ResumeTy`. /// -/// - Eliminates all the `get_context` calls that async lowering created. -/// - Replace all `Local` `ResumeTy` types with `&mut Context<'_>` (`context_mut_ref`). +/// The `ResumeTy` hides a `&mut Context<'_>` behind an unsafe binder. /// -/// The `Local`s that have their types replaced are: -/// - The `resume` argument itself. -/// - The argument to `get_context`. -/// - The yielded value of a `yield`. -/// -/// The `ResumeTy` hides a `&mut Context<'_>` behind an unsafe raw pointer, and the -/// `get_context` function is being used to convert that back to a `&mut Context<'_>`. -/// -/// Ideally the async lowering would not use the `ResumeTy`/`get_context` indirection, +/// Ideally the async lowering would not use the `ResumeTy` indirection, /// but rather directly use `&mut Context<'_>`, however that would currently /// lead to higher-kinded lifetime errors. /// See . @@ -585,78 +578,20 @@ 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> { - let context_mut_ref = Ty::new_task_context(tcx); - - // replace the type of the `resume` argument - replace_resume_ty_local(tcx, body, CTX_ARG, context_mut_ref); +fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let resume_ty = body.local_decls[CTX_ARG].ty; + let resume_local = body.local_decls.push(LocalDecl::new(Ty::new_task_context(tcx), body.span)); + body.local_decls.swap(CTX_ARG, resume_local); - let get_context_def_id = tcx.require_lang_item(LangItem::GetContext, body.span); + RenameLocalVisitor { from: CTX_ARG, to: resume_local, tcx }.visit_body(body); - for bb in body.basic_blocks.indices() { - let bb_data = &body[bb]; - if bb_data.is_cleanup { - continue; - } - - match &bb_data.terminator().kind { - TerminatorKind::Call { func, .. } => { - let func_ty = func.ty(body, tcx); - if let ty::FnDef(def_id, _) = *func_ty.kind() - && def_id == get_context_def_id - { - let local = eliminate_get_context_call(&mut body[bb]); - replace_resume_ty_local(tcx, body, local, context_mut_ref); - } - } - TerminatorKind::Yield { resume_arg, .. } => { - replace_resume_ty_local(tcx, body, resume_arg.local, context_mut_ref); - } - _ => {} - } - } - context_mut_ref -} - -fn eliminate_get_context_call<'tcx>(bb_data: &mut BasicBlockData<'tcx>) -> Local { - let terminator = bb_data.terminator.take().unwrap(); - let TerminatorKind::Call { args, destination, target, .. } = terminator.kind else { - bug!(); - }; - let [arg] = *Box::try_from(args).unwrap(); - let local = arg.node.place().unwrap().local; - - let arg = Rvalue::Use(arg.node, WithRetag::Yes); - let assign = - Statement::new(terminator.source_info, StatementKind::Assign(Box::new((destination, arg)))); - bb_data.statements.push(assign); - bb_data.terminator = Some(Terminator { - source_info: terminator.source_info, - kind: TerminatorKind::Goto { target: target.unwrap() }, - }); - local -} - -#[cfg_attr(not(debug_assertions), allow(unused))] -#[tracing::instrument(level = "trace", skip(tcx, body), ret)] -fn replace_resume_ty_local<'tcx>( - tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, - local: Local, - context_mut_ref: Ty<'tcx>, -) { - let local_ty = std::mem::replace(&mut body.local_decls[local].ty, context_mut_ref); - // We have to replace the `ResumeTy` that is used for type and borrow checking - // with `&mut Context<'_>` in MIR. - #[cfg(debug_assertions)] - { - if let ty::Adt(resume_ty_adt, _) = local_ty.kind() { - let expected_adt = tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, body.span)); - assert_eq!(*resume_ty_adt, expected_adt); - } else { - panic!("expected `ResumeTy`, found `{:?}`", local_ty); - }; - } + // Now `CTX_ARG` is `&mut Context` and `resume_local` is a `unsafe<>`. + let source_info = SourceInfo::outermost(body.span); + let rhs = Rvalue::WrapUnsafeBinder(Operand::Move(CTX_ARG.into()), resume_ty); + let assign = StatementKind::Assign(Box::new((resume_local.into(), rhs))); + body.basic_blocks.as_mut_preserves_cfg()[START_BLOCK] + .statements + .insert(0, Statement::new(source_info, assign)); } /// Transforms the `body` of the coroutine applying the following transform: @@ -1314,6 +1249,12 @@ 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 transform.coroutine_kind.is_async_desugaring() { + transform_async_context(tcx, body); + } + if let Some(dumper) = MirDumper::new(tcx, "coroutine_resume", body) { dumper.dump_mir(body); } @@ -1361,13 +1302,13 @@ fn create_cases<'tcx>( } } + // Move the resume argument to the destination place of the `Yield` terminator if operation == Operation::Resume && point.resume_arg != CTX_ARG.into() { - // Move the resume argument to the destination place of the `Yield` terminator statements.push(Statement::new( source_info, StatementKind::Assign(Box::new(( point.resume_arg, - Rvalue::Use(Operand::Move(CTX_ARG.into()), WithRetag::Yes), + Rvalue::Use(Operand::Copy(CTX_ARG.into()), WithRetag::Yes), ))), )); } @@ -1519,18 +1460,11 @@ 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 has_async_drops = coroutine_kind.is_async_desugaring() + && has_expandable_async_drops(tcx, body, coroutine_ty); - // 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 has_async_drops { + expand_async_drops(tcx, body, coroutine_kind, coroutine_ty); if let Some(dumper) = MirDumper::new(tcx, "coroutine_async_drop_expand", body) { dumper.dump_mir(body); @@ -1650,30 +1584,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, coroutine_kind); 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..44a3acfa9c1d8 100644 --- a/compiler/rustc_mir_transform/src/coroutine/drop.rs +++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs @@ -39,7 +39,8 @@ fn build_poll_call<'tcx>( switch_block: BasicBlock, fut_pin_place: &Place<'tcx>, fut_ty: Ty<'tcx>, - context_ref_place: &Place<'tcx>, + // This local has type `ResumeTy`. + resume_local: Local, unwind: UnwindAction, ) -> BasicBlock { let poll_fn = tcx.require_lang_item(LangItem::FuturePoll, DUMMY_SP); @@ -49,11 +50,15 @@ fn build_poll_call<'tcx>( user_ty: None, const_: Const::zero_sized(poll_fn), })); + let context_ref_place = tcx.mk_place_elem( + resume_local.into(), + PlaceElem::UnwrapUnsafeBinder(Ty::new_task_context(tcx)), + ); let call = TerminatorKind::Call { func: poll_fn.clone(), args: [ dummy_spanned(Operand::Move(*fut_pin_place)), - dummy_spanned(Operand::Move(*context_ref_place)), + dummy_spanned(Operand::Move(context_ref_place)), ] .into(), destination: *poll_unit_place, @@ -255,10 +260,10 @@ pub(super) fn has_expandable_async_drops<'tcx>( 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 resume_ty = Ty::new_resume_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>| { @@ -326,12 +331,13 @@ pub(super) fn expand_async_drops<'tcx>( 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); + let resume_local = body.local_decls.push(LocalDecl::new(resume_ty, source_info.span)); body[bb].statements.push(Statement::new( source_info, - StatementKind::Assign(Box::new((context_ref_place, arg))), + StatementKind::Assign(Box::new(( + resume_local.into(), + Rvalue::Use(Operand::Move(CTX_ARG.into()), WithRetag::Yes), + ))), )); let yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield let (pin_bb, fut_pin_place) = @@ -352,19 +358,17 @@ pub(super) fn expand_async_drops<'tcx>( switch_block, &fut_pin_place, fut_ty, - &context_ref_place, + resume_local, 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_resume_local: 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 resume_local2 = body.local_decls.push(LocalDecl::new(resume_ty, 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); @@ -384,12 +388,12 @@ pub(super) fn expand_async_drops<'tcx>( drop_switch_block, &fut_pin_place2, fut_ty, - &context_ref_place2, + resume_local2, unwind, ); dropline_transition_bb = Some(pin_bb2); dropline_yield_bb = Some(drop_yield_block); - dropline_context_ref = Some(context_ref_place2); + dropline_resume_local = Some(resume_local2); dropline_call_bb = Some(drop_call_bb); } @@ -428,20 +432,20 @@ pub(super) fn expand_async_drops<'tcx>( body[yield_block].terminator_mut().kind = TerminatorKind::Yield { value: value.clone(), resume: panic_bb, - resume_arg: context_ref_place, + resume_arg: resume_local.into(), drop: Some(pin_bb), }; } else { body[yield_block].terminator_mut().kind = TerminatorKind::Yield { value: value.clone(), resume: pin_bb, - resume_arg: context_ref_place, + resume_arg: resume_local.into(), drop: dropline_transition_bb, }; body[dropline_yield_bb.unwrap()].terminator_mut().kind = TerminatorKind::Yield { value, resume: panic_bb, - resume_arg: dropline_context_ref.unwrap(), + resume_arg: dropline_resume_local.unwrap().into(), drop: dropline_transition_bb, }; } @@ -600,6 +604,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 +710,12 @@ 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 transform.coroutine_kind.is_async_desugaring() { + transform_async_context(tcx, &mut body); + } + if let Some(dumper) = MirDumper::new(tcx, "coroutine_drop_async", &body) { dumper.dump_mir(&body); } @@ -715,6 +728,7 @@ pub(super) fn create_coroutine_drop_shim_async<'tcx>( pub(super) fn create_coroutine_drop_shim_proxy_async<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, + coroutine_kind: CoroutineKind, ) -> Body<'tcx> { let mut body = body.clone(); // Take the coroutine info out of the body, since the drop shim is @@ -750,6 +764,12 @@ pub(super) fn create_coroutine_drop_shim_proxy_async<'tcx>( }; 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 coroutine_kind.is_async_desugaring() { + transform_async_context(tcx, &mut body); + } + if let Some(dumper) = MirDumper::new(tcx, "coroutine_drop_proxy_async", &body) { dumper.dump_mir(&body); } 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..abdcb92ec3f40 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -64,8 +64,7 @@ pub(super) fn build_async_drop_shim<'tcx>( let needs_async_drop = drop_ty.needs_async_drop(tcx, typing_env); let needs_sync_drop = !needs_async_drop && drop_ty.needs_drop(tcx, typing_env); - let resume_adt = tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, DUMMY_SP)); - let resume_ty = Ty::new_adt(tcx, resume_adt, ty::List::empty()); + let resume_ty = Ty::new_resume_ty(tcx); let fn_sig = ty::Binder::dummy(tcx.mk_fn_sig_safe_rust_abi([ty, resume_ty], tcx.types.unit)); let sig = tcx.instantiate_bound_regions_with_erased(fn_sig); diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 815b94dc510e8..5ef336ff1ac86 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -874,7 +874,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let ty::UnsafeBinder(binder_ty) = *binder_ty.ty.kind() else { self.fail( location, - format!("WrapUnsafeBinder does not produce a ty::UnsafeBinder"), + format!("WrapUnsafeBinder does not produce a ty::UnsafeBinder, found {binder_ty:?}"), ); return; }; @@ -1434,7 +1434,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let ty::UnsafeBinder(binder_ty) = *ty.kind() else { self.fail( location, - format!("WrapUnsafeBinder does not produce a ty::UnsafeBinder"), + format!( + "WrapUnsafeBinder does not produce a ty::UnsafeBinder, found {ty:?}" + ), ); return; }; diff --git a/compiler/rustc_public/src/mir/body.rs b/compiler/rustc_public/src/mir/body.rs index f9b5f9af951e5..c6d5af49525e4 100644 --- a/compiler/rustc_public/src/mir/body.rs +++ b/compiler/rustc_public/src/mir/body.rs @@ -534,6 +534,9 @@ pub enum Rvalue { /// deref operation, immediately followed by one or more projections. CopyForDeref(Place), + /// Wraps a value in an unsafe binder. + WrapUnsafeBinder(Operand, Ty), + /// Computes the discriminant of the place, returning it as an integer. /// Returns zero for types without discriminant. /// @@ -650,6 +653,7 @@ impl Rvalue { AggregateKind::RawPtr(ty, mutability) => Ok(Ty::new_ptr(ty, mutability)), }, Rvalue::CopyForDeref(place) => place.ty(locals), + Rvalue::WrapUnsafeBinder(_, ty) => Ok(*ty), } } } @@ -835,6 +839,10 @@ pub enum ProjectionElem { /// Like an explicit cast from an opaque type to a concrete type, but without /// requiring an intermediate variable. OpaqueCast(Ty), + + /// A transmute from an unsafe binder to the type that it wraps. This is a projection + /// of a place, so it doesn't necessarily constitute a move out of the binder. + UnwrapUnsafeBinder(Ty), } #[derive(Clone, Debug, Eq, PartialEq, Serialize)] @@ -1069,6 +1077,7 @@ impl ProjectionElem { } ProjectionElem::Downcast(_) => Ok(ty), ProjectionElem::OpaqueCast(ty) => Ok(*ty), + ProjectionElem::UnwrapUnsafeBinder(ty) => Ok(*ty), } } diff --git a/compiler/rustc_public/src/mir/pretty.rs b/compiler/rustc_public/src/mir/pretty.rs index dec4044fd260b..c69853572a684 100644 --- a/compiler/rustc_public/src/mir/pretty.rs +++ b/compiler/rustc_public/src/mir/pretty.rs @@ -364,6 +364,9 @@ fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { Rvalue::CopyForDeref(deref) => { write!(writer, "CopyForDeref({deref:?})") } + Rvalue::WrapUnsafeBinder(operand, ty) => { + write!(writer, "wrap_binder!({operand:?}; {ty:?})") + } Rvalue::Discriminant(place) => { write!(writer, "discriminant({place:?})") } diff --git a/compiler/rustc_public/src/mir/visit.rs b/compiler/rustc_public/src/mir/visit.rs index 5a3afc9937351..c6b297b4ca2cb 100644 --- a/compiler/rustc_public/src/mir/visit.rs +++ b/compiler/rustc_public/src/mir/visit.rs @@ -267,6 +267,10 @@ macro_rules! make_mir_visitor { Rvalue::CopyForDeref(place) | Rvalue::Discriminant(place) | Rvalue::Len(place) => { self.visit_place(place, PlaceContext::NON_MUTATING, location); } + Rvalue::WrapUnsafeBinder(operand, ty) => { + self.visit_operand(operand, location); + self.visit_ty(ty, location); + } Rvalue::Ref(region, kind, place) => { self.visit_region(region, location); let pcx = PlaceContext { is_mut: matches!(kind, BorrowKind::Mut { .. }) }; @@ -468,6 +472,7 @@ macro_rules! visit_place_fns { ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {} ProjectionElem::Downcast(_idx) => {} ProjectionElem::OpaqueCast(ty) => self.visit_ty(ty, location), + ProjectionElem::UnwrapUnsafeBinder(ty) => self.visit_ty(ty, location), } } }; @@ -508,6 +513,7 @@ macro_rules! visit_place_fns { ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {} ProjectionElem::Downcast(_idx) => {} ProjectionElem::OpaqueCast(ty) => self.visit_ty(ty, location), + ProjectionElem::UnwrapUnsafeBinder(ty) => self.visit_ty(ty, location), } } }; diff --git a/compiler/rustc_public/src/ty.rs b/compiler/rustc_public/src/ty.rs index f71ca7213e9ed..22e89eab45088 100644 --- a/compiler/rustc_public/src/ty.rs +++ b/compiler/rustc_public/src/ty.rs @@ -561,6 +561,7 @@ pub enum RigidTy { Ref(Region, Ty, Mutability), FnDef(FnDef, GenericArgs), FnPtr(PolyFnSig), + UnsafeBinder(Binder), Closure(ClosureDef, GenericArgs), Coroutine(CoroutineDef, GenericArgs), CoroutineClosure(CoroutineClosureDef, GenericArgs), diff --git a/compiler/rustc_public/src/unstable/convert/internal.rs b/compiler/rustc_public/src/unstable/convert/internal.rs index 37f00da9f7103..d90d4a3df7b6a 100644 --- a/compiler/rustc_public/src/unstable/convert/internal.rs +++ b/compiler/rustc_public/src/unstable/convert/internal.rs @@ -178,6 +178,9 @@ impl RustcInternal for RigidTy { let (sig_tys, hdr) = sig.internal(tables, tcx).split(); rustc_ty::TyKind::FnPtr(sig_tys, hdr) } + RigidTy::UnsafeBinder(binder) => { + rustc_ty::TyKind::UnsafeBinder(binder.internal(tables, tcx).into()) + } RigidTy::Closure(def, args) => { rustc_ty::TyKind::Closure(def.0.internal(tables, tcx), args.internal(tables, tcx)) } @@ -737,6 +740,9 @@ impl RustcInternal for ProjectionElem { ProjectionElem::OpaqueCast(ty) => { rustc_middle::mir::PlaceElem::OpaqueCast(ty.internal(tables, tcx)) } + ProjectionElem::UnwrapUnsafeBinder(ty) => { + rustc_middle::mir::PlaceElem::UnwrapUnsafeBinder(ty.internal(tables, tcx)) + } } } } diff --git a/compiler/rustc_public/src/unstable/convert/stable/mir.rs b/compiler/rustc_public/src/unstable/convert/stable/mir.rs index 7e76d5a91ac66..5af9238fe8c6b 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/mir.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/mir.rs @@ -245,7 +245,10 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { crate::mir::Rvalue::Aggregate(agg_kind.stable(tables, cx), operands) } CopyForDeref(place) => crate::mir::Rvalue::CopyForDeref(place.stable(tables, cx)), - WrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"), + WrapUnsafeBinder(operand, ty) => crate::mir::Rvalue::WrapUnsafeBinder( + operand.stable(tables, cx), + ty.stable(tables, cx), + ), } } } @@ -446,7 +449,9 @@ impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> { // found at https://github.com/rust-lang/rust/pull/117517#issuecomment-1811683486 Downcast(_, idx) => crate::mir::ProjectionElem::Downcast(idx.stable(tables, cx)), OpaqueCast(ty) => crate::mir::ProjectionElem::OpaqueCast(ty.stable(tables, cx)), - UnwrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"), + UnwrapUnsafeBinder(ty) => { + crate::mir::ProjectionElem::UnwrapUnsafeBinder(ty.stable(tables, cx)) + } } } } diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index c4f1da14da23e..41c913ec41688 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -453,8 +453,9 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { ty::FnPtr(sig_tys, hdr) => { TyKind::RigidTy(RigidTy::FnPtr(sig_tys.with(*hdr).stable(tables, cx))) } - // FIXME(unsafe_binders): - ty::UnsafeBinder(_) => todo!(), + ty::UnsafeBinder(binder) => { + TyKind::RigidTy(RigidTy::UnsafeBinder(binder.stable(tables, cx))) + } ty::Dynamic(existential_predicates, region) => TyKind::RigidTy(RigidTy::Dynamic( existential_predicates .iter() diff --git a/compiler/rustc_public/src/visitor.rs b/compiler/rustc_public/src/visitor.rs index acc3334769613..fe2e11bf97668 100644 --- a/compiler/rustc_public/src/visitor.rs +++ b/compiler/rustc_public/src/visitor.rs @@ -171,6 +171,7 @@ impl Visitable for RigidTy { | RigidTy::CoroutineClosure(_, args) | RigidTy::FnDef(_, args) => args.visit(visitor), RigidTy::FnPtr(sig) => sig.visit(visitor), + RigidTy::UnsafeBinder(binder) => binder.visit(visitor), RigidTy::Dynamic(pred, r) => { pred.visit(visitor)?; r.visit(visitor) diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 02739ef6a4135..fb0bfec099ec2 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -155,16 +155,11 @@ fn fn_sig_for_fn_abi<'tcx>( // with `&mut Context<'_>` which is used in codegen. #[cfg(debug_assertions)] { - if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() { - let expected_adt = - tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, DUMMY_SP)); - assert_eq!(*resume_ty_adt, expected_adt); - } else { - panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty); - }; + let resume_ty = Ty::new_resume_ty(tcx); + assert_eq!(resume_ty, sig.resume_ty); } - let context_mut_ref = Ty::new_task_context(tcx); + let context_mut_ref = Ty::new_task_context(tcx); (Some(context_mut_ref), ret_ty) } hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) => { @@ -191,16 +186,11 @@ fn fn_sig_for_fn_abi<'tcx>( // with `&mut Context<'_>` which is used in codegen. #[cfg(debug_assertions)] { - if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() { - let expected_adt = - tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, DUMMY_SP)); - assert_eq!(*resume_ty_adt, expected_adt); - } else { - panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty); - }; + let resume_ty = Ty::new_resume_ty(tcx); + assert_eq!(resume_ty, sig.resume_ty); } - let context_mut_ref = Ty::new_task_context(tcx); + let context_mut_ref = Ty::new_task_context(tcx); (Some(context_mut_ref), ret_ty) } hir::CoroutineKind::Coroutine(_) => { diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index 2b16a568b4031..ebc6e376477e6 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -9,7 +9,6 @@ //! [`await`]: ../../std/keyword.await.html //! [async book]: https://rust-lang.github.io/async-book/ -use crate::ptr::NonNull; use crate::task::Context; mod async_drop; @@ -47,22 +46,10 @@ pub use self::join::join; #[lang = "ResumeTy"] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "none")] -#[derive(Debug, Copy, Clone)] -pub struct ResumeTy(NonNull>); +pub type ResumeTy = unsafe<'a, 'b> &'a mut Context<'b>; #[unstable(feature = "gen_future", issue = "none")] unsafe impl Send for ResumeTy {} #[unstable(feature = "gen_future", issue = "none")] unsafe impl Sync for ResumeTy {} - -#[lang = "get_context"] -#[doc(hidden)] -#[unstable(feature = "gen_future", issue = "none")] -#[must_use] -#[inline] -pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { - // SAFETY: the caller must guarantee that `cx.0` is a valid pointer - // that fulfills all the requirements for a mutable reference. - unsafe { &mut *cx.0.as_ptr().cast() } -} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 3e18f87e20537..40d3c327bfb15 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -172,6 +172,7 @@ #![feature(try_blocks)] #![feature(uint_carryless_mul)] #![feature(unboxed_closures)] +#![feature(unsafe_binders)] #![feature(unsized_fn_params)] #![feature(with_negative_coherence)] // tidy-alphabetical-end 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/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir index 4c9ca11f82834..7065f87d66d87 100644 --- a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir @@ -1,6 +1,6 @@ // MIR for `foo::{closure#0}::{closure#0}` after built -fn foo::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: std::future::ResumeTy) -> () +fn foo::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: unsafe<'a, 'b> &'a mut Context<'b>) -> () yields () { debug _task_context => _2; 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/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir index e80fdea7051dc..30d7ea567e757 100644 --- a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir @@ -1,6 +1,6 @@ // MIR for `foo::{closure#0}::{synthetic#0}` after built -fn foo::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: std::future::ResumeTy) -> () +fn foo::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: unsafe<'a, 'b> &'a mut Context<'b>) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir index 075065b4c0903..1e6099604cac8 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}::{closure#0}::{closure#0}` after built -fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: std::future::ResumeTy) -> () +fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: unsafe<'a, 'b> &'a mut std::task::Context<'b>) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir index 0f4e5f3cb02f7..272765819257a 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}::{closure#0}::{synthetic#0}` after built -fn main::{closure#0}::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: std::future::ResumeTy) -> () +fn main::{closure#0}::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: unsafe<'a, 'b> &'a mut std::task::Context<'b>) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir index 18f4e741384f2..efd569b00abea 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}::{closure#1}::{closure#0}` after built -fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: std::future::ResumeTy) -> () +fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: unsafe<'a, 'b> &'a mut std::task::Context<'b>) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir index 257586c4a0808..0a3b5255373fd 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}::{closure#1}::{synthetic#0}` after built -fn main::{closure#0}::{closure#1}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: std::future::ResumeTy) -> () +fn main::{closure#0}::{closure#1}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: unsafe<'a, 'b> &'a mut std::task::Context<'b>) -> () yields () { debug _task_context => _2; 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 index 0a1cab37427c8..09a6921a3e474 100644 --- 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 @@ -1,7 +1,7 @@ // 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 _task_context => _20; debug x => ((*_19).0: T); let mut _0: std::task::Poll<()>; let _3: T; @@ -10,22 +10,24 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) 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 _9: unsafe<'a, 'b> &'a mut std::task::Context<'b>; 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 _13: unsafe<'a, 'b> &'a mut std::task::Context<'b>; 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()}; + let mut _20: unsafe<'a, 'b> &'a mut std::task::Context<'b>; scope 1 { debug x => (((*_19) as variant#4).0: T); } bb0: { + _20 = wrap_binder!(move _2; unsafe<'a, 'b> &'a mut std::task::Context<'b>); _19 = copy (_1.0: &mut {async fn body of a()}); _18 = discriminant((*_19)); switchInt(move _18) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14]; @@ -65,7 +67,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) } bb7: { - _8 = as Future>::poll(move _15, move _13) -> [return: bb6, unwind unreachable]; + _8 = as Future>::poll(move _15, move unwrap_binder!(_13; &mut Context<'_>)) -> [return: bb6, unwind unreachable]; } bb8: { 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 index 62fbf10356558..2ac822c2bbf43 100644 --- 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 @@ -1,7 +1,7 @@ // 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 _task_context => _20; debug x => ((*_19).0: T); let mut _0: std::task::Poll<()>; let _3: T; @@ -10,22 +10,24 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) 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 _9: unsafe<'a, 'b> &'a mut std::task::Context<'b>; 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 _13: unsafe<'a, 'b> &'a mut std::task::Context<'b>; 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()}; + let mut _20: unsafe<'a, 'b> &'a mut std::task::Context<'b>; scope 1 { debug x => (((*_19) as variant#4).0: T); } bb0: { + _20 = wrap_binder!(move _2; unsafe<'a, 'b> &'a mut std::task::Context<'b>); _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]; @@ -79,7 +81,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) } bb10: { - _8 = as Future>::poll(move _15, move _13) -> [return: bb9, unwind: bb3]; + _8 = as Future>::poll(move _15, move unwrap_binder!(_13; &mut Context<'_>)) -> [return: bb9, unwind: bb3]; } bb11: { 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 index d83a51141bd40..42250a1673496 100644 --- 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 @@ -1,6 +1,6 @@ // 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) -> () +fn async_drop_in_place::{closure#0}(_1: {async fn body of async_drop_in_place<[Foo; 1]>()}, _2: unsafe<'a, 'b> &'a mut Context<'b>) -> () yields () { let mut _0: (); 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..3fa89ef87351f 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 @@ -10,13 +10,15 @@ } */ fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { - debug _task_context => _2; + debug _task_context => _6; let mut _0: std::task::Poll<()>; let mut _3: (); let mut _4: u32; let mut _5: &mut {async fn body of a()}; + let mut _6: unsafe<'a, 'b> &'a mut std::task::Context<'b>; bb0: { + _6 = wrap_binder!(move _2; unsafe<'a, 'b> &'a mut std::task::Context<'b>); _5 = copy (_1.0: &mut {async fn body of a()}); _4 = discriminant((*_5)); switchInt(move _4) -> [0: bb1, 1: bb4, otherwise: bb5]; 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..e814ec272b73b 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 @@ -6,7 +6,7 @@ DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), [ (), - std::future::ResumeTy, + Binder { value: &'^0 mut std::task::Context<'^1>, bound_vars: [Region(BrAnon), Region(BrAnon)] }, (), (), (), @@ -23,7 +23,7 @@ DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), [ (), - std::future::ResumeTy, + Binder { value: &'^0 mut std::task::Context<'^1>, bound_vars: [Region(BrAnon), Region(BrAnon)] }, (), (), (), @@ -50,7 +50,7 @@ } */ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> { - debug _task_context => _2; + debug _task_context => _38; let mut _0: std::task::Poll<()>; let _3: (); let mut _4: {async fn body of a()}; @@ -63,49 +63,49 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> let mut _11: &mut {async fn body of a()}; let mut _12: &mut {async fn body of a()}; let mut _13: &mut std::task::Context<'_>; - let mut _14: &mut std::task::Context<'_>; - let mut _15: &mut std::task::Context<'_>; - let mut _16: isize; - let mut _18: !; - let mut _19: &mut std::task::Context<'_>; - let mut _20: (); + let mut _14: isize; + let mut _16: !; + let mut _17: unsafe<'a, 'b> &'a mut std::task::Context<'b>; + let mut _18: (); + let mut _19: {async fn body of a()}; + let mut _20: {async fn body of a()}; let mut _21: {async fn body of a()}; - let mut _22: {async fn body of a()}; - let mut _23: {async fn body of a()}; - let _24: (); - let mut _25: std::task::Poll<()>; - let mut _26: std::pin::Pin<&mut {async fn body of a()}>; - let mut _27: &mut {async fn body of a()}; - let mut _28: &mut {async fn body of a()}; - let mut _29: &mut std::task::Context<'_>; - let mut _30: &mut std::task::Context<'_>; - let mut _31: &mut std::task::Context<'_>; - let mut _32: isize; - let mut _34: !; - let mut _35: &mut std::task::Context<'_>; - let mut _36: (); - let mut _37: (); - let mut _38: u32; - let mut _39: &mut {async fn body of b()}; + let _22: (); + let mut _23: std::task::Poll<()>; + let mut _24: std::pin::Pin<&mut {async fn body of a()}>; + let mut _25: &mut {async fn body of a()}; + let mut _26: &mut {async fn body of a()}; + let mut _27: &mut std::task::Context<'_>; + let mut _28: isize; + let mut _30: !; + let mut _31: unsafe<'a, 'b> &'a mut std::task::Context<'b>; + let mut _32: (); + let mut _33: &mut std::task::Context<'_>; + let mut _34: &mut std::task::Context<'_>; + let mut _35: (); + let mut _36: u32; + let mut _37: &mut {async fn body of b()}; + let mut _38: unsafe<'a, 'b> &'a mut std::task::Context<'b>; scope 1 { - debug __awaitee => (((*_39) as variant#3).0: {async fn body of a()}); - let _17: (); + debug __awaitee => (((*_37) as variant#3).0: {async fn body of a()}); + let _15: (); scope 2 { - debug result => _17; + debug result => _15; } } scope 3 { - debug __awaitee => (((*_39) as variant#4).0: {async fn body of a()}); - let _33: (); + debug __awaitee => (((*_37) as variant#4).0: {async fn body of a()}); + let _29: (); scope 4 { - debug result => _33; + debug result => _29; } } bb0: { - _39 = copy (_1.0: &mut {async fn body of b()}); - _38 = discriminant((*_39)); - switchInt(move _38) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb8]; + _38 = wrap_binder!(move _2; unsafe<'a, 'b> &'a mut std::task::Context<'b>); + _37 = copy (_1.0: &mut {async fn body of b()}); + _36 = discriminant((*_37)); + switchInt(move _36) -> [0: bb1, 1: bb27, 3: bb25, 4: bb26, otherwise: bb7]; } bb1: { @@ -123,7 +123,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageDead(_5); PlaceMention(_4); nop; - (((*_39) as variant#3).0: {async fn body of a()}) = move _4; + (((*_37) as variant#3).0: {async fn body of a()}) = move _4; goto -> bb4; } @@ -133,7 +133,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> StorageLive(_10); StorageLive(_11); StorageLive(_12); - _12 = &mut (((*_39) as variant#3).0: {async fn body of a()}); + _12 = &mut (((*_37) as variant#3).0: {async fn body of a()}); _11 = &mut (*_12); _10 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _11) -> [return: bb5, unwind unreachable]; } @@ -141,204 +141,184 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> bb5: { StorageDead(_11); StorageLive(_13); - StorageLive(_14); - StorageLive(_15); - _15 = copy _2; - _14 = move _15; - goto -> bb6; + _33 = no_retag copy unwrap_binder!(_38; &mut Context<'_>); + _13 = &mut (*_33); + _9 = <{async fn body of a()} as Future>::poll(move _10, move _13) -> [return: bb6, unwind unreachable]; } bb6: { - _13 = &mut (*_14); - StorageDead(_15); - _9 = <{async fn body of a()} as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable]; - } - - bb7: { StorageDead(_13); StorageDead(_10); PlaceMention(_9); - _16 = discriminant(_9); - switchInt(move _16) -> [0: bb10, 1: bb9, otherwise: bb8]; + _14 = discriminant(_9); + switchInt(move _14) -> [0: bb9, 1: bb8, otherwise: bb7]; } - bb8: { + bb7: { unreachable; } - bb9: { + bb8: { _8 = const (); - StorageDead(_14); StorageDead(_12); StorageDead(_9); StorageDead(_8); - StorageLive(_19); - StorageLive(_20); - _20 = (); + StorageLive(_17); + StorageLive(_18); + _18 = (); _0 = Poll::<()>::Pending; StorageDead(_3); StorageDead(_4); - StorageDead(_19); - StorageDead(_20); - discriminant((*_39)) = 3; + StorageDead(_17); + StorageDead(_18); + discriminant((*_37)) = 3; return; } - bb10: { - StorageLive(_17); - _17 = copy ((_9 as Ready).0: ()); - _3 = copy _17; - StorageDead(_17); - StorageDead(_14); + bb9: { + StorageLive(_15); + _15 = copy ((_9 as Ready).0: ()); + _3 = copy _15; + StorageDead(_15); StorageDead(_12); StorageDead(_9); StorageDead(_8); - drop((((*_39) as variant#3).0: {async fn body of a()})) -> [return: bb12, unwind unreachable]; + drop((((*_37) as variant#3).0: {async fn body of a()})) -> [return: bb11, unwind unreachable]; } - bb11: { - StorageDead(_20); - _2 = move _19; - StorageDead(_19); + bb10: { + StorageDead(_18); + _38 = move _17; + StorageDead(_17); _7 = const (); goto -> bb4; } - bb12: { + bb11: { nop; - goto -> bb13; + goto -> bb12; } - bb13: { + bb12: { StorageDead(_4); StorageDead(_3); - StorageLive(_21); - StorageLive(_22); - _22 = a() -> [return: bb14, unwind unreachable]; + StorageLive(_19); + StorageLive(_20); + _20 = a() -> [return: bb13, unwind unreachable]; } - bb14: { - _21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable]; + bb13: { + _19 = <{async fn body of a()} as IntoFuture>::into_future(move _20) -> [return: bb14, unwind unreachable]; } - bb15: { - StorageDead(_22); - PlaceMention(_21); + bb14: { + StorageDead(_20); + PlaceMention(_19); nop; - (((*_39) as variant#4).0: {async fn body of a()}) = move _21; - goto -> bb16; + (((*_37) as variant#4).0: {async fn body of a()}) = move _19; + goto -> bb15; } - bb16: { + bb15: { + StorageLive(_22); + StorageLive(_23); StorageLive(_24); StorageLive(_25); StorageLive(_26); + _26 = &mut (((*_37) as variant#4).0: {async fn body of a()}); + _25 = &mut (*_26); + _24 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _25) -> [return: bb16, unwind unreachable]; + } + + bb16: { + StorageDead(_25); StorageLive(_27); - StorageLive(_28); - _28 = &mut (((*_39) as variant#4).0: {async fn body of a()}); - _27 = &mut (*_28); - _26 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _27) -> [return: bb17, unwind unreachable]; + _34 = no_retag copy unwrap_binder!(_38; &mut Context<'_>); + _27 = &mut (*_34); + _23 = <{async fn body of a()} as Future>::poll(move _24, move _27) -> [return: bb17, unwind unreachable]; } bb17: { StorageDead(_27); - StorageLive(_29); - StorageLive(_30); - StorageLive(_31); - _31 = copy _2; - _30 = move _31; - goto -> bb18; + StorageDead(_24); + PlaceMention(_23); + _28 = discriminant(_23); + switchInt(move _28) -> [0: bb19, 1: bb18, otherwise: bb7]; } bb18: { - _29 = &mut (*_30); + _22 = const (); + StorageDead(_26); + StorageDead(_23); + StorageDead(_22); + StorageLive(_31); + StorageLive(_32); + _32 = (); + _0 = Poll::<()>::Pending; + StorageDead(_19); StorageDead(_31); - _25 = <{async fn body of a()} as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable]; + StorageDead(_32); + discriminant((*_37)) = 4; + return; } bb19: { + StorageLive(_29); + _29 = copy ((_23 as Ready).0: ()); + _35 = copy _29; StorageDead(_29); StorageDead(_26); - PlaceMention(_25); - _32 = discriminant(_25); - switchInt(move _32) -> [0: bb21, 1: bb20, otherwise: bb8]; + StorageDead(_23); + StorageDead(_22); + drop((((*_37) as variant#4).0: {async fn body of a()})) -> [return: bb21, unwind unreachable]; } bb20: { - _24 = const (); - StorageDead(_30); - StorageDead(_28); - StorageDead(_25); - StorageDead(_24); - StorageLive(_35); - StorageLive(_36); - _36 = (); - _0 = Poll::<()>::Pending; - StorageDead(_21); - StorageDead(_35); - StorageDead(_36); - discriminant((*_39)) = 4; - return; + StorageDead(_32); + _38 = move _31; + StorageDead(_31); + _7 = const (); + goto -> bb15; } bb21: { - StorageLive(_33); - _33 = copy ((_25 as Ready).0: ()); - _37 = copy _33; - StorageDead(_33); - StorageDead(_30); - StorageDead(_28); - StorageDead(_25); - StorageDead(_24); - drop((((*_39) as variant#4).0: {async fn body of a()})) -> [return: bb23, unwind unreachable]; + nop; + goto -> bb22; } bb22: { - StorageDead(_36); - _2 = move _35; - StorageDead(_35); - _7 = const (); - goto -> bb16; + StorageDead(_19); + goto -> bb24; } bb23: { - nop; - goto -> bb24; + _0 = Poll::<()>::Ready(move _35); + discriminant((*_37)) = 1; + return; } bb24: { - StorageDead(_21); - goto -> bb26; + goto -> bb23; } bb25: { - _0 = Poll::<()>::Ready(move _37); - discriminant((*_39)) = 1; - return; - } - - bb26: { - goto -> bb25; - } - - bb27: { StorageLive(_3); StorageLive(_4); - StorageLive(_19); - StorageLive(_20); - _19 = move _2; - goto -> bb11; + StorageLive(_17); + StorageLive(_18); + _17 = copy _38; + goto -> bb10; } - bb28: { - StorageLive(_21); - StorageLive(_35); - StorageLive(_36); - _35 = move _2; - goto -> bb22; + bb26: { + StorageLive(_19); + StorageLive(_31); + StorageLive(_32); + _31 = copy _38; + goto -> bb20; } - bb29: { - assert(const false, "`async fn` resumed after completion") -> [success: bb29, unwind unreachable]; + bb27: { + assert(const false, "`async fn` resumed after completion") -> [success: bb27, unwind unreachable]; } } 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..518f4f6b16de6 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 @@ -162,7 +162,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 bb17: { StorageLive(_3); StorageLive(_4); - _3 = move _2; + _3 = copy _2; goto -> bb5; } @@ -171,7 +171,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2 StorageLive(_9); StorageLive(_11); StorageLive(_15); - _8 = move _2; + _8 = copy _2; goto -> bb11; } 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..d4c98979c0065 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 @@ -162,7 +162,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 bb17: { StorageLive(_3); StorageLive(_4); - _3 = move _2; + _3 = copy _2; goto -> bb5; } @@ -171,7 +171,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2 StorageLive(_9); StorageLive(_11); StorageLive(_15); - _8 = move _2; + _8 = copy _2; goto -> bb11; } diff --git a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir index 222c7144ef07d..1429fdd007865 100644 --- a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir @@ -79,7 +79,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13} StorageLive(_4); StorageLive(_6); StorageLive(_7); - _6 = move _2; + _6 = copy _2; goto -> bb3; } diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index f8ef70bd6c9ce..9394e320f01bb 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -32,19 +32,19 @@ + let mut _20: &mut std::future::Ready<()>; + let mut _21: &mut std::future::Ready<()>; + let mut _22: &mut std::task::Context<'_>; -+ let mut _23: &mut std::task::Context<'_>; -+ let mut _24: &mut std::task::Context<'_>; -+ let mut _25: isize; -+ let mut _27: !; ++ let mut _23: isize; ++ let mut _25: !; ++ let mut _26: unsafe<'a, 'b> &'a mut std::task::Context<'b>; ++ let mut _27: (); + let mut _28: &mut std::task::Context<'_>; + let mut _29: (); -+ let mut _30: (); -+ let mut _31: u32; -+ let mut _32: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _30: u32; ++ let mut _31: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _32: unsafe<'a, 'b> &'a mut std::task::Context<'b>; + scope 7 { + let mut _15: std::future::Ready<()>; + scope 8 { -+ let _26: (); ++ let _24: (); + scope 9 { + } + scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { @@ -121,13 +121,16 @@ _9 = &mut (*_10); - _7 = <{async fn body of ActionPermit<'_, T>::perform()} as Future>::poll(move _8, move _9) -> [return: bb3, unwind unreachable]; + StorageLive(_16); -+ StorageLive(_25); ++ StorageLive(_23); ++ StorageLive(_28); ++ StorageLive(_29); + StorageLive(_30); + StorageLive(_31); + StorageLive(_32); -+ _32 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ _31 = discriminant((*_32)); -+ switchInt(move _31) -> [0: bb3, 1: bb10, 3: bb9, otherwise: bb5]; ++ _32 = wrap_binder!(move _9; unsafe<'a, 'b> &'a mut std::task::Context<'b>); ++ _31 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); ++ _30 = discriminant((*_31)); ++ switchInt(move _30) -> [0: bb3, 1: bb10, 3: bb9, otherwise: bb5]; } - bb3: { @@ -140,7 +143,9 @@ + StorageDead(_32); + StorageDead(_31); + StorageDead(_30); -+ StorageDead(_25); ++ StorageDead(_29); ++ StorageDead(_28); ++ StorageDead(_23); + StorageDead(_16); StorageDead(_9); StorageDead(_8); @@ -154,7 +159,7 @@ } + bb3: { -+ (((*_32) as variant#3).0: ActionPermit<'_, T>) = move ((*_32).0: ActionPermit<'_, T>); ++ (((*_31) as variant#3).0: ActionPermit<'_, T>) = move ((*_31).0: ActionPermit<'_, T>); + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); @@ -166,7 +171,7 @@ + StorageDead(_14); + _12 = move _13; + StorageDead(_13); -+ (((*_32) as variant#3).1: std::future::Ready<()>) = move _12; ++ (((*_31) as variant#3).1: std::future::Ready<()>) = move _12; + goto -> bb4; + } + @@ -178,17 +183,13 @@ + StorageLive(_19); + StorageLive(_20); + StorageLive(_21); -+ _21 = &mut (((*_32) as variant#3).1: std::future::Ready<()>); ++ _21 = &mut (((*_31) as variant#3).1: std::future::Ready<()>); + _20 = &mut (*_21); + _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 }; + StorageDead(_20); + StorageLive(_22); -+ StorageLive(_23); -+ StorageLive(_24); -+ _24 = copy _9; -+ _23 = move _24; -+ _22 = &mut (*_23); -+ StorageDead(_24); ++ _28 = no_retag copy unwrap_binder!(_32; &mut Context<'_>); ++ _22 = &mut (*_28); + StorageLive(_37); + StorageLive(_39); + StorageLive(_44); @@ -215,48 +216,46 @@ + + bb6: { + _17 = const (); -+ StorageDead(_23); + StorageDead(_21); + StorageDead(_18); + StorageDead(_17); -+ StorageLive(_28); -+ StorageLive(_29); -+ _29 = (); ++ StorageLive(_26); ++ StorageLive(_27); ++ _27 = (); + _7 = Poll::<()>::Pending; + StorageDead(_12); -+ StorageDead(_28); -+ StorageDead(_29); -+ discriminant((*_32)) = 3; ++ StorageDead(_26); ++ StorageDead(_27); ++ discriminant((*_31)) = 3; + goto -> bb2; + } + + bb7: { -+ StorageLive(_26); -+ _26 = copy ((_18 as Ready).0: ()); -+ _30 = copy _26; -+ StorageDead(_26); -+ StorageDead(_23); ++ StorageLive(_24); ++ _24 = copy ((_18 as Ready).0: ()); ++ _29 = copy _24; ++ StorageDead(_24); + StorageDead(_21); + StorageDead(_18); + StorageDead(_17); + StorageDead(_12); -+ drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable]; ++ drop((((*_31) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable]; + } + + bb8: { -+ _7 = Poll::<()>::Ready(move _30); -+ discriminant((*_32)) = 1; ++ _7 = Poll::<()>::Ready(move _29); ++ discriminant((*_31)) = 1; + goto -> bb2; + } + + bb9: { + StorageLive(_12); -+ StorageLive(_28); -+ StorageLive(_29); -+ _28 = move _9; -+ StorageDead(_29); -+ _9 = move _28; -+ StorageDead(_28); ++ StorageLive(_26); ++ StorageLive(_27); ++ _26 = copy _32; ++ StorageDead(_27); ++ _32 = move _26; ++ StorageDead(_26); + _16 = const (); + goto -> bb4; + } @@ -280,8 +279,8 @@ + StorageDead(_37); + StorageDead(_22); + StorageDead(_19); -+ _25 = discriminant(_18); -+ switchInt(move _25) -> [0: bb7, 1: bb6, otherwise: bb5]; ++ _23 = discriminant(_18); ++ switchInt(move _23) -> [0: bb7, 1: bb6, otherwise: bb5]; + } + } + diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index 18be10c534ec4..ac70781798156 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -32,19 +32,19 @@ + let mut _20: &mut std::future::Ready<()>; + let mut _21: &mut std::future::Ready<()>; + let mut _22: &mut std::task::Context<'_>; -+ let mut _23: &mut std::task::Context<'_>; -+ let mut _24: &mut std::task::Context<'_>; -+ let mut _25: isize; -+ let mut _27: !; ++ let mut _23: isize; ++ let mut _25: !; ++ let mut _26: unsafe<'a, 'b> &'a mut std::task::Context<'b>; ++ let mut _27: (); + let mut _28: &mut std::task::Context<'_>; + let mut _29: (); -+ let mut _30: (); -+ let mut _31: u32; -+ let mut _32: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _30: u32; ++ let mut _31: &mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _32: unsafe<'a, 'b> &'a mut std::task::Context<'b>; + scope 7 { + let mut _15: std::future::Ready<()>; + scope 8 { -+ let _26: (); ++ let _24: (); + scope 9 { + } + scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { @@ -121,13 +121,16 @@ _9 = &mut (*_10); - _7 = <{async fn body of ActionPermit<'_, T>::perform()} as Future>::poll(move _8, move _9) -> [return: bb3, unwind: bb5]; + StorageLive(_16); -+ StorageLive(_25); ++ StorageLive(_23); ++ StorageLive(_28); ++ StorageLive(_29); + StorageLive(_30); + StorageLive(_31); + StorageLive(_32); -+ _32 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ _31 = discriminant((*_32)); -+ switchInt(move _31) -> [0: bb5, 1: bb15, 2: bb14, 3: bb13, otherwise: bb7]; ++ _32 = wrap_binder!(move _9; unsafe<'a, 'b> &'a mut std::task::Context<'b>); ++ _31 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); ++ _30 = discriminant((*_31)); ++ switchInt(move _30) -> [0: bb5, 1: bb15, 2: bb14, 3: bb13, otherwise: bb7]; } - bb3: { @@ -148,7 +151,9 @@ + StorageDead(_32); + StorageDead(_31); + StorageDead(_30); -+ StorageDead(_25); ++ StorageDead(_29); ++ StorageDead(_28); ++ StorageDead(_23); + StorageDead(_16); StorageDead(_9); StorageDead(_8); @@ -165,7 +170,7 @@ - StorageDead(_2); - return; + bb5: { -+ (((*_32) as variant#3).0: ActionPermit<'_, T>) = move ((*_32).0: ActionPermit<'_, T>); ++ (((*_31) as variant#3).0: ActionPermit<'_, T>) = move ((*_31).0: ActionPermit<'_, T>); + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); @@ -177,7 +182,7 @@ + StorageDead(_14); + _12 = move _13; + StorageDead(_13); -+ (((*_32) as variant#3).1: std::future::Ready<()>) = move _12; ++ (((*_31) as variant#3).1: std::future::Ready<()>) = move _12; + goto -> bb6; } @@ -189,17 +194,13 @@ + StorageLive(_19); + StorageLive(_20); + StorageLive(_21); -+ _21 = &mut (((*_32) as variant#3).1: std::future::Ready<()>); ++ _21 = &mut (((*_31) as variant#3).1: std::future::Ready<()>); + _20 = &mut (*_21); + _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 }; + StorageDead(_20); + StorageLive(_22); -+ StorageLive(_23); -+ StorageLive(_24); -+ _24 = copy _9; -+ _23 = move _24; -+ _22 = &mut (*_23); -+ StorageDead(_24); ++ _28 = no_retag copy unwrap_binder!(_32; &mut Context<'_>); ++ _22 = &mut (*_28); + StorageLive(_37); + StorageLive(_39); + StorageLive(_44); @@ -228,64 +229,61 @@ + + bb8: { + _17 = const (); -+ StorageDead(_23); + StorageDead(_21); + StorageDead(_18); + StorageDead(_17); -+ StorageLive(_28); -+ StorageLive(_29); -+ _29 = (); ++ StorageLive(_26); ++ StorageLive(_27); ++ _27 = (); + _7 = Poll::<()>::Pending; + StorageDead(_12); -+ StorageDead(_28); -+ StorageDead(_29); -+ discriminant((*_32)) = 3; ++ StorageDead(_26); ++ StorageDead(_27); ++ discriminant((*_31)) = 3; + goto -> bb4; + } + + bb9: { -+ StorageLive(_26); -+ _26 = copy ((_18 as Ready).0: ()); -+ _30 = copy _26; -+ StorageDead(_26); -+ StorageDead(_23); ++ StorageLive(_24); ++ _24 = copy ((_18 as Ready).0: ()); ++ _29 = copy _24; ++ StorageDead(_24); + StorageDead(_21); + StorageDead(_18); + StorageDead(_17); + StorageDead(_12); -+ drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12]; ++ drop((((*_31) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12]; + } + + bb10: { -+ _7 = Poll::<()>::Ready(move _30); -+ discriminant((*_32)) = 1; ++ _7 = Poll::<()>::Ready(move _29); ++ discriminant((*_31)) = 1; + goto -> bb4; + } + + bb11 (cleanup): { + StorageDead(_22); + StorageDead(_19); -+ StorageDead(_23); + StorageDead(_21); + StorageDead(_18); + StorageDead(_17); + StorageDead(_12); -+ drop((((*_32) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)]; ++ drop((((*_31) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)]; + } + + bb12 (cleanup): { -+ discriminant((*_32)) = 2; ++ discriminant((*_31)) = 2; + goto -> bb2; + } + + bb13: { + StorageLive(_12); -+ StorageLive(_28); -+ StorageLive(_29); -+ _28 = move _9; -+ StorageDead(_29); -+ _9 = move _28; -+ StorageDead(_28); ++ StorageLive(_26); ++ StorageLive(_27); ++ _26 = copy _32; ++ StorageDead(_27); ++ _32 = move _26; ++ StorageDead(_26); + _16 = const (); + goto -> bb6; + } @@ -313,8 +311,8 @@ + StorageDead(_37); + StorageDead(_22); + StorageDead(_19); -+ _25 = discriminant(_18); -+ switchInt(move _25) -> [0: bb9, 1: bb8, otherwise: bb7]; ++ _23 = discriminant(_18); ++ switchInt(move _23) -> [0: bb9, 1: bb8, otherwise: bb7]; + } + } + diff --git a/tests/ui/async-await/async-closures/def-path.rs b/tests/ui/async-await/async-closures/def-path.rs index 838556966e865..fd9f63e23ab9d 100644 --- a/tests/ui/async-await/async-closures/def-path.rs +++ b/tests/ui/async-await/async-closures/def-path.rs @@ -1,5 +1,6 @@ //@ compile-flags: -Zverbose-internals //@ edition:2021 +//@ normalize-stderr: "DefId\([^)]*" -> "" fn main() { let x = async || {}; diff --git a/tests/ui/async-await/async-closures/def-path.stderr b/tests/ui/async-await/async-closures/def-path.stderr index e140e9b94b30b..8670dd07940b2 100644 --- a/tests/ui/async-await/async-closures/def-path.stderr +++ b/tests/ui/async-await/async-closures/def-path.stderr @@ -1,15 +1,15 @@ error[E0308]: mismatched types - --> $DIR/def-path.rs:7:9 + --> $DIR/def-path.rs:8:9 | LL | let x = async || {}; | -- the expected `async` closure body LL | LL | let () = x(); - | ^^ --- this expression has type `{static main::{closure#0}::{closure#0} upvar_tys=?14t resume_ty=std::future::ResumeTy yield_ty=() return_ty=()}` + | ^^ --- this expression has type `{static main::{closure#0}::{closure#0} upvar_tys=?14t resume_ty=unsafe &'^0.Named()) mut Context<'^1.Named())> yield_ty=() return_ty=()}` | | | expected `async` closure body, found `()` | - = note: expected `async` closure body `{static main::{closure#0}::{closure#0} upvar_tys=?14t resume_ty=std::future::ResumeTy yield_ty=() return_ty=()}` + = note: expected `async` closure body `{static main::{closure#0}::{closure#0} upvar_tys=?14t resume_ty=unsafe &'^0.Named()) mut Context<'^1.Named())> yield_ty=() return_ty=()}` found unit type `()` error: aborting due to 1 previous error diff --git a/tests/ui/attributes/instruction-set.rs b/tests/ui/attributes/instruction-set.rs index dafa907cb5684..c47eff95e7ede 100644 --- a/tests/ui/attributes/instruction-set.rs +++ b/tests/ui/attributes/instruction-set.rs @@ -5,7 +5,7 @@ //@ edition: 2024 #![crate_type = "lib"] -#![feature(no_core, lang_items,)] +#![feature(no_core, lang_items, unsafe_binders)] #![no_core] extern crate minicore; @@ -70,7 +70,7 @@ impl Bazzest for Fooer { // The following lang items need to be defined for the async closure to work #[lang = "ResumeTy"] -pub struct ResumeTy(NonNull>); +pub type ResumeTy = unsafe<'a, 'b> &'a mut Context<'b>; #[lang = "future_trait"] pub trait Future { @@ -101,11 +101,5 @@ pub struct Context<'a> { _marker: PhantomData &'a ()>, } -#[lang = "get_context"] -pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { - // NOTE: the actual implementation looks different. - unsafe {mem::transmute(cx.0)} -} - #[lang = "pin"] pub struct Pin(T); diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/c-variadic.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/c-variadic.rs index 213b69b6fa201..44fa8c2c1daef 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/c-variadic.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/c-variadic.rs @@ -3,7 +3,7 @@ //@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib //@ needs-llvm-components: arm //@ ignore-backends: gcc -#![feature(cmse_nonsecure_entry, c_variadic, no_core, lang_items)] +#![feature(cmse_nonsecure_entry, c_variadic, no_core, lang_items, unsafe_binders)] #![no_core] extern crate minicore; @@ -33,7 +33,7 @@ async unsafe extern "cmse-nonsecure-entry" fn async_is_not_allowed() { // them. #[lang = "ResumeTy"] -pub struct ResumeTy(NonNull>); +pub type ResumeTy = unsafe<'a, 'b> &'a mut Context<'b>; #[lang = "future_trait"] pub trait Future { @@ -64,11 +64,5 @@ pub struct Context<'a> { _marker: PhantomData &'a ()>, } -#[lang = "get_context"] -pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { - // NOTE: the actual implementation looks different. - mem::transmute(cx.0) -} - #[lang = "pin"] pub struct Pin(T); diff --git a/tests/ui/rustc_public-ir-print/async-closure.stdout b/tests/ui/rustc_public-ir-print/async-closure.stdout index 3aca86ae66935..edf28b3f52847 100644 --- a/tests/ui/rustc_public-ir-print/async-closure.stdout +++ b/tests/ui/rustc_public-ir-print/async-closure.stdout @@ -42,10 +42,12 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo let mut _5: (); let mut _6: u32; let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; - debug _task_context => _2; + let mut _8: unsafe<'a, 'b> &'a mut Context<'b>; + debug _task_context => _8; debug y => (*((*_7).0: &i32)); debug y => _3; bb0: { + _8 = wrap_binder!(Move(_2); Ty { id: 12, kind: RigidTy(UnsafeBinder(Binder { value: Ty { id: 19, kind: RigidTy(Ref(Region { kind: ReBound(0, BoundRegion { var: 0, kind: BrAnon }) }, Ty { id: 20, kind: RigidTy(Adt(AdtDef(DefId { id: 5, name: "std::task::Context" }), GenericArgs([Lifetime(Region { kind: ReBound(0, BoundRegion { var: 1, kind: BrAnon }) })]))) }, Mut)) }, bound_vars: [Region(BrAnon), Region(BrAnon)] })) }); _7 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}); _6 = discriminant((*_7)); switchInt(move _6) -> [0: bb1, 1: bb2, otherwise: bb3]; @@ -74,10 +76,12 @@ fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-c let mut _5: (); let mut _6: u32; let mut _7: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}; - debug _task_context => _2; + let mut _8: unsafe<'a, 'b> &'a mut Context<'b>; + debug _task_context => _8; debug y => (*((*_7).0: &i32)); debug y => _3; bb0: { + _8 = wrap_binder!(Move(_2); Ty { id: 12, kind: RigidTy(UnsafeBinder(Binder { value: Ty { id: 19, kind: RigidTy(Ref(Region { kind: ReBound(0, BoundRegion { var: 0, kind: BrAnon }) }, Ty { id: 20, kind: RigidTy(Adt(AdtDef(DefId { id: 5, name: "std::task::Context" }), GenericArgs([Lifetime(Region { kind: ReBound(0, BoundRegion { var: 1, kind: BrAnon }) })]))) }, Mut)) }, bound_vars: [Region(BrAnon), Region(BrAnon)] })) }); _7 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}); _6 = discriminant((*_7)); switchInt(move _6) -> [0: bb1, 1: bb2, otherwise: bb3];