@@ -2,6 +2,7 @@ use std::fmt::Debug;
22use std:: ops:: ControlFlow ;
33
44use rustc_hir:: def_id:: DefId ;
5+ use rustc_infer:: infer:: at:: ToTrace ;
56use rustc_infer:: infer:: { BoundRegionConversionTime , TyCtxtInferExt } ;
67use rustc_infer:: traits:: ObligationCause ;
78use rustc_infer:: traits:: util:: PredicateSet ;
@@ -24,6 +25,8 @@ pub enum VtblSegment<'tcx> {
2425}
2526
2627/// Prepare the segments for a vtable
28+ // FIXME: This should take a `PolyExistentialTraitRef`, since we don't care
29+ // about our `Self` type here.
2730pub fn prepare_vtable_segments < ' tcx , T > (
2831 tcx : TyCtxt < ' tcx > ,
2932 trait_ref : ty:: PolyTraitRef < ' tcx > ,
@@ -385,7 +388,7 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
385388 let ty:: Dynamic ( target, _, _) = * target. kind ( ) else {
386389 bug ! ( ) ;
387390 } ;
388- let target_principal = target. principal ( ) ?. with_self_ty ( tcx , tcx . types . trait_object_dummy_self ) ;
391+ let target_principal = target. principal ( ) ?;
389392
390393 // Given that we have a target principal, it is a bug for there not to be a source principal.
391394 let ty:: Dynamic ( source, _, _) = * source. kind ( ) else {
@@ -394,39 +397,22 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
394397 let source_principal =
395398 source. principal ( ) . unwrap ( ) . with_self_ty ( tcx, tcx. types . trait_object_dummy_self ) ;
396399
397- let infcx = tcx. infer_ctxt ( ) . build ( ) ;
398- let param_env = ty:: ParamEnv :: reveal_all ( ) ;
399- let trait_refs_are_compatible =
400- |source : ty:: PolyTraitRef < ' tcx > , target : ty:: PolyTraitRef < ' tcx > | {
401- infcx. probe ( |_| {
402- let ocx = ObligationCtxt :: new ( & infcx) ;
403- let source = ocx. normalize ( & ObligationCause :: dummy ( ) , param_env, source) ;
404- let target = ocx. normalize ( & ObligationCause :: dummy ( ) , param_env, target) ;
405- infcx. enter_forall ( target, |target| {
406- let source = infcx. instantiate_binder_with_fresh_vars (
407- DUMMY_SP ,
408- BoundRegionConversionTime :: HigherRankedType ,
409- source,
410- ) ;
411- let Ok ( ( ) ) = ocx. eq ( & ObligationCause :: dummy ( ) , param_env, target, source)
412- else {
413- return false ;
414- } ;
415- ocx. select_all_or_error ( ) . is_empty ( )
416- } )
417- } )
418- } ;
419-
420400 let vtable_segment_callback = {
421401 let mut vptr_offset = 0 ;
422402 move |segment| {
423403 match segment {
424404 VtblSegment :: MetadataDSA => {
425405 vptr_offset += TyCtxt :: COMMON_VTABLE_ENTRIES . len ( ) ;
426406 }
427- VtblSegment :: TraitOwnEntries { trait_ref, emit_vptr } => {
428- vptr_offset += tcx. own_existential_vtable_entries ( trait_ref. def_id ( ) ) . len ( ) ;
429- if trait_refs_are_compatible ( trait_ref, target_principal) {
407+ VtblSegment :: TraitOwnEntries { trait_ref : vtable_principal, emit_vptr } => {
408+ vptr_offset +=
409+ tcx. own_existential_vtable_entries ( vtable_principal. def_id ( ) ) . len ( ) ;
410+ if trait_refs_are_compatible (
411+ tcx,
412+ vtable_principal
413+ . map_bound ( |t| ty:: ExistentialTraitRef :: erase_self_ty ( tcx, t) ) ,
414+ target_principal,
415+ ) {
430416 if emit_vptr {
431417 return ControlFlow :: Break ( Some ( vptr_offset) ) ;
432418 } else {
@@ -446,6 +432,41 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
446432 prepare_vtable_segments ( tcx, source_principal, vtable_segment_callback) . unwrap ( )
447433}
448434
435+ fn trait_refs_are_compatible < ' tcx > (
436+ tcx : TyCtxt < ' tcx > ,
437+ hr_vtable_principal : ty:: PolyExistentialTraitRef < ' tcx > ,
438+ hr_target_principal : ty:: PolyExistentialTraitRef < ' tcx > ,
439+ ) -> bool {
440+ if hr_vtable_principal. def_id ( ) != hr_target_principal. def_id ( ) {
441+ return false ;
442+ }
443+
444+ let infcx = tcx. infer_ctxt ( ) . build ( ) ;
445+ let param_env = ty:: ParamEnv :: reveal_all ( ) ;
446+ let ocx = ObligationCtxt :: new ( & infcx) ;
447+ let hr_source_principal =
448+ ocx. normalize ( & ObligationCause :: dummy ( ) , param_env, hr_vtable_principal) ;
449+ let hr_target_principal =
450+ ocx. normalize ( & ObligationCause :: dummy ( ) , param_env, hr_target_principal) ;
451+ infcx. enter_forall ( hr_target_principal, |target_principal| {
452+ let source_principal = infcx. instantiate_binder_with_fresh_vars (
453+ DUMMY_SP ,
454+ BoundRegionConversionTime :: HigherRankedType ,
455+ hr_source_principal,
456+ ) ;
457+ let Ok ( ( ) ) = ocx. eq_trace (
458+ & ObligationCause :: dummy ( ) ,
459+ param_env,
460+ ToTrace :: to_trace ( & ObligationCause :: dummy ( ) , hr_target_principal, hr_source_principal) ,
461+ target_principal,
462+ source_principal,
463+ ) else {
464+ return false ;
465+ } ;
466+ ocx. select_all_or_error ( ) . is_empty ( )
467+ } )
468+ }
469+
449470pub ( super ) fn provide ( providers : & mut Providers ) {
450471 * providers = Providers {
451472 own_existential_vtable_entries,
0 commit comments