about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-07-07 10:21:14 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2011-07-07 10:37:19 +0200
commit007a736642ac88c0adf0d68e8dc6fcb22f0609c3 (patch)
tree484c7c2ebb05f270ae6f6c79ae1c2a97d17bf4f3
parent130006cdda2f40872f6b44665a9b2a0d2d9ded52 (diff)
Improve handling of move and swap by alias checker
Closes issue #541.
Closes issue #591
-rw-r--r--src/comp/middle/alias.rs34
1 files changed, 24 insertions, 10 deletions
diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs
index 0c2200d9771..e2c6036be98 100644
--- a/src/comp/middle/alias.rs
+++ b/src/comp/middle/alias.rs
@@ -14,14 +14,14 @@ import std::option::some;
 import std::option::none;
 import std::option::is_none;
 
-
 // This is not an alias-analyser (though it would merit from becoming one, or
-// at getting input from one, to be more precise). It is a pass that checks
+// getting input from one, to be more precise). It is a pass that checks
 // whether aliases are used in a safe way. Beyond that, though it doesn't have
 // a lot to do with aliases, it also checks whether assignments are valid
 // (using an lval, which is actually mutable), since it already has all the
 // information needed to do that (and the typechecker, which would be a
 // logical place for such a check, doesn't).
+
 tag valid { valid; overwritten(span, ast::path); val_taken(span, ast::path); }
 
 type restrict =
@@ -40,12 +40,10 @@ type ctx = rec(@ty::ctxt tcx,
                std::map::hashmap[node_id, local_info] local_map);
 
 fn check_crate(@ty::ctxt tcx, &@ast::crate crate) {
-    auto cx =
-        @rec(tcx=tcx,
-
-             // Stores information about object fields and function
-             // arguments that's otherwise not easily available.
-             local_map=std::map::new_int_hash());
+    auto cx = @rec(tcx=tcx,
+                   // Stores information about object fields and function
+                   // arguments that's otherwise not easily available.
+                   local_map=std::map::new_int_hash());
     auto v =
         @rec(visit_fn=bind visit_fn(cx, _, _, _, _, _, _, _),
              visit_item=bind visit_item(cx, _, _, _),
@@ -117,9 +115,11 @@ fn visit_expr(@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
         case (ast::expr_swap(?lhs, ?rhs)) {
             check_lval(cx, lhs, sc, v);
             check_lval(cx, rhs, sc, v);
+            handled = false;
         }
         case (ast::expr_move(?dest, ?src)) {
             check_assign(cx, dest, src, sc, v);
+            check_move_rhs(cx, src, sc, v);
         }
         case (ast::expr_assign(?dest, ?src)) {
             check_assign(cx, dest, src, sc, v);
@@ -369,7 +369,6 @@ fn check_var(&ctx cx, &@ast::expr ex, &ast::path p, ast::node_id id,
     auto my_defnum = ast::def_id_of_def(def)._1;
     auto var_t = ty::expr_ty(*cx.tcx, ex);
     for (restrict r in sc) {
-
         // excludes variables introduced since the alias was made
         if (my_defnum < r.block_defnum) {
             for (ty::t t in r.tys) {
@@ -399,7 +398,6 @@ fn check_lval(&@ctx cx, &@ast::expr dest, &scope sc, &vt[scope] v) {
                     r.ok = overwritten(dest.span, p);
                 }
             }
-            check_var(*cx, dest, p, dest.id, true, sc);
         }
         case (_) {
             auto root = expr_root(*cx, dest, false);
@@ -420,6 +418,22 @@ fn check_lval(&@ctx cx, &@ast::expr dest, &scope sc, &vt[scope] v) {
     }
 }
 
+fn check_move_rhs(&@ctx cx, &@ast::expr src, &scope sc, &vt[scope] v) {
+    alt (src.node) {
+        case (ast::expr_path(?p)) {
+            check_lval(cx, src, sc, v);
+        }
+        case (_) {
+            auto root = expr_root(*cx, src, false);
+            // Not a path and no-derefs means this is a temporary.
+            if (vec::len(root.ds) != 0u) {
+                cx.tcx.sess.span_err
+                    (src.span, "moving out of a data structure");
+            }
+        }
+    }
+}
+
 fn check_assign(&@ctx cx, &@ast::expr dest, &@ast::expr src, &scope sc,
                 &vt[scope] v) {
     visit_expr(cx, src, sc, v);