diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 47d0e22b527d3..e354bfbdcbfe0 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -608,7 +608,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { | ty::InstanceKind::ReifyShim(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::FnPtrShim(..) | ty::InstanceKind::DropGlue(..) | ty::InstanceKind::CloneShim(..) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 061db14ad0a61..c92fa2984e728 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -199,10 +199,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } }); - // Freeze definitions as we don't add new ones at this point. This improves performance by - // allowing lock-free access to them. - tcx.untracked().definitions.freeze(); - // FIXME: Remove this when we implement creating `DefId`s // for anon constants during their parents' typeck. // Typeck all body owners in parallel will produce queries diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 8c99b1f444766..43b878ae25a24 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -816,6 +816,13 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { ); } }); + // Freeze definitions as we don't add new ones at this point. + // We need to wait until now since we synthesize a by-move body + // This improves performance by allowing lock-free access to them. + // FIXME(async_closures): We could force `coroutine_by_move_body_def_id` + // immediately after typeck, then freeze after that. + tcx.untracked().definitions.freeze(); + sess.time("layout_testing", || layout_test::test_layout(tcx)); sess.time("abi_testing", || abi_test::test_abi(tcx)); } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 0d83f8c6c5c93..001d31621fae8 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1366,7 +1366,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def_span = tcx.def_span(local_id); record!(self.tables.def_span[def_id] <- def_span); } - if should_encode_attrs(def_kind) { + // FIXME(async_closures): We should just use `tcx.attrs` rather than going + // through the HIR. Historically, though, this has been inefficient apparently. + // For now, it's kind of pointless to fix, because coroutine-closures' coroutine + // bodies have no attrs anyways. + if should_encode_attrs(def_kind) && !tcx.is_synthetic_mir(local_id) { self.encode_attrs(local_id); } if should_encode_expn_that_defined(def_kind) { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index b9c93edcd80e4..807091d6d7865 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -267,18 +267,6 @@ pub struct CoroutineInfo<'tcx> { /// Coroutine drop glue. This field is populated after the state transform pass. pub coroutine_drop: Option>, - /// The body of the coroutine, modified to take its upvars by move rather than by ref. - /// - /// This is used by coroutine-closures, which must return a different flavor of coroutine - /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` pass which - /// is run right after building the initial MIR, and will only be populated for coroutines - /// which come out of the async closure desugaring. - /// - /// This body should be processed in lockstep with the containing body -- any optimization - /// passes, etc, should be applied to this body as well. This is done automatically if - /// using `run_passes`. - pub by_move_body: Option>, - /// The layout of a coroutine. This field is populated after the state transform pass. pub coroutine_layout: Option>, @@ -298,7 +286,6 @@ impl<'tcx> CoroutineInfo<'tcx> { coroutine_kind, yield_ty: Some(yield_ty), resume_ty: Some(resume_ty), - by_move_body: None, coroutine_drop: None, coroutine_layout: None, } @@ -663,10 +650,6 @@ impl<'tcx> Body<'tcx> { self.coroutine.as_ref().and_then(|coroutine| coroutine.coroutine_drop.as_ref()) } - pub fn coroutine_by_move_body(&self) -> Option<&Body<'tcx>> { - self.coroutine.as_ref()?.by_move_body.as_ref() - } - #[inline] pub fn coroutine_kind(&self) -> Option { self.coroutine.as_ref().map(|coroutine| coroutine.coroutine_kind) diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 336a9388a561e..1d94c364ae3af 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -415,7 +415,6 @@ impl<'tcx> CodegenUnit<'tcx> { | InstanceKind::Virtual(..) | InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::CloneShim(..) | InstanceKind::ThreadLocalShim(..) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 0031ded244062..6902d3e335cf4 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -349,7 +349,6 @@ macro_rules! make_mir_visitor { coroutine_closure_def_id: _def_id, receiver_by_ref: _, } | - ty::InstanceKind::CoroutineKindShim { coroutine_def_id: _def_id } | ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, None) | ty::InstanceKind::DropGlue(_def_id, None) => {} diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c22c2e985abba..4e6d06106a4f0 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -327,6 +327,7 @@ rustc_queries! { query predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing predicates of `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } + feedable } query opaque_types_defined_by( @@ -488,6 +489,11 @@ rustc_queries! { separate_provide_extern } + query is_synthetic_mir(key: LocalDefId) -> bool { + desc { |tcx| "checking if `{}` is synthetic", tcx.def_path_str(key) } + feedable + } + /// Build the MIR for a given `DefId` and prepare it for const qualification. /// /// See the [rustc dev guide] for more info. @@ -495,6 +501,7 @@ rustc_queries! { /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/construction.html query mir_built(key: LocalDefId) -> &'tcx Steal> { desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key) } + feedable } /// Try to build an abstract representation of the given constant. @@ -739,6 +746,7 @@ rustc_queries! { query constness(key: DefId) -> hir::Constness { desc { |tcx| "checking if item is const: `{}`", tcx.def_path_str(key) } separate_provide_extern + feedable } query asyncness(key: DefId) -> ty::Asyncness { @@ -757,10 +765,22 @@ rustc_queries! { desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) } } + /// The body of the coroutine, modified to take its upvars by move rather than by ref. + /// + /// This is used by coroutine-closures, which must return a different flavor of coroutine + /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` pass which + /// is run right after building the initial MIR, and will only be populated for coroutines + /// which come out of the async closure desugaring. + query coroutine_by_move_body_def_id(def_id: DefId) -> DefId { + desc { |tcx| "looking up the coroutine by-move body for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern + } + /// Returns `Some(coroutine_kind)` if the node pointed to by `def_id` is a coroutine. query coroutine_kind(def_id: DefId) -> Option { desc { |tcx| "looking up coroutine kind of `{}`", tcx.def_path_str(def_id) } separate_provide_extern + feedable } query coroutine_for_closure(def_id: DefId) -> DefId { diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 0496c571f5e0a..2f11643ba337a 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -141,14 +141,6 @@ pub enum InstanceKind<'tcx> { receiver_by_ref: bool, }, - /// `<[coroutine] as Future>::poll`, but for coroutines produced when `AsyncFnOnce` - /// is called on a coroutine-closure whose closure kind greater than `FnOnce`, or - /// similarly for `AsyncFnMut`. - /// - /// This will select the body that is produced by the `ByMoveBody` transform, and thus - /// take and use all of its upvars by-move rather than by-ref. - CoroutineKindShim { coroutine_def_id: DefId }, - /// Compiler-generated accessor for thread locals which returns a reference to the thread local /// the `DefId` defines. This is used to export thread locals from dylibs on platforms lacking /// native support. @@ -248,7 +240,6 @@ impl<'tcx> InstanceKind<'tcx> { coroutine_closure_def_id: def_id, receiver_by_ref: _, } - | ty::InstanceKind::CoroutineKindShim { coroutine_def_id: def_id } | InstanceKind::DropGlue(def_id, _) | InstanceKind::CloneShim(def_id, _) | InstanceKind::FnPtrAddrShim(def_id, _) @@ -270,7 +261,6 @@ impl<'tcx> InstanceKind<'tcx> { | InstanceKind::Intrinsic(..) | InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::AsyncDropGlueCtorShim(..) | InstanceKind::CloneShim(..) @@ -377,7 +367,6 @@ impl<'tcx> InstanceKind<'tcx> { | InstanceKind::AsyncDropGlueCtorShim(_, Some(_)) => false, InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::AsyncDropGlueCtorShim(..) | InstanceKind::Item(_) @@ -452,7 +441,6 @@ pub fn fmt_instance( InstanceKind::FnPtrShim(_, ty) => write!(f, " - shim({ty})"), InstanceKind::ClosureOnceShim { .. } => write!(f, " - shim"), InstanceKind::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"), - InstanceKind::CoroutineKindShim { .. } => write!(f, " - shim"), InstanceKind::DropGlue(_, None) => write!(f, " - shim(None)"), InstanceKind::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), InstanceKind::CloneShim(_, ty) => write!(f, " - shim({ty})"), @@ -850,7 +838,9 @@ impl<'tcx> Instance<'tcx> { Some(Instance { def: ty::InstanceKind::Item(coroutine_def_id), args }) } else { Some(Instance { - def: ty::InstanceKind::CoroutineKindShim { coroutine_def_id }, + def: ty::InstanceKind::Item( + tcx.coroutine_by_move_body_def_id(coroutine_def_id), + ), args, }) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9736428e6f7c7..1bf079eda64d8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1755,7 +1755,6 @@ impl<'tcx> TyCtxt<'tcx> { | ty::InstanceKind::Virtual(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::DropGlue(..) | ty::InstanceKind::CloneShim(..) | ty::InstanceKind::ThreadLocalShim(..) @@ -1873,7 +1872,8 @@ impl<'tcx> TyCtxt<'tcx> { identity_kind_ty.to_opt_closure_kind(), Some(ClosureKind::Fn | ClosureKind::FnMut) ); - mir.coroutine_by_move_body().unwrap().coroutine_layout_raw() + self.optimized_mir(self.coroutine_by_move_body_def_id(def_id)) + .coroutine_layout_raw() } } } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 82528109be9ab..aa841c9417af0 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -53,7 +53,7 @@ mod by_move_body; use std::{iter, ops}; -pub use by_move_body::ByMoveBody; +pub use by_move_body::coroutine_by_move_body_def_id; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; use rustc_hir as hir; diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 69d21a63f557b..5452d7f152e34 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -69,135 +69,151 @@ //! in case precise captures (edition 2021 closure capture rules) caused the inner coroutine //! to split one field capture into two. +use rustc_data_structures::steal::Steal; use rustc_data_structures::unord::UnordMap; use rustc_hir as hir; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::bug; use rustc_middle::hir::place::{Projection, ProjectionKind}; use rustc_middle::mir::visit::MutVisitor; -use rustc_middle::mir::{self, dump_mir, MirPass}; +use rustc_middle::mir::{self, dump_mir}; use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, TypeVisitableExt}; +use rustc_span::symbol::kw; use rustc_target::abi::{FieldIdx, VariantIdx}; -pub struct ByMoveBody; +pub fn coroutine_by_move_body_def_id<'tcx>( + tcx: TyCtxt<'tcx>, + coroutine_def_id: LocalDefId, +) -> DefId { + let body = tcx.mir_built(coroutine_def_id).borrow(); -impl<'tcx> MirPass<'tcx> for ByMoveBody { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { - // We only need to generate by-move coroutine bodies for coroutines that come - // from coroutine-closures. - let Some(coroutine_def_id) = body.source.def_id().as_local() else { - return; - }; - let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = - tcx.coroutine_kind(coroutine_def_id) - else { - return; - }; + let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = + tcx.coroutine_kind(coroutine_def_id) + else { + bug!("should only be invoked on coroutine-closures"); + }; - // Also, let's skip processing any bodies with errors, since there's no guarantee - // the MIR body will be constructed well. - let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; - if coroutine_ty.references_error() { - return; - } + // Also, let's skip processing any bodies with errors, since there's no guarantee + // the MIR body will be constructed well. + let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; - // We don't need to generate a by-move coroutine if the coroutine body was - // produced by the `CoroutineKindShim`, since it's already by-move. - if matches!(body.source.instance, ty::InstanceKind::CoroutineKindShim { .. }) { - return; - } + let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; + let args = args.as_coroutine(); - let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; - let args = args.as_coroutine(); + let coroutine_kind = args.kind_ty().to_opt_closure_kind().unwrap(); - let coroutine_kind = args.kind_ty().to_opt_closure_kind().unwrap(); + let parent_def_id = tcx.local_parent(coroutine_def_id); + let ty::CoroutineClosure(_, parent_args) = + *tcx.type_of(parent_def_id).instantiate_identity().kind() + else { + bug!(); + }; + if parent_args.references_error() { + return coroutine_def_id.to_def_id(); + } - let parent_def_id = tcx.local_parent(coroutine_def_id); - let ty::CoroutineClosure(_, parent_args) = - *tcx.type_of(parent_def_id).instantiate_identity().kind() - else { - bug!(); - }; - let parent_closure_args = parent_args.as_coroutine_closure(); - let num_args = parent_closure_args - .coroutine_closure_sig() - .skip_binder() - .tupled_inputs_ty - .tuple_fields() - .len(); + let parent_closure_args = parent_args.as_coroutine_closure(); + let num_args = parent_closure_args + .coroutine_closure_sig() + .skip_binder() + .tupled_inputs_ty + .tuple_fields() + .len(); - let field_remapping: UnordMap<_, _> = ty::analyze_coroutine_closure_captures( - tcx.closure_captures(parent_def_id).iter().copied(), - tcx.closure_captures(coroutine_def_id).iter().skip(num_args).copied(), - |(parent_field_idx, parent_capture), (child_field_idx, child_capture)| { - // Store this set of additional projections (fields and derefs). - // We need to re-apply them later. - let child_precise_captures = - &child_capture.place.projections[parent_capture.place.projections.len()..]; + let field_remapping: UnordMap<_, _> = ty::analyze_coroutine_closure_captures( + tcx.closure_captures(parent_def_id).iter().copied(), + tcx.closure_captures(coroutine_def_id).iter().skip(num_args).copied(), + |(parent_field_idx, parent_capture), (child_field_idx, child_capture)| { + // Store this set of additional projections (fields and derefs). + // We need to re-apply them later. + let child_precise_captures = + &child_capture.place.projections[parent_capture.place.projections.len()..]; - // If the parent captures by-move, and the child captures by-ref, then we - // need to peel an additional `deref` off of the body of the child. - let needs_deref = child_capture.is_by_ref() && !parent_capture.is_by_ref(); - if needs_deref { - assert_ne!( - coroutine_kind, - ty::ClosureKind::FnOnce, - "`FnOnce` coroutine-closures return coroutines that capture from \ + // If the parent captures by-move, and the child captures by-ref, then we + // need to peel an additional `deref` off of the body of the child. + let needs_deref = child_capture.is_by_ref() && !parent_capture.is_by_ref(); + if needs_deref { + assert_ne!( + coroutine_kind, + ty::ClosureKind::FnOnce, + "`FnOnce` coroutine-closures return coroutines that capture from \ their body; it will always result in a borrowck error!" - ); - } + ); + } - // Finally, store the type of the parent's captured place. We need - // this when building the field projection in the MIR body later on. - let mut parent_capture_ty = parent_capture.place.ty(); - parent_capture_ty = match parent_capture.info.capture_kind { - ty::UpvarCapture::ByValue => parent_capture_ty, - ty::UpvarCapture::ByRef(kind) => Ty::new_ref( - tcx, - tcx.lifetimes.re_erased, - parent_capture_ty, - kind.to_mutbl_lossy(), - ), - }; + // Finally, store the type of the parent's captured place. We need + // this when building the field projection in the MIR body later on. + let mut parent_capture_ty = parent_capture.place.ty(); + parent_capture_ty = match parent_capture.info.capture_kind { + ty::UpvarCapture::ByValue => parent_capture_ty, + ty::UpvarCapture::ByRef(kind) => Ty::new_ref( + tcx, + tcx.lifetimes.re_erased, + parent_capture_ty, + kind.to_mutbl_lossy(), + ), + }; + ( + FieldIdx::from_usize(child_field_idx + num_args), ( - FieldIdx::from_usize(child_field_idx + num_args), - ( - FieldIdx::from_usize(parent_field_idx + num_args), - parent_capture_ty, - needs_deref, - child_precise_captures, - ), - ) - }, - ) - .collect(); + FieldIdx::from_usize(parent_field_idx + num_args), + parent_capture_ty, + needs_deref, + child_precise_captures, + ), + ) + }, + ) + .collect(); - if coroutine_kind == ty::ClosureKind::FnOnce { - assert_eq!(field_remapping.len(), tcx.closure_captures(parent_def_id).len()); - return; - } + if coroutine_kind == ty::ClosureKind::FnOnce { + assert_eq!(field_remapping.len(), tcx.closure_captures(parent_def_id).len()); + // The by-move body is just the body :) + return coroutine_def_id.to_def_id(); + } - let by_move_coroutine_ty = tcx - .instantiate_bound_regions_with_erased(parent_closure_args.coroutine_closure_sig()) - .to_coroutine_given_kind_and_upvars( - tcx, - parent_closure_args.parent_args(), - coroutine_def_id.to_def_id(), - ty::ClosureKind::FnOnce, - tcx.lifetimes.re_erased, - parent_closure_args.tupled_upvars_ty(), - parent_closure_args.coroutine_captures_by_ref_ty(), - ); + let by_move_coroutine_ty = tcx + .instantiate_bound_regions_with_erased(parent_closure_args.coroutine_closure_sig()) + .to_coroutine_given_kind_and_upvars( + tcx, + parent_closure_args.parent_args(), + coroutine_def_id.to_def_id(), + ty::ClosureKind::FnOnce, + tcx.lifetimes.re_erased, + parent_closure_args.tupled_upvars_ty(), + parent_closure_args.coroutine_captures_by_ref_ty(), + ); - let mut by_move_body = body.clone(); - MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body); - dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(())); - // FIXME: use query feeding to generate the body right here and then only store the `DefId` of the new body. - by_move_body.source = mir::MirSource::from_instance(InstanceKind::CoroutineKindShim { - coroutine_def_id: coroutine_def_id.to_def_id(), - }); - body.coroutine.as_mut().unwrap().by_move_body = Some(by_move_body); - } + let mut by_move_body = body.clone(); + MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body); + dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(())); + + let body_def = tcx.create_def(coroutine_def_id, kw::Empty, DefKind::Closure); + by_move_body.source = + mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id())); + + // Inherited from the by-ref coroutine. + body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone()); + body_def.constness(tcx.constness(coroutine_def_id).clone()); + body_def.coroutine_kind(tcx.coroutine_kind(coroutine_def_id).clone()); + body_def.def_ident_span(tcx.def_ident_span(coroutine_def_id)); + body_def.def_span(tcx.def_span(coroutine_def_id)); + body_def.explicit_predicates_of(tcx.explicit_predicates_of(coroutine_def_id).clone()); + body_def.generics_of(tcx.generics_of(coroutine_def_id).clone()); + body_def.param_env(tcx.param_env(coroutine_def_id).clone()); + body_def.predicates_of(tcx.predicates_of(coroutine_def_id).clone()); + + // The type of the coroutine is the `by_move_coroutine_ty`. + body_def.type_of(ty::EarlyBinder::bind(by_move_coroutine_ty)); + + // Mark the body as synthetic so it doesn't get borrowck'd. + body_def.is_synthetic_mir(true); + + body_def.mir_built(tcx.arena.alloc(Steal::new(by_move_body))); + + body_def.def_id().to_def_id() } struct MakeByMoveBody<'tcx> { diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 36b2b3b7c4466..06d5968efc4f1 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -341,7 +341,6 @@ impl<'tcx> Inliner<'tcx> { | InstanceKind::FnPtrShim(..) | InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::CloneShim(..) | InstanceKind::ThreadLocalShim(..) diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index f5274c664cfa7..56e8905bead3c 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -88,7 +88,6 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( | InstanceKind::FnPtrShim(..) | InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::ThreadLocalShim { .. } | InstanceKind::CloneShim(..) => {} diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index ac3a44c803a5f..016f269de0a11 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -124,6 +124,7 @@ pub fn provide(providers: &mut Providers) { providers.queries = query::Providers { mir_keys, mir_built, + is_synthetic_mir: |_, _| false, mir_const_qualif, mir_promoted, mir_drops_elaborated_and_const_checked, @@ -136,6 +137,7 @@ pub fn provide(providers: &mut Providers) { mir_inliner_callees: inline::cycle::mir_inliner_callees, promoted_mir, deduced_param_attrs: deduce_param_attrs::deduced_param_attrs, + coroutine_by_move_body_def_id: coroutine::coroutine_by_move_body_def_id, ..providers.queries }; } @@ -294,10 +296,6 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal> { &Lint(check_packed_ref::CheckPackedRef), &Lint(check_const_item_mutation::CheckConstItemMutation), &Lint(function_item_references::FunctionItemReferences), - // If this is an async closure's output coroutine, generate - // by-move and by-mut bodies if needed. We do this first so - // they can be optimized in lockstep with their parent bodies. - &coroutine::ByMoveBody, // What we need to do constant evaluation. &simplify::SimplifyCfg::Initial, &rustc_peek::SanityCheck, // Just a lint @@ -330,8 +328,20 @@ fn mir_promoted( | DefKind::AnonConst => tcx.mir_const_qualif(def), _ => ConstQualifs::default(), }; - // has_ffi_unwind_calls query uses the raw mir, so make sure it is run. + + // the `has_ffi_unwind_calls` query uses the raw mir, so make sure it is run. tcx.ensure_with_value().has_ffi_unwind_calls(def); + + // the `by_move_body` query uses the raw mir, so make sure it is run. + if matches!( + tcx.coroutine_kind(def), + Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) + ) && let ty::Coroutine(_, args) = tcx.type_of(def).instantiate_identity().kind() + && args.as_coroutine().kind_ty().to_opt_closure_kind() != Some(ty::ClosureKind::FnOnce) + { + tcx.ensure_with_value().coroutine_by_move_body_def_id(def); + } + let mut body = tcx.mir_built(def).steal(); if let Some(error_reported) = const_qualifs.tainted_by_errors { body.tainted_by_errors = Some(error_reported); @@ -396,7 +406,10 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & if tcx.is_coroutine(def.to_def_id()) { tcx.ensure_with_value().mir_coroutine_witnesses(def); } - let mir_borrowck = tcx.mir_borrowck(def); + + // We only need to borrowck non-synthetic MIR. + let tainted_by_errors = + if !tcx.is_synthetic_mir(def) { tcx.mir_borrowck(def).tainted_by_errors } else { None }; let is_fn_like = tcx.def_kind(def).is_fn_like(); if is_fn_like { @@ -408,7 +421,8 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & let (body, _) = tcx.mir_promoted(def); let mut body = body.steal(); - if let Some(error_reported) = mir_borrowck.tainted_by_errors { + + if let Some(error_reported) = tainted_by_errors { body.tainted_by_errors = Some(error_reported); } @@ -678,7 +692,9 @@ fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec( body.pass_count = 1; } - - if let Some(coroutine) = body.coroutine.as_mut() { - if let Some(by_move_body) = coroutine.by_move_body.as_mut() { - run_passes_inner(tcx, by_move_body, passes, phase_change, validate_each); - } - } } pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index e2fafa3a1a30b..7bf2d1575daf6 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -78,15 +78,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< receiver_by_ref, } => build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id, receiver_by_ref), - ty::InstanceKind::CoroutineKindShim { coroutine_def_id } => { - return tcx.optimized_mir(coroutine_def_id).coroutine_by_move_body().unwrap().clone(); - } - ty::InstanceKind::DropGlue(def_id, ty) => { // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end // of this function. Is this intentional? - if let Some(ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) { - let coroutine_body = tcx.optimized_mir(*coroutine_def_id); + if let Some(&ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) { + let coroutine_body = tcx.optimized_mir(coroutine_def_id); let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind() else { @@ -105,7 +101,9 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(), ty::ClosureKind::FnOnce ); - coroutine_body.coroutine_by_move_body().unwrap().coroutine_drop().unwrap() + tcx.optimized_mir(tcx.coroutine_by_move_body_def_id(coroutine_def_id)) + .coroutine_drop() + .unwrap() }; let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args); diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 746d423b7a98c..d63308a955e5c 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -102,25 +102,6 @@ impl<'tcx> MirPass<'tcx> for Validator { } } } - - // Enforce that coroutine-closure layouts are identical. - if let Some(layout) = body.coroutine_layout_raw() - && let Some(by_move_body) = body.coroutine_by_move_body() - && let Some(by_move_layout) = by_move_body.coroutine_layout_raw() - { - // FIXME(async_closures): We could do other validation here? - if layout.variant_fields.len() != by_move_layout.variant_fields.len() { - cfg_checker.fail( - Location::START, - format!( - "Coroutine layout has different number of variant fields from \ - by-move coroutine layout:\n\ - layout: {layout:#?}\n\ - by_move_layout: {by_move_layout:#?}", - ), - ); - } - } } } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 99cac67f5b1c1..f9caee78007f7 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -918,7 +918,6 @@ fn visit_instance_use<'tcx>( | ty::InstanceKind::ReifyShim(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::Item(..) | ty::InstanceKind::FnPtrShim(..) | ty::InstanceKind::CloneShim(..) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 65a3d8d1742d9..dd01cd4da8807 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -626,7 +626,6 @@ fn characteristic_def_id_of_mono_item<'tcx>( | ty::InstanceKind::FnPtrShim(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::Intrinsic(..) | ty::InstanceKind::DropGlue(..) | ty::InstanceKind::Virtual(..) @@ -794,7 +793,6 @@ fn mono_item_visibility<'tcx>( | InstanceKind::Intrinsic(..) | InstanceKind::ClosureOnceShim { .. } | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::CoroutineKindShim { .. } | InstanceKind::DropGlue(..) | InstanceKind::AsyncDropGlueCtorShim(..) | InstanceKind::CloneShim(..) diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index ef2eb7d52eaef..58955a7acf8ed 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -849,7 +849,6 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { | ty::InstanceKind::FnPtrAddrShim(..) | ty::InstanceKind::ClosureOnceShim { .. } | ty::InstanceKind::ConstructCoroutineInClosureShim { .. } - | ty::InstanceKind::CoroutineKindShim { .. } | ty::InstanceKind::ThreadLocalShim(..) | ty::InstanceKind::DropGlue(..) | ty::InstanceKind::CloneShim(..) diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 0f91684a3a48b..59ccd6dff8588 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -92,9 +92,6 @@ pub(super) fn mangle<'tcx>( .write_str(if receiver_by_ref { "{{by-move-shim}}" } else { "{{by-ref-shim}}" }) .unwrap(); } - ty::InstanceKind::CoroutineKindShim { .. } => { - printer.write_str("{{by-move-body-shim}}").unwrap(); - } _ => {} } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index c2451c08d1158..c4cf361b5d8c1 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -56,7 +56,6 @@ pub(super) fn mangle<'tcx>( ty::InstanceKind::ConstructCoroutineInClosureShim { receiver_by_ref: false, .. } => { Some("by_ref") } - ty::InstanceKind::CoroutineKindShim { .. } => Some("by_move_body"), _ => None, }; diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index f1675f80717f0..71b927a0c8cb7 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -169,39 +169,6 @@ fn fn_sig_for_fn_abi<'tcx>( kind: ty::BoundRegionKind::BrEnv, }; - let mut ty = ty; - // When this `Closure` comes from a `CoroutineKindShim`, - // make sure we respect the `target_kind` in that shim. - // FIXME(async_closures): This shouldn't be needed, and we should be populating - // a separate def-id for these bodies. - if let InstanceKind::CoroutineKindShim { .. } = instance.def { - // Grab the parent coroutine-closure. It has the same args for the purposes - // of instantiation, so this will be okay to do. - let ty::CoroutineClosure(_, coroutine_closure_args) = *tcx - .instantiate_and_normalize_erasing_regions( - args, - param_env, - tcx.type_of(tcx.parent(did)), - ) - .kind() - else { - bug!("CoroutineKindShim comes from calling a coroutine-closure"); - }; - let coroutine_closure_args = coroutine_closure_args.as_coroutine_closure(); - ty = tcx.instantiate_bound_regions_with_erased( - coroutine_closure_args.coroutine_closure_sig().map_bound(|sig| { - sig.to_coroutine_given_kind_and_upvars( - tcx, - coroutine_closure_args.parent_args(), - did, - ty::ClosureKind::FnOnce, - tcx.lifetimes.re_erased, - coroutine_closure_args.tupled_upvars_ty(), - coroutine_closure_args.coroutine_captures_by_ref_ty(), - ) - }), - ); - } let env_ty = Ty::new_mut_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), ty); let pin_did = tcx.require_lang_item(LangItem::Pin, None);