]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #26378 - arielb1:unused-mut, r=pnkfelix
authorbors <bors@rust-lang.org>
Fri, 3 Jul 2015 21:31:46 +0000 (21:31 +0000)
committerbors <bors@rust-lang.org>
Fri, 3 Jul 2015 21:31:46 +0000 (21:31 +0000)
This makes it somewhat more aggressive, so this is kind-of a [breaking-change] for these compiling with `#[deny(unused_mut)]`.

r? @pnkfelix

src/libcore/iter.rs
src/libfmt_macros/lib.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_trans/save/dump_csv.rs
src/libsyntax/parse/lexer/mod.rs
src/test/compile-fail/lint-unused-mut-variables.rs

index 3026f91e853eee34f69833a1615d05da56be928a..4c8511eb1902c55f0e2fec2c09ad4934530f53ea 100644 (file)
@@ -2655,8 +2655,8 @@ fn step(&self, by: &$t) -> Option<$t> {
             #[allow(trivial_numeric_casts)]
             fn steps_between(start: &$t, end: &$t, by: &$t) -> Option<usize> {
                 if *by == 0 { return None; }
-                let mut diff: usize;
-                let mut by_u: usize;
+                let diff: usize;
+                let by_u: usize;
                 if *by > 0 {
                     if *start >= *end {
                         return Some(0);
index c2b28bd134d478f7c64be02c634f05067f89f069..7ca89cfd0c9cc828cee98ef95f313011d8bb7750 100644 (file)
@@ -399,7 +399,7 @@ fn word(&mut self) -> &'a str {
             }
             Some(..) | None => { return &self.input[..0]; }
         };
-        let mut end;
+        let end;
         loop {
             match self.cur.clone().next() {
                 Some((_, c)) if c.is_xid_continue() => {
index 17075c0cba6cabe0f64ba18bd6a7f5b73f5ef1d2..6d5b47d8ed980bb40a0d3eef2c3ea8f53f1222fb 100644 (file)
@@ -1854,7 +1854,7 @@ fn inc_counter(&self) {
     }
 
     fn give_lifetime(&self) -> ast::Lifetime {
-        let mut lifetime;
+        let lifetime;
         loop {
             let mut s = String::from("'");
             s.push_str(&num_to_string(self.counter.get()));
index 7c2318eef9cdd067157a9a2068582ce94ec9eb79..1be2b605dbdcc5f45c0e0492e2d6f65a3294ad2d 100644 (file)
@@ -183,7 +183,7 @@ fn mutate(&mut self,
             None => { }
         }
 
-        self.check_assignment(assignment_id, assignment_span, assignee_cmt, mode);
+        self.check_assignment(assignment_id, assignment_span, assignee_cmt);
     }
 
     fn decl_without_init(&mut self, _id: ast::NodeId, _span: Span) { }
@@ -567,13 +567,6 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
         true
     }
 
-    fn is_local_variable_or_arg(&self, cmt: mc::cmt<'tcx>) -> bool {
-        match cmt.cat {
-          mc::cat_local(_) => true,
-          _ => false
-        }
-    }
-
     fn consume_common(&self,
                       id: ast::NodeId,
                       span: Span,
@@ -791,202 +784,35 @@ fn check_if_assigned_path_is_moved(&self,
     fn check_assignment(&self,
                         assignment_id: ast::NodeId,
                         assignment_span: Span,
-                        assignee_cmt: mc::cmt<'tcx>,
-                        mode: euv::MutateMode) {
+                        assignee_cmt: mc::cmt<'tcx>) {
         debug!("check_assignment(assignee_cmt={:?})", assignee_cmt);
 
-        // Mutable values can be assigned, as long as they obey loans
-        // and aliasing restrictions:
-        if assignee_cmt.mutbl.is_mutable() {
-            if check_for_aliasable_mutable_writes(self, assignment_span, assignee_cmt.clone()) {
-                if mode != euv::Init {
-                    check_for_assignment_to_borrowed_path(
-                        self, assignment_id, assignment_span, assignee_cmt.clone());
-                    mark_variable_as_used_mut(self, assignee_cmt);
-                }
-            }
-
-            return;
-        }
-
-        // Initializations are OK if and only if they aren't partial
-        // reinitialization of a partially-uninitialized structure.
-        if mode == euv::Init {
-            return
-        }
-
-        // For immutable local variables, assignments are legal
-        // if they cannot already have been assigned
-        if self.is_local_variable_or_arg(assignee_cmt.clone()) {
-            assert!(assignee_cmt.mutbl.is_immutable()); // no "const" locals
-            let lp = opt_loan_path(&assignee_cmt).unwrap();
-            self.move_data.each_assignment_of(assignment_id, &lp, |assign| {
-                self.bccx.report_reassigned_immutable_variable(
-                    assignment_span,
-                    &*lp,
-                    assign);
+        // Check that we don't invalidate any outstanding loans
+        if let Some(loan_path) = opt_loan_path(&assignee_cmt) {
+            let scope = region::CodeExtent::from_node_id(assignment_id);
+            self.each_in_scope_loan_affecting_path(scope, &*loan_path, |loan| {
+                self.report_illegal_mutation(assignment_span, &*loan_path, loan);
                 false
             });
-            return;
         }
 
-        // Otherwise, just a plain error.
-        match assignee_cmt.note {
-            mc::NoteClosureEnv(upvar_id) => {
-                // If this is an `Fn` closure, it simply can't mutate upvars.
-                // If it's an `FnMut` closure, the original variable was declared immutable.
-                // We need to determine which is the case here.
-                let kind = match assignee_cmt.upvar().unwrap().cat {
-                    mc::cat_upvar(mc::Upvar { kind, .. }) => kind,
-                    _ => unreachable!()
-                };
-                if kind == ty::FnClosureKind {
-                    self.bccx.span_err(
-                        assignment_span,
-                        &format!("cannot assign to {}",
-                                self.bccx.cmt_to_string(&*assignee_cmt)));
-                    self.bccx.span_help(
-                        self.tcx().map.span(upvar_id.closure_expr_id),
-                        "consider changing this closure to take self by mutable reference");
+        // Check for reassignments to (immutable) local variables. This
+        // needs to be done here instead of in check_loans because we
+        // depend on move data.
+        if let mc::cat_local(local_id) = assignee_cmt.cat {
+            let lp = opt_loan_path(&assignee_cmt).unwrap();
+            self.move_data.each_assignment_of(assignment_id, &lp, |assign| {
+                if assignee_cmt.mutbl.is_mutable() {
+                    self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
                 } else {
-                    self.bccx.span_err(
+                    self.bccx.report_reassigned_immutable_variable(
                         assignment_span,
-                        &format!("cannot assign to {} {}",
-                                assignee_cmt.mutbl.to_user_str(),
-                                self.bccx.cmt_to_string(&*assignee_cmt)));
-                }
-            }
-            _ => match opt_loan_path(&assignee_cmt) {
-                Some(lp) => {
-                    self.bccx.span_err(
-                        assignment_span,
-                        &format!("cannot assign to {} {} `{}`",
-                                assignee_cmt.mutbl.to_user_str(),
-                                self.bccx.cmt_to_string(&*assignee_cmt),
-                                self.bccx.loan_path_to_string(&*lp)));
-                }
-                None => {
-                    self.bccx.span_err(
-                        assignment_span,
-                        &format!("cannot assign to {} {}",
-                                assignee_cmt.mutbl.to_user_str(),
-                                self.bccx.cmt_to_string(&*assignee_cmt)));
-                }
-            }
-        }
-        return;
-
-        fn mark_variable_as_used_mut<'a, 'tcx>(this: &CheckLoanCtxt<'a, 'tcx>,
-                                               mut cmt: mc::cmt<'tcx>) {
-            //! 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.
-
-            loop {
-                debug!("mark_variable_as_used_mut(cmt={:?})", cmt);
-                match cmt.cat.clone() {
-                    mc::cat_upvar(mc::Upvar { id: ty::UpvarId { var_id: id, .. }, .. }) |
-                    mc::cat_local(id) => {
-                        this.tcx().used_mut_nodes.borrow_mut().insert(id);
-                        return;
-                    }
-
-                    mc::cat_rvalue(..) |
-                    mc::cat_static_item |
-                    mc::cat_deref(_, _, mc::UnsafePtr(..)) |
-                    mc::cat_deref(_, _, mc::Implicit(..)) => {
-                        assert_eq!(cmt.mutbl, mc::McDeclared);
-                        return;
-                    }
-
-                    mc::cat_deref(_, _, mc::BorrowedPtr(..)) => {
-                        assert_eq!(cmt.mutbl, mc::McDeclared);
-                        // We need to drill down to upvar if applicable
-                        match cmt.upvar() {
-                            Some(b) => cmt = b,
-                            None => return
-                        }
-                    }
-
-                    mc::cat_deref(b, _, mc::Unique) => {
-                        assert_eq!(cmt.mutbl, mc::McInherited);
-                        cmt = b;
-                    }
-
-                    mc::cat_downcast(b, _) |
-                    mc::cat_interior(b, _) => {
-                        assert_eq!(cmt.mutbl, mc::McInherited);
-                        cmt = b;
-                    }
-                }
-            }
-        }
-
-        fn check_for_aliasable_mutable_writes<'a, 'tcx>(this: &CheckLoanCtxt<'a, 'tcx>,
-                                                        span: Span,
-                                                        cmt: mc::cmt<'tcx>) -> bool {
-            //! Safety checks related to writes to aliasable, mutable locations
-
-            let guarantor = cmt.guarantor();
-            debug!("check_for_aliasable_mutable_writes(cmt={:?}, guarantor={:?})",
-                   cmt, guarantor);
-            if let mc::cat_deref(ref b, _, mc::BorrowedPtr(ty::MutBorrow, _)) = guarantor.cat {
-                // Statically prohibit writes to `&mut` when aliasable
-                check_for_aliasability_violation(this, span, b.clone());
-            }
-
-            return true; // no errors reported
-        }
-
-        fn check_for_aliasability_violation<'a, 'tcx>(this: &CheckLoanCtxt<'a, 'tcx>,
-                                                      span: Span,
-                                                      cmt: mc::cmt<'tcx>)
-                                                      -> bool {
-            match cmt.freely_aliasable(this.tcx()) {
-                mc::Aliasability::NonAliasable => {
-                    return true;
-                }
-                mc::Aliasability::FreelyAliasable(mc::AliasableStaticMut(..)) => {
-                    return true;
-                }
-                mc::Aliasability::ImmutableUnique(_) => {
-                    this.bccx.report_aliasability_violation(
-                        span,
-                        MutabilityViolation,
-                        mc::AliasableReason::UnaliasableImmutable);
-                    return false;
-                }
-                mc::Aliasability::FreelyAliasable(cause) => {
-                    this.bccx.report_aliasability_violation(
-                        span,
-                        MutabilityViolation,
-                        cause);
-                    return false;
+                        &*lp,
+                        assign);
                 }
-            }
-        }
-
-        fn check_for_assignment_to_borrowed_path<'a, 'tcx>(
-            this: &CheckLoanCtxt<'a, 'tcx>,
-            assignment_id: ast::NodeId,
-            assignment_span: Span,
-            assignee_cmt: mc::cmt<'tcx>)
-        {
-            //! Check for assignments that violate the terms of an
-            //! outstanding loan.
-
-            let loan_path = match opt_loan_path(&assignee_cmt) {
-                Some(lp) => lp,
-                None => { return; /* no loan path, can't be any loans */ }
-            };
-
-            let scope = region::CodeExtent::from_node_id(assignment_id);
-            this.each_in_scope_loan_affecting_path(scope, &*loan_path, |loan| {
-                this.report_illegal_mutation(assignment_span, &*loan_path, loan);
                 false
             });
+            return
         }
     }
 
index 427d78e89b3e2dbe11a787298ac418e45c1f7d5d..919bc45f00ddfe955e4ae188574ef83af8cb3a54 100644 (file)
@@ -137,7 +137,7 @@ fn scope(&self, cmt: &mc::cmt) -> ty::Region {
     fn report_error(&self, code: bckerr_code) {
         self.bccx.report(BckError { cmt: self.cmt_original.clone(),
                                     span: self.span,
-                                    cause: self.cause,
+                                    cause: BorrowViolation(self.cause),
                                     code: code });
     }
 }
index 432d6289efec5a017d8d1144cc7662578138bb9a..6899892a245ed5d5d4512705e36cc2f0428839d3 100644 (file)
@@ -152,22 +152,10 @@ fn mutate(&mut self,
               assignee_cmt: mc::cmt<'tcx>,
               mode: euv::MutateMode)
     {
-        let opt_lp = opt_loan_path(&assignee_cmt);
-        debug!("mutate(assignment_id={}, assignee_cmt={:?}) opt_lp={:?}",
-               assignment_id, assignee_cmt, opt_lp);
-
-        match opt_lp {
-            Some(lp) => {
-                gather_moves::gather_assignment(self.bccx, &self.move_data,
-                                                assignment_id, assignment_span,
-                                                lp, assignee_cmt.id, mode);
-            }
-            None => {
-                // This can occur with e.g. `*foo() = 5`.  In such
-                // cases, there is no need to check for conflicts
-                // with moves etc, just ignore.
-            }
-        }
+        self.guarantee_assignment_valid(assignment_id,
+                                        assignment_span,
+                                        assignee_cmt,
+                                        mode);
     }
 
     fn decl_without_init(&mut self, id: ast::NodeId, span: Span) {
@@ -178,7 +166,7 @@ fn decl_without_init(&mut self, id: ast::NodeId, span: Span) {
 /// Implements the A-* rules in README.md.
 fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                 borrow_span: Span,
-                                loan_cause: euv::LoanCause,
+                                loan_cause: AliasableViolationKind,
                                 cmt: mc::cmt<'tcx>,
                                 req_kind: ty::BorrowKind)
                                 -> Result<(),()> {
@@ -204,7 +192,7 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         (mc::Aliasability::ImmutableUnique(_), ty::MutBorrow) => {
             bccx.report_aliasability_violation(
                         borrow_span,
-                        BorrowViolation(loan_cause),
+                        loan_cause,
                         mc::AliasableReason::UnaliasableImmutable);
             Err(())
         }
@@ -212,7 +200,7 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         (mc::Aliasability::FreelyAliasable(alias_cause), ty::MutBorrow) => {
             bccx.report_aliasability_violation(
                         borrow_span,
-                        BorrowViolation(loan_cause),
+                        loan_cause,
                         alias_cause);
             Err(())
         }
@@ -222,9 +210,94 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     }
 }
 
+/// Implements the M-* rules in README.md.
+fn check_mutability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
+                              borrow_span: Span,
+                              cause: AliasableViolationKind,
+                              cmt: mc::cmt<'tcx>,
+                              req_kind: ty::BorrowKind)
+                              -> Result<(),()> {
+    debug!("check_mutability(cause={:?} cmt={:?} req_kind={:?}",
+           cause, cmt, req_kind);
+    match req_kind {
+        ty::UniqueImmBorrow | ty::ImmBorrow => {
+            match cmt.mutbl {
+                // I am intentionally leaving this here to help
+                // refactoring if, in the future, we should add new
+                // kinds of mutability.
+                mc::McImmutable | mc::McDeclared | mc::McInherited => {
+                    // both imm and mut data can be lent as imm;
+                    // for mutable data, this is a freeze
+                    Ok(())
+                }
+            }
+        }
+
+        ty::MutBorrow => {
+            // Only mutable data can be lent as mutable.
+            if !cmt.mutbl.is_mutable() {
+                Err(bccx.report(BckError { span: borrow_span,
+                                           cause: cause,
+                                           cmt: cmt,
+                                           code: err_mutbl }))
+            } else {
+                Ok(())
+            }
+        }
+    }
+}
+
 impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
     pub fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.bccx.tcx }
 
+    /// Guarantees that `cmt` is assignable, or reports an error.
+    fn guarantee_assignment_valid(&mut self,
+                                  assignment_id: ast::NodeId,
+                                  assignment_span: Span,
+                                  cmt: mc::cmt<'tcx>,
+                                  mode: euv::MutateMode) {
+
+        let opt_lp = opt_loan_path(&cmt);
+        debug!("guarantee_assignment_valid(assignment_id={}, cmt={:?}) opt_lp={:?}",
+               assignment_id, cmt, opt_lp);
+
+        if let mc::cat_local(..) = cmt.cat {
+            // Only re-assignments to locals require it to be
+            // mutable - this is checked in check_loans.
+        } else {
+            // Check that we don't allow assignments to non-mutable data.
+            if check_mutability(self.bccx, assignment_span, MutabilityViolation,
+                                cmt.clone(), ty::MutBorrow).is_err() {
+                return; // reported an error, no sense in reporting more.
+            }
+        }
+
+        // Check that we don't allow assignments to aliasable data
+        if check_aliasability(self.bccx, assignment_span, MutabilityViolation,
+                              cmt.clone(), ty::MutBorrow).is_err() {
+            return; // reported an error, no sense in reporting more.
+        }
+
+        match opt_lp {
+            Some(lp) => {
+                if let mc::cat_local(..) = cmt.cat {
+                    // Only re-assignments to locals require it to be
+                    // mutable - this is checked in check_loans.
+                } else {
+                    self.mark_loan_path_as_mutated(&lp);
+                }
+                gather_moves::gather_assignment(self.bccx, &self.move_data,
+                                                assignment_id, assignment_span,
+                                                lp, cmt.id, mode);
+            }
+            None => {
+                // This can occur with e.g. `*foo() = 5`.  In such
+                // cases, there is no need to check for conflicts
+                // with moves etc, just ignore.
+            }
+        }
+    }
+
     /// Guarantees that `addr_of(cmt)` will be valid for the duration of `static_scope_r`, or
     /// reports an error.  This may entail taking out loans, which will be added to the
     /// `req_loan_map`.
@@ -257,13 +330,13 @@ fn guarantee_valid(&mut self,
         }
 
         // Check that we don't allow mutable borrows of non-mutable data.
-        if check_mutability(self.bccx, borrow_span, cause,
+        if check_mutability(self.bccx, borrow_span, BorrowViolation(cause),
                             cmt.clone(), req_kind).is_err() {
             return; // reported an error, no sense in reporting more.
         }
 
         // Check that we don't allow mutable borrows of aliasable data.
-        if check_aliasability(self.bccx, borrow_span, cause,
+        if check_aliasability(self.bccx, borrow_span, BorrowViolation(cause),
                               cmt.clone(), req_kind).is_err() {
             return; // reported an error, no sense in reporting more.
         }
@@ -369,43 +442,6 @@ fn guarantee_valid(&mut self,
             //        restrictions: restrictions
             //    }
         // }
-
-        fn check_mutability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
-                                      borrow_span: Span,
-                                      cause: euv::LoanCause,
-                                      cmt: mc::cmt<'tcx>,
-                                      req_kind: ty::BorrowKind)
-                                      -> Result<(),()> {
-            //! Implements the M-* rules in README.md.
-            debug!("check_mutability(cause={:?} cmt={:?} req_kind={:?}",
-                   cause, cmt, req_kind);
-            match req_kind {
-                ty::UniqueImmBorrow | ty::ImmBorrow => {
-                    match cmt.mutbl {
-                        // I am intentionally leaving this here to help
-                        // refactoring if, in the future, we should add new
-                        // kinds of mutability.
-                        mc::McImmutable | mc::McDeclared | mc::McInherited => {
-                            // both imm and mut data can be lent as imm;
-                            // for mutable data, this is a freeze
-                            Ok(())
-                        }
-                    }
-                }
-
-                ty::MutBorrow => {
-                    // Only mutable data can be lent as mutable.
-                    if !cmt.mutbl.is_mutable() {
-                        Err(bccx.report(BckError { span: borrow_span,
-                                                   cause: cause,
-                                                   cmt: cmt,
-                                                   code: err_mutbl }))
-                    } else {
-                        Ok(())
-                    }
-                }
-            }
-        }
     }
 
     pub fn mark_loan_path_as_mutated(&self, loan_path: &LoanPath) {
@@ -496,7 +532,8 @@ fn visit_expr(&mut self, ex: &Expr) {
             let base_cmt = mc.cat_expr(&**base).unwrap();
             let borrow_kind = ty::BorrowKind::from_mutbl(mutbl);
             // Check that we don't allow borrows of unsafe static items.
-            if check_aliasability(self.bccx, ex.span, euv::AddrOf,
+            if check_aliasability(self.bccx, ex.span,
+                                  BorrowViolation(euv::AddrOf),
                                   base_cmt, borrow_kind).is_err() {
                 return; // reported an error, no sense in reporting more.
             }
index 345f5378f69e106c0fd3142f66d31f94229f3de1..4c186dd840610a071816952be41a50c671314d4f 100644 (file)
@@ -124,7 +124,7 @@ fn restrict(&self,
                             self.bccx.report(
                                 BckError {
                                     span: self.span,
-                                    cause: self.cause,
+                                    cause: BorrowViolation(self.cause),
                                     cmt: cmt_base,
                                     code: err_borrowed_pointer_too_short(
                                         self.loan_region, lt)});
index 3a4318527fb4036263d1c400ede0092bf2d26c7e..0d475e125714188e1780766d97a97d39c5289f8a 100644 (file)
@@ -545,12 +545,12 @@ pub enum bckerr_code {
 #[derive(PartialEq)]
 pub struct BckError<'tcx> {
     span: Span,
-    cause: euv::LoanCause,
+    cause: AliasableViolationKind,
     cmt: mc::cmt<'tcx>,
     code: bckerr_code
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug, PartialEq)]
 pub enum AliasableViolationKind {
     MutabilityViolation,
     BorrowViolation(euv::LoanCause)
@@ -575,8 +575,10 @@ pub fn is_subregion_of(&self, r_sub: ty::Region, r_sup: ty::Region)
     pub fn report(&self, err: BckError<'tcx>) {
         // Catch and handle some particular cases.
         match (&err.code, &err.cause) {
-            (&err_out_of_scope(ty::ReScope(_), ty::ReStatic), &euv::ClosureCapture(span)) |
-            (&err_out_of_scope(ty::ReScope(_), ty::ReFree(..)), &euv::ClosureCapture(span)) => {
+            (&err_out_of_scope(ty::ReScope(_), ty::ReStatic),
+             &BorrowViolation(euv::ClosureCapture(span))) |
+            (&err_out_of_scope(ty::ReScope(_), ty::ReFree(..)),
+             &BorrowViolation(euv::ClosureCapture(span))) => {
                 return self.report_out_of_scope_escaping_closure_capture(&err, span);
             }
             _ => { }
@@ -795,10 +797,6 @@ pub fn span_end_note(&self, s: Span, m: &str) {
         self.tcx.sess.span_end_note(s, m);
     }
 
-    pub fn span_help(&self, s: Span, m: &str) {
-        self.tcx.sess.span_help(s, m);
-    }
-
     pub fn fileline_help(&self, s: Span, m: &str) {
         self.tcx.sess.fileline_help(s, m);
     }
@@ -826,19 +824,22 @@ pub fn bckerr_to_string(&self, err: &BckError<'tcx>) -> String {
                 };
 
                 match err.cause {
-                    euv::ClosureCapture(_) => {
+                    MutabilityViolation => {
+                        format!("cannot assign to {}", descr)
+                    }
+                    BorrowViolation(euv::ClosureCapture(_)) => {
                         format!("closure cannot assign to {}", descr)
                     }
-                    euv::OverloadedOperator |
-                    euv::AddrOf |
-                    euv::RefBinding |
-                    euv::AutoRef |
-                    euv::AutoUnsafe |
-                    euv::ForLoop |
-                    euv::MatchDiscriminant => {
+                    BorrowViolation(euv::OverloadedOperator) |
+                    BorrowViolation(euv::AddrOf) |
+                    BorrowViolation(euv::RefBinding) |
+                    BorrowViolation(euv::AutoRef) |
+                    BorrowViolation(euv::AutoUnsafe) |
+                    BorrowViolation(euv::ForLoop) |
+                    BorrowViolation(euv::MatchDiscriminant) => {
                         format!("cannot borrow {} as mutable", descr)
                     }
-                    euv::ClosureInvocation => {
+                    BorrowViolation(euv::ClosureInvocation) => {
                         self.tcx.sess.span_bug(err.span,
                             "err_mutbl with a closure invocation");
                     }
index c0bfd6fbcb713c151637dd84e7f27ed623a71c03..4e3b99276a9c76646e04fdf294287c71249fa7a3 100644 (file)
@@ -308,7 +308,7 @@ fn process_method(&mut self, sig: &ast::MethodSig,
 
         debug!("process_method: {}:{}", id, token::get_name(name));
 
-        let mut scope_id;
+        let scope_id;
         // The qualname for a method is the trait name or name of the struct in an impl in
         // which the method is declared in, followed by the method's name.
         let qualname = match self.tcx.impl_of_method(ast_util::local_def(id)) {
index b6b5ac5c01eee1f48f591f67bb1dc7aa0128b382..507bd9de2a11a769488fd3ade4775b15a4bfd7db 100644 (file)
@@ -598,7 +598,7 @@ fn scan_digits(&mut self, real_radix: u32, scan_radix: u32) -> usize {
 
     /// Lex a LIT_INTEGER or a LIT_FLOAT
     fn scan_number(&mut self, c: char) -> token::Lit {
-        let mut num_digits;
+        let num_digits;
         let mut base = 10;
         let start_bpos = self.last_pos;
 
index dcc82b8920ff5b51245b6fb52880011da181e6fb..8165dd0fa29c0ee7049522f2f46969a46d78bf57 100644 (file)
@@ -23,6 +23,15 @@ fn main() {
     let mut b = 3; //~ ERROR: variable does not need to be mutable
     let mut a = vec!(3); //~ ERROR: variable does not need to be mutable
     let (mut a, b) = (1, 2); //~ ERROR: variable does not need to be mutable
+    let mut a; //~ ERROR: variable does not need to be mutable
+    a = 3;
+
+    let mut b; //~ ERROR: variable does not need to be mutable
+    if true {
+        b = 3;
+    } else {
+        b = 4;
+    }
 
     match 30 {
         mut x => {} //~ ERROR: variable does not need to be mutable