@@ -65,31 +65,36 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
65
65
let func_ty = self . operand_ty ( func) ;
66
66
let fn_def = match func_ty. sty {
67
67
ty:: TyFnPtr ( bare_sig) => {
68
+ let bare_sig = self . tcx . erase_late_bound_regions ( & bare_sig) ;
69
+ let bare_sig = self . tcx . erase_regions ( & bare_sig) ;
68
70
let fn_ptr = self . eval_operand_to_primval ( func) ?. to_ptr ( ) ?;
69
71
let fn_def = self . memory . get_fn ( fn_ptr. alloc_id ) ?;
70
72
match fn_def {
71
73
Function :: Concrete ( fn_def) => {
72
74
// transmuting function pointers in miri is fine as long as the number of
73
75
// arguments and the abi don't change.
74
- // FIXME: also check the size of the arguments' type and the return type
75
- // Didn't get it to work, since that triggers an assertion in rustc which
76
- // checks whether the type has escaping regions
77
- if fn_def. sig . abi ( ) != bare_sig. abi ( ) ||
78
- fn_def. sig . variadic ( ) != bare_sig. variadic ( ) ||
79
- fn_def. sig . inputs ( ) . skip_binder ( ) . len ( ) != bare_sig. inputs ( ) . skip_binder ( ) . len ( ) {
80
- return Err ( EvalError :: FunctionPointerTyMismatch ( fn_def. sig , bare_sig) ) ;
76
+ let sig = self . tcx . erase_late_bound_regions ( & fn_def. sig ) ;
77
+ let sig = self . tcx . erase_regions ( & sig) ;
78
+ if sig. abi != bare_sig. abi ||
79
+ sig. variadic != bare_sig. variadic ||
80
+ sig. inputs_and_output != bare_sig. inputs_and_output {
81
+ return Err ( EvalError :: FunctionPointerTyMismatch ( sig, bare_sig) ) ;
81
82
}
82
83
} ,
83
84
Function :: NonCaptureClosureAsFnPtr ( fn_def) => {
84
- assert_eq ! ( fn_def. sig. abi( ) , Abi :: RustCall ) ;
85
- if fn_def. sig . variadic ( ) != bare_sig. variadic ( ) ||
86
- fn_def. sig . inputs ( ) . skip_binder ( ) . len ( ) != 1 {
87
- return Err ( EvalError :: FunctionPointerTyMismatch ( fn_def. sig , bare_sig) ) ;
85
+ let sig = self . tcx . erase_late_bound_regions ( & fn_def. sig ) ;
86
+ let sig = self . tcx . erase_regions ( & sig) ;
87
+ assert_eq ! ( sig. abi, Abi :: RustCall ) ;
88
+ if sig. variadic != bare_sig. variadic ||
89
+ sig. inputs ( ) . len ( ) != 1 {
90
+ return Err ( EvalError :: FunctionPointerTyMismatch ( sig, bare_sig) ) ;
88
91
}
89
- if let ty:: TyTuple ( fields, _) = fn_def . sig . inputs ( ) . skip_binder ( ) [ 0 ] . sty {
90
- if fields. len ( ) != bare_sig. inputs ( ) . skip_binder ( ) . len ( ) {
91
- return Err ( EvalError :: FunctionPointerTyMismatch ( fn_def . sig , bare_sig) ) ;
92
+ if let ty:: TyTuple ( fields, _) = sig. inputs ( ) [ 0 ] . sty {
93
+ if * * fields != * bare_sig. inputs ( ) {
94
+ return Err ( EvalError :: FunctionPointerTyMismatch ( sig, bare_sig) ) ;
92
95
}
96
+ } else {
97
+ return Err ( EvalError :: FunctionPointerTyMismatch ( sig, bare_sig) ) ;
93
98
}
94
99
} ,
95
100
other => return Err ( EvalError :: ExpectedConcreteFunction ( other) ) ,
@@ -165,7 +170,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
165
170
match fn_def {
166
171
// Intrinsics can only be addressed directly
167
172
Function :: Concrete ( FunctionDefinition { def_id, substs, sig } ) if sig. abi ( ) == Abi :: RustIntrinsic => {
168
- let ty = * sig. output ( ) . skip_binder ( ) ;
173
+ let sig = self . tcx . erase_late_bound_regions ( & sig) ;
174
+ let sig = self . tcx . erase_regions ( & sig) ;
175
+ let ty = sig. output ( ) ;
169
176
let layout = self . type_layout ( ty) ?;
170
177
let ( ret, target) = match destination {
171
178
Some ( dest) if is_inhabited ( self . tcx , ty) => dest,
@@ -177,7 +184,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
177
184
} ,
178
185
// C functions can only be addressed directly
179
186
Function :: Concrete ( FunctionDefinition { def_id, sig, ..} ) if sig. abi ( ) == Abi :: C => {
180
- let ty = * sig. output ( ) . skip_binder ( ) ;
187
+ let sig = self . tcx . erase_late_bound_regions ( & sig) ;
188
+ let sig = self . tcx . erase_regions ( & sig) ;
189
+ let ty = sig. output ( ) ;
181
190
let ( ret, target) = destination. unwrap ( ) ;
182
191
self . call_c_abi ( def_id, arg_operands, ret, ty) ?;
183
192
self . dump_local ( ret) ;
@@ -266,6 +275,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
266
275
)
267
276
} ,
268
277
Function :: NonCaptureClosureAsFnPtr ( FunctionDefinition { def_id, substs, sig } ) if sig. abi ( ) == Abi :: RustCall => {
278
+ let sig = self . tcx . erase_late_bound_regions ( & sig) ;
279
+ let sig = self . tcx . erase_regions ( & sig) ;
269
280
let mut args = Vec :: new ( ) ;
270
281
for arg in arg_operands {
271
282
let arg_val = self . eval_operand ( arg) ?;
@@ -274,7 +285,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
274
285
}
275
286
args. insert ( 0 , (
276
287
Value :: ByVal ( PrimVal :: Undef ) ,
277
- sig. inputs ( ) . skip_binder ( ) [ 0 ] ,
288
+ sig. inputs ( ) [ 0 ] ,
278
289
) ) ;
279
290
self . eval_fn_call_inner (
280
291
def_id,
@@ -285,7 +296,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
285
296
span,
286
297
)
287
298
}
288
- other => Err ( EvalError :: Unimplemented ( format ! ( "can't call function kind {:?}" , other) ) ) ,
299
+ Function :: Concrete ( fn_def) => Err ( EvalError :: Unimplemented ( format ! ( "can't handle function with {:?} ABI" , fn_def. sig. abi( ) ) ) ) ,
300
+ other => Err ( EvalError :: Unimplemented ( format ! ( "can't call function kind {:#?}" , other) ) ) ,
289
301
}
290
302
}
291
303
0 commit comments