@@ -11,6 +11,7 @@ use rustc_data_structures::base_n;
1111use  rustc_data_structures:: fx:: FxHashMap ; 
1212use  rustc_hir as  hir; 
1313use  rustc_middle:: ty:: layout:: IntegerExt ; 
14+ use  rustc_middle:: ty:: TypeVisitableExt ; 
1415use  rustc_middle:: ty:: { 
1516    self ,  Const ,  ExistentialPredicate ,  FloatTy ,  FnSig ,  Instance ,  IntTy ,  List ,  Region ,  RegionKind , 
1617    TermKind ,  Ty ,  TyCtxt ,  UintTy , 
@@ -21,7 +22,9 @@ use rustc_span::sym;
2122use  rustc_target:: abi:: call:: { Conv ,  FnAbi ,  PassMode } ; 
2223use  rustc_target:: abi:: Integer ; 
2324use  rustc_target:: spec:: abi:: Abi ; 
25+ use  rustc_trait_selection:: traits; 
2426use  std:: fmt:: Write  as  _; 
27+ use  std:: iter; 
2528
2629use  crate :: typeid:: TypeIdOptions ; 
2730
@@ -1113,51 +1116,46 @@ pub fn typeid_for_instance<'tcx>(
11131116        instance. args  = strip_receiver_auto ( tcx,  instance. args ) 
11141117    } 
11151118
1119+     if  let  Some ( impl_id)  = tcx. impl_of_method ( instance. def_id ( ) ) 
1120+         && let  Some ( trait_ref)  = tcx. impl_trait_ref ( impl_id) 
1121+     { 
1122+         let  impl_method = tcx. associated_item ( instance. def_id ( ) ) ; 
1123+         let  method_id = impl_method
1124+             . trait_item_def_id 
1125+             . expect ( "Part of a trait implementation, but not linked to the def_id?" ) ; 
1126+         let  trait_method = tcx. associated_item ( method_id) ; 
1127+         if  traits:: is_vtable_safe_method ( tcx,  trait_ref. skip_binder ( ) . def_id ,  trait_method)  { 
1128+             // Trait methods will have a Self polymorphic parameter, where the concreteized 
1129+             // implementatation will not. We need to walk back to the more general trait method 
1130+             let  trait_ref = tcx. instantiate_and_normalize_erasing_regions ( 
1131+                 instance. args , 
1132+                 ty:: ParamEnv :: reveal_all ( ) , 
1133+                 trait_ref, 
1134+             ) ; 
1135+             let  invoke_ty = trait_object_ty ( tcx,  ty:: Binder :: dummy ( trait_ref) ) ; 
1136+ 
1137+             // At the call site, any call to this concrete function through a vtable will be 
1138+             // `Virtual(method_id, idx)` with appropriate arguments for the method. Since we have the 
1139+             // original method id, and we've recovered the trait arguments, we can make the callee 
1140+             // instance we're computing the alias set for match the caller instance. 
1141+             // 
1142+             // Right now, our code ignores the vtable index everywhere, so we use 0 as a placeholder. 
1143+             // If we ever *do* start encoding the vtable index, we will need to generate an alias set 
1144+             // based on which vtables we are putting this method into, as there will be more than one 
1145+             // index value when supertraits are involved. 
1146+             instance. def  = ty:: InstanceDef :: Virtual ( method_id,  0 ) ; 
1147+             let  abstract_trait_args =
1148+                 tcx. mk_args_trait ( invoke_ty,  trait_ref. args . into_iter ( ) . skip ( 1 ) ) ; 
1149+             instance. args  = instance. args . rebase_onto ( tcx,  impl_id,  abstract_trait_args) ; 
1150+         } 
1151+     } 
1152+ 
11161153    let  fn_abi = tcx
11171154        . fn_abi_of_instance ( tcx. param_env ( instance. def_id ( ) ) . and ( ( instance,  ty:: List :: empty ( ) ) ) ) 
11181155        . unwrap_or_else ( |instance| { 
11191156            bug ! ( "typeid_for_instance: couldn't get fn_abi of instance {:?}" ,  instance) 
11201157        } ) ; 
11211158
1122-     // If this instance is a method and self is a reference, get the impl it belongs to 
1123-     let  impl_def_id = tcx. impl_of_method ( instance. def_id ( ) ) ; 
1124-     if  impl_def_id. is_some ( )  && !fn_abi. args . is_empty ( )  && fn_abi. args [ 0 ] . layout . ty . is_ref ( )  { 
1125-         // If this impl is not an inherent impl, get the trait it implements 
1126-         if  let  Some ( trait_ref)  = tcx. impl_trait_ref ( impl_def_id. unwrap ( ) )  { 
1127-             // Transform the concrete self into a reference to a trait object 
1128-             let  existential_predicate = trait_ref. map_bound ( |trait_ref| { 
1129-                 ty:: ExistentialPredicate :: Trait ( ty:: ExistentialTraitRef :: erase_self_ty ( 
1130-                     tcx,  trait_ref, 
1131-                 ) ) 
1132-             } ) ; 
1133-             let  existential_predicates = tcx. mk_poly_existential_predicates ( & [ ty:: Binder :: dummy ( 
1134-                 existential_predicate. skip_binder ( ) , 
1135-             ) ] ) ; 
1136-             // Is the concrete self mutable? 
1137-             let  self_ty = if  fn_abi. args [ 0 ] . layout . ty . is_mutable_ptr ( )  { 
1138-                 Ty :: new_mut_ref ( 
1139-                     tcx, 
1140-                     tcx. lifetimes . re_erased , 
1141-                     Ty :: new_dynamic ( tcx,  existential_predicates,  tcx. lifetimes . re_erased ,  ty:: Dyn ) , 
1142-                 ) 
1143-             }  else  { 
1144-                 Ty :: new_imm_ref ( 
1145-                     tcx, 
1146-                     tcx. lifetimes . re_erased , 
1147-                     Ty :: new_dynamic ( tcx,  existential_predicates,  tcx. lifetimes . re_erased ,  ty:: Dyn ) , 
1148-                 ) 
1149-             } ; 
1150- 
1151-             // Replace the concrete self in an fn_abi clone by the reference to a trait object 
1152-             let  mut  fn_abi = fn_abi. clone ( ) ; 
1153-             // HACK(rcvalle): It is okay to not replace or update the entire ArgAbi here because the 
1154-             //   other fields are never used. 
1155-             fn_abi. args [ 0 ] . layout . ty  = self_ty; 
1156- 
1157-             return  typeid_for_fnabi ( tcx,  & fn_abi,  options) ; 
1158-         } 
1159-     } 
1160- 
11611159    typeid_for_fnabi ( tcx,  fn_abi,  options) 
11621160} 
11631161
@@ -1183,3 +1181,36 @@ fn strip_receiver_auto<'tcx>(
11831181    } ; 
11841182    tcx. mk_args_trait ( new_rcvr,  args. into_iter ( ) . skip ( 1 ) ) 
11851183} 
1184+ 
1185+ fn  trait_object_ty < ' tcx > ( tcx :  TyCtxt < ' tcx > ,  poly_trait_ref :  ty:: PolyTraitRef < ' tcx > )  -> Ty < ' tcx >  { 
1186+     assert ! ( !poly_trait_ref. has_non_region_param( ) ) ; 
1187+     let  principal_pred = poly_trait_ref. map_bound ( |trait_ref| { 
1188+         ty:: ExistentialPredicate :: Trait ( ty:: ExistentialTraitRef :: erase_self_ty ( tcx,  trait_ref) ) 
1189+     } ) ; 
1190+     let  mut  assoc_preds:  Vec < _ >  = traits:: supertraits ( tcx,  poly_trait_ref) 
1191+         . flat_map ( |super_poly_trait_ref| { 
1192+             tcx. associated_items ( super_poly_trait_ref. def_id ( ) ) 
1193+                 . in_definition_order ( ) 
1194+                 . filter ( |item| item. kind  == ty:: AssocKind :: Type ) 
1195+                 . map ( move  |assoc_ty| { 
1196+                     super_poly_trait_ref. map_bound ( |super_trait_ref| { 
1197+                         let  alias_ty = ty:: AliasTy :: new ( tcx,  assoc_ty. def_id ,  super_trait_ref. args ) ; 
1198+                         let  resolved = tcx. normalize_erasing_regions ( 
1199+                             ty:: ParamEnv :: reveal_all ( ) , 
1200+                             alias_ty. to_ty ( tcx) , 
1201+                         ) ; 
1202+                         ty:: ExistentialPredicate :: Projection ( ty:: ExistentialProjection  { 
1203+                             def_id :  assoc_ty. def_id , 
1204+                             args :  ty:: ExistentialTraitRef :: erase_self_ty ( tcx,  super_trait_ref) . args , 
1205+                             term :  resolved. into ( ) , 
1206+                         } ) 
1207+                     } ) 
1208+                 } ) 
1209+         } ) 
1210+         . collect ( ) ; 
1211+     assoc_preds. sort_by ( |a,  b| a. skip_binder ( ) . stable_cmp ( tcx,  & b. skip_binder ( ) ) ) ; 
1212+     let  preds = tcx. mk_poly_existential_predicates_from_iter ( 
1213+         iter:: once ( principal_pred) . chain ( assoc_preds. into_iter ( ) ) , 
1214+     ) ; 
1215+     Ty :: new_dynamic ( tcx,  preds,  tcx. lifetimes . re_erased ,  ty:: Dyn ) 
1216+ } 
0 commit comments