Auto merge of #128506 - compiler-errors:by-move-body, r=cjgillot
Stop storing a special inner body for the coroutine by-move body for async closures ...and instead, just synthesize an item which is treated mostly normally by the MIR pipeline. This PR does a few things: * We synthesize a new `DefId` for the by-move body of a closure, which has its `mir_built` fed with the output of the `ByMoveBody` MIR transformation, and some other relevant queries. * This has the `DefKind::ByMoveBody`, which we use to distinguish it from "real" bodies (that come from HIR) which need to be borrowck'd. Introduce `TyCtxt::is_synthetic_mir` to skip over `mir_borrowck` which is called by `mir_promoted`; borrowck isn't really possible to make work ATM since it heavily relies being called on a body generated from HIR, and is redundant by the construction of the by-move-body. * Remove the special `PassManager` hacks for handling the inner `by_move_body` stored within the coroutine's mir body. Instead, this body is fed like a regular MIR body, so it's goes through all of the `tcx.*_mir` stages normally (build -> promoted -> ...etc... -> optimized) ✨. * Remove the `InstanceKind::ByMoveBody` shim, since now we have a "regular" def id, we can just use `InstanceKind::Item`. This also allows us to remove the corresponding hacks from codegen, such as in `fn_sig_for_fn_abi` ✨. Notable remarks: * ~~I know it's kind of weird to be using `DefKind::Closure` here, since it's not a distinct closure but just a new MIR body. I don't believe it really matters, but I could also use a different `DefKind`... maybe one that we could use for synthetic MIR bodies in general?~~ edit: We're doing this now.
This commit is contained in:
commit
d9a2cc4dae
40 changed files with 288 additions and 315 deletions
|
@ -307,7 +307,7 @@ impl<'hir> Map<'hir> {
|
|||
}
|
||||
DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
|
||||
DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
|
||||
DefKind::Closure => BodyOwnerKind::Closure,
|
||||
DefKind::Closure | DefKind::SyntheticCoroutineBody => BodyOwnerKind::Closure,
|
||||
DefKind::Static { safety: _, mutability, nested: false } => {
|
||||
BodyOwnerKind::Static(mutability)
|
||||
}
|
||||
|
|
|
@ -267,18 +267,6 @@ pub struct CoroutineInfo<'tcx> {
|
|||
/// Coroutine drop glue. This field is populated after the state transform pass.
|
||||
pub coroutine_drop: Option<Body<'tcx>>,
|
||||
|
||||
/// 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<Body<'tcx>>,
|
||||
|
||||
/// The layout of a coroutine. This field is populated after the state transform pass.
|
||||
pub coroutine_layout: Option<CoroutineLayout<'tcx>>,
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -665,10 +652,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<CoroutineKind> {
|
||||
self.coroutine.as_ref().map(|coroutine| coroutine.coroutine_kind)
|
||||
|
|
|
@ -415,7 +415,6 @@ impl<'tcx> CodegenUnit<'tcx> {
|
|||
| InstanceKind::Virtual(..)
|
||||
| InstanceKind::ClosureOnceShim { .. }
|
||||
| InstanceKind::ConstructCoroutineInClosureShim { .. }
|
||||
| InstanceKind::CoroutineKindShim { .. }
|
||||
| InstanceKind::DropGlue(..)
|
||||
| InstanceKind::CloneShim(..)
|
||||
| InstanceKind::ThreadLocalShim(..)
|
||||
|
|
|
@ -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) => {}
|
||||
|
||||
|
|
|
@ -326,6 +326,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(
|
||||
|
@ -498,6 +499,7 @@ rustc_queries! {
|
|||
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/construction.html
|
||||
query mir_built(key: LocalDefId) -> &'tcx Steal<mir::Body<'tcx>> {
|
||||
desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key) }
|
||||
feedable
|
||||
}
|
||||
|
||||
/// Try to build an abstract representation of the given constant.
|
||||
|
@ -742,6 +744,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 {
|
||||
|
@ -760,10 +763,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<hir::CoroutineKind> {
|
||||
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 {
|
||||
|
|
|
@ -1579,6 +1579,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
// Whether the body owner is synthetic, which in this case means it does not correspond to
|
||||
// meaningful HIR. This is currently used to skip over MIR borrowck.
|
||||
pub fn is_synthetic_mir(self, def_id: impl Into<DefId>) -> bool {
|
||||
matches!(self.def_kind(def_id.into()), DefKind::SyntheticCoroutineBody)
|
||||
}
|
||||
|
||||
/// Returns `true` if the node pointed to by `def_id` is a general coroutine that implements `Coroutine`.
|
||||
/// This means it is neither an `async` or `gen` construct.
|
||||
pub fn is_general_coroutine(self, def_id: DefId) -> bool {
|
||||
|
@ -3168,6 +3174,18 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity)
|
||||
}
|
||||
|
||||
pub fn needs_coroutine_by_move_body_def_id(self, def_id: LocalDefId) -> bool {
|
||||
if let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) =
|
||||
self.coroutine_kind(def_id)
|
||||
&& let ty::Coroutine(_, args) = self.type_of(def_id).instantiate_identity().kind()
|
||||
&& args.as_coroutine().kind_ty().to_opt_closure_kind() != Some(ty::ClosureKind::FnOnce)
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]`
|
||||
pub fn do_not_recommend_impl(self, def_id: DefId) -> bool {
|
||||
matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true })
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1756,7 +1756,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(..)
|
||||
|
@ -1874,7 +1873,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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue