diff options
| author | Maybe Waffle <waffle.lapkin@gmail.com> | 2023-07-19 11:50:40 +0000 |
|---|---|---|
| committer | Maybe Waffle <waffle.lapkin@gmail.com> | 2023-07-19 12:06:31 +0000 |
| commit | 1f02c75718706d6180f9b25f55aa50f1b4ce75e1 (patch) | |
| tree | 26274a01c60443fb7007c55c309dd89e38a92b2c /compiler/rustc_trait_selection/src/traits/vtable.rs | |
| parent | b5d122850821f80f9496abc09840102561ec4267 (diff) | |
| download | rust-1f02c75718706d6180f9b25f55aa50f1b4ce75e1.tar.gz rust-1f02c75718706d6180f9b25f55aa50f1b4ce75e1.zip | |
Don't emit useless vptrs for marker traits
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/vtable.rs')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/vtable.rs | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 13ece4ccebb..b4f614e3e22 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -147,9 +147,6 @@ fn prepare_vtable_segments_inner<'tcx, T>( } } - // Other than the left-most path, vptr should be emitted for each trait. - emit_vptr_on_new_entry = true; - // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level. while let Some((inner_most_trait_ref, emit_vptr, mut siblings)) = stack.pop() { segment_visitor(VtblSegment::TraitOwnEntries { @@ -157,6 +154,14 @@ fn prepare_vtable_segments_inner<'tcx, T>( emit_vptr, })?; + // If we've emitted (fed to `segment_visitor`) a trait that has methods present in the vtable, + // we'll need to emit vptrs from now on. + if !emit_vptr_on_new_entry + && has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id()) + { + emit_vptr_on_new_entry = true; + } + if let Some(next_inner_most_trait_ref) = siblings.find(|&sibling| visited.insert(sibling.to_predicate(tcx))) { @@ -196,11 +201,23 @@ fn dump_vtable_entries<'tcx>( }); } +fn has_own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { + own_existential_vtable_entries_iter(tcx, trait_def_id).next().is_some() +} + fn own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &[DefId] { + tcx.arena.alloc_from_iter(own_existential_vtable_entries_iter(tcx, trait_def_id)) +} + +fn own_existential_vtable_entries_iter( + tcx: TyCtxt<'_>, + trait_def_id: DefId, +) -> impl Iterator<Item = DefId> + '_ { let trait_methods = tcx .associated_items(trait_def_id) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Fn); + // Now list each method's DefId (for within its trait). let own_entries = trait_methods.filter_map(move |&trait_method| { 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 Some(def_id) }); - tcx.arena.alloc_from_iter(own_entries.into_iter()) + own_entries } /// Given a trait `trait_ref`, iterates the vtable entries |
