diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index 15922d57ba8..263ed47b29e 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -160,16 +160,8 @@ fn gather_loans_in_local(this: &mut GatherLoanCtxt, }) } Some(init) => { - // Variable declarations with initializers are considered "assigns": - let tcx = this.bccx.tcx; - pat_util::pat_bindings(tcx.def_map, local.pat, |_, id, span, _| { - gather_moves::gather_assignment(this.bccx, - &this.move_data, - id, - span, - @LpVar(id), - id); - }); + // Variable declarations with initializers are considered "assigns", + // which is handled by `gather_pat`: let init_cmt = this.bccx.cat_expr(init); this.gather_pat(init_cmt, local.pat, None); } @@ -811,6 +803,17 @@ impl<'a> GatherLoanCtxt<'a> { self.bccx.cat_pattern(discr_cmt, root_pat, |cmt, pat| { match pat.node { ast::PatIdent(bm, _, _) if self.pat_is_binding(pat) => { + // Each match binding is effectively an assignment. + let tcx = self.bccx.tcx; + pat_util::pat_bindings(tcx.def_map, pat, |_, id, span, _| { + gather_moves::gather_assignment(self.bccx, + &self.move_data, + id, + span, + @LpVar(id), + id); + }); + match bm { ast::BindByRef(mutbl) => { // ref x or ref x @ p --- creates a ptr which must diff --git a/src/test/compile-fail/borrowck-match-binding-is-assignment.rs b/src/test/compile-fail/borrowck-match-binding-is-assignment.rs new file mode 100644 index 00000000000..72d9afd4d2b --- /dev/null +++ b/src/test/compile-fail/borrowck-match-binding-is-assignment.rs @@ -0,0 +1,51 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that immutable pattern bindings cannot be reassigned. + +enum E { + Foo(int) +} + +struct S { + bar: int, +} + +pub fn main() { + match 1i { + x => { + x += 1; //~ ERROR re-assignment of immutable variable `x` + } + } + + match Foo(1) { + Foo(x) => { + x += 1; //~ ERROR re-assignment of immutable variable `x` + } + } + + match S { bar: 1 } { + S { bar: x } => { + x += 1; //~ ERROR re-assignment of immutable variable `x` + } + } + + match (1i,) { + (x,) => { + x += 1; //~ ERROR re-assignment of immutable variable `x` + } + } + + match [1,2,3] { + [x,_,_] => { + x += 1; //~ ERROR re-assignment of immutable variable `x` + } + } +}