@@ -153,16 +153,26 @@ fn prepare_vtable_segments_inner<'tcx, T>(
153153
154154 // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
155155 while let Some ( ( inner_most_trait_ref, emit_vptr, mut siblings) ) = stack. pop ( ) {
156- let has_entries = has_own_existential_vtable_entries ( tcx, inner_most_trait_ref. def_id ) ;
157-
156+ let is_non_auto = !tcx. trait_is_auto ( inner_most_trait_ref. def_id ) ;
157+
158+ // We don't need to emit a vptr for "truly-empty" supertraits, but we *do* need to emit a
159+ // vptr for supertraits that have no methods, but that themselves have supertraits
160+ // with methods (so we can't just use `own_existential_vtable_entries`, as that
161+ // does not account for vtable entries coming from supertraits).
162+ // As an overapproximation, we treat all non-auto traits as though they are not empty.
163+ // FIXME: don't emit vptr for empty supertraits (whose vtables would only have DSA),
164+ // (even if they aren't auto traits), but in a way that doesn't
165+ // regress #131813 or #145752. Note that this would require considering their
166+ // supertraits, not just their own entries.
158167 segment_visitor ( VtblSegment :: TraitOwnEntries {
159168 trait_ref : inner_most_trait_ref,
160- emit_vptr : emit_vptr && has_entries && !tcx. sess . opts . unstable_opts . no_trait_vptr ,
169+ emit_vptr : emit_vptr && is_non_auto && !tcx. sess . opts . unstable_opts . no_trait_vptr ,
161170 } ) ?;
162171
163172 // If we've emitted (fed to `segment_visitor`) a trait that has methods present in the vtable,
164173 // we'll need to emit vptrs from now on.
165- emit_vptr_on_new_entry |= has_entries;
174+ // FIXME: as above, we overapproximate and assume any non-auto trait could have methods.
175+ emit_vptr_on_new_entry |= is_non_auto;
166176
167177 if let Some ( next_inner_most_trait_ref) =
168178 siblings. find ( |& sibling| visited. insert ( sibling. upcast ( tcx) ) )
@@ -185,10 +195,6 @@ fn maybe_iter<I: Iterator>(i: Option<I>) -> impl Iterator<Item = I::Item> {
185195 i. into_iter ( ) . flatten ( )
186196}
187197
188- fn has_own_existential_vtable_entries ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> bool {
189- own_existential_vtable_entries_iter ( tcx, trait_def_id) . next ( ) . is_some ( )
190- }
191-
192198fn own_existential_vtable_entries ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> & [ DefId ] {
193199 tcx. arena . alloc_from_iter ( own_existential_vtable_entries_iter ( tcx, trait_def_id) )
194200}
0 commit comments