@@ -745,6 +745,19 @@ fn encode_ty<'tcx>(
745
745
typeid
746
746
}
747
747
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
+
748
761
/// Transforms predicates for being encoded and used in the substitution dictionary.
749
762
fn transform_predicates < ' tcx > (
750
763
tcx : TyCtxt < ' tcx > ,
@@ -1112,8 +1125,48 @@ pub fn typeid_for_instance<'tcx>(
1112
1125
mut instance : Instance < ' tcx > ,
1113
1126
options : TypeIdOptions ,
1114
1127
) -> 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 ) ;
1117
1170
}
1118
1171
1119
1172
if let Some ( impl_id) = tcx. impl_of_method ( instance. def_id ( ) )
0 commit comments