about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2013-01-07 10:16:30 -0800
committerTim Chevalier <chevalier@alum.wellesley.edu>2013-01-13 14:37:59 -0800
commitc75d45d7e3bf3a6f45029baf97e0448bbcf07608 (patch)
tree89d1bc09842774ba6d40d9a2c2218ed7bd38e237
parent745a020db5a1139270579ae102d444aaec51597d (diff)
downloadrust-c75d45d7e3bf3a6f45029baf97e0448bbcf07608.tar.gz
rust-c75d45d7e3bf3a6f45029baf97e0448bbcf07608.zip
For `for` loop bodies, translate the type of the closure
based on the expr_loop_body expression and not the inner closure
-rw-r--r--src/librustc/middle/trans/callee.rs4
-rw-r--r--src/librustc/middle/trans/closure.rs33
-rw-r--r--src/librustc/middle/trans/expr.rs9
3 files changed, 35 insertions, 11 deletions
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 2f43f421abb..e154d62147c 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 0e0ff7ef5be..eae73729b58 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<Option<ValueRef>>,
-                 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 a13aa73f330..5cbd7fa47c5 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),