about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2012-05-29 15:37:50 -0700
committerNiko Matsakis <niko@alum.mit.edu>2012-05-29 16:22:17 -0700
commitf90228b8a82deb8da178d32322057d7e17245a77 (patch)
treec3121277e2296d1e65d4ca405e376914d51acb7a /src
parent47375439ed3563f0ba8e37f5d7737011383ecbd0 (diff)
downloadrust-f90228b8a82deb8da178d32322057d7e17245a77.tar.gz
rust-f90228b8a82deb8da178d32322057d7e17245a77.zip
make all arguments modes immutable
note: you can still move from copy/move mode args
Diffstat (limited to 'src')
-rw-r--r--src/libcore/dvec.rs12
-rw-r--r--src/rustc/middle/borrowck.rs11
-rw-r--r--src/rustc/middle/liveness.rs46
-rw-r--r--src/test/compile-fail/liveness-move-from-args.rs24
-rw-r--r--src/test/compile-fail/mutable-arguments.rs30
-rw-r--r--src/test/run-pass/argument-passing.rs1
6 files changed, 109 insertions, 15 deletions
diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs
index 1a46d630d4f..c7a31b39ad5 100644
--- a/src/libcore/dvec.rs
+++ b/src/libcore/dvec.rs
@@ -131,12 +131,15 @@ impl extensions<A> for dvec<A> {
 impl extensions<A:copy> for dvec<A> {
     #[doc = "Append a single item to the end of the list"]
     fn push(t: A) {
-        self.swap { |v| v += [t]; v } // more efficient than v + [t]
+        self.swap { |v|
+            let mut v <- v; v += [t]; v // more efficient than v + [t]
+        }
     }
 
     #[doc = "Remove and return the last element"]
     fn pop() -> A {
         self.borrow { |v|
+            let mut v <- v;
             let result = vec::pop(v);
             self.return(v);
             result
@@ -157,6 +160,7 @@ impl extensions<A:copy> for dvec<A> {
     "]
     fn push_slice(ts: [const A]/&, from_idx: uint, to_idx: uint) {
         self.swap { |v|
+            let mut v <- v;
             let new_len = vec::len(v) + to_idx - from_idx;
             vec::reserve(v, new_len);
             let mut i = from_idx;
@@ -232,6 +236,10 @@ impl extensions<A:copy> for dvec<A> {
 
     #[doc = "Overwrites the contents of the element at `idx` with `a`"]
     fn grow_set_elt(idx: uint, initval: A, val: A) {
-        self.swap { |v| vec::grow_set(v, idx, initval, val); v }
+        self.swap { |v|
+            let mut v <- v;
+            vec::grow_set(v, idx, initval, val);
+            v
+        }
     }
 }
\ No newline at end of file
diff --git a/src/rustc/middle/borrowck.rs b/src/rustc/middle/borrowck.rs
index d6e7ce1b990..71a1e9d2d21 100644
--- a/src/rustc/middle/borrowck.rs
+++ b/src/rustc/middle/borrowck.rs
@@ -843,11 +843,8 @@ impl methods for check_loan_ctxt {
                self.bccx.cmt_to_repr(cmt)];
 
         alt cmt.cat {
-          // Rvalues and locals can be moved:
-          cat_rvalue | cat_local(_) { }
-
-          // Owned arguments can be moved:
-          cat_arg(_) if cmt.mutbl == m_mutbl { }
+          // Rvalues, locals, and arguments can be moved:
+          cat_rvalue | cat_local(_) | cat_arg(_) { }
 
           // We allow moving out of static items because the old code
           // did.  This seems consistent with permitting moves out of
@@ -1348,7 +1345,7 @@ impl categorize_methods for borrowck_ctxt {
                  lp: none}
               }
               ast::by_move | ast::by_copy {
-                {m: m_mutbl,
+                {m: m_imm,
                  lp: some(@lp_arg(vid))}
               }
               ast::by_ref {
@@ -1506,7 +1503,7 @@ impl categorize_methods for borrowck_ctxt {
           cat_special(sk_heap_upvar) { "upvar" }
           cat_rvalue { "non-lvalue" }
           cat_local(_) { mut_str + " local variable" }
-          cat_arg(_) { mut_str + " argument" }
+          cat_arg(_) { "argument" }
           cat_deref(_, _, pk) { #fmt["dereference of %s %s pointer",
                                      mut_str, self.pk_to_sigil(pk)] }
           cat_stack_upvar(_) { mut_str + " upvar" }
diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs
index 9b732d08052..3f82e647ab6 100644
--- a/src/rustc/middle/liveness.rs
+++ b/src/rustc/middle/liveness.rs
@@ -1506,10 +1506,7 @@ impl check_methods for @liveness {
             (*self.ir).add_spill(var);
           }
           some(lnk) {
-            self.report_illegal_read(span, lnk, var, moved_variable);
-            self.tcx.sess.span_note(
-                span,
-                "move of variable occurred here");
+            self.report_illegal_move(span, lnk, var);
           }
         }
     }
@@ -1637,6 +1634,44 @@ impl check_methods for @liveness {
         }
     }
 
+    fn report_illegal_move(move_span: span,
+                           lnk: live_node_kind,
+                           var: variable) {
+
+        // the only time that it is possible to have a moved variable
+        // used by lnk_exit would be arguments or fields in a ctor.
+        // we give a slightly different error message in those cases.
+        if lnk == lnk_exit {
+            let vk = self.ir.var_kinds[*var];
+            alt vk {
+              vk_arg(_, name, _) {
+                self.tcx.sess.span_err(
+                    move_span,
+                    #fmt["illegal move from argument `%s`, which is not \
+                          copy or move mode", name]);
+                ret;
+              }
+              vk_field(name) {
+                self.tcx.sess.span_err(
+                    move_span,
+                    #fmt["illegal move from field `%s`", name]);
+                ret;
+              }
+              vk_local(*) | vk_self | vk_implicit_ret {
+                self.tcx.sess.span_bug(
+                    move_span,
+                    #fmt["illegal reader (%?) for `%?`",
+                         lnk, vk]);
+              }
+            }
+        }
+
+        self.report_illegal_read(move_span, lnk, var, moved_variable);
+        self.tcx.sess.span_note(
+            move_span, "move of variable occurred here");
+
+    }
+
     fn report_illegal_read(chk_span: span,
                            lnk: live_node_kind,
                            var: variable,
@@ -1658,7 +1693,8 @@ impl check_methods for @liveness {
                 span,
                 #fmt["use of %s: `%s`", msg, name]);
           }
-          lnk_exit | lnk_vdef(_) {
+          lnk_exit |
+          lnk_vdef(_) {
             self.tcx.sess.span_bug(
                 chk_span,
                 #fmt["illegal reader: %?", lnk]);
diff --git a/src/test/compile-fail/liveness-move-from-args.rs b/src/test/compile-fail/liveness-move-from-args.rs
new file mode 100644
index 00000000000..0c3e594040b
--- /dev/null
+++ b/src/test/compile-fail/liveness-move-from-args.rs
@@ -0,0 +1,24 @@
+fn take(-_x: int) { }
+
+fn from_by_value_arg(++x: int) {
+    take(x);  //! ERROR illegal move from argument `x`, which is not copy or move mode
+}
+
+fn from_by_mut_ref_arg(&x: int) {
+    take(x);  //! ERROR illegal move from argument `x`, which is not copy or move mode
+}
+
+fn from_by_ref_arg(&&x: int) {
+    take(x);  //! ERROR illegal move from argument `x`, which is not copy or move mode
+}
+
+fn from_copy_arg(+x: int) {
+    take(x);
+}
+
+fn from_move_arg(-x: int) {
+    take(x);
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/mutable-arguments.rs b/src/test/compile-fail/mutable-arguments.rs
new file mode 100644
index 00000000000..79e7f412163
--- /dev/null
+++ b/src/test/compile-fail/mutable-arguments.rs
@@ -0,0 +1,30 @@
+// Note: it would be nice to give fewer warnings in these cases.
+
+fn mutate_by_mut_ref(&x: uint) {
+    x = 0u;
+}
+
+fn mutate_by_ref(&&x: uint) {
+    //!^ WARNING unused variable: `x`
+    x = 0u; //! ERROR assigning to argument
+}
+
+fn mutate_by_val(++x: uint) {
+    //!^ WARNING unused variable: `x`
+    x = 0u; //! ERROR assigning to argument
+}
+
+fn mutate_by_copy(+x: uint) {
+    //!^ WARNING unused variable: `x`
+    x = 0u; //! ERROR assigning to argument
+    //!^ WARNING value assigned to `x` is never read
+}
+
+fn mutate_by_move(-x: uint) {
+    //!^ WARNING unused variable: `x`
+    x = 0u; //! ERROR assigning to argument
+    //!^ WARNING value assigned to `x` is never read
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/argument-passing.rs b/src/test/run-pass/argument-passing.rs
index 2f17efd3279..bd8f56eec0b 100644
--- a/src/test/run-pass/argument-passing.rs
+++ b/src/test/run-pass/argument-passing.rs
@@ -2,7 +2,6 @@ fn f1(a: {mut x: int}, &b: int, -c: int) -> int {
     let r = a.x + b + c;
     a.x = 0;
     b = 10;
-    c = 20;
     ret r;
 }