@@ -261,9 +261,12 @@ pub trait FnTypeExt<'a, 'tcx> {
261
261
fn new_vtable ( cx : & CodegenCx < ' a , ' tcx > ,
262
262
sig : ty:: FnSig < ' tcx > ,
263
263
extra_args : & [ Ty < ' tcx > ] ) -> Self ;
264
- fn unadjusted ( cx : & CodegenCx < ' a , ' tcx > ,
265
- sig : ty:: FnSig < ' tcx > ,
266
- extra_args : & [ Ty < ' tcx > ] ) -> Self ;
264
+ fn new_internal (
265
+ cx : & CodegenCx < ' a , ' tcx > ,
266
+ sig : ty:: FnSig < ' tcx > ,
267
+ extra_args : & [ Ty < ' tcx > ] ,
268
+ mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgType < ' tcx , Ty < ' tcx > > ,
269
+ ) -> Self ;
267
270
fn adjust_for_abi ( & mut self ,
268
271
cx : & CodegenCx < ' a , ' tcx > ,
269
272
abi : Abi ) ;
@@ -285,40 +288,40 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
285
288
fn new ( cx : & CodegenCx < ' a , ' tcx > ,
286
289
sig : ty:: FnSig < ' tcx > ,
287
290
extra_args : & [ Ty < ' tcx > ] ) -> Self {
288
- let mut fn_ty = FnType :: unadjusted ( cx, sig, extra_args) ;
289
- fn_ty . adjust_for_abi ( cx, sig . abi ) ;
290
- fn_ty
291
+ FnType :: new_internal ( cx, sig, extra_args, |ty , _| {
292
+ ArgType :: new ( cx. layout_of ( ty ) )
293
+ } )
291
294
}
292
295
293
296
fn new_vtable ( cx : & CodegenCx < ' a , ' tcx > ,
294
297
sig : ty:: FnSig < ' tcx > ,
295
298
extra_args : & [ Ty < ' tcx > ] ) -> Self {
296
- let mut fn_ty = FnType :: unadjusted ( cx, sig, extra_args) ;
297
- // Don't pass the vtable, it's not an argument of the virtual fn.
298
- {
299
- let self_arg = & mut fn_ty. args [ 0 ] ;
300
- match self_arg. mode {
301
- PassMode :: Pair ( data_ptr, _) => {
302
- self_arg. mode = PassMode :: Direct ( data_ptr) ;
303
- }
304
- _ => bug ! ( "FnType::new_vtable: non-pair self {:?}" , self_arg)
305
- }
306
-
307
- let pointee = self_arg. layout . ty . builtin_deref ( true )
308
- . unwrap_or_else ( || {
309
- bug ! ( "FnType::new_vtable: non-pointer self {:?}" , self_arg)
310
- } ) . ty ;
311
- let fat_ptr_ty = cx. tcx . mk_mut_ptr ( pointee) ;
312
- self_arg. layout = cx. layout_of ( fat_ptr_ty) . field ( cx, 0 ) ;
313
- }
314
- fn_ty. adjust_for_abi ( cx, sig. abi ) ;
315
- fn_ty
299
+ FnType :: new_internal ( cx, sig, extra_args, |ty, arg_idx| {
300
+ let mut layout = cx. layout_of ( ty) ;
301
+ // Don't pass the vtable, it's not an argument of the virtual fn.
302
+ // Instead, pass just the (thin pointer) first field of `*dyn Trait`.
303
+ if arg_idx == Some ( 0 ) {
304
+ // FIXME(eddyb) `layout.field(cx, 0)` is not enough because e.g.
305
+ // `Box<dyn Trait>` has a few newtype wrappers around the raw
306
+ // pointer, so we'd have to "dig down" to find `*dyn Trait`.
307
+ let pointee = layout. ty . builtin_deref ( true )
308
+ . unwrap_or_else ( || {
309
+ bug ! ( "FnType::new_vtable: non-pointer self {:?}" , layout)
310
+ } ) . ty ;
311
+ let fat_ptr_ty = cx. tcx . mk_mut_ptr ( pointee) ;
312
+ layout = cx. layout_of ( fat_ptr_ty) . field ( cx, 0 ) ;
313
+ }
314
+ ArgType :: new ( layout)
315
+ } )
316
316
}
317
317
318
- fn unadjusted ( cx : & CodegenCx < ' a , ' tcx > ,
319
- sig : ty:: FnSig < ' tcx > ,
320
- extra_args : & [ Ty < ' tcx > ] ) -> Self {
321
- debug ! ( "FnType::unadjusted({:?}, {:?})" , sig, extra_args) ;
318
+ fn new_internal (
319
+ cx : & CodegenCx < ' a , ' tcx > ,
320
+ sig : ty:: FnSig < ' tcx > ,
321
+ extra_args : & [ Ty < ' tcx > ] ,
322
+ mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgType < ' tcx , Ty < ' tcx > > ,
323
+ ) -> Self {
324
+ debug ! ( "FnType::new_internal({:?}, {:?})" , sig, extra_args) ;
322
325
323
326
use self :: Abi :: * ;
324
327
let conv = match cx. sess ( ) . target . target . adjust_abi ( sig. abi ) {
@@ -435,8 +438,9 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
435
438
}
436
439
} ;
437
440
438
- let arg_of = |ty : Ty < ' tcx > , is_return : bool | {
439
- let mut arg = ArgType :: new ( cx. layout_of ( ty) ) ;
441
+ let arg_of = |ty : Ty < ' tcx > , arg_idx : Option < usize > | {
442
+ let is_return = arg_idx. is_none ( ) ;
443
+ let mut arg = mk_arg_type ( ty, arg_idx) ;
440
444
if arg. layout . is_zst ( ) {
441
445
// For some forsaken reason, x86_64-pc-windows-gnu
442
446
// doesn't ignore zero-sized struct arguments.
@@ -479,14 +483,16 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
479
483
arg
480
484
} ;
481
485
482
- FnType {
483
- ret : arg_of ( sig. output ( ) , true ) ,
484
- args : inputs. iter ( ) . chain ( extra_args. iter ( ) ) . map ( |ty | {
485
- arg_of ( ty, false )
486
+ let mut fn_ty = FnType {
487
+ ret : arg_of ( sig. output ( ) , None ) ,
488
+ args : inputs. iter ( ) . chain ( extra_args) . enumerate ( ) . map ( |( i , ty ) | {
489
+ arg_of ( ty, Some ( i ) )
486
490
} ) . collect ( ) ,
487
491
variadic : sig. variadic ,
488
492
conv,
489
- }
493
+ } ;
494
+ fn_ty. adjust_for_abi ( cx, sig. abi ) ;
495
+ fn_ty
490
496
}
491
497
492
498
fn adjust_for_abi ( & mut self ,
0 commit comments