@@ -2,6 +2,7 @@ use std::fmt::Debug;
2
2
use std:: ops:: ControlFlow ;
3
3
4
4
use rustc_hir:: def_id:: DefId ;
5
+ use rustc_infer:: infer:: at:: ToTrace ;
5
6
use rustc_infer:: infer:: { BoundRegionConversionTime , TyCtxtInferExt } ;
6
7
use rustc_infer:: traits:: ObligationCause ;
7
8
use rustc_infer:: traits:: util:: PredicateSet ;
@@ -24,6 +25,8 @@ pub enum VtblSegment<'tcx> {
24
25
}
25
26
26
27
/// Prepare the segments for a vtable
28
+ // FIXME: This should take a `PolyExistentialTraitRef`, since we don't care
29
+ // about our `Self` type here.
27
30
pub fn prepare_vtable_segments < ' tcx , T > (
28
31
tcx : TyCtxt < ' tcx > ,
29
32
trait_ref : ty:: PolyTraitRef < ' tcx > ,
@@ -385,7 +388,7 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
385
388
let ty:: Dynamic ( target, _, _) = * target. kind ( ) else {
386
389
bug ! ( ) ;
387
390
} ;
388
- let target_principal = target. principal ( ) ?. with_self_ty ( tcx , tcx . types . trait_object_dummy_self ) ;
391
+ let target_principal = target. principal ( ) ?;
389
392
390
393
// Given that we have a target principal, it is a bug for there not to be a source principal.
391
394
let ty:: Dynamic ( source, _, _) = * source. kind ( ) else {
@@ -394,39 +397,22 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
394
397
let source_principal =
395
398
source. principal ( ) . unwrap ( ) . with_self_ty ( tcx, tcx. types . trait_object_dummy_self ) ;
396
399
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
-
420
400
let vtable_segment_callback = {
421
401
let mut vptr_offset = 0 ;
422
402
move |segment| {
423
403
match segment {
424
404
VtblSegment :: MetadataDSA => {
425
405
vptr_offset += TyCtxt :: COMMON_VTABLE_ENTRIES . len ( ) ;
426
406
}
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
+ ) {
430
416
if emit_vptr {
431
417
return ControlFlow :: Break ( Some ( vptr_offset) ) ;
432
418
} else {
@@ -446,6 +432,41 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
446
432
prepare_vtable_segments ( tcx, source_principal, vtable_segment_callback) . unwrap ( )
447
433
}
448
434
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
+
449
470
pub ( super ) fn provide ( providers : & mut Providers ) {
450
471
* providers = Providers {
451
472
own_existential_vtable_entries,
0 commit comments