From 04fb1f2f9aed1fdf7013cb9f3c8d872fa4108884 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 10 Jan 2025 04:47:45 +0000 Subject: [PATCH] Normalize vtable entries before walking and deduplicating them --- compiler/rustc_interface/src/passes.rs | 53 ++++++++++--------- .../src/traits/vtable.rs | 30 +++++++++-- 2 files changed, 54 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index ed02a059b0ef..32c8c8493dd4 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1026,37 +1026,42 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { // Here `dyn B` will have 4 entries, while `dyn B` will only have 3. // However, since we don't know `T`, we can't know if `T: Copy` holds or not, // thus we lean on the bigger side and say it has 4 entries. - traits::vtable::prepare_vtable_segments(tcx, trait_ref, |segment| { - match segment { - traits::vtable::VtblSegment::MetadataDSA => { - // If this is the first dsa, it would be included either way, - // otherwise it's needed for upcasting - if std::mem::take(&mut first_dsa) { - entries_ignoring_upcasting += 3; - } else { - entries_for_upcasting += 3; + traits::vtable::prepare_vtable_segments( + tcx, + trait_ref, + ty::TypingEnv::post_analysis(tcx, tr), + |segment| { + match segment { + traits::vtable::VtblSegment::MetadataDSA => { + // If this is the first dsa, it would be included either way, + // otherwise it's needed for upcasting + if std::mem::take(&mut first_dsa) { + entries_ignoring_upcasting += 3; + } else { + entries_for_upcasting += 3; + } } - } - traits::vtable::VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { - // Lookup the shape of vtable for the trait. - let own_existential_entries = - tcx.own_existential_vtable_entries(trait_ref.def_id); + traits::vtable::VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { + // Lookup the shape of vtable for the trait. + let own_existential_entries = + tcx.own_existential_vtable_entries(trait_ref.def_id); - // The original code here ignores the method if its predicates are - // impossible. We can't really do that as, for example, all not trivial - // bounds on generic parameters are impossible (since we don't know the - // parameters...), see the comment above. - entries_ignoring_upcasting += own_existential_entries.len(); + // The original code here ignores the method if its predicates are + // impossible. We can't really do that as, for example, all not trivial + // bounds on generic parameters are impossible (since we don't know the + // parameters...), see the comment above. + entries_ignoring_upcasting += own_existential_entries.len(); - if emit_vptr { - entries_for_upcasting += 1; + if emit_vptr { + entries_for_upcasting += 1; + } } } - } - std::ops::ControlFlow::Continue::(()) - }); + std::ops::ControlFlow::Continue::(()) + }, + ); sess.code_stats.record_vtable_size(tr, &name, VTableSizeInfo { trait_name: name.clone(), diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 09d2ca621fac..de6e0306233b 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -30,9 +30,10 @@ pub enum VtblSegment<'tcx> { pub fn prepare_vtable_segments<'tcx, T>( tcx: TyCtxt<'tcx>, trait_ref: ty::TraitRef<'tcx>, + typing_env: ty::TypingEnv<'tcx>, segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow, ) -> Option { - prepare_vtable_segments_inner(tcx, trait_ref, segment_visitor).break_value() + prepare_vtable_segments_inner(tcx, trait_ref, typing_env, segment_visitor).break_value() } /// Helper for [`prepare_vtable_segments`] that returns `ControlFlow`, @@ -40,6 +41,7 @@ pub fn prepare_vtable_segments<'tcx, T>( fn prepare_vtable_segments_inner<'tcx, T>( tcx: TyCtxt<'tcx>, trait_ref: ty::TraitRef<'tcx>, + typing_env: ty::TypingEnv<'tcx>, mut segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow, ) -> ControlFlow { // The following constraints holds for the final arrangement. @@ -129,7 +131,8 @@ fn prepare_vtable_segments_inner<'tcx, T>( .iter_identity_copied() .filter_map(move |(pred, _)| { Some( - tcx.instantiate_bound_regions_with_erased( + tcx.normalize_erasing_late_bound_regions( + typing_env, pred.instantiate_supertrait( tcx, ty::Binder::dummy(inner_most_trait_ref), @@ -306,7 +309,12 @@ fn vtable_entries<'tcx>( ControlFlow::Continue(()) }; - let _ = prepare_vtable_segments(tcx, trait_ref, vtable_segment_callback); + let _ = prepare_vtable_segments( + tcx, + trait_ref, + ty::TypingEnv::fully_monomorphized(), + vtable_segment_callback, + ); if tcx.has_attr(trait_ref.def_id, sym::rustc_dump_vtable) { let sp = tcx.def_span(trait_ref.def_id); @@ -358,7 +366,13 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe } }; - prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap() + prepare_vtable_segments( + tcx, + source_principal, + ty::TypingEnv::fully_monomorphized(), + vtable_segment_callback, + ) + .unwrap() } /// Given a `dyn Subtrait` and `dyn Supertrait` trait object, find the slot of @@ -420,7 +434,13 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( } }; - prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap() + prepare_vtable_segments( + tcx, + source_principal, + ty::TypingEnv::fully_monomorphized(), + vtable_segment_callback, + ) + .unwrap() } fn trait_refs_are_compatible<'tcx>(