@@ -2514,7 +2514,7 @@ where
25142514 extra_args : & [ Ty < ' tcx > ] ,
25152515 caller_location : Option < Ty < ' tcx > > ,
25162516 codegen_fn_attr_flags : CodegenFnAttrFlags ,
2517- mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgAbi < ' tcx , Ty < ' tcx > > ,
2517+ make_self_ptr_thin : bool ,
25182518 ) -> Self ;
25192519 fn adjust_for_abi ( & mut self , cx : & C , abi : SpecAbi ) ;
25202520}
@@ -2574,9 +2574,7 @@ where
25742574 // Assume that fn pointers may always unwind
25752575 let codegen_fn_attr_flags = CodegenFnAttrFlags :: UNWIND ;
25762576
2577- call:: FnAbi :: new_internal ( cx, sig, extra_args, None , codegen_fn_attr_flags, |ty, _| {
2578- ArgAbi :: new ( cx. layout_of ( ty) )
2579- } )
2577+ call:: FnAbi :: new_internal ( cx, sig, extra_args, None , codegen_fn_attr_flags, false )
25802578 }
25812579
25822580 fn of_instance ( cx : & C , instance : ty:: Instance < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
@@ -2590,55 +2588,14 @@ where
25902588
25912589 let attrs = cx. tcx ( ) . codegen_fn_attrs ( instance. def_id ( ) ) . flags ;
25922590
2593- call:: FnAbi :: new_internal ( cx, sig, extra_args, caller_location, attrs, |ty, arg_idx| {
2594- let mut layout = cx. layout_of ( ty) ;
2595- // Don't pass the vtable, it's not an argument of the virtual fn.
2596- // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
2597- // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
2598- if let ( ty:: InstanceDef :: Virtual ( ..) , Some ( 0 ) ) = ( & instance. def , arg_idx) {
2599- let fat_pointer_ty = if layout. is_unsized ( ) {
2600- // unsized `self` is passed as a pointer to `self`
2601- // FIXME (mikeyhew) change this to use &own if it is ever added to the language
2602- cx. tcx ( ) . mk_mut_ptr ( layout. ty )
2603- } else {
2604- match layout. abi {
2605- Abi :: ScalarPair ( ..) => ( ) ,
2606- _ => bug ! ( "receiver type has unsupported layout: {:?}" , layout) ,
2607- }
2608-
2609- // In the case of Rc<Self>, we need to explicitly pass a *mut RcBox<Self>
2610- // with a Scalar (not ScalarPair) ABI. This is a hack that is understood
2611- // elsewhere in the compiler as a method on a `dyn Trait`.
2612- // To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
2613- // get a built-in pointer type
2614- let mut fat_pointer_layout = layout;
2615- ' descend_newtypes: while !fat_pointer_layout. ty . is_unsafe_ptr ( )
2616- && !fat_pointer_layout. ty . is_region_ptr ( )
2617- {
2618- for i in 0 ..fat_pointer_layout. fields . count ( ) {
2619- let field_layout = fat_pointer_layout. field ( cx, i) ;
2620-
2621- if !field_layout. is_zst ( ) {
2622- fat_pointer_layout = field_layout;
2623- continue ' descend_newtypes;
2624- }
2625- }
2626-
2627- bug ! ( "receiver has no non-zero-sized fields {:?}" , fat_pointer_layout) ;
2628- }
2629-
2630- fat_pointer_layout. ty
2631- } ;
2632-
2633- // we now have a type like `*mut RcBox<dyn Trait>`
2634- // change its layout to that of `*mut ()`, a thin pointer, but keep the same type
2635- // this is understood as a special case elsewhere in the compiler
2636- let unit_pointer_ty = cx. tcx ( ) . mk_mut_ptr ( cx. tcx ( ) . mk_unit ( ) ) ;
2637- layout = cx. layout_of ( unit_pointer_ty) ;
2638- layout. ty = fat_pointer_ty;
2639- }
2640- ArgAbi :: new ( layout)
2641- } )
2591+ call:: FnAbi :: new_internal (
2592+ cx,
2593+ sig,
2594+ extra_args,
2595+ caller_location,
2596+ attrs,
2597+ matches ! ( instance. def, ty:: InstanceDef :: Virtual ( ..) ) ,
2598+ )
26422599 }
26432600
26442601 fn new_internal (
@@ -2647,7 +2604,7 @@ where
26472604 extra_args : & [ Ty < ' tcx > ] ,
26482605 caller_location : Option < Ty < ' tcx > > ,
26492606 codegen_fn_attr_flags : CodegenFnAttrFlags ,
2650- mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgAbi < ' tcx , Ty < ' tcx > > ,
2607+ force_thin_self_ptr : bool ,
26512608 ) -> Self {
26522609 debug ! ( "FnAbi::new_internal({:?}, {:?})" , sig, extra_args) ;
26532610
@@ -2778,7 +2735,18 @@ where
27782735
27792736 let arg_of = |ty : Ty < ' tcx > , arg_idx : Option < usize > | {
27802737 let is_return = arg_idx. is_none ( ) ;
2781- let mut arg = mk_arg_type ( ty, arg_idx) ;
2738+
2739+ let layout = if force_thin_self_ptr && arg_idx == Some ( 0 ) {
2740+ // Don't pass the vtable, it's not an argument of the virtual fn.
2741+ // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
2742+ // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
2743+ make_thin_self_ptr ( cx, cx. layout_of ( ty) )
2744+ } else {
2745+ cx. layout_of ( ty)
2746+ } ;
2747+
2748+ let mut arg = ArgAbi :: new ( layout) ;
2749+
27822750 if arg. layout . is_zst ( ) {
27832751 // For some forsaken reason, x86_64-pc-windows-gnu
27842752 // doesn't ignore zero-sized struct arguments.
@@ -2912,3 +2880,56 @@ where
29122880 }
29132881 }
29142882}
2883+
2884+ fn make_thin_self_ptr < ' tcx , C > (
2885+ cx : & C ,
2886+ mut layout : TyAndLayout < ' tcx > ,
2887+ ) -> TyAndLayout < ' tcx >
2888+ where C : LayoutOf < Ty = Ty < ' tcx > , TyAndLayout = TyAndLayout < ' tcx > >
2889+ //+ HasDataLayout
2890+ //+ HasTargetSpec
2891+ + HasTyCtxt < ' tcx >
2892+ + HasParamEnv < ' tcx >
2893+ {
2894+ let fat_pointer_ty = if layout. is_unsized ( ) {
2895+ // unsized `self` is passed as a pointer to `self`
2896+ // FIXME (mikeyhew) change this to use &own if it is ever added to the language
2897+ cx. tcx ( ) . mk_mut_ptr ( layout. ty )
2898+ } else {
2899+ match layout. abi {
2900+ Abi :: ScalarPair ( ..) => ( ) ,
2901+ _ => bug ! ( "receiver type has unsupported layout: {:?}" , layout) ,
2902+ }
2903+
2904+ // In the case of Rc<Self>, we need to explicitly pass a *mut RcBox<Self>
2905+ // with a Scalar (not ScalarPair) ABI. This is a hack that is understood
2906+ // elsewhere in the compiler as a method on a `dyn Trait`.
2907+ // To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
2908+ // get a built-in pointer type
2909+ let mut fat_pointer_layout = layout;
2910+ ' descend_newtypes: while !fat_pointer_layout. ty . is_unsafe_ptr ( )
2911+ && !fat_pointer_layout. ty . is_region_ptr ( )
2912+ {
2913+ for i in 0 ..fat_pointer_layout. fields . count ( ) {
2914+ let field_layout = fat_pointer_layout. field ( cx, i) ;
2915+
2916+ if !field_layout. is_zst ( ) {
2917+ fat_pointer_layout = field_layout;
2918+ continue ' descend_newtypes;
2919+ }
2920+ }
2921+
2922+ bug ! ( "receiver has no non-zero-sized fields {:?}" , fat_pointer_layout) ;
2923+ }
2924+
2925+ fat_pointer_layout. ty
2926+ } ;
2927+
2928+ // we now have a type like `*mut RcBox<dyn Trait>`
2929+ // change its layout to that of `*mut ()`, a thin pointer, but keep the same type
2930+ // this is understood as a special case elsewhere in the compiler
2931+ let unit_pointer_ty = cx. tcx ( ) . mk_mut_ptr ( cx. tcx ( ) . mk_unit ( ) ) ;
2932+ layout = cx. layout_of ( unit_pointer_ty) ;
2933+ layout. ty = fat_pointer_ty;
2934+ layout
2935+ }
0 commit comments