@@ -31,9 +31,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
31
31
32
32
let mut result = match instance {
33
33
ty:: InstanceDef :: Item ( ..) => bug ! ( "item {:?} passed to make_shim" , instance) ,
34
- ty:: InstanceDef :: VtableShim ( def_id) => {
35
- build_call_shim ( tcx, instance, Adjustment :: DerefMove , CallKind :: Direct ( def_id) , None )
36
- }
34
+ ty:: InstanceDef :: VtableShim ( def_id) => build_call_shim (
35
+ tcx,
36
+ instance,
37
+ Some ( Adjustment :: DerefMove ) ,
38
+ CallKind :: Direct ( def_id) ,
39
+ None ,
40
+ ) ,
37
41
ty:: InstanceDef :: FnPtrShim ( def_id, ty) => {
38
42
let trait_ = tcx. trait_of_item ( def_id) . unwrap ( ) ;
39
43
let adjustment = match tcx. lang_items ( ) . fn_trait_kind ( trait_) {
@@ -50,15 +54,15 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
50
54
let sig = tcx. erase_late_bound_regions ( & ty. fn_sig ( tcx) ) ;
51
55
let arg_tys = sig. inputs ( ) ;
52
56
53
- build_call_shim ( tcx, instance, adjustment, CallKind :: Indirect , Some ( arg_tys) )
57
+ build_call_shim ( tcx, instance, Some ( adjustment) , CallKind :: Indirect , Some ( arg_tys) )
54
58
}
55
59
// We are generating a call back to our def-id, which the
56
60
// codegen backend knows to turn to an actual call, be it
57
61
// a virtual call, or a direct call to a function for which
58
62
// indirect calls must be codegen'd differently than direct ones
59
63
// (such as `#[track_caller]`).
60
64
ty:: InstanceDef :: ReifyShim ( def_id) => {
61
- build_call_shim ( tcx, instance, Adjustment :: Identity , CallKind :: Direct ( def_id) , None )
65
+ build_call_shim ( tcx, instance, None , CallKind :: Direct ( def_id) , None )
62
66
}
63
67
ty:: InstanceDef :: ClosureOnceShim { call_once : _ } => {
64
68
let fn_mut = tcx. lang_items ( ) . fn_mut_trait ( ) . unwrap ( ) ;
@@ -68,7 +72,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
68
72
. unwrap ( )
69
73
. def_id ;
70
74
71
- build_call_shim ( tcx, instance, Adjustment :: RefMut , CallKind :: Direct ( call_mut) , None )
75
+ build_call_shim (
76
+ tcx,
77
+ instance,
78
+ Some ( Adjustment :: RefMut ) ,
79
+ CallKind :: Direct ( call_mut) ,
80
+ None ,
81
+ )
72
82
}
73
83
ty:: InstanceDef :: DropGlue ( def_id, ty) => build_drop_shim ( tcx, def_id, ty) ,
74
84
ty:: InstanceDef :: CloneShim ( def_id, ty) => {
@@ -648,7 +658,7 @@ impl CloneShimBuilder<'tcx> {
648
658
fn build_call_shim < ' tcx > (
649
659
tcx : TyCtxt < ' tcx > ,
650
660
instance : ty:: InstanceDef < ' tcx > ,
651
- rcvr_adjustment : Adjustment ,
661
+ rcvr_adjustment : Option < Adjustment > ,
652
662
call_kind : CallKind ,
653
663
untuple_args : Option < & [ Ty < ' tcx > ] > ,
654
664
) -> BodyAndCache < ' tcx > {
@@ -680,14 +690,16 @@ fn build_call_shim<'tcx>(
680
690
let mut local_decls = local_decls_for_sig ( & sig, span) ;
681
691
let source_info = SourceInfo { span, scope : OUTERMOST_SOURCE_SCOPE } ;
682
692
683
- let rcvr_arg = Local :: new ( 1 + 0 ) ;
684
- let rcvr_l = Place :: from ( rcvr_arg) ;
693
+ let rcvr_place = || {
694
+ assert ! ( rcvr_adjustment. is_some( ) ) ;
695
+ Place :: from ( Local :: new ( 1 + 0 ) )
696
+ } ;
685
697
let mut statements = vec ! [ ] ;
686
698
687
- let rcvr = match rcvr_adjustment {
688
- Adjustment :: Identity => Operand :: Move ( rcvr_l ) ,
689
- Adjustment :: Deref => Operand :: Copy ( tcx. mk_place_deref ( rcvr_l ) ) ,
690
- Adjustment :: DerefMove => Operand :: Move ( tcx. mk_place_deref ( rcvr_l ) ) ,
699
+ let rcvr = rcvr_adjustment . map ( |rcvr_adjustment| match rcvr_adjustment {
700
+ Adjustment :: Identity => Operand :: Move ( rcvr_place ( ) ) ,
701
+ Adjustment :: Deref => Operand :: Copy ( tcx. mk_place_deref ( rcvr_place ( ) ) ) ,
702
+ Adjustment :: DerefMove => Operand :: Move ( tcx. mk_place_deref ( rcvr_place ( ) ) ) ,
691
703
Adjustment :: RefMut => {
692
704
// let rcvr = &mut rcvr;
693
705
let ref_rcvr = local_decls. push ( temp_decl (
@@ -703,15 +715,15 @@ fn build_call_shim<'tcx>(
703
715
source_info,
704
716
kind : StatementKind :: Assign ( box (
705
717
Place :: from ( ref_rcvr) ,
706
- Rvalue :: Ref ( tcx. lifetimes . re_erased , borrow_kind, rcvr_l ) ,
718
+ Rvalue :: Ref ( tcx. lifetimes . re_erased , borrow_kind, rcvr_place ( ) ) ,
707
719
) ) ,
708
720
} ) ;
709
721
Operand :: Move ( Place :: from ( ref_rcvr) )
710
722
}
711
- } ;
723
+ } ) ;
712
724
713
725
let ( callee, mut args) = match call_kind {
714
- CallKind :: Indirect => ( rcvr, vec ! [ ] ) ,
726
+ CallKind :: Indirect => ( rcvr. unwrap ( ) , vec ! [ ] ) ,
715
727
CallKind :: Direct ( def_id) => {
716
728
let ty = tcx. type_of ( def_id) ;
717
729
(
@@ -720,21 +732,35 @@ fn build_call_shim<'tcx>(
720
732
user_ty : None ,
721
733
literal : ty:: Const :: zero_sized ( tcx, ty) ,
722
734
} ) ,
723
- vec ! [ rcvr] ,
735
+ rcvr. into_iter ( ) . collect :: < Vec < _ > > ( ) ,
724
736
)
725
737
}
726
738
} ;
727
739
740
+ let mut arg_range = 0 ..sig. inputs ( ) . len ( ) ;
741
+
742
+ // Take the `self` ("receiver") argument out of the range (it's adjusted above).
743
+ if rcvr_adjustment. is_some ( ) {
744
+ arg_range. start += 1 ;
745
+ }
746
+
747
+ // Take the last argument, if we need to untuple it (handled below).
748
+ if untuple_args. is_some ( ) {
749
+ arg_range. end -= 1 ;
750
+ }
751
+
752
+ // Pass all of the non-special arguments directly.
753
+ args. extend ( arg_range. map ( |i| Operand :: Move ( Place :: from ( Local :: new ( 1 + i) ) ) ) ) ;
754
+
755
+ // Untuple the last argument, if we have to.
728
756
if let Some ( untuple_args) = untuple_args {
757
+ let tuple_arg = Local :: new ( 1 + ( sig. inputs ( ) . len ( ) - 1 ) ) ;
729
758
args. extend ( untuple_args. iter ( ) . enumerate ( ) . map ( |( i, ity) | {
730
- let arg_place = Place :: from ( Local :: new ( 1 + 1 ) ) ;
731
- Operand :: Move ( tcx. mk_place_field ( arg_place, Field :: new ( i) , * ity) )
759
+ Operand :: Move ( tcx. mk_place_field ( Place :: from ( tuple_arg) , Field :: new ( i) , * ity) )
732
760
} ) ) ;
733
- } else {
734
- args. extend ( ( 1 ..sig. inputs ( ) . len ( ) ) . map ( |i| Operand :: Move ( Place :: from ( Local :: new ( 1 + i) ) ) ) ) ;
735
761
}
736
762
737
- let n_blocks = if let Adjustment :: RefMut = rcvr_adjustment { 5 } else { 2 } ;
763
+ let n_blocks = if let Some ( Adjustment :: RefMut ) = rcvr_adjustment { 5 } else { 2 } ;
738
764
let mut blocks = IndexVec :: with_capacity ( n_blocks) ;
739
765
let block = |blocks : & mut IndexVec < _ , _ > , statements, kind, is_cleanup| {
740
766
blocks. push ( BasicBlockData {
@@ -752,7 +778,7 @@ fn build_call_shim<'tcx>(
752
778
func : callee,
753
779
args,
754
780
destination : Some ( ( Place :: return_place ( ) , BasicBlock :: new ( 1 ) ) ) ,
755
- cleanup : if let Adjustment :: RefMut = rcvr_adjustment {
781
+ cleanup : if let Some ( Adjustment :: RefMut ) = rcvr_adjustment {
756
782
Some ( BasicBlock :: new ( 3 ) )
757
783
} else {
758
784
None
@@ -762,13 +788,13 @@ fn build_call_shim<'tcx>(
762
788
false ,
763
789
) ;
764
790
765
- if let Adjustment :: RefMut = rcvr_adjustment {
791
+ if let Some ( Adjustment :: RefMut ) = rcvr_adjustment {
766
792
// BB #1 - drop for Self
767
793
block (
768
794
& mut blocks,
769
795
vec ! [ ] ,
770
796
TerminatorKind :: Drop {
771
- location : Place :: from ( rcvr_arg ) ,
797
+ location : rcvr_place ( ) ,
772
798
target : BasicBlock :: new ( 2 ) ,
773
799
unwind : None ,
774
800
} ,
@@ -777,13 +803,13 @@ fn build_call_shim<'tcx>(
777
803
}
778
804
// BB #1/#2 - return
779
805
block ( & mut blocks, vec ! [ ] , TerminatorKind :: Return , false ) ;
780
- if let Adjustment :: RefMut = rcvr_adjustment {
806
+ if let Some ( Adjustment :: RefMut ) = rcvr_adjustment {
781
807
// BB #3 - drop if closure panics
782
808
block (
783
809
& mut blocks,
784
810
vec ! [ ] ,
785
811
TerminatorKind :: Drop {
786
- location : Place :: from ( rcvr_arg ) ,
812
+ location : rcvr_place ( ) ,
787
813
target : BasicBlock :: new ( 4 ) ,
788
814
unwind : None ,
789
815
} ,
0 commit comments