@@ -1112,8 +1112,40 @@ pub fn typeid_for_instance<'tcx>(
11121112 mut instance : Instance < ' tcx > ,
11131113 options : TypeIdOptions ,
11141114) -> String {
1115- if matches ! ( instance. def, ty:: InstanceDef :: Virtual ( ..) ) {
1116- instance. args = strip_receiver_auto ( tcx, instance. args )
1115+ if ( matches ! ( instance. def, ty:: InstanceDef :: Virtual ( ..) )
1116+ && Some ( instance. def_id ( ) ) == tcx. lang_items ( ) . drop_in_place_fn ( ) )
1117+ || matches ! ( instance. def, ty:: InstanceDef :: DropGlue ( ..) )
1118+ {
1119+ // Adjust the type ids of DropGlues
1120+ //
1121+ // DropGlues may have indirect calls to one or more given types drop function. Rust allows
1122+ // for types to be erased to any trait object and retains the drop function for the original
1123+ // type, which means at the indirect call sites in DropGlues, when typeid_for_fnabi is
1124+ // called a second time, it only has information after type erasure and it could be a call
1125+ // on any arbitrary trait object. Normalize them to a synthesized Drop trait object, both on
1126+ // declaration/definition, and during code generation at call sites so they have the same
1127+ // type id and match.
1128+ //
1129+ // FIXME(rcvalle): This allows a drop call on any trait object to call the drop function of
1130+ // any other type.
1131+ //
1132+ let def_id = tcx
1133+ . lang_items ( )
1134+ . drop_trait ( )
1135+ . unwrap_or_else ( || bug ! ( "typeid_for_instance: couldn't get drop_trait lang item" ) ) ;
1136+ let predicate = ty:: ExistentialPredicate :: Trait ( ty:: ExistentialTraitRef {
1137+ def_id : def_id,
1138+ args : List :: empty ( ) ,
1139+ } ) ;
1140+ let predicates = tcx. mk_poly_existential_predicates ( & [ ty:: Binder :: dummy ( predicate) ] ) ;
1141+ let self_ty = Ty :: new_imm_ref (
1142+ tcx,
1143+ tcx. lifetimes . re_erased ,
1144+ Ty :: new_dynamic ( tcx, predicates, tcx. lifetimes . re_erased , ty:: Dyn ) ,
1145+ ) ;
1146+ instance. args = tcx. mk_args_trait ( self_ty, List :: empty ( ) ) ;
1147+ } else if matches ! ( instance. def, ty:: InstanceDef :: Virtual ( ..) ) {
1148+ instance. args = strip_receiver_auto ( tcx, instance. args ) ;
11171149 }
11181150
11191151 if let Some ( impl_id) = tcx. impl_of_method ( instance. def_id ( ) )
0 commit comments