1010use rustc_data_structures:: base_n;
1111use rustc_data_structures:: fx:: FxHashMap ;
1212use rustc_hir as hir;
13+ use rustc_hir:: lang_items:: LangItem ;
1314use rustc_middle:: ty:: layout:: IntegerExt ;
1415use rustc_middle:: ty:: TypeVisitableExt ;
1516use rustc_middle:: ty:: {
@@ -641,9 +642,7 @@ fn encode_ty<'tcx>(
641642 }
642643
643644 // 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) => {
647646 // u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>,
648647 // as vendor extended type.
649648 let mut s = String :: new ( ) ;
@@ -654,6 +653,18 @@ fn encode_ty<'tcx>(
654653 typeid. push_str ( & s) ;
655654 }
656655
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+
657668 ty:: Coroutine ( def_id, args, ..) => {
658669 // u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>,
659670 // as vendor extended type.
@@ -1151,43 +1162,91 @@ pub fn typeid_for_instance<'tcx>(
11511162 } ;
11521163 let stripped_ty = strip_receiver_auto ( tcx, upcast_ty) ;
11531164 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 ) ) ;
11541173 }
11551174
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)
11681178 {
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] ) ;
11761237 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 ;
11771247
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;
11911250 }
11921251 }
11931252
0 commit comments