From c75d45d7e3bf3a6f45029baf97e0448bbcf07608 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 7 Jan 2013 10:16:30 -0800 Subject: [PATCH] For `for` loop bodies, translate the type of the closure based on the expr_loop_body expression and not the inner closure --- src/librustc/middle/trans/callee.rs | 4 ++-- src/librustc/middle/trans/closure.rs | 33 +++++++++++++++++++++++----- src/librustc/middle/trans/expr.rs | 9 +++++--- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 2f43f421abbe..e154d62147cb 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -638,8 +638,8 @@ fn trans_arg_expr(bcx: block, let arg_ty = expr_ty(bcx, arg_expr); let proto = ty::ty_fn_proto(arg_ty); let bcx = closure::trans_expr_fn( - bcx, proto, decl, /*bad*/copy *body, blk.id, cap, - Some(ret_flag), expr::SaveIn(scratch)); + bcx, proto, decl, /*bad*/copy *body, arg_expr.id, + blk.id, cap, Some(ret_flag), expr::SaveIn(scratch)); DatumBlock {bcx: bcx, datum: Datum {val: scratch, ty: scratch_ty, diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 0e0ff7ef5be6..eae73729b584 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -381,10 +381,30 @@ fn trans_expr_fn(bcx: block, proto: ast::Proto, +decl: ast::fn_decl, +body: ast::blk, - id: ast::node_id, + outer_id: ast::node_id, + user_id: ast::node_id, cap_clause: ast::capture_clause, is_loop_body: Option>, - dest: expr::Dest) -> block { + dest: expr::Dest) -> block +{ + /*! + * + * Translates the body of a closure expression. + * + * - `proto` + * - `decl` + * - `body` + * - `outer_id`: The id of the closure expression with the correct type. + * This is usually the same as as `user_id`, but in the case of a `for` loop, + * the `outer_id` will have the return type of boolean, and the `user_id` will + * have the return type of `nil`. + * - `user_id`: The id of the closure as the user expressed it. Generally + the same as `outer_id` + * - `cap_clause`: information about captured variables, if any. + * - `is_loop_body`: `Some()` if this is part of a `for` loop. + * - `dest`: where to write the closure value, which must be a (fn ptr, env) pair + */ + let _icx = bcx.insn_ctxt("closure::trans_expr_fn"); let dest_addr = match dest { @@ -395,7 +415,7 @@ fn trans_expr_fn(bcx: block, }; let ccx = bcx.ccx(); - let fty = node_id_type(bcx, id); + let fty = node_id_type(bcx, outer_id); let llfnty = type_of_fn_from_ty(ccx, fty); let sub_path = vec::append_one(/*bad*/copy bcx.fcx.path, path_name(special_idents::anon)); @@ -407,14 +427,15 @@ fn trans_expr_fn(bcx: block, // XXX: Bad copies. let trans_closure_env = |proto, copy body, copy sub_path, copy decl| { - let cap_vars = capture::compute_capture_vars(ccx.tcx, id, proto, + let cap_vars = capture::compute_capture_vars(ccx.tcx, user_id, proto, cap_clause); let ret_handle = match is_loop_body { Some(x) => x, None => None }; // XXX: Bad copy. let {llbox, cdata_ty, bcx} = build_closure(bcx, copy cap_vars, proto, ret_handle); trans_closure(ccx, /*bad*/copy sub_path, decl, body, llfn, no_self, - /*bad*/copy bcx.fcx.param_substs, id, None, |fcx| { + /*bad*/copy bcx.fcx.param_substs, user_id, None, + |fcx| { load_environment(fcx, cdata_ty, copy cap_vars, ret_handle.is_some(), proto); }, |bcx| { @@ -431,7 +452,7 @@ fn trans_expr_fn(bcx: block, } ast::ProtoBare => { trans_closure(ccx, sub_path, decl, body, llfn, no_self, None, - id, None, |_fcx| { }, |_bcx| { }); + user_id, None, |_fcx| { }, |_bcx| { }); rslt(bcx, C_null(T_opaque_box_ptr(ccx))) } }; diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index a13aa73f330d..5cbd7fa47c53 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -564,8 +564,10 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, ast::expr_fn(proto, copy decl, ref body, cap_clause) => { // Don't use this function for anything real. Use the one in // astconv instead. - return closure::trans_expr_fn(bcx, proto, decl, /*bad*/copy *body, - expr.id, cap_clause, None, dest); + return closure::trans_expr_fn(bcx, proto, decl, + /*bad*/copy *body, + expr.id, expr.id, + cap_clause, None, dest); } ast::expr_fn_block(ref decl, ref body, cap_clause) => { let expr_ty = expr_ty(bcx, expr); @@ -576,7 +578,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, ty_to_str(tcx, expr_ty)); return closure::trans_expr_fn( bcx, fn_ty.meta.proto, /*bad*/copy *decl, - /*bad*/copy *body, expr.id, + /*bad*/copy *body, expr.id, expr.id, cap_clause, None, dest); } _ => { @@ -595,6 +597,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, fn_ty.meta.proto, decl, /*bad*/copy *body, + expr.id, blk.id, cap, Some(None),