1
1
use rustc_middle:: mir:: interpret:: { InterpResult , Pointer } ;
2
2
use rustc_middle:: ty:: layout:: LayoutOf ;
3
- use rustc_middle:: ty:: { self , Ty , TyCtxt , VtblEntry } ;
3
+ use rustc_middle:: ty:: { self , ExistentialPredicateStableCmpExt , Ty , TyCtxt , VtblEntry } ;
4
4
use rustc_target:: abi:: { Align , Size } ;
5
5
use tracing:: trace;
6
6
@@ -18,19 +18,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
18
18
pub fn get_vtable_ptr (
19
19
& self ,
20
20
ty : Ty < ' tcx > ,
21
- poly_trait_ref : Option < ty:: PolyExistentialTraitRef < ' tcx > > ,
21
+ vtable : & ' tcx ty :: List < ty:: PolyExistentialPredicate < ' tcx > > ,
22
22
) -> InterpResult < ' tcx , Pointer < Option < M :: Provenance > > > {
23
- trace ! ( "get_vtable(trait_ref={ :?})" , poly_trait_ref ) ;
23
+ trace ! ( "get_vtable(ty={ty :?}, vtable={vtable:?})" ) ;
24
24
25
- let ( ty, poly_trait_ref ) = self . tcx . erase_regions ( ( ty, poly_trait_ref ) ) ;
25
+ let ( ty, vtable ) = self . tcx . erase_regions ( ( ty, vtable ) ) ;
26
26
27
27
// All vtables must be monomorphic, bail out otherwise.
28
28
ensure_monomorphic_enough ( * self . tcx , ty) ?;
29
- ensure_monomorphic_enough ( * self . tcx , poly_trait_ref ) ?;
29
+ ensure_monomorphic_enough ( * self . tcx , vtable ) ?;
30
30
31
31
let salt = M :: get_global_alloc_salt ( self , None ) ;
32
- let vtable_symbolic_allocation =
33
- self . tcx . reserve_and_set_vtable_alloc ( ty, poly_trait_ref, salt) ;
32
+ let vtable_symbolic_allocation = self . tcx . reserve_and_set_vtable_alloc ( ty, vtable, salt) ;
34
33
let vtable_ptr = self . global_root_pointer ( Pointer :: from ( vtable_symbolic_allocation) ) ?;
35
34
Ok ( vtable_ptr. into ( ) )
36
35
}
@@ -64,17 +63,42 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
64
63
/// expected trait type.
65
64
pub ( super ) fn check_vtable_for_type (
66
65
& self ,
67
- vtable_trait : Option < ty:: PolyExistentialTraitRef < ' tcx > > ,
68
- expected_trait : & ' tcx ty:: List < ty:: PolyExistentialPredicate < ' tcx > > ,
66
+ allocated_vtable : & ' tcx ty :: List < ty:: PolyExistentialPredicate < ' tcx > > ,
67
+ expected_vtable : & ' tcx ty:: List < ty:: PolyExistentialPredicate < ' tcx > > ,
69
68
) -> InterpResult < ' tcx > {
70
- let eq = match ( expected_trait. principal ( ) , vtable_trait) {
71
- ( Some ( a) , Some ( b) ) => self . eq_in_param_env ( a, b) ,
72
- ( None , None ) => true ,
73
- _ => false ,
74
- } ;
75
- if !eq {
76
- throw_ub ! ( InvalidVTableTrait { expected_trait, vtable_trait } ) ;
69
+ let mut sorted_allocated_v: Vec < _ > = allocated_vtable. without_auto_traits ( ) . collect ( ) ;
70
+ let mut sorted_expected_v: Vec < _ > = expected_vtable. without_auto_traits ( ) . collect ( ) ;
71
+ // `skip_binder` here is okay because `stable_cmp` doesn't look at binders
72
+ sorted_allocated_v. sort_by ( |a, b| a. skip_binder ( ) . stable_cmp ( * self . tcx , & b. skip_binder ( ) ) ) ;
73
+ sorted_allocated_v. dedup ( ) ;
74
+ sorted_expected_v. sort_by ( |a, b| a. skip_binder ( ) . stable_cmp ( * self . tcx , & b. skip_binder ( ) ) ) ;
75
+ sorted_expected_v. dedup ( ) ;
76
+
77
+ if sorted_allocated_v. len ( ) != sorted_expected_v. len ( ) {
78
+ throw_ub ! ( InvalidVTableTrait { allocated_vtable, expected_vtable } ) ;
79
+ }
80
+
81
+ for ( a_pred, b_pred) in std:: iter:: zip ( sorted_allocated_v, sorted_expected_v) {
82
+ let is_eq = match ( a_pred. skip_binder ( ) , b_pred. skip_binder ( ) ) {
83
+ (
84
+ ty:: ExistentialPredicate :: Trait ( a_data) ,
85
+ ty:: ExistentialPredicate :: Trait ( b_data) ,
86
+ ) => self . eq_in_param_env ( a_pred. rebind ( a_data) , b_pred. rebind ( b_data) ) ,
87
+
88
+ (
89
+ ty:: ExistentialPredicate :: Projection ( a_data) ,
90
+ ty:: ExistentialPredicate :: Projection ( b_data) ,
91
+ ) => self . eq_in_param_env ( a_pred. rebind ( a_data) , b_pred. rebind ( b_data) ) ,
92
+
93
+ _ => false ,
94
+ } ;
95
+ if !is_eq {
96
+ throw_ub ! ( InvalidVTableTrait { allocated_vtable, expected_vtable } ) ;
97
+ }
77
98
}
99
+
100
+ // FIXME: Should we validate auto traits here?
101
+
78
102
Ok ( ( ) )
79
103
}
80
104
0 commit comments