@@ -261,9 +261,12 @@ pub trait FnTypeExt<'a, 'tcx> {
261261 fn new_vtable ( cx : & CodegenCx < ' a , ' tcx > ,
262262 sig : ty:: FnSig < ' tcx > ,
263263 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 ;
267270 fn adjust_for_abi ( & mut self ,
268271 cx : & CodegenCx < ' a , ' tcx > ,
269272 abi : Abi ) ;
@@ -285,40 +288,40 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
285288 fn new ( cx : & CodegenCx < ' a , ' tcx > ,
286289 sig : ty:: FnSig < ' tcx > ,
287290 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+ } )
291294 }
292295
293296 fn new_vtable ( cx : & CodegenCx < ' a , ' tcx > ,
294297 sig : ty:: FnSig < ' tcx > ,
295298 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+ } )
316316 }
317317
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) ;
322325
323326 use self :: Abi :: * ;
324327 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>> {
435438 }
436439 } ;
437440
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) ;
440444 if arg. layout . is_zst ( ) {
441445 // For some forsaken reason, x86_64-pc-windows-gnu
442446 // doesn't ignore zero-sized struct arguments.
@@ -479,14 +483,16 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
479483 arg
480484 } ;
481485
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 ) )
486490 } ) . collect ( ) ,
487491 variadic : sig. variadic ,
488492 conv,
489- }
493+ } ;
494+ fn_ty. adjust_for_abi ( cx, sig. abi ) ;
495+ fn_ty
490496 }
491497
492498 fn adjust_for_abi ( & mut self ,
0 commit comments