mirror of
https://github.com/rust-lang/rust.git
synced 2026-06-01 05:57:03 +03:00
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.
This commit is contained in:
@@ -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<ty::Freevar>,
|
||||
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::Freevar> =
|
||||
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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user