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.
@@ -1151,43 +1162,91 @@ pub fn typeid_for_instance<'tcx>(
1151
1162
} ;
1152
1163
let stripped_ty = strip_receiver_auto ( tcx, upcast_ty) ;
1153
1164
instance. args = tcx. mk_args_trait ( stripped_ty, instance. args . into_iter ( ) . skip ( 1 ) ) ;
1165
+ } else if let ty:: InstanceDef :: VTableShim ( def_id) = instance. def
1166
+ && let Some ( trait_id) = tcx. trait_of_item ( def_id)
1167
+ {
1168
+ // VTableShims may have a trait method, but a concrete Self. This is not suitable for a vtable,
1169
+ // as the caller will not know the concrete Self.
1170
+ let trait_ref = ty:: TraitRef :: new ( tcx, trait_id, instance. args ) ;
1171
+ let invoke_ty = trait_object_ty ( tcx, ty:: Binder :: dummy ( trait_ref) ) ;
1172
+ instance. args = tcx. mk_args_trait ( invoke_ty, trait_ref. args . into_iter ( ) . skip ( 1 ) ) ;
1154
1173
}
1155
1174
1156
- if !options. contains ( EncodeTyOptions :: NO_SELF_TYPE_ERASURE )
1157
- && let Some ( impl_id) = tcx. impl_of_method ( instance. def_id ( ) )
1158
- && let Some ( trait_ref) = tcx. impl_trait_ref ( impl_id)
1159
- {
1160
- let impl_method = tcx. associated_item ( instance. def_id ( ) ) ;
1161
- let method_id = impl_method
1162
- . trait_item_def_id
1163
- . expect ( "Part of a trait implementation, but not linked to the def_id?" ) ;
1164
- let trait_method = tcx. associated_item ( method_id) ;
1165
- let trait_id = trait_ref. skip_binder ( ) . def_id ;
1166
- if traits:: is_vtable_safe_method ( tcx, trait_id, trait_method)
1167
- && tcx. object_safety_violations ( trait_id) . is_empty ( )
1175
+ if !options. contains ( EncodeTyOptions :: NO_SELF_TYPE_ERASURE ) {
1176
+ if let Some ( impl_id) = tcx. impl_of_method ( instance. def_id ( ) )
1177
+ && let Some ( trait_ref) = tcx. impl_trait_ref ( impl_id)
1168
1178
{
1169
- // Trait methods will have a Self polymorphic parameter, where the concreteized
1170
- // implementatation will not. We need to walk back to the more general trait method
1171
- let trait_ref = tcx. instantiate_and_normalize_erasing_regions (
1172
- instance. args ,
1173
- ty:: ParamEnv :: reveal_all ( ) ,
1174
- trait_ref,
1175
- ) ;
1179
+ let impl_method = tcx. associated_item ( instance. def_id ( ) ) ;
1180
+ let method_id = impl_method
1181
+ . trait_item_def_id
1182
+ . expect ( "Part of a trait implementation, but not linked to the def_id?" ) ;
1183
+ let trait_method = tcx. associated_item ( method_id) ;
1184
+ let trait_id = trait_ref. skip_binder ( ) . def_id ;
1185
+ if traits:: is_vtable_safe_method ( tcx, trait_id, trait_method)
1186
+ && tcx. object_safety_violations ( trait_id) . is_empty ( )
1187
+ {
1188
+ // Trait methods will have a Self polymorphic parameter, where the concreteized
1189
+ // implementatation will not. We need to walk back to the more general trait method
1190
+ let trait_ref = tcx. instantiate_and_normalize_erasing_regions (
1191
+ instance. args ,
1192
+ ty:: ParamEnv :: reveal_all ( ) ,
1193
+ trait_ref,
1194
+ ) ;
1195
+ let invoke_ty = trait_object_ty ( tcx, ty:: Binder :: dummy ( trait_ref) ) ;
1196
+
1197
+ // At the call site, any call to this concrete function through a vtable will be
1198
+ // `Virtual(method_id, idx)` with appropriate arguments for the method. Since we have the
1199
+ // original method id, and we've recovered the trait arguments, we can make the callee
1200
+ // instance we're computing the alias set for match the caller instance.
1201
+ //
1202
+ // Right now, our code ignores the vtable index everywhere, so we use 0 as a placeholder.
1203
+ // If we ever *do* start encoding the vtable index, we will need to generate an alias set
1204
+ // based on which vtables we are putting this method into, as there will be more than one
1205
+ // index value when supertraits are involved.
1206
+ instance. def = ty:: InstanceDef :: Virtual ( method_id, 0 ) ;
1207
+ let abstract_trait_args =
1208
+ tcx. mk_args_trait ( invoke_ty, trait_ref. args . into_iter ( ) . skip ( 1 ) ) ;
1209
+ instance. args = instance. args . rebase_onto ( tcx, impl_id, abstract_trait_args) ;
1210
+ }
1211
+ } else if tcx. is_closure_like ( instance. def_id ( ) ) {
1212
+ // We're either a closure or a coroutine. Our goal is to find the trait we're defined on,
1213
+ // instantiate it, and take the type of its only method as our own.
1214
+ let closure_ty = instance. ty ( tcx, ty:: ParamEnv :: reveal_all ( ) ) ;
1215
+ let ( trait_id, inputs) = match closure_ty. kind ( ) {
1216
+ ty:: Closure ( ..) => {
1217
+ let closure_args = instance. args . as_closure ( ) ;
1218
+ let trait_id = tcx. fn_trait_kind_to_def_id ( closure_args. kind ( ) ) . unwrap ( ) ;
1219
+ let tuple_args =
1220
+ tcx. instantiate_bound_regions_with_erased ( closure_args. sig ( ) ) . inputs ( ) [ 0 ] ;
1221
+ ( trait_id, tuple_args)
1222
+ }
1223
+ ty:: Coroutine ( ..) => (
1224
+ tcx. require_lang_item ( LangItem :: Coroutine , None ) ,
1225
+ instance. args . as_coroutine ( ) . resume_ty ( ) ,
1226
+ ) ,
1227
+ ty:: CoroutineClosure ( ..) => (
1228
+ tcx. require_lang_item ( LangItem :: FnOnce , None ) ,
1229
+ tcx. instantiate_bound_regions_with_erased (
1230
+ instance. args . as_coroutine_closure ( ) . coroutine_closure_sig ( ) ,
1231
+ )
1232
+ . tupled_inputs_ty ,
1233
+ ) ,
1234
+ x => bug ! ( "Unexpected type kind for closure-like: {x:?}" ) ,
1235
+ } ;
1236
+ let trait_ref = ty:: TraitRef :: new ( tcx, trait_id, [ closure_ty, inputs] ) ;
1176
1237
let invoke_ty = trait_object_ty ( tcx, ty:: Binder :: dummy ( trait_ref) ) ;
1238
+ let abstract_args = tcx. mk_args_trait ( invoke_ty, trait_ref. args . into_iter ( ) . skip ( 1 ) ) ;
1239
+ // There should be exactly one method on this trait, and it should be the one we're
1240
+ // defining.
1241
+ let call = tcx
1242
+ . associated_items ( trait_id)
1243
+ . in_definition_order ( )
1244
+ . find ( |it| it. kind == ty:: AssocKind :: Fn )
1245
+ . expect ( "No call-family function on closure-like Fn trait?" )
1246
+ . def_id ;
1177
1247
1178
- // At the call site, any call to this concrete function through a vtable will be
1179
- // `Virtual(method_id, idx)` with appropriate arguments for the method. Since we have the
1180
- // original method id, and we've recovered the trait arguments, we can make the callee
1181
- // instance we're computing the alias set for match the caller instance.
1182
- //
1183
- // Right now, our code ignores the vtable index everywhere, so we use 0 as a placeholder.
1184
- // If we ever *do* start encoding the vtable index, we will need to generate an alias set
1185
- // based on which vtables we are putting this method into, as there will be more than one
1186
- // index value when supertraits are involved.
1187
- instance. def = ty:: InstanceDef :: Virtual ( method_id, 0 ) ;
1188
- let abstract_trait_args =
1189
- tcx. mk_args_trait ( invoke_ty, trait_ref. args . into_iter ( ) . skip ( 1 ) ) ;
1190
- instance. args = instance. args . rebase_onto ( tcx, impl_id, abstract_trait_args) ;
1248
+ instance. def = ty:: InstanceDef :: Virtual ( call, 0 ) ;
1249
+ instance. args = abstract_args;
1191
1250
}
1192
1251
}
1193
1252
0 commit comments