@@ -32,13 +32,15 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
32
32
let mut result = match instance {
33
33
ty:: InstanceDef :: Item ( ..) => bug ! ( "item {:?} passed to make_shim" , instance) ,
34
34
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) )
36
37
}
37
38
ty:: InstanceDef :: FnPtrShim ( def_id, ty) => {
38
39
let trait_ = tcx. trait_of_item ( def_id) . unwrap ( ) ;
39
40
let adjustment = match tcx. fn_trait_kind_from_def_id ( trait_) {
40
41
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 } ,
42
44
None => bug ! ( "fn pointer {:?} is not an fn" , ty) ,
43
45
} ;
44
46
@@ -107,16 +109,26 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
107
109
result
108
110
}
109
111
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
+
110
122
#[ derive( Copy , Clone , Debug , PartialEq ) ]
111
123
enum Adjustment {
112
124
/// Pass the receiver as-is.
113
125
Identity ,
114
126
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`.
116
128
///
117
129
/// This either copies `self` (if `Self: Copy`, eg. for function items), or moves out of it
118
130
/// (for `VTableShim`, which effectively is passed `&own Self`).
119
- Deref ,
131
+ Deref { source : DerefSource } ,
120
132
121
133
/// We get passed `self: Self` and call the target with `&mut self`.
122
134
///
@@ -667,8 +679,12 @@ fn build_call_shim<'tcx>(
667
679
let self_arg = & mut inputs_and_output[ 0 ] ;
668
680
* self_arg = match rcvr_adjustment. unwrap ( ) {
669
681
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:?}" ) ,
672
688
} ;
673
689
sig. inputs_and_output = tcx. mk_type_list ( & inputs_and_output) ;
674
690
}
@@ -699,7 +715,7 @@ fn build_call_shim<'tcx>(
699
715
700
716
let rcvr = rcvr_adjustment. map ( |rcvr_adjustment| match rcvr_adjustment {
701
717
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 ( ) ) ) ,
703
719
Adjustment :: RefMut => {
704
720
// let rcvr = &mut rcvr;
705
721
let ref_rcvr = local_decls. push (
0 commit comments