diff options
| -rw-r--r-- | src/librustc/middle/borrowck/gather_loans/gather_moves.rs | 17 | ||||
| -rw-r--r-- | src/librustc/middle/borrowck/gather_loans/mod.rs | 54 | ||||
| -rw-r--r-- | src/librustc/middle/borrowck/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/borrowck/move_data.rs | 15 | ||||
| -rw-r--r-- | src/librustc/middle/liveness.rs | 62 | ||||
| -rw-r--r-- | src/test/compile-fail/asm-out-read-uninit.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-and-init.rs (renamed from src/test/compile-fail/liveness-and-init.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-block-unint.rs (renamed from src/test/compile-fail/liveness-block-unint.rs) | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-break-uninit-2.rs (renamed from src/test/compile-fail/liveness-break-uninit-2.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-break-uninit.rs (renamed from src/test/compile-fail/liveness-break-uninit.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-if-no-else.rs (renamed from src/test/compile-fail/liveness-if-no-else.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-if-with-else.rs (renamed from src/test/compile-fail/liveness-if-with-else.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-init-in-called-fn-expr.rs (renamed from src/test/compile-fail/liveness-init-in-called-fn-expr.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-init-in-fn-expr.rs (renamed from src/test/compile-fail/liveness-init-in-fn-expr.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-init-in-fru.rs (renamed from src/test/compile-fail/liveness-init-in-fru.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-init-op-equal.rs (renamed from src/test/compile-fail/liveness-init-op-equal.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-init-plus-equal.rs (renamed from src/test/compile-fail/liveness-init-plus-equal.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-or-init.rs (renamed from src/test/compile-fail/liveness-or-init.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-return.rs (renamed from src/test/compile-fail/liveness-return.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-uninit-after-item.rs (renamed from src/test/compile-fail/liveness-uninit-after-item.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-uninit-in-assignop.rs | 44 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-uninit.rs (renamed from src/test/compile-fail/liveness-uninit.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-use-in-index-lvalue.rs (renamed from src/test/compile-fail/liveness-use-in-index-lvalue.rs) | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-while-break.rs (renamed from src/test/compile-fail/liveness-while-break.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-while-cond.rs (renamed from src/test/compile-fail/liveness-while-cond.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck-while.rs (renamed from src/test/compile-fail/liveness-while.rs) | 0 | ||||
| -rw-r--r-- | src/test/compile-fail/liveness-unused.rs | 5 |
27 files changed, 119 insertions, 90 deletions
diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs index 7ec9f1f8f47..6dd7ae31c9d 100644 --- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs @@ -94,7 +94,22 @@ pub fn gather_assignment(bccx: &BorrowckCtxt, assignee_loan_path, assignment_id, assignment_span, - assignee_id); + assignee_id, + false); +} + +pub fn gather_move_and_assignment(bccx: &BorrowckCtxt, + move_data: &MoveData, + assignment_id: ast::NodeId, + assignment_span: Span, + assignee_loan_path: @LoanPath, + assignee_id: ast::NodeId) { + move_data.add_assignment(bccx.tcx, + assignee_loan_path, + assignment_id, + assignment_span, + assignee_id, + true); } fn check_is_legal_to_move_from(bccx: &BorrowckCtxt, diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index d6666eb6293..e50d6da378a 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -214,20 +214,19 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt, visit::walk_expr(this, ex, ()); } - ast::ExprAssign(l, _) | ast::ExprAssignOp(_, l, _) => { - let l_cmt = this.bccx.cat_expr(l); - match opt_loan_path(l_cmt) { - Some(l_lp) => { - gather_moves::gather_assignment(this.bccx, &this.move_data, - ex.id, ex.span, - l_lp, l.id); - } - 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. - } - } + ast::ExprAssign(l, _) => { + with_assignee_loan_path( + this.bccx, l, + |lp| gather_moves::gather_assignment(this.bccx, &this.move_data, + ex.id, ex.span, lp, l.id)); + visit::walk_expr(this, ex, ()); + } + + ast::ExprAssignOp(_, l, _) => { + with_assignee_loan_path( + this.bccx, l, + |lp| gather_moves::gather_move_and_assignment(this.bccx, &this.move_data, + ex.id, ex.span, lp, l.id)); visit::walk_expr(this, ex, ()); } @@ -288,17 +287,10 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt, ast::ExprInlineAsm(ref ia) => { for &(_, out) in ia.outputs.iter() { - let out_cmt = this.bccx.cat_expr(out); - match opt_loan_path(out_cmt) { - Some(out_lp) => { - gather_moves::gather_assignment(this.bccx, &this.move_data, - ex.id, ex.span, - out_lp, out.id); - } - None => { - // See the comment for ExprAssign. - } - } + with_assignee_loan_path( + this.bccx, out, + |lp| gather_moves::gather_assignment(this.bccx, &this.move_data, + ex.id, ex.span, lp, out.id)); } visit::walk_expr(this, ex, ()); } @@ -309,6 +301,18 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt, } } +fn with_assignee_loan_path(bccx: &BorrowckCtxt, expr: &ast::Expr, op: |@LoanPath|) { + let cmt = bccx.cat_expr(expr); + match opt_loan_path(cmt) { + Some(lp) => op(lp), + 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. + } + } +} + impl<'a> GatherLoanCtxt<'a> { pub fn tcx(&self) -> ty::ctxt { self.bccx.tcx } diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 9767b50ae96..654203bf077 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -535,7 +535,7 @@ impl BorrowckCtxt { move_data::Declared => { self.tcx.sess.span_err( use_span, - format!("{} of possibly uninitialized value: `{}`", + format!("{} of possibly uninitialized variable: `{}`", verb, self.loan_path_to_str(lp))); } diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs index e1434a8ac4e..5f4d5b43231 100644 --- a/src/librustc/middle/borrowck/move_data.rs +++ b/src/librustc/middle/borrowck/move_data.rs @@ -33,23 +33,25 @@ use util::ppaux::Repr; pub struct MoveData { /// Move paths. See section "Move paths" in `doc.rs`. - paths: RefCell<Vec<MovePath> >, + paths: RefCell<Vec<MovePath>>, /// Cache of loan path to move path index, for easy lookup. path_map: RefCell<HashMap<@LoanPath, MovePathIndex>>, /// Each move or uninitialized variable gets an entry here. - moves: RefCell<Vec<Move> >, + moves: RefCell<Vec<Move>>, /// Assignments to a variable, like `x = foo`. These are assigned /// bits for dataflow, since we must track them to ensure that /// immutable variables are assigned at most once along each path. - var_assignments: RefCell<Vec<Assignment> >, + var_assignments: RefCell<Vec<Assignment>>, /// Assignments to a path, like `x.f = foo`. These are not /// assigned dataflow bits, but we track them because they still /// kill move bits. - path_assignments: RefCell<Vec<Assignment> >, + path_assignments: RefCell<Vec<Assignment>>, + + /// Assignments to a variable or path, like `x = foo`, but not `x += foo`. assignee_ids: RefCell<HashSet<ast::NodeId>>, } @@ -392,7 +394,8 @@ impl MoveData { lp: @LoanPath, assign_id: ast::NodeId, span: Span, - assignee_id: ast::NodeId) { + assignee_id: ast::NodeId, + is_also_move: bool) { /*! * Adds a new record for an assignment to `lp` that occurs at * location `id` with the given `span`. @@ -403,7 +406,7 @@ impl MoveData { let path_index = self.move_path(tcx, lp); - { + if !is_also_move { let mut assignee_ids = self.assignee_ids.borrow_mut(); assignee_ids.get().insert(assignee_id); } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 04f2b2f2823..02a947a0ddc 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1468,28 +1468,14 @@ impl Liveness { fn check_local(this: &mut Liveness, local: &Local) { match local.init { - Some(_) => { - this.warn_about_unused_or_dead_vars_in_pat(local.pat); - } - None => { - - // No initializer: the variable might be unused; if not, it - // should not be live at this point. - - debug!("check_local() with no initializer"); - this.pat_bindings(local.pat, |ln, var, sp, id| { - if !this.warn_about_unused(sp, id, ln, var) { - match this.live_on_exit(ln, var) { - None => { /* not live: good */ } - Some(lnk) => { - this.report_illegal_read( - local.span, lnk, var, - PossiblyUninitializedVariable); - } - } - } - }) - } + Some(_) => { + this.warn_about_unused_or_dead_vars_in_pat(local.pat); + }, + None => { + this.pat_bindings(local.pat, |ln, var, sp, id| { + this.warn_about_unused(sp, id, ln, var); + }) + } } visit::walk_local(this, local, ()); @@ -1644,38 +1630,6 @@ impl Liveness { } } - pub fn report_illegal_read(&self, - chk_span: Span, - lnk: LiveNodeKind, - var: Variable, - rk: ReadKind) { - let msg = match rk { - PossiblyUninitializedVariable => "possibly uninitialized \ - variable", - PossiblyUninitializedField => "possibly uninitialized field", - MovedValue => "moved value", - PartiallyMovedValue => "partially moved value" - }; - let name = self.ir.variable_name(var); - match lnk { - FreeVarNode(span) => { - self.tcx.sess.span_err( - span, - format!("capture of {}: `{}`", msg, name)); - } - ExprNode(span) => { - self.tcx.sess.span_err( - span, - format!("use of {}: `{}`", msg, name)); - } - ExitNode | VarDefNode(_) => { - self.tcx.sess.span_bug( - chk_span, - format!("illegal reader: {:?}", lnk)); - } - } - } - pub fn should_warn(&self, var: Variable) -> Option<~str> { let name = self.ir.variable_name(var); if name.len() == 0 || name[0] == ('_' as u8) { None } else { Some(name) } diff --git a/src/test/compile-fail/asm-out-read-uninit.rs b/src/test/compile-fail/asm-out-read-uninit.rs index b63865921c6..65750eb926b 100644 --- a/src/test/compile-fail/asm-out-read-uninit.rs +++ b/src/test/compile-fail/asm-out-read-uninit.rs @@ -19,7 +19,7 @@ fn foo(x: int) { info!("{}", x); } pub fn main() { let x: int; unsafe { - asm!("mov $1, $0" : "=r"(x) : "r"(x)); //~ ERROR use of possibly uninitialized value: `x` + asm!("mov $1, $0" : "=r"(x) : "r"(x)); //~ ERROR use of possibly uninitialized variable: `x` } foo(x); } diff --git a/src/test/compile-fail/liveness-and-init.rs b/src/test/compile-fail/borrowck-and-init.rs index 134390d0b59..134390d0b59 100644 --- a/src/test/compile-fail/liveness-and-init.rs +++ b/src/test/compile-fail/borrowck-and-init.rs diff --git a/src/test/compile-fail/liveness-block-unint.rs b/src/test/compile-fail/borrowck-block-unint.rs index c46b9013a06..fc865e271e3 100644 --- a/src/test/compile-fail/liveness-block-unint.rs +++ b/src/test/compile-fail/borrowck-block-unint.rs @@ -11,7 +11,7 @@ fn force(f: ||) { f(); } fn main() { let x: int; - force(|| { - info!("{}", x); //~ ERROR capture of possibly uninitialized variable: `x` + force(|| { //~ ERROR capture of possibly uninitialized variable: `x` + info!("{}", x); }); } diff --git a/src/test/compile-fail/liveness-break-uninit-2.rs b/src/test/compile-fail/borrowck-break-uninit-2.rs index accb9076974..accb9076974 100644 --- a/src/test/compile-fail/liveness-break-uninit-2.rs +++ b/src/test/compile-fail/borrowck-break-uninit-2.rs diff --git a/src/test/compile-fail/liveness-break-uninit.rs b/src/test/compile-fail/borrowck-break-uninit.rs index d49e79d2c64..d49e79d2c64 100644 --- a/src/test/compile-fail/liveness-break-uninit.rs +++ b/src/test/compile-fail/borrowck-break-uninit.rs diff --git a/src/test/compile-fail/liveness-if-no-else.rs b/src/test/compile-fail/borrowck-if-no-else.rs index 8dc590b47f0..8dc590b47f0 100644 --- a/src/test/compile-fail/liveness-if-no-else.rs +++ b/src/test/compile-fail/borrowck-if-no-else.rs diff --git a/src/test/compile-fail/liveness-if-with-else.rs b/src/test/compile-fail/borrowck-if-with-else.rs index 55fb8222634..55fb8222634 100644 --- a/src/test/compile-fail/liveness-if-with-else.rs +++ b/src/test/compile-fail/borrowck-if-with-else.rs diff --git a/src/test/compile-fail/liveness-init-in-called-fn-expr.rs b/src/test/compile-fail/borrowck-init-in-called-fn-expr.rs index d759a5738bd..d759a5738bd 100644 --- a/src/test/compile-fail/liveness-init-in-called-fn-expr.rs +++ b/src/test/compile-fail/borrowck-init-in-called-fn-expr.rs diff --git a/src/test/compile-fail/liveness-init-in-fn-expr.rs b/src/test/compile-fail/borrowck-init-in-fn-expr.rs index f6bb2f54283..f6bb2f54283 100644 --- a/src/test/compile-fail/liveness-init-in-fn-expr.rs +++ b/src/test/compile-fail/borrowck-init-in-fn-expr.rs diff --git a/src/test/compile-fail/liveness-init-in-fru.rs b/src/test/compile-fail/borrowck-init-in-fru.rs index 97fc2b4d44c..97fc2b4d44c 100644 --- a/src/test/compile-fail/liveness-init-in-fru.rs +++ b/src/test/compile-fail/borrowck-init-in-fru.rs diff --git a/src/test/compile-fail/liveness-init-op-equal.rs b/src/test/compile-fail/borrowck-init-op-equal.rs index cbe805551c2..cbe805551c2 100644 --- a/src/test/compile-fail/liveness-init-op-equal.rs +++ b/src/test/compile-fail/borrowck-init-op-equal.rs diff --git a/src/test/compile-fail/liveness-init-plus-equal.rs b/src/test/compile-fail/borrowck-init-plus-equal.rs index 6e813809f03..6e813809f03 100644 --- a/src/test/compile-fail/liveness-init-plus-equal.rs +++ b/src/test/compile-fail/borrowck-init-plus-equal.rs diff --git a/src/test/compile-fail/liveness-or-init.rs b/src/test/compile-fail/borrowck-or-init.rs index f878afce969..f878afce969 100644 --- a/src/test/compile-fail/liveness-or-init.rs +++ b/src/test/compile-fail/borrowck-or-init.rs diff --git a/src/test/compile-fail/liveness-return.rs b/src/test/compile-fail/borrowck-return.rs index 6558bc57968..6558bc57968 100644 --- a/src/test/compile-fail/liveness-return.rs +++ b/src/test/compile-fail/borrowck-return.rs diff --git a/src/test/compile-fail/liveness-uninit-after-item.rs b/src/test/compile-fail/borrowck-uninit-after-item.rs index a828b1d6b9f..a828b1d6b9f 100644 --- a/src/test/compile-fail/liveness-uninit-after-item.rs +++ b/src/test/compile-fail/borrowck-uninit-after-item.rs diff --git a/src/test/compile-fail/borrowck-uninit-in-assignop.rs b/src/test/compile-fail/borrowck-uninit-in-assignop.rs new file mode 100644 index 00000000000..b5e462e592a --- /dev/null +++ b/src/test/compile-fail/borrowck-uninit-in-assignop.rs @@ -0,0 +1,44 @@ +// Copyright 2012-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. + +// Tests that the use of uninitialized variable in assignment operator +// expression is detected. + +pub fn main() { + let x: int; + x += 1; //~ ERROR use of possibly uninitialized variable: `x` + + let x: int; + x -= 1; //~ ERROR use of possibly uninitialized variable: `x` + + let x: int; + x *= 1; //~ ERROR use of possibly uninitialized variable: `x` + + let x: int; + x /= 1; //~ ERROR use of possibly uninitialized variable: `x` + + let x: int; + x %= 1; //~ ERROR use of possibly uninitialized variable: `x` + + let x: int; + x ^= 1; //~ ERROR use of possibly uninitialized variable: `x` + + let x: int; + x &= 1; //~ ERROR use of possibly uninitialized variable: `x` + + let x: int; + x |= 1; //~ ERROR use of possibly uninitialized variable: `x` + + let x: int; + x <<= 1; //~ ERROR use of possibly uninitialized variable: `x` + + let x: int; + x >>= 1; //~ ERROR use of possibly uninitialized variable: `x` +} diff --git a/src/test/compile-fail/liveness-uninit.rs b/src/test/compile-fail/borrowck-uninit.rs index a6ce736c89b..a6ce736c89b 100644 --- a/src/test/compile-fail/liveness-uninit.rs +++ b/src/test/compile-fail/borrowck-uninit.rs diff --git a/src/test/compile-fail/liveness-use-in-index-lvalue.rs b/src/test/compile-fail/borrowck-use-in-index-lvalue.rs index 7ec0607fc97..3ced9859240 100644 --- a/src/test/compile-fail/liveness-use-in-index-lvalue.rs +++ b/src/test/compile-fail/borrowck-use-in-index-lvalue.rs @@ -11,6 +11,10 @@ fn test() { let w: ~[int]; w[5] = 0; //~ ERROR use of possibly uninitialized variable: `w` + //~^ ERROR cannot assign to immutable vec content `w[..]` + + let mut w: ~[int]; + w[5] = 0; //~ ERROR use of possibly uninitialized variable: `w` } fn main() { test(); } diff --git a/src/test/compile-fail/liveness-while-break.rs b/src/test/compile-fail/borrowck-while-break.rs index e5d4b6ef48c..e5d4b6ef48c 100644 --- a/src/test/compile-fail/liveness-while-break.rs +++ b/src/test/compile-fail/borrowck-while-break.rs diff --git a/src/test/compile-fail/liveness-while-cond.rs b/src/test/compile-fail/borrowck-while-cond.rs index 27d42d666ea..27d42d666ea 100644 --- a/src/test/compile-fail/liveness-while-cond.rs +++ b/src/test/compile-fail/borrowck-while-cond.rs diff --git a/src/test/compile-fail/liveness-while.rs b/src/test/compile-fail/borrowck-while.rs index b904fd53d72..b904fd53d72 100644 --- a/src/test/compile-fail/liveness-while.rs +++ b/src/test/compile-fail/borrowck-while.rs diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs index 83c911d916e..33fc094abbe 100644 --- a/src/test/compile-fail/liveness-unused.rs +++ b/src/test/compile-fail/liveness-unused.rs @@ -23,6 +23,11 @@ fn f1b(x: &mut int) { #[allow(unused_variable)] fn f1c(x: int) {} +fn f1d() { + let x: int; + //~^ ERROR unused variable: `x` +} + fn f2() { let x = 3; //~^ ERROR unused variable: `x` |
