@@ -43,77 +43,72 @@ pub const COMMON_VTABLE_ENTRIES_DROPINPLACE: usize = 0;
43
43
pub const COMMON_VTABLE_ENTRIES_SIZE : usize = 1 ;
44
44
pub const COMMON_VTABLE_ENTRIES_ALIGN : usize = 2 ;
45
45
46
- impl < ' tcx > TyCtxt < ' tcx > {
47
- /// Retrieves an allocation that represents the contents of a vtable.
48
- /// There's a cache within `TyCtxt` so it will be deduplicated.
49
- pub fn vtable_allocation (
50
- self ,
51
- ty : Ty < ' tcx > ,
52
- poly_trait_ref : Option < ty:: PolyExistentialTraitRef < ' tcx > > ,
53
- ) -> AllocId {
54
- let tcx = self ;
46
+ /// Retrieves an allocation that represents the contents of a vtable.
47
+ /// Since this is a query, allocations are cached and not duplicated.
48
+ pub ( super ) fn vtable_allocation_provider < ' tcx > (
49
+ tcx : TyCtxt < ' tcx > ,
50
+ key : ( Ty < ' tcx > , Option < ty:: PolyExistentialTraitRef < ' tcx > > ) ,
51
+ ) -> AllocId {
52
+ let ( ty, poly_trait_ref) = key;
55
53
56
- let vtable_entries = if let Some ( poly_trait_ref) = poly_trait_ref {
57
- let trait_ref = poly_trait_ref. with_self_ty ( tcx, ty) ;
58
- let trait_ref = tcx. erase_regions ( trait_ref) ;
54
+ let vtable_entries = if let Some ( poly_trait_ref) = poly_trait_ref {
55
+ let trait_ref = poly_trait_ref. with_self_ty ( tcx, ty) ;
56
+ let trait_ref = tcx. erase_regions ( trait_ref) ;
59
57
60
- tcx. vtable_entries ( trait_ref)
61
- } else {
62
- COMMON_VTABLE_ENTRIES
63
- } ;
64
-
65
- let layout = tcx
66
- . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( ty) )
67
- . expect ( "failed to build vtable representation" ) ;
68
- assert ! ( !layout. is_unsized( ) , "can't create a vtable for an unsized type" ) ;
69
- let size = layout. size . bytes ( ) ;
70
- let align = layout. align . abi . bytes ( ) ;
58
+ tcx. vtable_entries ( trait_ref)
59
+ } else {
60
+ COMMON_VTABLE_ENTRIES
61
+ } ;
71
62
72
- let ptr_size = tcx. data_layout . pointer_size ;
73
- let ptr_align = tcx. data_layout . pointer_align . abi ;
63
+ let layout = tcx
64
+ . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( ty) )
65
+ . expect ( "failed to build vtable representation" ) ;
66
+ assert ! ( !layout. is_unsized( ) , "can't create a vtable for an unsized type" ) ;
67
+ let size = layout. size . bytes ( ) ;
68
+ let align = layout. align . abi . bytes ( ) ;
74
69
75
- let vtable_size = ptr_size * u64:: try_from ( vtable_entries. len ( ) ) . unwrap ( ) ;
76
- let mut vtable =
77
- Allocation :: uninit ( vtable_size, ptr_align, /* panic_on_fail */ true ) . unwrap ( ) ;
70
+ let ptr_size = tcx. data_layout . pointer_size ;
71
+ let ptr_align = tcx. data_layout . pointer_align . abi ;
78
72
79
- // No need to do any alignment checks on the memory accesses below, because we know the
80
- // allocation is correctly aligned as we created it above. Also we're only offsetting by
81
- // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`.
73
+ let vtable_size = ptr_size * u64:: try_from ( vtable_entries. len ( ) ) . unwrap ( ) ;
74
+ let mut vtable = Allocation :: uninit ( vtable_size, ptr_align, /* panic_on_fail */ true ) . unwrap ( ) ;
82
75
83
- for ( idx, entry) in vtable_entries. iter ( ) . enumerate ( ) {
84
- let idx: u64 = u64:: try_from ( idx) . unwrap ( ) ;
85
- let scalar = match entry {
86
- VtblEntry :: MetadataDropInPlace => {
87
- let instance = ty:: Instance :: resolve_drop_in_place ( tcx, ty) ;
88
- let fn_alloc_id = tcx. create_fn_alloc ( instance) ;
89
- let fn_ptr = Pointer :: from ( fn_alloc_id) ;
90
- ScalarMaybeUninit :: from_pointer ( fn_ptr, & tcx)
91
- }
92
- VtblEntry :: MetadataSize => Scalar :: from_uint ( size, ptr_size) . into ( ) ,
93
- VtblEntry :: MetadataAlign => Scalar :: from_uint ( align, ptr_size) . into ( ) ,
94
- VtblEntry :: Vacant => continue ,
95
- VtblEntry :: Method ( instance) => {
96
- // Prepare the fn ptr we write into the vtable.
97
- let instance = instance. polymorphize ( tcx) ;
98
- let fn_alloc_id = tcx. create_fn_alloc ( instance) ;
99
- let fn_ptr = Pointer :: from ( fn_alloc_id) ;
100
- ScalarMaybeUninit :: from_pointer ( fn_ptr, & tcx)
101
- }
102
- VtblEntry :: TraitVPtr ( trait_ref) => {
103
- let super_trait_ref = trait_ref. map_bound ( |trait_ref| {
104
- ty:: ExistentialTraitRef :: erase_self_ty ( tcx, trait_ref)
105
- } ) ;
106
- let supertrait_alloc_id = self . vtable_allocation ( ty, Some ( super_trait_ref) ) ;
107
- let vptr = Pointer :: from ( supertrait_alloc_id) ;
108
- ScalarMaybeUninit :: from_pointer ( vptr, & tcx)
109
- }
110
- } ;
111
- vtable
112
- . write_scalar ( & tcx, alloc_range ( ptr_size * idx, ptr_size) , scalar)
113
- . expect ( "failed to build vtable representation" ) ;
114
- }
76
+ // No need to do any alignment checks on the memory accesses below, because we know the
77
+ // allocation is correctly aligned as we created it above. Also we're only offsetting by
78
+ // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`.
115
79
116
- vtable. mutability = Mutability :: Not ;
117
- tcx. create_memory_alloc ( tcx. intern_const_alloc ( vtable) )
80
+ for ( idx, entry) in vtable_entries. iter ( ) . enumerate ( ) {
81
+ let idx: u64 = u64:: try_from ( idx) . unwrap ( ) ;
82
+ let scalar = match entry {
83
+ VtblEntry :: MetadataDropInPlace => {
84
+ let instance = ty:: Instance :: resolve_drop_in_place ( tcx, ty) ;
85
+ let fn_alloc_id = tcx. create_fn_alloc ( instance) ;
86
+ let fn_ptr = Pointer :: from ( fn_alloc_id) ;
87
+ ScalarMaybeUninit :: from_pointer ( fn_ptr, & tcx)
88
+ }
89
+ VtblEntry :: MetadataSize => Scalar :: from_uint ( size, ptr_size) . into ( ) ,
90
+ VtblEntry :: MetadataAlign => Scalar :: from_uint ( align, ptr_size) . into ( ) ,
91
+ VtblEntry :: Vacant => continue ,
92
+ VtblEntry :: Method ( instance) => {
93
+ // Prepare the fn ptr we write into the vtable.
94
+ let instance = instance. polymorphize ( tcx) ;
95
+ let fn_alloc_id = tcx. create_fn_alloc ( instance) ;
96
+ let fn_ptr = Pointer :: from ( fn_alloc_id) ;
97
+ ScalarMaybeUninit :: from_pointer ( fn_ptr, & tcx)
98
+ }
99
+ VtblEntry :: TraitVPtr ( trait_ref) => {
100
+ let super_trait_ref = trait_ref
101
+ . map_bound ( |trait_ref| ty:: ExistentialTraitRef :: erase_self_ty ( tcx, trait_ref) ) ;
102
+ let supertrait_alloc_id = tcx. vtable_allocation ( ( ty, Some ( super_trait_ref) ) ) ;
103
+ let vptr = Pointer :: from ( supertrait_alloc_id) ;
104
+ ScalarMaybeUninit :: from_pointer ( vptr, & tcx)
105
+ }
106
+ } ;
107
+ vtable
108
+ . write_scalar ( & tcx, alloc_range ( ptr_size * idx, ptr_size) , scalar)
109
+ . expect ( "failed to build vtable representation" ) ;
118
110
}
111
+
112
+ vtable. mutability = Mutability :: Not ;
113
+ tcx. create_memory_alloc ( tcx. intern_const_alloc ( vtable) )
119
114
}
0 commit comments