@@ -24,22 +24,36 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
24
24
pub fn get_vtable (
25
25
& mut self ,
26
26
ty : Ty < ' tcx > ,
27
- trait_ref : ty:: PolyTraitRef < ' tcx > ,
27
+ poly_trait_ref : Option < ty:: PolyExistentialTraitRef < ' tcx > > ,
28
28
) -> EvalResult < ' tcx , Pointer < M :: PointerTag > > {
29
- debug ! ( "get_vtable(trait_ref={:?})" , trait_ref ) ;
29
+ debug ! ( "get_vtable(trait_ref={:?})" , poly_trait_ref ) ;
30
30
31
- // FIXME: Cache this!
31
+ let ( ty , poly_trait_ref ) = self . tcx . erase_regions ( & ( ty , poly_trait_ref ) ) ;
32
32
33
- let layout = self . layout_of ( trait_ref. self_ty ( ) ) ?;
33
+ if let Some ( & vtable) = self . vtables . get ( & ( ty, poly_trait_ref) ) {
34
+ return Ok ( Pointer :: from ( vtable) . with_default_tag ( ) ) ;
35
+ }
36
+
37
+ let trait_ref = poly_trait_ref. map ( |trait_ref| {
38
+ let trait_ref = trait_ref. with_self_ty ( * self . tcx , ty) ;
39
+ self . tcx . erase_regions ( & trait_ref)
40
+ } ) ;
41
+
42
+ let methods = trait_ref. map ( |trait_ref| self . tcx . vtable_methods ( trait_ref) ) ;
43
+
44
+ let layout = self . layout_of ( ty) ?;
34
45
assert ! ( !layout. is_unsized( ) , "can't create a vtable for an unsized type" ) ;
35
46
let size = layout. size . bytes ( ) ;
36
47
let align = layout. align . abi ( ) ;
37
48
38
49
let ptr_size = self . pointer_size ( ) ;
39
50
let ptr_align = self . tcx . data_layout . pointer_align ;
40
- let methods = self . tcx . vtable_methods ( trait_ref) ;
51
+ // /////////////////////////////////////////////////////////////////////////////////////////
52
+ // If you touch this code, be sure to also make the corresponding changes to
53
+ // `get_vtable` in rust_codegen_llvm/meth.rs
54
+ // /////////////////////////////////////////////////////////////////////////////////////////
41
55
let vtable = self . memory . allocate (
42
- ptr_size * ( 3 + methods. len ( ) as u64 ) ,
56
+ ptr_size * ( 3 + methods. as_ref ( ) . map_or ( 0 , |m| m . len ( ) as u64 ) ) ,
43
57
ptr_align,
44
58
MemoryKind :: Vtable ,
45
59
) ?;
@@ -54,16 +68,19 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
54
68
self . memory . write_ptr_sized ( align_ptr, ptr_align,
55
69
Scalar :: from_uint ( align, ptr_size) . into ( ) ) ?;
56
70
57
- for ( i, method) in methods. iter ( ) . enumerate ( ) {
58
- if let Some ( ( def_id, substs) ) = * method {
59
- let instance = self . resolve ( def_id, substs) ?;
60
- let fn_ptr = self . memory . create_fn_alloc ( instance) ;
61
- let method_ptr = vtable. offset ( ptr_size * ( 3 + i as u64 ) , & self ) ?;
62
- self . memory . write_ptr_sized ( method_ptr, ptr_align, Scalar :: Ptr ( fn_ptr) . into ( ) ) ?;
71
+ if let Some ( methods) = methods {
72
+ for ( i, method) in methods. iter ( ) . enumerate ( ) {
73
+ if let Some ( ( def_id, substs) ) = * method {
74
+ let instance = self . resolve ( def_id, substs) ?;
75
+ let fn_ptr = self . memory . create_fn_alloc ( instance) ;
76
+ let method_ptr = vtable. offset ( ptr_size * ( 3 + i as u64 ) , & self ) ?;
77
+ self . memory . write_ptr_sized ( method_ptr, ptr_align, Scalar :: Ptr ( fn_ptr) . into ( ) ) ?;
78
+ }
63
79
}
64
80
}
65
81
66
82
self . memory . mark_immutable ( vtable. alloc_id ) ?;
83
+ assert ! ( self . vtables. insert( ( ty, poly_trait_ref) , vtable. alloc_id) . is_none( ) ) ;
67
84
68
85
Ok ( vtable)
69
86
}
0 commit comments