Skip to content

Commit c4c19fe

Browse files
committed
Correctly trans capture-by-ref unboxed closures
Store references to the freevars instead of copies when constructing the environment and insert an additional load when reading them from the environment.
1 parent 72dc0f5 commit c4c19fe

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

src/librustc/middle/trans/closure.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
301301
fn load_unboxed_closure_environment<'blk, 'tcx>(
302302
bcx: Block<'blk, 'tcx>,
303303
arg_scope_id: ScopeId,
304+
freevar_mode: ast::CaptureClause,
304305
freevars: &Vec<ty::Freevar>,
305306
closure_id: ast::DefId)
306307
-> Block<'blk, 'tcx> {
@@ -326,11 +327,14 @@ fn load_unboxed_closure_environment<'blk, 'tcx>(
326327
};
327328

328329
for (i, freevar) in freevars.iter().enumerate() {
329-
let upvar_ptr = GEPi(bcx, llenv, [0, i]);
330+
let mut upvar_ptr = GEPi(bcx, llenv, [0, i]);
331+
if freevar_mode == ast::CaptureByRef {
332+
upvar_ptr = Load(bcx, upvar_ptr);
333+
}
330334
let def_id = freevar.def.def_id();
331335
bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvar_ptr);
332336

333-
if kind == ty::FnOnceUnboxedClosureKind {
337+
if kind == ty::FnOnceUnboxedClosureKind && freevar_mode == ast::CaptureByValue {
334338
bcx.fcx.schedule_drop_mem(arg_scope_id,
335339
upvar_ptr,
336340
node_id_type(bcx, def_id.node))
@@ -477,6 +481,7 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
477481
let freevars: Vec<ty::Freevar> =
478482
ty::with_freevars(bcx.tcx(), id, |fv| fv.iter().map(|&fv| fv).collect());
479483
let freevars_ptr = &freevars;
484+
let freevar_mode = bcx.tcx().capture_mode(id);
480485

481486
trans_closure(bcx.ccx(),
482487
decl,
@@ -493,6 +498,7 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
493498
|bcx, arg_scope| {
494499
load_unboxed_closure_environment(bcx,
495500
arg_scope,
501+
freevar_mode,
496502
freevars_ptr,
497503
closure_id)
498504
});
@@ -518,7 +524,14 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
518524
dest_addr,
519525
0,
520526
i);
521-
bcx = datum.store_to(bcx, upvar_slot_dest);
527+
match freevar_mode {
528+
ast::CaptureByValue => {
529+
bcx = datum.store_to(bcx, upvar_slot_dest);
530+
}
531+
ast::CaptureByRef => {
532+
Store(bcx, datum.to_llref(), upvar_slot_dest);
533+
}
534+
}
522535
}
523536
adt::trans_set_discr(bcx, &*repr, dest_addr, 0);
524537

0 commit comments

Comments
 (0)