@@ -1150,6 +1150,40 @@ pub fn typeid_for_instance<'tcx>(
11501150 tcx. mk_args_trait ( invoke_ty, trait_ref. args . into_iter ( ) . skip ( 1 ) ) ;
11511151 instance. args = instance. args . rebase_onto ( tcx, impl_id, abstract_trait_args) ;
11521152 }
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+ }
11531187 }
11541188
11551189 let fn_abi = tcx
0 commit comments