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 } ;
84use rustc_target:: abi:: { Align , Size } ;
95
106use super :: util:: ensure_monomorphic_enough;
11- use super :: { FnVal , InterpCx , Machine } ;
7+ use super :: { InterpCx , Machine } ;
128
139impl < ' mir , ' tcx : ' mir , M : Machine < ' mir , ' tcx > > InterpCx < ' mir , ' tcx , M > {
1410 /// 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> {
1713 /// The `trait_ref` encodes the erased self type. Hence, if we are
1814 /// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
1915 /// `trait_ref` would map `T: Trait`.
20- pub fn get_vtable (
21- & mut self ,
16+ pub fn get_vtable_ptr (
17+ & self ,
2218 ty : Ty < ' tcx > ,
2319 poly_trait_ref : Option < ty:: PolyExistentialTraitRef < ' tcx > > ,
2420 ) -> InterpResult < ' tcx , Pointer < Option < M :: Provenance > > > {
@@ -30,114 +26,33 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
3026 ensure_monomorphic_enough ( * self . tcx , ty) ?;
3127 ensure_monomorphic_enough ( * self . tcx , poly_trait_ref) ?;
3228
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) ) ?;
3731 Ok ( vtable_ptr. into ( ) )
3832 }
3933
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 (
4436 & self ,
4537 vtable : Pointer < Option < M :: Provenance > > ,
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+ } )
5547 }
5648
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 :: Provenance > > ,
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 (
9150 & self ,
9251 vtable : Pointer < Option < M :: Provenance > > ,
9352 ) -> 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 :: Provenance > > ,
130- idx : u64 ,
131- ) -> InterpResult < ' tcx , Pointer < Option < M :: Provenance > > > {
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 ) )
14257 }
14358}
0 commit comments