@@ -264,24 +264,36 @@ fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
264
264
/// but for the bare function type given.
265
265
pub fn trans_fn_pointer_shim < ' a , ' tcx > (
266
266
ccx : & ' a CrateContext < ' a , ' tcx > ,
267
+ closure_kind : ty:: ClosureKind ,
267
268
bare_fn_ty : Ty < ' tcx > )
268
269
-> ValueRef
269
270
{
270
271
let _icx = push_ctxt ( "trans_fn_pointer_shim" ) ;
271
272
let tcx = ccx. tcx ( ) ;
272
273
274
+ // Normalize the type for better caching.
273
275
let bare_fn_ty = common:: erase_regions ( tcx, & bare_fn_ty) ;
274
- match ccx. fn_pointer_shims ( ) . borrow ( ) . get ( & bare_fn_ty) {
276
+
277
+ // If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`.
278
+ let is_by_ref = match closure_kind {
279
+ ty:: FnClosureKind | ty:: FnMutClosureKind => true ,
280
+ ty:: FnOnceClosureKind => false ,
281
+ } ;
282
+ let bare_fn_ty_maybe_ref = if is_by_ref {
283
+ ty:: mk_imm_rptr ( tcx, tcx. mk_region ( ty:: ReStatic ) , bare_fn_ty)
284
+ } else {
285
+ bare_fn_ty
286
+ } ;
287
+
288
+ // Check if we already trans'd this shim.
289
+ match ccx. fn_pointer_shims ( ) . borrow ( ) . get ( & bare_fn_ty_maybe_ref) {
275
290
Some ( & llval) => { return llval; }
276
291
None => { }
277
292
}
278
293
279
294
debug ! ( "trans_fn_pointer_shim(bare_fn_ty={})" ,
280
295
bare_fn_ty. repr( tcx) ) ;
281
296
282
- // This is an impl of `Fn` trait, so receiver is `&self`.
283
- let bare_fn_ty_ref = ty:: mk_imm_rptr ( tcx, tcx. mk_region ( ty:: ReStatic ) , bare_fn_ty) ;
284
-
285
297
// Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`,
286
298
// which is the fn pointer, and `args`, which is the arguments tuple.
287
299
let ( opt_def_id, sig) =
@@ -306,7 +318,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
306
318
unsafety : ast:: Unsafety :: Normal ,
307
319
abi : synabi:: RustCall ,
308
320
sig : ty:: Binder ( ty:: FnSig {
309
- inputs : vec ! [ bare_fn_ty_ref ,
321
+ inputs : vec ! [ bare_fn_ty_maybe_ref ,
310
322
tuple_input_ty] ,
311
323
output : sig. output ,
312
324
variadic : false
@@ -337,8 +349,11 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
337
349
let mut bcx = init_function ( & fcx, false , sig. output ) ;
338
350
339
351
// the first argument (`self`) will be ptr to the the fn pointer
340
- let llfnpointer =
341
- Load ( bcx, get_param ( fcx. llfn , fcx. arg_pos ( 0 ) as u32 ) ) ;
352
+ let llfnpointer = if is_by_ref {
353
+ Load ( bcx, get_param ( fcx. llfn , fcx. arg_pos ( 0 ) as u32 ) )
354
+ } else {
355
+ get_param ( fcx. llfn , fcx. arg_pos ( 0 ) as u32 )
356
+ } ;
342
357
343
358
// the remaining arguments will be the untupled values
344
359
let llargs: Vec < _ > =
@@ -361,7 +376,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
361
376
362
377
finish_fn ( & fcx, bcx, sig. output , DebugLoc :: None ) ;
363
378
364
- ccx. fn_pointer_shims ( ) . borrow_mut ( ) . insert ( bare_fn_ty , llfn) ;
379
+ ccx. fn_pointer_shims ( ) . borrow_mut ( ) . insert ( bare_fn_ty_maybe_ref , llfn) ;
365
380
366
381
llfn
367
382
}
0 commit comments