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);