about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-08-09 11:36:22 +0000
committerbors <bors@rust-lang.org>2014-08-09 11:36:22 +0000
commit1712ab2300df3a319c4e9595cd7fa4fd1c8a3aab (patch)
treeec90d65cf5e61b21b53b5efc58c3090720be7610 /src
parent87134c7d72d0a39f696051a22c05aa2b328a6d00 (diff)
parentf765759af24ffa8ccc6f9b3913d2e135146e230e (diff)
downloadrust-1712ab2300df3a319c4e9595cd7fa4fd1c8a3aab.tar.gz
rust-1712ab2300df3a319c4e9595cd7fa4fd1c8a3aab.zip
auto merge of #16253 : luqmana/rust/muv, r=nikomatsakis
Fixes #11958.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs8
-rw-r--r--src/librustc/middle/mem_categorization.rs57
-rw-r--r--src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs15
-rw-r--r--src/test/compile-fail/unused-mut-warning-captured-var.rs17
-rw-r--r--src/test/run-pass/issue-11958.rs22
5 files changed, 91 insertions, 28 deletions
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index 7dec42538cf..65c7e1a6031 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -764,18 +764,17 @@ impl<'a> CheckLoanCtxt<'a> {
         return;
 
         fn mark_variable_as_used_mut(this: &CheckLoanCtxt,
-                                     cmt: mc::cmt) {
+                                     mut cmt: mc::cmt) {
             //! If the mutability of the `cmt` being written is inherited
             //! from a local variable, liveness will
             //! not have been able to detect that this variable's mutability
             //! is important, so we must add the variable to the
             //! `used_mut_nodes` table here.
 
-            let mut cmt = cmt;
             loop {
-                debug!("mark_writes_through_upvars_as_used_mut(cmt={})",
-                       cmt.repr(this.tcx()));
+                debug!("mark_variable_as_used_mut(cmt={})", cmt.repr(this.tcx()));
                 match cmt.cat.clone() {
+                    mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id, .. }) |
                     mc::cat_local(id) | mc::cat_arg(id) => {
                         this.tcx().used_mut_nodes.borrow_mut().insert(id);
                         return;
@@ -792,7 +791,6 @@ impl<'a> CheckLoanCtxt<'a> {
 
                     mc::cat_rvalue(..) |
                     mc::cat_static_item |
-                    mc::cat_copied_upvar(..) |
                     mc::cat_deref(_, _, mc::UnsafePtr(..)) |
                     mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
                     mc::cat_deref(_, _, mc::Implicit(..)) => {
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 52a32241faf..39a7b4aa3d6 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -306,6 +306,29 @@ impl MutabilityCategory {
         }
     }
 
+    fn from_def(def: &def::Def) -> MutabilityCategory {
+        match *def {
+            def::DefFn(..) | def::DefStaticMethod(..) | def::DefSelfTy(..) |
+            def::DefMod(..) | def::DefForeignMod(..) | def::DefVariant(..) |
+            def::DefTy(..) | def::DefTrait(..) | def::DefPrimTy(..) |
+            def::DefTyParam(..) | def::DefUse(..) | def::DefStruct(..) |
+            def::DefTyParamBinder(..) | def::DefRegion(..) | def::DefLabel(..) |
+            def::DefMethod(..) => fail!("no MutabilityCategory for def: {}", *def),
+
+            def::DefStatic(_, false) => McImmutable,
+            def::DefStatic(_, true) => McDeclared,
+
+            def::DefArg(_, binding_mode) |
+            def::DefBinding(_, binding_mode) |
+            def::DefLocal(_, binding_mode)  => match binding_mode {
+                ast::BindByValue(ast::MutMutable) => McDeclared,
+                _ => McImmutable
+            },
+
+            def::DefUpvar(_, def, _, _) => MutabilityCategory::from_def(&*def)
+        }
+    }
+
     pub fn inherit(&self) -> MutabilityCategory {
         match *self {
             McImmutable => McImmutable,
@@ -503,8 +526,8 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
           def::DefStaticMethod(..) => {
                 Ok(self.cat_rvalue_node(id, span, expr_ty))
           }
-          def::DefMod(_) | def::DefForeignMod(_) | def::DefStatic(_, false) |
-          def::DefUse(_) | def::DefTrait(_) | def::DefTy(_) | def::DefPrimTy(_) |
+          def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
+          def::DefTrait(_) | def::DefTy(_) | def::DefPrimTy(_) |
           def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
           def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) => {
               Ok(Rc::new(cmt_ {
@@ -516,30 +539,25 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
               }))
           }
 
-          def::DefStatic(_, true) => {
+          def::DefStatic(_, _) => {
               Ok(Rc::new(cmt_ {
                   id:id,
                   span:span,
                   cat:cat_static_item,
-                  mutbl: McDeclared,
+                  mutbl: MutabilityCategory::from_def(&def),
                   ty:expr_ty
               }))
           }
 
-          def::DefArg(vid, binding_mode) => {
+          def::DefArg(vid, _) => {
             // Idea: make this could be rewritten to model by-ref
             // stuff as `&const` and `&mut`?
 
-            // m: mutability of the argument
-            let m = match binding_mode {
-                ast::BindByValue(ast::MutMutable) => McDeclared,
-                _ => McImmutable
-            };
             Ok(Rc::new(cmt_ {
                 id: id,
                 span: span,
                 cat: cat_arg(vid),
-                mutbl: m,
+                mutbl: MutabilityCategory::from_def(&def),
                 ty:expr_ty
             }))
           }
@@ -564,7 +582,6 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
                       if var_is_refd {
                           self.cat_upvar(id, span, var_id, fn_node_id)
                       } else {
-                          // FIXME #2152 allow mutation of moved upvars
                           Ok(Rc::new(cmt_ {
                               id:id,
                               span:span,
@@ -573,13 +590,12 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
                                   onceness: closure_ty.onceness,
                                   capturing_proc: fn_node_id,
                               }),
-                              mutbl:McImmutable,
+                              mutbl: MutabilityCategory::from_def(&def),
                               ty:expr_ty
                           }))
                       }
                   }
                   ty::ty_unboxed_closure(_) => {
-                      // FIXME #2152 allow mutation of moved upvars
                       Ok(Rc::new(cmt_ {
                           id: id,
                           span: span,
@@ -588,7 +604,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
                               onceness: ast::Many,
                               capturing_proc: fn_node_id,
                           }),
-                          mutbl: McImmutable,
+                          mutbl: MutabilityCategory::from_def(&def),
                           ty: expr_ty
                       }))
                   }
@@ -602,19 +618,14 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
               }
           }
 
