@@ -1150,6 +1150,40 @@ pub fn typeid_for_instance<'tcx>(
1150
1150
tcx. mk_args_trait ( invoke_ty, trait_ref. args . into_iter ( ) . skip ( 1 ) ) ;
1151
1151
instance. args = instance. args . rebase_onto ( tcx, impl_id, abstract_trait_args) ;
1152
1152
}
1153
+ } else if tcx. is_closure_like ( instance. def_id ( ) ) {
1154
+ // We're either a closure or a coroutine. Our goal is to find the trait we're defined on,
1155
+ // instantiate it, and take the type of its only method as our own.
1156
+ let closure_ty = instance. ty ( tcx, ty:: ParamEnv :: reveal_all ( ) ) ;
1157
+ match closure_ty. kind ( ) {
1158
+ ty:: Closure ( _def_id, args) => {
1159
+ let ca = ty:: ClosureArgs { args } ;
1160
+ let trait_id = tcx
1161
+ . fn_trait_kind_to_def_id ( ca. kind ( ) )
1162
+ . expect ( "Resolving abstract closure typeid for undefined Fn trait?" ) ;
1163
+ let tuple_args = ca
1164
+ . sig ( )
1165
+ . inputs ( )
1166
+ . no_bound_vars ( )
1167
+ . expect ( "We are at codegen, this instance should be fully instantiated." ) [ 0 ] ;
1168
+ let trait_ref = ty:: TraitRef :: new ( tcx, trait_id, [ closure_ty, tuple_args] ) ;
1169
+ let invoke_ty = trait_object_ty ( tcx, ty:: Binder :: dummy ( trait_ref) ) ;
1170
+ let abstract_args =
1171
+ tcx. mk_args_trait ( invoke_ty, trait_ref. args . into_iter ( ) . skip ( 1 ) ) ;
1172
+ // There should be exactly one method on this trait, and it should be the one we're
1173
+ // defining.
1174
+ let call = tcx
1175
+ . associated_items ( trait_id)
1176
+ . in_definition_order ( )
1177
+ . find ( |it| it. kind == ty:: AssocKind :: Fn )
1178
+ . expect ( "No call-family function on closure-like Fn trait?" )
1179
+ . def_id ;
1180
+
1181
+ instance. def = ty:: InstanceDef :: Virtual ( call, 0 ) ;
1182
+ instance. args = abstract_args;
1183
+ }
1184
+ ty:: CoroutineClosure ( _def_id, _args) => unimplemented ! ( ) ,
1185
+ x => bug ! ( "Unexpected type kind for closure-like: {x:?}" ) ,
1186
+ }
1153
1187
}
1154
1188
1155
1189
let fn_abi = tcx
0 commit comments