Construct body for by-move coroutine closure output
This commit is contained in:
parent
fc4fff4038
commit
427896dd7e
24 changed files with 233 additions and 15 deletions
|
@ -262,6 +262,10 @@ 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.
|
||||
/// TODO:
|
||||
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>>,
|
||||
|
||||
|
@ -281,6 +285,7 @@ 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,
|
||||
}
|
||||
|
|
|
@ -403,6 +403,7 @@ impl<'tcx> CodegenUnit<'tcx> {
|
|||
| InstanceDef::Virtual(..)
|
||||
| InstanceDef::ClosureOnceShim { .. }
|
||||
| InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| InstanceDef::CoroutineByMoveShim { .. }
|
||||
| InstanceDef::DropGlue(..)
|
||||
| InstanceDef::CloneShim(..)
|
||||
| InstanceDef::ThreadLocalShim(..)
|
||||
|
|
|
@ -346,6 +346,7 @@ macro_rules! make_mir_visitor {
|
|||
ty::InstanceDef::ThreadLocalShim(_def_id) |
|
||||
ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } |
|
||||
ty::InstanceDef::ConstructCoroutineInClosureShim { coroutine_closure_def_id: _def_id, target_kind: _ } |
|
||||
ty::InstanceDef::CoroutineByMoveShim { coroutine_def_id: _def_id } |
|
||||
ty::InstanceDef::DropGlue(_def_id, None) => {}
|
||||
|
||||
ty::InstanceDef::FnPtrShim(_def_id, ty) |
|
||||
|
|
|
@ -101,6 +101,9 @@ pub enum InstanceDef<'tcx> {
|
|||
target_kind: ty::ClosureKind,
|
||||
},
|
||||
|
||||
/// TODO:
|
||||
CoroutineByMoveShim { 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.
|
||||
|
@ -186,6 +189,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
coroutine_closure_def_id: def_id,
|
||||
target_kind: _,
|
||||
}
|
||||
| ty::InstanceDef::CoroutineByMoveShim { coroutine_def_id: def_id }
|
||||
| InstanceDef::DropGlue(def_id, _)
|
||||
| InstanceDef::CloneShim(def_id, _)
|
||||
| InstanceDef::FnPtrAddrShim(def_id, _) => def_id,
|
||||
|
@ -206,6 +210,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
| InstanceDef::Intrinsic(..)
|
||||
| InstanceDef::ClosureOnceShim { .. }
|
||||
| ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceDef::CoroutineByMoveShim { .. }
|
||||
| InstanceDef::DropGlue(..)
|
||||
| InstanceDef::CloneShim(..)
|
||||
| InstanceDef::FnPtrAddrShim(..) => None,
|
||||
|
@ -302,6 +307,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
| InstanceDef::DropGlue(_, Some(_)) => false,
|
||||
InstanceDef::ClosureOnceShim { .. }
|
||||
| InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| InstanceDef::CoroutineByMoveShim { .. }
|
||||
| InstanceDef::DropGlue(..)
|
||||
| InstanceDef::Item(_)
|
||||
| InstanceDef::Intrinsic(..)
|
||||
|
@ -340,6 +346,7 @@ fn fmt_instance(
|
|||
InstanceDef::FnPtrShim(_, ty) => write!(f, " - shim({ty})"),
|
||||
InstanceDef::ClosureOnceShim { .. } => write!(f, " - shim"),
|
||||
InstanceDef::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"),
|
||||
InstanceDef::CoroutineByMoveShim { .. } => write!(f, " - shim"),
|
||||
InstanceDef::DropGlue(_, None) => write!(f, " - shim(None)"),
|
||||
InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
|
||||
InstanceDef::CloneShim(_, ty) => write!(f, " - shim({ty})"),
|
||||
|
@ -631,7 +638,19 @@ impl<'tcx> Instance<'tcx> {
|
|||
};
|
||||
|
||||
if tcx.lang_items().get(coroutine_callable_item) == Some(trait_item_id) {
|
||||
Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args: args })
|
||||
let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind()
|
||||
else {
|
||||
bug!()
|
||||
};
|
||||
|
||||
if args.as_coroutine().kind_ty() == id_args.as_coroutine().kind_ty() {
|
||||
Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
|
||||
} else {
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::CoroutineByMoveShim { coroutine_def_id },
|
||||
args,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// All other methods should be defaulted methods of the built-in trait.
|
||||
// This is important for `Iterator`'s combinators, but also useful for
|
||||
|
|
|
@ -1681,6 +1681,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
| ty::InstanceDef::Virtual(..)
|
||||
| ty::InstanceDef::ClosureOnceShim { .. }
|
||||
| ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
|
||||
| ty::InstanceDef::CoroutineByMoveShim { .. }
|
||||
| ty::InstanceDef::DropGlue(..)
|
||||
| ty::InstanceDef::CloneShim(..)
|
||||
| ty::InstanceDef::ThreadLocalShim(..)
|
||||
|
|
|
@ -399,6 +399,7 @@ impl<'tcx> CoroutineClosureSignature<'tcx> {
|
|||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
parent_args: &'tcx [GenericArg<'tcx>],
|
||||
kind_ty: Ty<'tcx>,
|
||||
coroutine_def_id: DefId,
|
||||
tupled_upvars_ty: Ty<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
|
@ -406,6 +407,7 @@ impl<'tcx> CoroutineClosureSignature<'tcx> {
|
|||
tcx,
|
||||
ty::CoroutineArgsParts {
|
||||
parent_args,
|
||||
kind_ty,
|
||||
resume_ty: self.resume_ty,
|
||||
yield_ty: self.yield_ty,
|
||||
return_ty: self.return_ty,
|
||||
|
@ -436,7 +438,13 @@ impl<'tcx> CoroutineClosureSignature<'tcx> {
|
|||
env_region,
|
||||
);
|
||||
|
||||
self.to_coroutine(tcx, parent_args, coroutine_def_id, tupled_upvars_ty)
|
||||
self.to_coroutine(
|
||||
tcx,
|
||||
parent_args,
|
||||
Ty::from_closure_kind(tcx, closure_kind),
|
||||
coroutine_def_id,
|
||||
tupled_upvars_ty,
|
||||
)
|
||||
}
|
||||
|
||||
/// Given a closure kind, compute the tupled upvars that the given coroutine would return.
|
||||
|
@ -488,6 +496,8 @@ pub struct CoroutineArgs<'tcx> {
|
|||
pub struct CoroutineArgsParts<'tcx> {
|
||||
/// This is the args of the typeck root.
|
||||
pub parent_args: &'tcx [GenericArg<'tcx>],
|
||||
// TODO: why
|
||||
pub kind_ty: Ty<'tcx>,
|
||||
pub resume_ty: Ty<'tcx>,
|
||||
pub yield_ty: Ty<'tcx>,
|
||||
pub return_ty: Ty<'tcx>,
|
||||
|
@ -506,6 +516,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
|
|||
pub fn new(tcx: TyCtxt<'tcx>, parts: CoroutineArgsParts<'tcx>) -> CoroutineArgs<'tcx> {
|
||||
CoroutineArgs {
|
||||
args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([
|
||||
parts.kind_ty.into(),
|
||||
parts.resume_ty.into(),
|
||||
parts.yield_ty.into(),
|
||||
parts.return_ty.into(),
|
||||
|
@ -519,16 +530,23 @@ impl<'tcx> CoroutineArgs<'tcx> {
|
|||
/// The ordering assumed here must match that used by `CoroutineArgs::new` above.
|
||||
fn split(self) -> CoroutineArgsParts<'tcx> {
|
||||
match self.args[..] {
|
||||
[ref parent_args @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => {
|
||||
CoroutineArgsParts {
|
||||
parent_args,
|
||||
resume_ty: resume_ty.expect_ty(),
|
||||
yield_ty: yield_ty.expect_ty(),
|
||||
return_ty: return_ty.expect_ty(),
|
||||
witness: witness.expect_ty(),
|
||||
tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
|
||||
}
|
||||
}
|
||||
[
|
||||
ref parent_args @ ..,
|
||||
kind_ty,
|
||||
resume_ty,
|
||||
yield_ty,
|
||||
return_ty,
|
||||
witness,
|
||||
tupled_upvars_ty,
|
||||
] => CoroutineArgsParts {
|
||||
parent_args,
|
||||
kind_ty: kind_ty.expect_ty(),
|
||||
resume_ty: resume_ty.expect_ty(),
|
||||
yield_ty: yield_ty.expect_ty(),
|
||||
return_ty: return_ty.expect_ty(),
|
||||
witness: witness.expect_ty(),
|
||||
tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
|
||||
},
|
||||
_ => bug!("coroutine args missing synthetics"),
|
||||
}
|
||||
}
|
||||
|
@ -538,6 +556,11 @@ impl<'tcx> CoroutineArgs<'tcx> {
|
|||
self.split().parent_args
|
||||
}
|
||||
|
||||
// TODO:
|
||||
pub fn kind_ty(self) -> Ty<'tcx> {
|
||||
self.split().kind_ty
|
||||
}
|
||||
|
||||
/// This describes the types that can be contained in a coroutine.
|
||||
/// It will be a type variable initially and unified in the last stages of typeck of a body.
|
||||
/// It contains a tuple of all the types that could end up on a coroutine frame.
|
||||
|
@ -1628,7 +1651,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
) -> Ty<'tcx> {
|
||||
debug_assert_eq!(
|
||||
coroutine_args.len(),
|
||||
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5,
|
||||
tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 6,
|
||||
"coroutine constructed with incorrect number of substitutions"
|
||||
);
|
||||
Ty::new(tcx, Coroutine(def_id, coroutine_args))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue