]> git.lizzy.rs Git - rust.git/commitdiff
librustc: Automatically move non-implicitly-copyable types into unique closures....
authorPatrick Walton <pcwalton@mimiga.net>
Mon, 10 Dec 2012 21:59:51 +0000 (13:59 -0800)
committerPatrick Walton <pcwalton@mimiga.net>
Thu, 13 Dec 2012 23:33:33 +0000 (15:33 -0800)
src/librustc/middle/capture.rs
src/librustc/middle/kind.rs
src/librustc/middle/liveness.rs
src/librustc/middle/trans/callee.rs
src/librustc/middle/trans/expr.rs
src/test/compile-fail/moves-based-on-type-capture-clause-bad.rs [new file with mode: 0644]
src/test/run-pass/moves-based-on-type-capture-clause.rs [new file with mode: 0644]

index bce59a087e90331e0b0d36f0bee23cce2e10d452..f9a7459c67176561fdddcdc35e7dc1a621dd2e5b 100644 (file)
@@ -110,22 +110,29 @@ fn compute_capture_vars(tcx: ty::ctxt,
     // now go through anything that is referenced but was not explicitly
     // named and add that
 
-    let implicit_mode;
-    if fn_proto == ast::ProtoBorrowed {
-        implicit_mode = cap_ref;
-    } else {
-        implicit_mode = cap_copy;
-    }
-
+    let implicit_mode_is_by_ref = fn_proto == ast::ProtoBorrowed;
     for vec::each(*freevars) |fvar| {
         let fvar_def_id = ast_util::def_id_of_def(fvar.def).node;
         match cap_map.find(fvar_def_id) {
             option::Some(_) => { /* was explicitly named, do nothing */ }
             option::None => {
+                // Move if this type implicitly moves; copy otherwise.
+                let mode;
+                if implicit_mode_is_by_ref {
+                    mode = cap_ref;
+                } else {
+                    let fvar_ty = ty::node_id_to_type(tcx, fvar_def_id);
+                    if ty::type_implicitly_moves(tcx, fvar_ty) {
+                        mode = cap_move;
+                    } else {
+                        mode = cap_copy;
+                    }
+                };
+
                 cap_map.insert(fvar_def_id, {def:fvar.def,
                                              span: fvar.span,
                                              cap_item: None,
-                                             mode:implicit_mode});
+                                             mode:mode});
             }
         }
     }
index a8395013958eb3c71e904518f0c62c0796c77630..8075fdfe65e4113762e22affc38dedb0c4da0126 100644 (file)
@@ -201,7 +201,6 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
             let cap_def = cx.tcx.def_map.get(cap_item.id);
             let cap_def_id = ast_util::def_id_of_def(cap_def).node;
             let ty = ty::node_id_to_type(cx.tcx, cap_def_id);
-            // Here's where is_move isn't always false...
             chk(cx, fn_id, None, cap_item.is_move, ty, cap_item.span);
             cap_def_id
         };
@@ -215,9 +214,12 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
             if captured_vars.contains(&id) { loop; }
 
             let ty = ty::node_id_to_type(cx.tcx, id);
-            // is_move is always false here. See the let captured_vars...
-            // code above for where it's not always false.
-            chk(cx, fn_id, Some(*fv), false, ty, fv.span);
+
+            // is_move is true if this type implicitly moves and false
+            // otherwise.
+            let is_move = ty::type_implicitly_moves(cx.tcx, ty);
+
+            chk(cx, fn_id, Some(*fv), is_move, ty, fv.span);
         }
     }
 
index 48fff1a269bde792cbf09af1f847f40000b4efb6..47284c1df5ac060c7c96356ccdd2fc92b732551e 100644 (file)
@@ -524,8 +524,8 @@ fn visit_expr(expr: @expr, &&self: @IrMaps, vt: vt<@IrMaps>) {
         // in better error messages than just pointing at the closure
         // construction site.
         let proto = ty::ty_fn_proto(ty::expr_ty(self.tcx, expr));
-        let cvs = capture::compute_capture_vars(self.tcx, expr.id,
-                                                proto, cap_clause);
+        let cvs = capture::compute_capture_vars(self.tcx, expr.id, proto,
+                                                cap_clause);
         let mut call_caps = ~[];
         for cvs.each |cv| {
             match relevant_def(cv.def) {
index 7117ae6910cc27271e6e4a2166f6c4833911e3e0..f9694b0ced6e9b5ae8a9185f53775dbaa1936f11 100644 (file)
@@ -621,8 +621,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, (*body), blk.id,
-                        cap, Some(ret_flag), expr::SaveIn(scratch));
+                        bcx, proto, decl, (*body), blk.id, cap,
+                        Some(ret_flag), expr::SaveIn(scratch));
                     DatumBlock {bcx: bcx,
                                 datum: Datum {val: scratch,
                                               ty: scratch_ty,
index 764ddabd1434f38a68b9c995354f3a5e66c897c5..d7a1b14fae3e05a0bfbd99c8c7cb2edd91a4eeef 100644 (file)
@@ -549,9 +549,8 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
         ast::expr_fn(proto, 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, (*body), expr.id, cap_clause,
-                                          None, dest);
+            return closure::trans_expr_fn(bcx, proto, decl, *body, expr.id,
+                                          cap_clause, None, dest);
         }
         ast::expr_fn_block(decl, ref body, cap_clause) => {
             let expr_ty = expr_ty(bcx, expr);
@@ -561,9 +560,8 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
                            expr_to_str(expr, tcx.sess.intr()),
                            ty_to_str(tcx, expr_ty));
                     return closure::trans_expr_fn(
-                        bcx, fn_ty.meta.proto, decl, (*body),
-                        expr.id, cap_clause, None,
-                        dest);
+                        bcx, fn_ty.meta.proto, decl, *body, expr.id,
+                        cap_clause, None, dest);
                 }
                 _ => {
                     bcx.sess().impossible_case(
@@ -577,7 +575,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
                     match blk.node {
                         ast::expr_fn_block(decl, ref body, cap) => {
                             return closure::trans_expr_fn(
-                                bcx, fn_ty.meta.proto, decl, (*body), blk.id,
+                                bcx, fn_ty.meta.proto, decl, *body, blk.id,
                                 cap, Some(None), dest);
                         }
                         _ => {
diff --git a/src/test/compile-fail/moves-based-on-type-capture-clause-bad.rs b/src/test/compile-fail/moves-based-on-type-capture-clause-bad.rs
new file mode 100644 (file)
index 0000000..26c1e13
--- /dev/null
@@ -0,0 +1,8 @@
+fn main() {
+    let x = ~"Hello world!";
+    do task::spawn {
+        io::println(x);
+    }
+    io::println(x); //~ ERROR use of moved variable
+}
+
diff --git a/src/test/run-pass/moves-based-on-type-capture-clause.rs b/src/test/run-pass/moves-based-on-type-capture-clause.rs
new file mode 100644 (file)
index 0000000..206d45b
--- /dev/null
@@ -0,0 +1,7 @@
+fn main() {
+    let x = ~"Hello world!";
+    do task::spawn {
+        io::println(x);
+    }
+}
+