1
1
use std:: convert:: TryFrom ;
2
+ use std:: fmt;
2
3
3
4
use crate :: mir:: interpret:: { alloc_range, AllocId , Allocation , Pointer , Scalar , ScalarMaybeUninit } ;
4
- use crate :: ty:: fold:: TypeFoldable ;
5
- use crate :: ty:: { self , DefId , SubstsRef , Ty , TyCtxt } ;
5
+ use crate :: ty:: { self , Instance , PolyTraitRef , Ty , TyCtxt } ;
6
6
use rustc_ast:: Mutability ;
7
7
8
- #[ derive( Clone , Copy , Debug , PartialEq , HashStable ) ]
8
+ #[ derive( Clone , Copy , PartialEq , HashStable ) ]
9
9
pub enum VtblEntry < ' tcx > {
10
+ /// destructor of this type (used in vtable header)
10
11
MetadataDropInPlace ,
12
+ /// layout size of this type (used in vtable header)
11
13
MetadataSize ,
14
+ /// layout align of this type (used in vtable header)
12
15
MetadataAlign ,
16
+ /// non-dispatchable associated function that is excluded from trait object
13
17
Vacant ,
14
- Method ( DefId , SubstsRef < ' tcx > ) ,
18
+ /// dispatchable associated function
19
+ Method ( Instance < ' tcx > ) ,
20
+ /// pointer to a separate supertrait vtable, can be used by trait upcasting coercion
21
+ TraitVPtr ( PolyTraitRef < ' tcx > ) ,
22
+ }
23
+
24
+ impl < ' tcx > fmt:: Debug for VtblEntry < ' tcx > {
25
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
26
+ // We want to call `Display` on `Instance` and `PolyTraitRef`,
27
+ // so we implement this manually.
28
+ match self {
29
+ VtblEntry :: MetadataDropInPlace => write ! ( f, "MetadataDropInPlace" ) ,
30
+ VtblEntry :: MetadataSize => write ! ( f, "MetadataSize" ) ,
31
+ VtblEntry :: MetadataAlign => write ! ( f, "MetadataAlign" ) ,
32
+ VtblEntry :: Vacant => write ! ( f, "Vacant" ) ,
33
+ VtblEntry :: Method ( instance) => write ! ( f, "Method({})" , instance) ,
34
+ VtblEntry :: TraitVPtr ( trait_ref) => write ! ( f, "TraitVPtr({})" , trait_ref) ,
35
+ }
36
+ }
15
37
}
16
38
17
39
pub const COMMON_VTABLE_ENTRIES : & [ VtblEntry < ' _ > ] =
@@ -36,11 +58,6 @@ impl<'tcx> TyCtxt<'tcx> {
36
58
}
37
59
drop ( vtables_cache) ;
38
60
39
- // See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674
40
- assert ! (
41
- !ty. needs_subst( ) && !poly_trait_ref. map_or( false , |trait_ref| trait_ref. needs_subst( ) )
42
- ) ;
43
- let param_env = ty:: ParamEnv :: reveal_all ( ) ;
44
61
let vtable_entries = if let Some ( poly_trait_ref) = poly_trait_ref {
45
62
let trait_ref = poly_trait_ref. with_self_ty ( tcx, ty) ;
46
63
let trait_ref = tcx. erase_regions ( trait_ref) ;
@@ -50,8 +67,9 @@ impl<'tcx> TyCtxt<'tcx> {
50
67
COMMON_VTABLE_ENTRIES
51
68
} ;
52
69
53
- let layout =
54
- tcx. layout_of ( param_env. and ( ty) ) . expect ( "failed to build vtable representation" ) ;
70
+ let layout = tcx
71
+ . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( ty) )
72
+ . expect ( "failed to build vtable representation" ) ;
55
73
assert ! ( !layout. is_unsized( ) , "can't create a vtable for an unsized type" ) ;
56
74
let size = layout. size . bytes ( ) ;
57
75
let align = layout. align . abi . bytes ( ) ;
@@ -79,19 +97,21 @@ impl<'tcx> TyCtxt<'tcx> {
79
97
VtblEntry :: MetadataSize => Scalar :: from_uint ( size, ptr_size) . into ( ) ,
80
98
VtblEntry :: MetadataAlign => Scalar :: from_uint ( align, ptr_size) . into ( ) ,
81
99
VtblEntry :: Vacant => continue ,
82
- VtblEntry :: Method ( def_id, substs) => {
83
- // See https://github.com/rust-lang/rust/pull/86475#discussion_r655162674
84
- assert ! ( !substs. needs_subst( ) ) ;
85
-
100
+ VtblEntry :: Method ( instance) => {
86
101
// Prepare the fn ptr we write into the vtable.
87
- let instance =
88
- ty:: Instance :: resolve_for_vtable ( tcx, param_env, * def_id, substs)
89
- . expect ( "resolution failed during building vtable representation" )
90
- . polymorphize ( tcx) ;
102
+ let instance = instance. polymorphize ( tcx) ;
91
103
let fn_alloc_id = tcx. create_fn_alloc ( instance) ;
92
104
let fn_ptr = Pointer :: from ( fn_alloc_id) ;
93
105
ScalarMaybeUninit :: from_pointer ( fn_ptr, & tcx)
94
106
}
107
+ VtblEntry :: TraitVPtr ( trait_ref) => {
108
+ let super_trait_ref = trait_ref. map_bound ( |trait_ref| {
109
+ ty:: ExistentialTraitRef :: erase_self_ty ( tcx, trait_ref)
110
+ } ) ;
111
+ let supertrait_alloc_id = self . vtable_allocation ( ty, Some ( super_trait_ref) ) ;
112
+ let vptr = Pointer :: from ( supertrait_alloc_id) ;
113
+ ScalarMaybeUninit :: from_pointer ( vptr, & tcx)
114
+ }
95
115
} ;
96
116
vtable
97
117
. write_scalar ( & tcx, alloc_range ( ptr_size * idx, ptr_size) , scalar)
0 commit comments