From c4c19fe96003bb5bdaa6ca35603eb4220b1d5ca8 Mon Sep 17 00:00:00 2001 From: Brian Koropoff Date: Thu, 2 Oct 2014 19:43:16 -0700 Subject: 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. --- src/librustc/middle/trans/closure.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index f08736335c3..1e2e8c589c6 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -301,6 +301,7 @@ fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, fn load_unboxed_closure_environment<'blk, 'tcx>( bcx: Block<'blk, 'tcx>, arg_scope_id: ScopeId, + freevar_mode: ast::CaptureClause, freevars: &Vec, closure_id: ast::DefId) -> Block<'blk, 'tcx> { @@ -326,11 +327,14 @@ fn load_unboxed_closure_environment<'blk, 'tcx>( }; for (i, freevar) in freevars.iter().enumerate() { - let upvar_ptr = GEPi(bcx, llenv, [0, i]); + let mut upvar_ptr = GEPi(bcx, llenv, [0, i]); + if freevar_mode == ast::CaptureByRef { + upvar_ptr = Load(bcx, upvar_ptr); + } let def_id = freevar.def.def_id(); bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvar_ptr); - if kind == ty::FnOnceUnboxedClosureKind { + if kind == ty::FnOnceUnboxedClosureKind && freevar_mode == ast::CaptureByValue { bcx.fcx.schedule_drop_mem(arg_scope_id, upvar_ptr, node_id_type(bcx, def_id.node)) @@ -477,6 +481,7 @@ pub fn trans_unboxed_closure<'blk, 'tcx>( let freevars: Vec = ty::with_freevars(bcx.tcx(), id, |fv| fv.iter().map(|&fv| fv).collect()); let freevars_ptr = &freevars; + let freevar_mode = bcx.tcx().capture_mode(id); trans_closure(bcx.ccx(), decl, @@ -493,6 +498,7 @@ pub fn trans_unboxed_closure<'blk, 'tcx>( |bcx, arg_scope| { load_unboxed_closure_environment(bcx, arg_scope, + freevar_mode, freevars_ptr, closure_id) }); @@ -518,7 +524,14 @@ pub fn trans_unboxed_closure<'blk, 'tcx>( dest_addr, 0, i); - bcx = datum.store_to(bcx, upvar_slot_dest); + match freevar_mode { + ast::CaptureByValue => { + bcx = datum.store_to(bcx, upvar_slot_dest); + } + ast::CaptureByRef => { + Store(bcx, datum.to_llref(), upvar_slot_dest); + } + } } adt::trans_set_discr(bcx, &*repr, dest_addr, 0); -- cgit 1.4.1-3-g733a5