@@ -38,7 +38,7 @@ use rustc_session::Session;
38
38
use rustc_span:: symbol:: sym;
39
39
use rustc_span:: Symbol ;
40
40
use rustc_span:: { DebuggerVisualizerFile , DebuggerVisualizerType } ;
41
- use rustc_target:: abi:: { Align , VariantIdx } ;
41
+ use rustc_target:: abi:: { Align , Size , VariantIdx } ;
42
42
43
43
use std:: collections:: BTreeSet ;
44
44
use std:: convert:: TryFrom ;
@@ -150,7 +150,12 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
150
150
( & ty:: Array ( _, len) , & ty:: Slice ( _) ) => {
151
151
cx. const_usize ( len. eval_usize ( cx. tcx ( ) , ty:: ParamEnv :: reveal_all ( ) ) )
152
152
}
153
- ( & ty:: Dynamic ( ref data_a, ..) , & ty:: Dynamic ( ref data_b, ..) ) => {
153
+ (
154
+ & ty:: Dynamic ( ref data_a, _, src_dyn_kind) ,
155
+ & ty:: Dynamic ( ref data_b, _, target_dyn_kind) ,
156
+ ) => {
157
+ assert_eq ! ( src_dyn_kind, target_dyn_kind) ;
158
+
154
159
let old_info =
155
160
old_info. expect ( "unsized_info: missing old info for trait upcasting coercion" ) ;
156
161
if data_a. principal_def_id ( ) == data_b. principal_def_id ( ) {
@@ -166,11 +171,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
166
171
if let Some ( entry_idx) = vptr_entry_idx {
167
172
let ptr_ty = cx. type_i8p ( ) ;
168
173
let ptr_align = cx. tcx ( ) . data_layout . pointer_align . abi ;
169
- let vtable_ptr_ty = cx. scalar_pair_element_backend_type (
170
- cx. layout_of ( cx. tcx ( ) . mk_mut_ptr ( target) ) ,
171
- 1 ,
172
- true ,
173
- ) ;
174
+ let vtable_ptr_ty = vtable_ptr_ty ( cx, target, target_dyn_kind) ;
174
175
let llvtable = bx. pointercast ( old_info, bx. type_ptr_to ( ptr_ty) ) ;
175
176
let gep = bx. inbounds_gep (
176
177
ptr_ty,
@@ -186,18 +187,32 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
186
187
old_info
187
188
}
188
189
}
189
- ( _, & ty:: Dynamic ( ref data, ..) ) => {
190
- let vtable_ptr_ty = cx. scalar_pair_element_backend_type (
191
- cx. layout_of ( cx. tcx ( ) . mk_mut_ptr ( target) ) ,
192
- 1 ,
193
- true ,
194
- ) ;
190
+ ( _, & ty:: Dynamic ( ref data, _, target_dyn_kind) ) => {
191
+ let vtable_ptr_ty = vtable_ptr_ty ( cx, target, target_dyn_kind) ;
195
192
cx. const_ptrcast ( meth:: get_vtable ( cx, source, data. principal ( ) ) , vtable_ptr_ty)
196
193
}
197
194
_ => bug ! ( "unsized_info: invalid unsizing {:?} -> {:?}" , source, target) ,
198
195
}
199
196
}
200
197
198
+ // Returns the vtable pointer type of a `dyn` or `dyn*` type
199
+ fn vtable_ptr_ty < ' tcx , Cx : CodegenMethods < ' tcx > > (
200
+ cx : & Cx ,
201
+ target : Ty < ' tcx > ,
202
+ kind : ty:: DynKind ,
203
+ ) -> <Cx as BackendTypes >:: Type {
204
+ cx. scalar_pair_element_backend_type (
205
+ cx. layout_of ( match kind {
206
+ // vtable is the second field of `*mut dyn Trait`
207
+ ty:: Dyn => cx. tcx ( ) . mk_mut_ptr ( target) ,
208
+ // vtable is the second field of `dyn* Trait`
209
+ ty:: DynStar => target,
210
+ } ) ,
211
+ 1 ,
212
+ true ,
213
+ )
214
+ }
215
+
201
216
/// Coerces `src` to `dst_ty`. `src_ty` must be a pointer.
202
217
pub fn unsize_ptr < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
203
218
bx : & mut Bx ,
@@ -247,6 +262,29 @@ pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
247
262
}
248
263
}
249
264
265
+ /// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type.
266
+ pub fn cast_to_dyn_star < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
267
+ bx : & mut Bx ,
268
+ src : Bx :: Value ,
269
+ src_ty_and_layout : TyAndLayout < ' tcx > ,
270
+ dst_ty : Ty < ' tcx > ,
271
+ old_info : Option < Bx :: Value > ,
272
+ ) -> ( Bx :: Value , Bx :: Value ) {
273
+ debug ! ( "cast_to_dyn_star: {:?} => {:?}" , src_ty_and_layout. ty, dst_ty) ;
274
+ assert ! (
275
+ matches!( dst_ty. kind( ) , ty:: Dynamic ( _, _, ty:: DynStar ) ) ,
276
+ "destination type must be a dyn*"
277
+ ) ;
278
+ // FIXME(dyn-star): this is probably not the best way to check if this is
279
+ // a pointer, and really we should ensure that the value is a suitable
280
+ // pointer earlier in the compilation process.
281
+ let src = match src_ty_and_layout. pointee_info_at ( bx. cx ( ) , Size :: ZERO ) {
282
+ Some ( _) => bx. ptrtoint ( src, bx. cx ( ) . type_isize ( ) ) ,
283
+ None => bx. bitcast ( src, bx. type_isize ( ) ) ,
284
+ } ;
285
+ ( src, unsized_info ( bx, src_ty_and_layout. ty , dst_ty, old_info) )
286
+ }
287
+
250
288
/// Coerces `src`, which is a reference to a value of type `src_ty`,
251
289
/// to a value of type `dst_ty`, and stores the result in `dst`.
252
290
pub fn coerce_unsized_into < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
0 commit comments