@@ -3,8 +3,8 @@ use rustc_hir::def_id::DefId;
33use rustc_hir:: lang_items:: LangItem ;
44use rustc_middle:: mir:: * ;
55use rustc_middle:: query:: Providers ;
6- use rustc_middle:: ty:: GenericArgs ;
76use rustc_middle:: ty:: { self , CoroutineArgs , EarlyBinder , Ty , TyCtxt } ;
7+ use rustc_middle:: ty:: { GenericArgs , CAPTURE_STRUCT_LOCAL } ;
88use rustc_target:: abi:: { FieldIdx , VariantIdx , FIRST_VARIANT } ;
99
1010use rustc_index:: { Idx , IndexVec } ;
@@ -66,6 +66,21 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
6666 build_call_shim ( tcx, instance, Some ( Adjustment :: RefMut ) , CallKind :: Direct ( call_mut) )
6767 }
6868
69+ ty:: InstanceDef :: ConstructCoroutineInClosureShim {
70+ coroutine_closure_def_id,
71+ target_kind,
72+ } => match target_kind {
73+ ty:: ClosureKind :: Fn => unreachable ! ( "shouldn't be building shim for Fn" ) ,
74+ ty:: ClosureKind :: FnMut => {
75+ let body = build_construct_coroutine_by_mut_shim ( tcx, coroutine_closure_def_id) ;
76+ // No need to optimize the body, it has already been optimized.
77+ return body;
78+ }
79+ ty:: ClosureKind :: FnOnce => {
80+ build_construct_coroutine_by_move_shim ( tcx, coroutine_closure_def_id)
81+ }
82+ } ,
83+
6984 ty:: InstanceDef :: DropGlue ( def_id, ty) => {
7085 // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end
7186 // of this function. Is this intentional?
@@ -981,3 +996,107 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t
981996 let source = MirSource :: from_instance ( ty:: InstanceDef :: FnPtrAddrShim ( def_id, self_ty) ) ;
982997 new_body ( source, IndexVec :: from_elem_n ( start_block, 1 ) , locals, sig. inputs ( ) . len ( ) , span)
983998}
999+
1000+ fn build_construct_coroutine_by_move_shim < ' tcx > (
1001+ tcx : TyCtxt < ' tcx > ,
1002+ coroutine_closure_def_id : DefId ,
1003+ ) -> Body < ' tcx > {
1004+ let self_ty = tcx. type_of ( coroutine_closure_def_id) . instantiate_identity ( ) ;
1005+ let ty:: CoroutineClosure ( _, args) = * self_ty. kind ( ) else {
1006+ bug ! ( ) ;
1007+ } ;
1008+
1009+ let poly_sig = args. as_coroutine_closure ( ) . coroutine_closure_sig ( ) . map_bound ( |sig| {
1010+ tcx. mk_fn_sig (
1011+ [ self_ty] . into_iter ( ) . chain ( sig. tupled_inputs_ty . tuple_fields ( ) ) ,
1012+ sig. to_coroutine_given_kind_and_upvars (
1013+ tcx,
1014+ args. as_coroutine_closure ( ) . parent_args ( ) ,
1015+ tcx. coroutine_for_closure ( coroutine_closure_def_id) ,
1016+ ty:: ClosureKind :: FnOnce ,
1017+ tcx. lifetimes . re_erased ,
1018+ args. as_coroutine_closure ( ) . tupled_upvars_ty ( ) ,
1019+ args. as_coroutine_closure ( ) . coroutine_captures_by_ref_ty ( ) ,
1020+ ) ,
1021+ sig. c_variadic ,
1022+ sig. unsafety ,
1023+ sig. abi ,
1024+ )
1025+ } ) ;
1026+ let sig = tcx. liberate_late_bound_regions ( coroutine_closure_def_id, poly_sig) ;
1027+ let ty:: Coroutine ( coroutine_def_id, coroutine_args) = * sig. output ( ) . kind ( ) else {
1028+ bug ! ( ) ;
1029+ } ;
1030+
1031+ let span = tcx. def_span ( coroutine_closure_def_id) ;
1032+ let locals = local_decls_for_sig ( & sig, span) ;
1033+
1034+ let mut fields = vec ! [ ] ;
1035+ for idx in 1 ..sig. inputs ( ) . len ( ) {
1036+ fields. push ( Operand :: Move ( Local :: from_usize ( idx + 1 ) . into ( ) ) ) ;
1037+ }
1038+ for ( idx, ty) in args. as_coroutine_closure ( ) . upvar_tys ( ) . iter ( ) . enumerate ( ) {
1039+ fields. push ( Operand :: Move ( tcx. mk_place_field (
1040+ Local :: from_usize ( 1 ) . into ( ) ,
1041+ FieldIdx :: from_usize ( idx) ,
1042+ ty,
1043+ ) ) ) ;
1044+ }
1045+
1046+ let source_info = SourceInfo :: outermost ( span) ;
1047+ let rvalue = Rvalue :: Aggregate (
1048+ Box :: new ( AggregateKind :: Coroutine ( coroutine_def_id, coroutine_args) ) ,
1049+ IndexVec :: from_raw ( fields) ,
1050+ ) ;
1051+ let stmt = Statement {
1052+ source_info,
1053+ kind : StatementKind :: Assign ( Box :: new ( ( Place :: return_place ( ) , rvalue) ) ) ,
1054+ } ;
1055+ let statements = vec ! [ stmt] ;
1056+ let start_block = BasicBlockData {
1057+ statements,
1058+ terminator : Some ( Terminator { source_info, kind : TerminatorKind :: Return } ) ,
1059+ is_cleanup : false ,
1060+ } ;
1061+
1062+ let source = MirSource :: from_instance ( ty:: InstanceDef :: ConstructCoroutineInClosureShim {
1063+ coroutine_closure_def_id,
1064+ target_kind : ty:: ClosureKind :: FnOnce ,
1065+ } ) ;
1066+
1067+ new_body ( source, IndexVec :: from_elem_n ( start_block, 1 ) , locals, sig. inputs ( ) . len ( ) , span)
1068+ }
1069+
1070+ fn build_construct_coroutine_by_mut_shim < ' tcx > (
1071+ tcx : TyCtxt < ' tcx > ,
1072+ coroutine_closure_def_id : DefId ,
1073+ ) -> Body < ' tcx > {
1074+ let mut body = tcx. optimized_mir ( coroutine_closure_def_id) . clone ( ) ;
1075+ let coroutine_closure_ty = tcx. type_of ( coroutine_closure_def_id) . instantiate_identity ( ) ;
1076+ let ty:: CoroutineClosure ( _, args) = * coroutine_closure_ty. kind ( ) else {
1077+ bug ! ( ) ;
1078+ } ;
1079+ let args = args. as_coroutine_closure ( ) ;
1080+
1081+ body. local_decls [ RETURN_PLACE ] . ty =
1082+ tcx. instantiate_bound_regions_with_erased ( args. coroutine_closure_sig ( ) . map_bound ( |sig| {
1083+ sig. to_coroutine_given_kind_and_upvars (
1084+ tcx,
1085+ args. parent_args ( ) ,
1086+ tcx. coroutine_for_closure ( coroutine_closure_def_id) ,
1087+ ty:: ClosureKind :: FnMut ,
1088+ tcx. lifetimes . re_erased ,
1089+ args. tupled_upvars_ty ( ) ,
1090+ args. coroutine_captures_by_ref_ty ( ) ,
1091+ )
1092+ } ) ) ;
1093+ body. local_decls [ CAPTURE_STRUCT_LOCAL ] . ty =
1094+ Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , coroutine_closure_ty) ;
1095+
1096+ body. source = MirSource :: from_instance ( ty:: InstanceDef :: ConstructCoroutineInClosureShim {
1097+ coroutine_closure_def_id,
1098+ target_kind : ty:: ClosureKind :: FnMut ,
1099+ } ) ;
1100+
1101+ body
1102+ }
0 commit comments