@@ -31,9 +31,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
3131
3232 let mut result = match instance {
3333 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+ ) ,
3741 ty:: InstanceDef :: FnPtrShim ( def_id, ty) => {
3842 let trait_ = tcx. trait_of_item ( def_id) . unwrap ( ) ;
3943 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
5054 let sig = tcx. erase_late_bound_regions ( & ty. fn_sig ( tcx) ) ;
5155 let arg_tys = sig. inputs ( ) ;
5256
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) )
5458 }
5559 // We are generating a call back to our def-id, which the
5660 // codegen backend knows to turn to an actual call, be it
5761 // a virtual call, or a direct call to a function for which
5862 // indirect calls must be codegen'd differently than direct ones
5963 // (such as `#[track_caller]`).
6064 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 )
6266 }
6367 ty:: InstanceDef :: ClosureOnceShim { call_once : _ } => {
6468 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
6872 . unwrap ( )
6973 . def_id ;
7074
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+ )
7282 }
7383 ty:: InstanceDef :: DropGlue ( def_id, ty) => build_drop_shim ( tcx, def_id, ty) ,
7484 ty:: InstanceDef :: CloneShim ( def_id, ty) => {
@@ -648,7 +658,7 @@ impl CloneShimBuilder<'tcx> {
648658fn build_call_shim < ' tcx > (
649659 tcx : TyCtxt < ' tcx > ,
650660 instance : ty:: InstanceDef < ' tcx > ,
651- rcvr_adjustment : Adjustment ,
661+ rcvr_adjustment : Option < Adjustment > ,
652662 call_kind : CallKind ,
653663 untuple_args : Option < & [ Ty < ' tcx > ] > ,
654664) -> BodyAndCache < ' tcx > {
@@ -680,14 +690,16 @@ fn build_call_shim<'tcx>(
680690 let mut local_decls = local_decls_for_sig ( & sig, span) ;
681691 let source_info = SourceInfo { span, scope : OUTERMOST_SOURCE_SCOPE } ;
682692
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+ } ;
685697 let mut statements = vec ! [ ] ;
686698
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 ( ) ) ) ,
691703 Adjustment :: RefMut => {
692704 // let rcvr = &mut rcvr;
693705 let ref_rcvr = local_decls. push ( temp_decl (
@@ -703,15 +715,15 @@ fn build_call_shim<'tcx>(
703715 source_info,
704716 kind : StatementKind :: Assign ( box (
705717 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 ( ) ) ,
707719 ) ) ,
708720 } ) ;
709721 Operand :: Move ( Place :: from ( ref_rcvr) )
710722 }
711- } ;
723+ } ) ;
712724
713725 let ( callee, mut args) = match call_kind {
714- CallKind :: Indirect => ( rcvr, vec ! [ ] ) ,
726+ CallKind :: Indirect => ( rcvr. unwrap ( ) , vec ! [ ] ) ,
715727 CallKind :: Direct ( def_id) => {
716728 let ty = tcx. type_of ( def_id) ;
717729 (
@@ -720,21 +732,35 @@ fn build_call_shim<'tcx>(
720732 user_ty : None ,
721733 literal : ty:: Const :: zero_sized ( tcx, ty) ,
722734 } ) ,
723- vec ! [ rcvr] ,
735+ rcvr. into_iter ( ) . collect :: < Vec < _ > > ( ) ,
724736 )
725737 }
726738 } ;
727739
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.
728756 if let Some ( untuple_args) = untuple_args {
757+ let tuple_arg = Local :: new ( 1 + ( sig. inputs ( ) . len ( ) - 1 ) ) ;
729758 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) )
732760 } ) ) ;
733- } else {
734- args. extend ( ( 1 ..sig. inputs ( ) . len ( ) ) . map ( |i| Operand :: Move ( Place :: from ( Local :: new ( 1 + i) ) ) ) ) ;
735761 }
736762
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 } ;
738764 let mut blocks = IndexVec :: with_capacity ( n_blocks) ;
739765 let block = |blocks : & mut IndexVec < _ , _ > , statements, kind, is_cleanup| {
740766 blocks. push ( BasicBlockData {
@@ -752,7 +778,7 @@ fn build_call_shim<'tcx>(
752778 func : callee,
753779 args,
754780 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 {
756782 Some ( BasicBlock :: new ( 3 ) )
757783 } else {
758784 None
@@ -762,13 +788,13 @@ fn build_call_shim<'tcx>(
762788 false ,
763789 ) ;
764790
765- if let Adjustment :: RefMut = rcvr_adjustment {
791+ if let Some ( Adjustment :: RefMut ) = rcvr_adjustment {
766792 // BB #1 - drop for Self
767793 block (
768794 & mut blocks,
769795 vec ! [ ] ,
770796 TerminatorKind :: Drop {
771- location : Place :: from ( rcvr_arg ) ,
797+ location : rcvr_place ( ) ,
772798 target : BasicBlock :: new ( 2 ) ,
773799 unwind : None ,
774800 } ,
@@ -777,13 +803,13 @@ fn build_call_shim<'tcx>(
777803 }
778804 // BB #1/#2 - return
779805 block ( & mut blocks, vec ! [ ] , TerminatorKind :: Return , false ) ;
780- if let Adjustment :: RefMut = rcvr_adjustment {
806+ if let Some ( Adjustment :: RefMut ) = rcvr_adjustment {
781807 // BB #3 - drop if closure panics
782808 block (
783809 & mut blocks,
784810 vec ! [ ] ,
785811 TerminatorKind :: Drop {
786- location : Place :: from ( rcvr_arg ) ,
812+ location : rcvr_place ( ) ,
787813 target : BasicBlock :: new ( 4 ) ,
788814 unwind : None ,
789815 } ,
0 commit comments