@@ -3,8 +3,8 @@ use rustc_hir::def_id::DefId;
3
3
use rustc_hir:: lang_items:: LangItem ;
4
4
use rustc_middle:: mir:: * ;
5
5
use rustc_middle:: query:: Providers ;
6
- use rustc_middle:: ty:: GenericArgs ;
7
6
use rustc_middle:: ty:: { self , CoroutineArgs , EarlyBinder , Ty , TyCtxt } ;
7
+ use rustc_middle:: ty:: { GenericArgs , CAPTURE_STRUCT_LOCAL } ;
8
8
use rustc_target:: abi:: { FieldIdx , VariantIdx , FIRST_VARIANT } ;
9
9
10
10
use rustc_index:: { Idx , IndexVec } ;
@@ -66,6 +66,21 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
66
66
build_call_shim ( tcx, instance, Some ( Adjustment :: RefMut ) , CallKind :: Direct ( call_mut) )
67
67
}
68
68
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
+
69
84
ty:: InstanceDef :: DropGlue ( def_id, ty) => {
70
85
// FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end
71
86
// 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
981
996
let source = MirSource :: from_instance ( ty:: InstanceDef :: FnPtrAddrShim ( def_id, self_ty) ) ;
982
997
new_body ( source, IndexVec :: from_elem_n ( start_block, 1 ) , locals, sig. inputs ( ) . len ( ) , span)
983
998
}
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