@@ -32,13 +32,15 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
3232 let mut result = match instance {
3333 ty:: InstanceDef :: Item ( ..) => bug ! ( "item {:?} passed to make_shim" , instance) ,
3434 ty:: InstanceDef :: VTableShim ( def_id) => {
35- build_call_shim ( tcx, instance, Some ( Adjustment :: Deref ) , CallKind :: Direct ( def_id) )
35+ let adjustment = Adjustment :: Deref { source : DerefSource :: MutPtr } ;
36+ build_call_shim ( tcx, instance, Some ( adjustment) , CallKind :: Direct ( def_id) )
3637 }
3738 ty:: InstanceDef :: FnPtrShim ( def_id, ty) => {
3839 let trait_ = tcx. trait_of_item ( def_id) . unwrap ( ) ;
3940 let adjustment = match tcx. fn_trait_kind_from_def_id ( trait_) {
4041 Some ( ty:: ClosureKind :: FnOnce ) => Adjustment :: Identity ,
41- Some ( ty:: ClosureKind :: FnMut | ty:: ClosureKind :: Fn ) => Adjustment :: Deref ,
42+ Some ( ty:: ClosureKind :: Fn ) => Adjustment :: Deref { source : DerefSource :: ImmRef } ,
43+ Some ( ty:: ClosureKind :: FnMut ) => Adjustment :: Deref { source : DerefSource :: MutRef } ,
4244 None => bug ! ( "fn pointer {:?} is not an fn" , ty) ,
4345 } ;
4446
@@ -107,16 +109,26 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
107109 result
108110}
109111
112+ #[ derive( Copy , Clone , Debug , PartialEq ) ]
113+ enum DerefSource {
114+ /// `fn shim(&self) { inner(*self )}`.
115+ ImmRef ,
116+ /// `fn shim(&mut self) { inner(*self )}`.
117+ MutRef ,
118+ /// `fn shim(*mut self) { inner(*self )}`.
119+ MutPtr ,
120+ }
121+
110122#[ derive( Copy , Clone , Debug , PartialEq ) ]
111123enum Adjustment {
112124 /// Pass the receiver as-is.
113125 Identity ,
114126
115- /// We get passed `&[mut] self` and call the target with `*self`.
127+ /// We get passed a reference or a raw pointer to ` self` and call the target with `*self`.
116128 ///
117129 /// This either copies `self` (if `Self: Copy`, eg. for function items), or moves out of it
118130 /// (for `VTableShim`, which effectively is passed `&own Self`).
119- Deref ,
131+ Deref { source : DerefSource } ,
120132
121133 /// We get passed `self: Self` and call the target with `&mut self`.
122134 ///
@@ -667,8 +679,12 @@ fn build_call_shim<'tcx>(
667679 let self_arg = & mut inputs_and_output[ 0 ] ;
668680 * self_arg = match rcvr_adjustment. unwrap ( ) {
669681 Adjustment :: Identity => fnty,
670- Adjustment :: Deref => tcx. mk_imm_ptr ( fnty) ,
671- Adjustment :: RefMut => tcx. mk_mut_ptr ( fnty) ,
682+ Adjustment :: Deref { source } => match source {
683+ DerefSource :: ImmRef => tcx. mk_imm_ref ( tcx. lifetimes . re_erased , fnty) ,
684+ DerefSource :: MutRef => tcx. mk_mut_ref ( tcx. lifetimes . re_erased , fnty) ,
685+ DerefSource :: MutPtr => tcx. mk_mut_ptr ( fnty) ,
686+ } ,
687+ Adjustment :: RefMut => bug ! ( "`RefMut` is never used with indirect calls: {instance:?}" ) ,
672688 } ;
673689 sig. inputs_and_output = tcx. mk_type_list ( & inputs_and_output) ;
674690 }
@@ -699,7 +715,7 @@ fn build_call_shim<'tcx>(
699715
700716 let rcvr = rcvr_adjustment. map ( |rcvr_adjustment| match rcvr_adjustment {
701717 Adjustment :: Identity => Operand :: Move ( rcvr_place ( ) ) ,
702- Adjustment :: Deref => Operand :: Move ( tcx. mk_place_deref ( rcvr_place ( ) ) ) ,
718+ Adjustment :: Deref { source : _ } => Operand :: Move ( tcx. mk_place_deref ( rcvr_place ( ) ) ) ,
703719 Adjustment :: RefMut => {
704720 // let rcvr = &mut rcvr;
705721 let ref_rcvr = local_decls. push (
0 commit comments