10
10
use rustc_data_structures:: base_n;
11
11
use rustc_data_structures:: fx:: FxHashMap ;
12
12
use rustc_hir as hir;
13
+ use rustc_hir:: lang_items:: LangItem ;
13
14
use rustc_middle:: ty:: layout:: IntegerExt ;
14
15
use rustc_middle:: ty:: TypeVisitableExt ;
15
16
use rustc_middle:: ty:: {
@@ -641,9 +642,7 @@ fn encode_ty<'tcx>(
641
642
}
642
643
643
644
// Function types
644
- ty:: FnDef ( def_id, args)
645
- | ty:: Closure ( def_id, args)
646
- | ty:: CoroutineClosure ( def_id, args) => {
645
+ ty:: FnDef ( def_id, args) | ty:: Closure ( def_id, args) => {
647
646
// u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>,
648
647
// as vendor extended type.
649
648
let mut s = String :: new ( ) ;
@@ -654,6 +653,18 @@ fn encode_ty<'tcx>(
654
653
typeid. push_str ( & s) ;
655
654
}
656
655
656
+ ty:: CoroutineClosure ( def_id, args) => {
657
+ // u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>,
658
+ // as vendor extended type.
659
+ let mut s = String :: new ( ) ;
660
+ let name = encode_ty_name ( tcx, * def_id) ;
661
+ let _ = write ! ( s, "u{}{}" , name. len( ) , & name) ;
662
+ let parent_args = tcx. mk_args ( args. as_coroutine_closure ( ) . parent_args ( ) ) ;
663
+ s. push_str ( & encode_args ( tcx, parent_args, dict, options) ) ;
664
+ compress ( dict, DictKey :: Ty ( ty, TyQ :: None ) , & mut s) ;
665
+ typeid. push_str ( & s) ;
666
+ }
667
+
657
668
ty:: Coroutine ( def_id, args, ..) => {
658
669
// u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>,
659
670
// as vendor extended type.
@@ -1142,6 +1153,14 @@ pub fn typeid_for_instance<'tcx>(
1142
1153
instance. args = tcx. mk_args_trait ( self_ty, List :: empty ( ) ) ;
1143
1154
} else if matches ! ( instance. def, ty:: InstanceDef :: Virtual ( ..) ) {
1144
1155
instance. args = strip_receiver_auto ( tcx, instance. args ) ;
1156
+ } else if let ty:: InstanceDef :: VTableShim ( def_id) = instance. def
1157
+ && let Some ( trait_id) = tcx. trait_of_item ( def_id)
1158
+ {
1159
+ // VTableShims may have a trait method, but a concrete Self. This is not suitable for a vtable,
1160
+ // as the caller will not know the concrete Self.
1161
+ let trait_ref = ty:: TraitRef :: new ( tcx, trait_id, instance. args ) ;
1162
+ let invoke_ty = trait_object_ty ( tcx, ty:: Binder :: dummy ( trait_ref) ) ;
1163
+ instance. args = tcx. mk_args_trait ( invoke_ty, trait_ref. args . into_iter ( ) . skip ( 1 ) ) ;
1145
1164
}
1146
1165
1147
1166
if !options. contains ( EncodeTyOptions :: NO_SELF_TYPE_ERASURE )
@@ -1180,6 +1199,45 @@ pub fn typeid_for_instance<'tcx>(
1180
1199
tcx. mk_args_trait ( invoke_ty, trait_ref. args . into_iter ( ) . skip ( 1 ) ) ;
1181
1200
instance. args = instance. args . rebase_onto ( tcx, impl_id, abstract_trait_args) ;
1182
1201
}
1202
+ } else if tcx. is_closure_like ( instance. def_id ( ) ) {
1203
+ // We're either a closure or a coroutine. Our goal is to find the trait we're defined on,
1204
+ // instantiate it, and take the type of its only method as our own.
1205
+ let closure_ty = instance. ty ( tcx, ty:: ParamEnv :: reveal_all ( ) ) ;
1206
+ let ( trait_id, inputs) = match closure_ty. kind ( ) {
1207
+ ty:: Closure ( ..) => {
1208
+ let closure_args = instance. args . as_closure ( ) ;
1209
+ let trait_id = tcx. fn_trait_kind_to_def_id ( closure_args. kind ( ) ) . unwrap ( ) ;
1210
+ let tuple_args =
1211
+ tcx. instantiate_bound_regions_with_erased ( closure_args. sig ( ) ) . inputs ( ) [ 0 ] ;
1212
+ ( trait_id, tuple_args)
1213
+ }
1214
+ ty:: Coroutine ( ..) => (
1215
+ tcx. require_lang_item ( LangItem :: Coroutine , None ) ,
1216
+ instance. args . as_coroutine ( ) . resume_ty ( ) ,
1217
+ ) ,
1218
+ ty:: CoroutineClosure ( ..) => (
1219
+ tcx. require_lang_item ( LangItem :: FnOnce , None ) ,
1220
+ tcx. instantiate_bound_regions_with_erased (
1221
+ instance. args . as_coroutine_closure ( ) . coroutine_closure_sig ( ) ,
1222
+ )
1223
+ . tupled_inputs_ty ,
1224
+ ) ,
1225
+ x => bug ! ( "Unexpected type kind for closure-like: {x:?}" ) ,
1226
+ } ;
1227
+ let trait_ref = ty:: TraitRef :: new ( tcx, trait_id, [ closure_ty, inputs] ) ;
1228
+ let invoke_ty = trait_object_ty ( tcx, ty:: Binder :: dummy ( trait_ref) ) ;
1229
+ let abstract_args = tcx. mk_args_trait ( invoke_ty, trait_ref. args . into_iter ( ) . skip ( 1 ) ) ;
1230
+ // There should be exactly one method on this trait, and it should be the one we're
1231
+ // defining.
1232
+ let call = tcx
1233
+ . associated_items ( trait_id)
1234
+ . in_definition_order ( )
1235
+ . find ( |it| it. kind == ty:: AssocKind :: Fn )
1236
+ . expect ( "No call-family function on closure-like Fn trait?" )
1237
+ . def_id ;
1238
+
1239
+ instance. def = ty:: InstanceDef :: Virtual ( call, 0 ) ;
1240
+ instance. args = abstract_args;
1183
1241
}
1184
1242
1185
1243
let fn_abi = tcx
0 commit comments