@@ -745,6 +745,19 @@ fn encode_ty<'tcx>(
745745 typeid
746746}
747747
748+ /// Creates a trait object.
749+ #[ inline]
750+ fn new_dynamic_trait < ' tcx > (
751+ tcx : TyCtxt < ' tcx > ,
752+ def_id : DefId ,
753+ args : GenericArgsRef < ' tcx > ,
754+ ) -> Ty < ' tcx > {
755+ let predicate =
756+ ty:: ExistentialPredicate :: Trait ( ty:: ExistentialTraitRef { def_id : def_id, args : args } ) ;
757+ let predicates = tcx. mk_poly_existential_predicates ( & [ ty:: Binder :: dummy ( predicate) ] ) ;
758+ Ty :: new_dynamic ( tcx, predicates, tcx. lifetimes . re_erased , ty:: Dyn )
759+ }
760+
748761/// Transforms predicates for being encoded and used in the substitution dictionary.
749762fn transform_predicates < ' tcx > (
750763 tcx : TyCtxt < ' tcx > ,
@@ -1112,8 +1125,48 @@ pub fn typeid_for_instance<'tcx>(
11121125 mut instance : Instance < ' tcx > ,
11131126 options : TypeIdOptions ,
11141127) -> String {
1115- if matches ! ( instance. def, ty:: InstanceDef :: Virtual ( ..) ) {
1116- instance. args = strip_receiver_auto ( tcx, instance. args )
1128+ if ( matches ! ( instance. def, ty:: InstanceDef :: Virtual ( ..) )
1129+ && instance. def_id ( ) == tcx. lang_items ( ) . drop_in_place_fn ( ) . unwrap ( ) )
1130+ || matches ! ( instance. def, ty:: InstanceDef :: DropGlue ( _, Some ( _ty) ) )
1131+ {
1132+ // Adjust the type ids of DropGlues
1133+ //
1134+ // DropGlues may have indirect calls to one or more given types drop function. Rust allows
1135+ // for types to be erased to any trait object and retains the drop function for the original
1136+ // type, which means at the indirect call sites in DropGlues, when typeid_for_fnabi is
1137+ // called a second time, it only has information after type erasure and it could be a call
1138+ // on any arbitrary trait object. Normalize them to a synthesized Drop trait object, both on
1139+ // declaration/definition, and during code generation at call sites so they have the same
1140+ // type id and match.
1141+ //
1142+ // FIXME(rcvalle): This allows a drop call on any trait object of types that have a
1143+ // non-empty DropGlue to call the DropGlue of any other types that have a non-empty
1144+ // DropGlue.
1145+ let fn_abi = tcx
1146+ . fn_abi_of_instance ( tcx. param_env ( instance. def_id ( ) ) . and ( ( instance, ty:: List :: empty ( ) ) ) )
1147+ . unwrap_or_else ( |instance| {
1148+ bug ! ( "typeid_for_instance: couldn't get fn_abi of instance {:?}" , instance)
1149+ } ) ;
1150+ let self_ty = if fn_abi. args [ 0 ] . layout . ty . is_mutable_ptr ( ) {
1151+ Ty :: new_mut_ref (
1152+ tcx,
1153+ tcx. lifetimes . re_erased ,
1154+ new_dynamic_trait ( tcx, tcx. lang_items ( ) . drop_trait ( ) . unwrap ( ) , List :: empty ( ) ) ,
1155+ )
1156+ } else {
1157+ Ty :: new_imm_ref (
1158+ tcx,
1159+ tcx. lifetimes . re_erased ,
1160+ new_dynamic_trait ( tcx, tcx. lang_items ( ) . drop_trait ( ) . unwrap ( ) , List :: empty ( ) ) ,
1161+ )
1162+ } ;
1163+ // HACK(rcvalle): It is okay to not replace or update the entire ArgAbi here because the
1164+ // other fields are never used.
1165+ let mut fn_abi = fn_abi. clone ( ) ;
1166+ fn_abi. args [ 0 ] . layout . ty = self_ty;
1167+ return typeid_for_fnabi ( tcx, & fn_abi, options) ;
1168+ } else if matches ! ( instance. def, ty:: InstanceDef :: Virtual ( ..) ) {
1169+ instance. args = strip_receiver_auto ( tcx, instance. args ) ;
11171170 }
11181171
11191172 if let Some ( impl_id) = tcx. impl_of_method ( instance. def_id ( ) )
0 commit comments