@@ -2514,7 +2514,7 @@ where
2514
2514
extra_args : & [ Ty < ' tcx > ] ,
2515
2515
caller_location : Option < Ty < ' tcx > > ,
2516
2516
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 ,
2518
2518
) -> Self ;
2519
2519
fn adjust_for_abi ( & mut self , cx : & C , abi : SpecAbi ) ;
2520
2520
}
@@ -2574,9 +2574,7 @@ where
2574
2574
// Assume that fn pointers may always unwind
2575
2575
let codegen_fn_attr_flags = CodegenFnAttrFlags :: UNWIND ;
2576
2576
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 )
2580
2578
}
2581
2579
2582
2580
fn of_instance ( cx : & C , instance : ty:: Instance < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
@@ -2590,55 +2588,14 @@ where
2590
2588
2591
2589
let attrs = cx. tcx ( ) . codegen_fn_attrs ( instance. def_id ( ) ) . flags ;
2592
2590
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
+ )
2642
2599
}
2643
2600
2644
2601
fn new_internal (
@@ -2647,7 +2604,7 @@ where
2647
2604
extra_args : & [ Ty < ' tcx > ] ,
2648
2605
caller_location : Option < Ty < ' tcx > > ,
2649
2606
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 ,
2651
2608
) -> Self {
2652
2609
debug ! ( "FnAbi::new_internal({:?}, {:?})" , sig, extra_args) ;
2653
2610
@@ -2778,7 +2735,18 @@ where
2778
2735
2779
2736
let arg_of = |ty : Ty < ' tcx > , arg_idx : Option < usize > | {
2780
2737
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
+
2782
2750
if arg. layout . is_zst ( ) {
2783
2751
// For some forsaken reason, x86_64-pc-windows-gnu
2784
2752
// doesn't ignore zero-sized struct arguments.
@@ -2912,3 +2880,56 @@ where
2912
2880
}
2913
2881
}
2914
2882
}
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