1
- use std:: convert:: TryFrom ;
2
-
3
- use rustc_middle:: mir:: interpret:: { alloc_range, InterpResult , Pointer , PointerArithmetic } ;
4
- use rustc_middle:: ty:: {
5
- self , Ty , TyCtxt , COMMON_VTABLE_ENTRIES_ALIGN , COMMON_VTABLE_ENTRIES_DROPINPLACE ,
6
- COMMON_VTABLE_ENTRIES_SIZE ,
7
- } ;
1
+ use rustc_middle:: mir:: interpret:: { InterpResult , Pointer } ;
2
+ use rustc_middle:: ty:: layout:: LayoutOf ;
3
+ use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
8
4
use rustc_target:: abi:: { Align , Size } ;
9
5
10
6
use super :: util:: ensure_monomorphic_enough;
11
- use super :: { FnVal , InterpCx , Machine } ;
7
+ use super :: { InterpCx , Machine } ;
12
8
13
9
impl < ' mir , ' tcx : ' mir , M : Machine < ' mir , ' tcx > > InterpCx < ' mir , ' tcx , M > {
14
10
/// Creates a dynamic vtable for the given type and vtable origin. This is used only for
@@ -17,8 +13,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
17
13
/// The `trait_ref` encodes the erased self type. Hence, if we are
18
14
/// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
19
15
/// `trait_ref` would map `T: Trait`.
20
- pub fn get_vtable (
21
- & mut self ,
16
+ pub fn get_vtable_ptr (
17
+ & self ,
22
18
ty : Ty < ' tcx > ,
23
19
poly_trait_ref : Option < ty:: PolyExistentialTraitRef < ' tcx > > ,
24
20
) -> InterpResult < ' tcx , Pointer < Option < M :: PointerTag > > > {
@@ -30,114 +26,33 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
30
26
ensure_monomorphic_enough ( * self . tcx , ty) ?;
31
27
ensure_monomorphic_enough ( * self . tcx , poly_trait_ref) ?;
32
28
33
- let vtable_allocation = self . tcx . vtable_allocation ( ( ty, poly_trait_ref) ) ;
34
-
35
- let vtable_ptr = self . global_base_pointer ( Pointer :: from ( vtable_allocation) ) ?;
36
-
29
+ let vtable_symbolic_allocation = self . tcx . create_vtable_alloc ( ty, poly_trait_ref) ;
30
+ let vtable_ptr = self . global_base_pointer ( Pointer :: from ( vtable_symbolic_allocation) ) ?;
37
31
Ok ( vtable_ptr. into ( ) )
38
32
}
39
33
40
- /// Resolves the function at the specified slot in the provided
41
- /// vtable. Currently an index of '3' (`TyCtxt::COMMON_VTABLE_ENTRIES.len()`)
42
- /// corresponds to the first method declared in the trait of the provided vtable.
43
- pub fn get_vtable_slot (
34
+ /// Returns a high-level representation of the entires of the given vtable.
35
+ pub fn get_vtable_entries (
44
36
& self ,
45
37
vtable : Pointer < Option < M :: PointerTag > > ,
46
- idx : u64 ,
47
- ) -> InterpResult < ' tcx , FnVal < ' tcx , M :: ExtraFnVal > > {
48
- let ptr_size = self . pointer_size ( ) ;
49
- let vtable_slot = vtable . offset ( ptr_size * idx , self ) ? ;
50
- let vtable_slot = self
51
- . get_ptr_alloc ( vtable_slot , ptr_size , self . tcx . data_layout . pointer_align . abi ) ?
52
- . expect ( "cannot be a ZST" ) ;
53
- let fn_ptr = self . scalar_to_ptr ( vtable_slot . read_pointer ( Size :: ZERO ) ? . check_init ( ) ? ) ? ;
54
- self . get_ptr_fn ( fn_ptr )
38
+ ) -> InterpResult < ' tcx , & ' tcx [ ty :: VtblEntry < ' tcx > ] > {
39
+ let ( ty , poly_trait_ref ) = self . get_ptr_vtable ( vtable ) ? ;
40
+ Ok ( if let Some ( poly_trait_ref ) = poly_trait_ref {
41
+ let trait_ref = poly_trait_ref . with_self_ty ( * self . tcx , ty ) ;
42
+ let trait_ref = self . tcx . erase_regions ( trait_ref ) ;
43
+ self . tcx . vtable_entries ( trait_ref )
44
+ } else {
45
+ TyCtxt :: COMMON_VTABLE_ENTRIES
46
+ } )
55
47
}
56
48
57
- /// Returns the drop fn instance as well as the actual dynamic type.
58
- pub fn read_drop_type_from_vtable (
59
- & self ,
60
- vtable : Pointer < Option < M :: PointerTag > > ,
61
- ) -> InterpResult < ' tcx , ( ty:: Instance < ' tcx > , Ty < ' tcx > ) > {
62
- let pointer_size = self . pointer_size ( ) ;
63
- // We don't care about the pointee type; we just want a pointer.
64
- let vtable = self
65
- . get_ptr_alloc (
66
- vtable,
67
- pointer_size * u64:: try_from ( TyCtxt :: COMMON_VTABLE_ENTRIES . len ( ) ) . unwrap ( ) ,
68
- self . tcx . data_layout . pointer_align . abi ,
69
- ) ?
70
- . expect ( "cannot be a ZST" ) ;
71
- let drop_fn = vtable
72
- . read_pointer ( pointer_size * u64:: try_from ( COMMON_VTABLE_ENTRIES_DROPINPLACE ) . unwrap ( ) ) ?
73
- . check_init ( ) ?;
74
- // We *need* an instance here, no other kind of function value, to be able
75
- // to determine the type.
76
- let drop_instance = self . get_ptr_fn ( self . scalar_to_ptr ( drop_fn) ?) ?. as_instance ( ) ?;
77
- trace ! ( "Found drop fn: {:?}" , drop_instance) ;
78
- let fn_sig = drop_instance. ty ( * self . tcx , self . param_env ) . fn_sig ( * self . tcx ) ;
79
- let fn_sig = self . tcx . normalize_erasing_late_bound_regions ( self . param_env , fn_sig) ;
80
- // The drop function takes `*mut T` where `T` is the type being dropped, so get that.
81
- let args = fn_sig. inputs ( ) ;
82
- if args. len ( ) != 1 {
83
- throw_ub ! ( InvalidVtableDropFn ( fn_sig) ) ;
84
- }
85
- let ty =
86
- args[ 0 ] . builtin_deref ( true ) . ok_or_else ( || err_ub ! ( InvalidVtableDropFn ( fn_sig) ) ) ?. ty ;
87
- Ok ( ( drop_instance, ty) )
88
- }
89
-
90
- pub fn read_size_and_align_from_vtable (
49
+ pub fn get_vtable_size_and_align (
91
50
& self ,
92
51
vtable : Pointer < Option < M :: PointerTag > > ,
93
52
) -> InterpResult < ' tcx , ( Size , Align ) > {
94
- let pointer_size = self . pointer_size ( ) ;
95
- // We check for `size = 3 * ptr_size`, which covers the drop fn (unused here),
96
- // the size, and the align (which we read below).
97
- let vtable = self
98
- . get_ptr_alloc (
99
- vtable,
100
- pointer_size * u64:: try_from ( TyCtxt :: COMMON_VTABLE_ENTRIES . len ( ) ) . unwrap ( ) ,
101
- self . tcx . data_layout . pointer_align . abi ,
102
- ) ?
103
- . expect ( "cannot be a ZST" ) ;
104
- let size = vtable
105
- . read_integer ( alloc_range (
106
- pointer_size * u64:: try_from ( COMMON_VTABLE_ENTRIES_SIZE ) . unwrap ( ) ,
107
- pointer_size,
108
- ) ) ?
109
- . check_init ( ) ?;
110
- let size = size. to_machine_usize ( self ) ?;
111
- let size = Size :: from_bytes ( size) ;
112
- let align = vtable
113
- . read_integer ( alloc_range (
114
- pointer_size * u64:: try_from ( COMMON_VTABLE_ENTRIES_ALIGN ) . unwrap ( ) ,
115
- pointer_size,
116
- ) ) ?
117
- . check_init ( ) ?;
118
- let align = align. to_machine_usize ( self ) ?;
119
- let align = Align :: from_bytes ( align) . map_err ( |e| err_ub ! ( InvalidVtableAlignment ( e) ) ) ?;
120
-
121
- if size > self . max_size_of_val ( ) {
122
- throw_ub ! ( InvalidVtableSize ) ;
123
- }
124
- Ok ( ( size, align) )
125
- }
126
-
127
- pub fn read_new_vtable_after_trait_upcasting_from_vtable (
128
- & self ,
129
- vtable : Pointer < Option < M :: PointerTag > > ,
130
- idx : u64 ,
131
- ) -> InterpResult < ' tcx , Pointer < Option < M :: PointerTag > > > {
132
- let pointer_size = self . pointer_size ( ) ;
133
-
134
- let vtable_slot = vtable. offset ( pointer_size * idx, self ) ?;
135
- let new_vtable = self
136
- . get_ptr_alloc ( vtable_slot, pointer_size, self . tcx . data_layout . pointer_align . abi ) ?
137
- . expect ( "cannot be a ZST" ) ;
138
-
139
- let new_vtable = self . scalar_to_ptr ( new_vtable. read_pointer ( Size :: ZERO ) ?. check_init ( ) ?) ?;
140
-
141
- Ok ( new_vtable)
53
+ let ( ty, _trait_ref) = self . get_ptr_vtable ( vtable) ?;
54
+ let layout = self . layout_of ( ty) ?;
55
+ assert ! ( !layout. is_unsized( ) , "there are no vtables for unsized types" ) ;
56
+ Ok ( ( layout. size , layout. align . abi ) )
142
57
}
143
58
}
0 commit comments