Skip to content

Commit c75d45d

Browse files
nikomatsakiscatamorphism
authored andcommitted
For for loop bodies, translate the type of the closure
based on the expr_loop_body expression and not the inner closure
1 parent 745a020 commit c75d45d

File tree

3 files changed

+35
-11
lines changed

3 files changed

+35
-11
lines changed

src/librustc/middle/trans/callee.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -638,8 +638,8 @@ fn trans_arg_expr(bcx: block,
638638
let arg_ty = expr_ty(bcx, arg_expr);
639639
let proto = ty::ty_fn_proto(arg_ty);
640640
let bcx = closure::trans_expr_fn(
641-
bcx, proto, decl, /*bad*/copy *body, blk.id, cap,
642-
Some(ret_flag), expr::SaveIn(scratch));
641+
bcx, proto, decl, /*bad*/copy *body, arg_expr.id,
642+
blk.id, cap, Some(ret_flag), expr::SaveIn(scratch));
643643
DatumBlock {bcx: bcx,
644644
datum: Datum {val: scratch,
645645
ty: scratch_ty,

src/librustc/middle/trans/closure.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -381,10 +381,30 @@ fn trans_expr_fn(bcx: block,
381381
proto: ast::Proto,
382382
+decl: ast::fn_decl,
383383
+body: ast::blk,
384-
id: ast::node_id,
384+
outer_id: ast::node_id,
385+
user_id: ast::node_id,
385386
cap_clause: ast::capture_clause,
386387
is_loop_body: Option<Option<ValueRef>>,
387-
dest: expr::Dest) -> block {
388+
dest: expr::Dest) -> block
389+
{
390+
/*!
391+
*
392+
* Translates the body of a closure expression.
393+
*
394+
* - `proto`
395+
* - `decl`
396+
* - `body`
397+
* - `outer_id`: The id of the closure expression with the correct type.
398+
* This is usually the same as as `user_id`, but in the case of a `for` loop,
399+
* the `outer_id` will have the return type of boolean, and the `user_id` will
400+
* have the return type of `nil`.
401+
* - `user_id`: The id of the closure as the user expressed it. Generally
402+
the same as `outer_id`
403+
* - `cap_clause`: information about captured variables, if any.
404+
* - `is_loop_body`: `Some()` if this is part of a `for` loop.
405+
* - `dest`: where to write the closure value, which must be a (fn ptr, env) pair
406+
*/
407+
388408
let _icx = bcx.insn_ctxt("closure::trans_expr_fn");
389409

390410
let dest_addr = match dest {
@@ -395,7 +415,7 @@ fn trans_expr_fn(bcx: block,
395415
};
396416

397417
let ccx = bcx.ccx();
398-
let fty = node_id_type(bcx, id);
418+
let fty = node_id_type(bcx, outer_id);
399419
let llfnty = type_of_fn_from_ty(ccx, fty);
400420
let sub_path = vec::append_one(/*bad*/copy bcx.fcx.path,
401421
path_name(special_idents::anon));
@@ -407,14 +427,15 @@ fn trans_expr_fn(bcx: block,
407427

408428
// XXX: Bad copies.
409429
let trans_closure_env = |proto, copy body, copy sub_path, copy decl| {
410-
let cap_vars = capture::compute_capture_vars(ccx.tcx, id, proto,
430+
let cap_vars = capture::compute_capture_vars(ccx.tcx, user_id, proto,
411431
cap_clause);
412432
let ret_handle = match is_loop_body { Some(x) => x, None => None };
413433
// XXX: Bad copy.
414434
let {llbox, cdata_ty, bcx} = build_closure(bcx, copy cap_vars, proto,
415435
ret_handle);
416436
trans_closure(ccx, /*bad*/copy sub_path, decl, body, llfn, no_self,
417-
/*bad*/copy bcx.fcx.param_substs, id, None, |fcx| {
437+
/*bad*/copy bcx.fcx.param_substs, user_id, None,
438+
|fcx| {
418439
load_environment(fcx, cdata_ty, copy cap_vars,
419440
ret_handle.is_some(), proto);
420441
}, |bcx| {
@@ -431,7 +452,7 @@ fn trans_expr_fn(bcx: block,
431452
}
432453
ast::ProtoBare => {
433454
trans_closure(ccx, sub_path, decl, body, llfn, no_self, None,
434-
id, None, |_fcx| { }, |_bcx| { });
455+
user_id, None, |_fcx| { }, |_bcx| { });
435456
rslt(bcx, C_null(T_opaque_box_ptr(ccx)))
436457
}
437458
};

src/librustc/middle/trans/expr.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -564,8 +564,10 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
564564
ast::expr_fn(proto, copy decl, ref body, cap_clause) => {
565565
// Don't use this function for anything real. Use the one in
566566
// astconv instead.
567-
return closure::trans_expr_fn(bcx, proto, decl, /*bad*/copy *body,
568-
expr.id, cap_clause, None, dest);
567+
return closure::trans_expr_fn(bcx, proto, decl,
568+
/*bad*/copy *body,
569+
expr.id, expr.id,
570+
cap_clause, None, dest);
569571
}
570572
ast::expr_fn_block(ref decl, ref body, cap_clause) => {
571573
let expr_ty = expr_ty(bcx, expr);
@@ -576,7 +578,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
576578
ty_to_str(tcx, expr_ty));
577579
return closure::trans_expr_fn(
578580
bcx, fn_ty.meta.proto, /*bad*/copy *decl,
579-
/*bad*/copy *body, expr.id,
581+
/*bad*/copy *body, expr.id, expr.id,
580582
cap_clause, None, dest);
581583
}
582584
_ => {
@@ -595,6 +597,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
595597
fn_ty.meta.proto,
596598
decl,
597599
/*bad*/copy *body,
600+
expr.id,
598601
blk.id,
599602
cap,
600603
Some(None),

0 commit comments

Comments
 (0)