@@ -147,16 +147,21 @@ fn prepare_vtable_segments_inner<'tcx, T>(
147
147
}
148
148
}
149
149
150
- // Other than the left-most path, vptr should be emitted for each trait.
151
- emit_vptr_on_new_entry = true ;
152
-
153
150
// emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
154
151
while let Some ( ( inner_most_trait_ref, emit_vptr, mut siblings) ) = stack. pop ( ) {
155
152
segment_visitor ( VtblSegment :: TraitOwnEntries {
156
153
trait_ref : inner_most_trait_ref,
157
154
emit_vptr,
158
155
} ) ?;
159
156
157
+ // If we've emitted (fed to `segment_visitor`) a trait that has methods present in the vtable,
158
+ // we'll need to emit vptrs from now on.
159
+ if !emit_vptr_on_new_entry
160
+ && has_own_existential_vtable_entries ( tcx, inner_most_trait_ref. def_id ( ) )
161
+ {
162
+ emit_vptr_on_new_entry = true ;
163
+ }
164
+
160
165
if let Some ( next_inner_most_trait_ref) =
161
166
siblings. find ( |& sibling| visited. insert ( sibling. to_predicate ( tcx) ) )
162
167
{
@@ -196,11 +201,23 @@ fn dump_vtable_entries<'tcx>(
196
201
} ) ;
197
202
}
198
203
204
+ fn has_own_existential_vtable_entries ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> bool {
205
+ own_existential_vtable_entries_iter ( tcx, trait_def_id) . next ( ) . is_some ( )
206
+ }
207
+
199
208
fn own_existential_vtable_entries ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> & [ DefId ] {
209
+ tcx. arena . alloc_from_iter ( own_existential_vtable_entries_iter ( tcx, trait_def_id) )
210
+ }
211
+
212
+ fn own_existential_vtable_entries_iter (
213
+ tcx : TyCtxt < ' _ > ,
214
+ trait_def_id : DefId ,
215
+ ) -> impl Iterator < Item = DefId > + ' _ {
200
216
let trait_methods = tcx
201
217
. associated_items ( trait_def_id)
202
218
. in_definition_order ( )
203
219
. filter ( |item| item. kind == ty:: AssocKind :: Fn ) ;
220
+
204
221
// Now list each method's DefId (for within its trait).
205
222
let own_entries = trait_methods. filter_map ( move |& trait_method| {
206
223
debug ! ( "own_existential_vtable_entry: trait_method={:?}" , trait_method) ;
@@ -215,7 +232,7 @@ fn own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &[Def
215
232
Some ( def_id)
216
233
} ) ;
217
234
218
- tcx . arena . alloc_from_iter ( own_entries. into_iter ( ) )
235
+ own_entries
219
236
}
220
237
221
238
/// Given a trait `trait_ref`, iterates the vtable entries
0 commit comments