-          def::DefLocal(vid, binding_mode) |
-          def::DefBinding(vid, binding_mode) => {
+          def::DefLocal(vid, _) |
+          def::DefBinding(vid, _) => {
             // by-value/by-ref bindings are local variables
-            let m = match binding_mode {
-                ast::BindByValue(ast::MutMutable) => McDeclared,
-                _ => McImmutable
-            };
-
             Ok(Rc::new(cmt_ {
                 id: id,
                 span: span,
                 cat: cat_local(vid),
-                mutbl: m,
+                mutbl: MutabilityCategory::from_def(&def),
                 ty: expr_ty
             }))
           }
diff --git a/src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs b/src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs
new file mode 100644
index 00000000000..6bc436d3c18
--- /dev/null
+++ b/src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs
@@ -0,0 +1,15 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x = 1i;
+    proc() { x = 2; };
+    //~^ ERROR: cannot assign to immutable captured outer variable in a proc `x`
+}
diff --git a/src/test/compile-fail/unused-mut-warning-captured-var.rs b/src/test/compile-fail/unused-mut-warning-captured-var.rs
new file mode 100644
index 00000000000..a3db84b0ac6
--- /dev/null
+++ b/src/test/compile-fail/unused-mut-warning-captured-var.rs
@@ -0,0 +1,17 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![forbid(unused_mut)]
+
+fn main() {
+    let mut x = 1i;
+    //~^ ERROR: variable does not need to be mutable
+    proc() { println!("{}", x); };
+}
diff --git a/src/test/run-pass/issue-11958.rs b/src/test/run-pass/issue-11958.rs
new file mode 100644
index 00000000000..f4ed7c5d9c8
--- /dev/null
+++ b/src/test/run-pass/issue-11958.rs
@@ -0,0 +1,22 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![forbid(warnings)]
+
+// Pretty printing tests complain about `use std::predule::*`
+#![allow(unused_imports)]
+
+// We shouldn't need to rebind a moved upvar as mut if it's already
+// marked as mut
+
+pub fn main() {
+    let mut x = 1i;
+    proc() { x = 2; };
+}