```
-Patterns can also dereference pointers by using the `&`, `box` symbols,
-as appropriate. For example, these two matches on `x: &int` are equivalent:
+Patterns can also dereference pointers by using the `&`, `&mut` and `box`
+symbols, as appropriate. For example, these two matches on `x: &int` are
+equivalent:
```
# let x = &3i;
impl<'a> CharEq for &'a [char] {
#[inline]
fn matches(&mut self, c: char) -> bool {
- self.iter().any(|&mut m| m.matches(c))
+ self.iter().any(|&m| { let mut m = m; m.matches(c) })
}
#[inline]
}
ast::PatBox(ref subpat) |
- ast::PatRegion(ref subpat) |
+ ast::PatRegion(ref subpat, _) |
ast::PatIdent(_, _, Some(ref subpat)) => {
let subpat_exit = self.pat(&**subpat, pred);
self.add_node(pat.id, &[subpat_exit])
}
}
- ty::ty_rptr(_, ty::mt { ty, .. }) => {
+ ty::ty_rptr(_, ty::mt { ty, mutbl }) => {
match ty.sty {
ty::ty_vec(_, Some(n)) => match ctor {
&Single => {
_ => {
assert_eq!(pats_len, 1);
- ast::PatRegion(pats.nth(0).unwrap())
+ ast::PatRegion(pats.nth(0).unwrap(), mutbl)
}
}
}
ast::PatTup(ref args) =>
Some(args.iter().map(|p| &**p).collect()),
- ast::PatBox(ref inner) | ast::PatRegion(ref inner) =>
+ ast::PatBox(ref inner) | ast::PatRegion(ref inner, _) =>
Some(vec![&**inner]),
ast::PatLit(ref expr) => {
}
}
- ast::PatBox(ref subpat) | ast::PatRegion(ref subpat) => {
- // @p1, ~p1, ref p1
+ ast::PatBox(ref subpat) | ast::PatRegion(ref subpat, _) => {
+ // box p1, &p1, &mut p1. we can ignore the mutability of
+ // PatRegion since that information is already contained
+ // in the type.
let subcmt = try!(self.cat_deref(pat, cmt, 0, false));
try!(self.cat_pattern_(subcmt, &**subpat, op));
}
}
fn any_region_pat(m: &[Match], col: uint) -> bool {
- any_pat!(m, col, ast::PatRegion(_))
+ any_pat!(m, col, ast::PatRegion(..))
}
fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: uint) -> bool {
let llbox = Load(bcx, val);
bcx = bind_irrefutable_pat(bcx, &**inner, llbox, cleanup_scope);
}
- ast::PatRegion(ref inner) => {
+ ast::PatRegion(ref inner, _) => {
let loaded_val = Load(bcx, val);
bcx = bind_irrefutable_pat(bcx, &**inner, loaded_val, cleanup_scope);
}
}
}
- ast::PatBox(ref sub_pat) | ast::PatRegion(ref sub_pat) => {
+ ast::PatBox(ref sub_pat) | ast::PatRegion(ref sub_pat, _) => {
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
}
check_pat(pcx, &**inner, tcx.types.err);
}
}
- ast::PatRegion(ref inner) => {
+ ast::PatRegion(ref inner, mutbl) => {
let inner_ty = fcx.infcx().next_ty_var();
- let mutbl =
+ // SNAP c894171 remove this `if`-`else` entirely after next snapshot
+ let mutbl = if mutbl == ast::MutImmutable {
ty::deref(fcx.infcx().shallow_resolve(expected), true)
- .map_or(ast::MutImmutable, |mt| mt.mutbl);
+ .map_or(ast::MutImmutable, |mt| mt.mutbl)
+ } else {
+ mutbl
+ };
let mt = ty::mt { ty: inner_ty, mutbl: mutbl };
let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
PatTup(ref elts) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
.collect::<Vec<String>>().connect(", ")),
PatBox(ref p) => name_from_pat(&**p),
- PatRegion(ref p) => name_from_pat(&**p),
+ PatRegion(ref p, _) => name_from_pat(&**p),
PatLit(..) => {
warn!("tried to get argument name from PatLit, \
which is silly in function arguments");
PatStruct(Path, Vec<Spanned<FieldPat>>, bool),
PatTup(Vec<P<Pat>>),
PatBox(P<Pat>),
- PatRegion(P<Pat>), // reference pattern
+ PatRegion(P<Pat>, Mutability), // reference pattern
PatLit(P<Expr>),
PatRange(P<Expr>, P<Expr>),
/// [a, b, ..i, y, z] is represented as:
PatEnum(_, Some(ref s)) | PatTup(ref s) => {
s.iter().all(|p| walk_pat_(&**p, it))
}
- PatBox(ref s) | PatRegion(ref s) => {
+ PatBox(ref s) | PatRegion(ref s, _) => {
walk_pat_(&**s, it)
}
PatVec(ref before, ref slice, ref after) => {
&**variant,
self_arg_name,
ast::MutImmutable);
- (cx.pat(sp, ast::PatRegion(p)), idents)
+ (cx.pat(sp, ast::PatRegion(p, ast::MutImmutable)), idents)
};
// A single arm has form (&VariantK, &VariantK, ...) => BodyK
}
PatTup(elts) => PatTup(elts.move_map(|x| folder.fold_pat(x))),
PatBox(inner) => PatBox(folder.fold_pat(inner)),
- PatRegion(inner) => PatRegion(folder.fold_pat(inner)),
+ PatRegion(inner, mutbl) => PatRegion(folder.fold_pat(inner), mutbl),
PatRange(e1, e2) => {
PatRange(folder.fold_expr(e1), folder.fold_expr(e2))
},
})
}
token::BinOp(token::And) | token::AndAnd => {
- // parse &pat
+ // parse &pat and &mut pat
let lo = self.span.lo;
self.expect_and();
+ let mutability = if self.eat_keyword(keywords::Mut) {
+ ast::MutMutable
+ } else {
+ ast::MutImmutable
+ };
let sub = self.parse_pat();
- pat = PatRegion(sub);
+ pat = PatRegion(sub, mutability);
hi = self.last_span.hi;
return P(ast::Pat {
id: ast::DUMMY_NODE_ID,
try!(word(&mut self.s, "box "));
try!(self.print_pat(&**inner));
}
- ast::PatRegion(ref inner) => {
+ ast::PatRegion(ref inner, mutbl) => {
try!(word(&mut self.s, "&"));
+ if mutbl == ast::MutMutable {
+ try!(word(&mut self.s, "mut "));
+ }
try!(self.print_pat(&**inner));
}
ast::PatLit(ref e) => try!(self.print_expr(&**e)),
}
}
PatBox(ref subpattern) |
- PatRegion(ref subpattern) => {
+ PatRegion(ref subpattern, _) => {
visitor.visit_pat(&**subpattern)
}
PatIdent(_, ref pth1, ref optional_subpattern) => {
fn sum(&self) -> T {
let mut partials = vec![];
- for &mut x in self.iter() {
+ for &x in self.iter() {
+ let mut x = x;
let mut j = 0;
// This inner loop applies `hi`/`lo` summation to each
// partial so that the list of partial sums remains exact.
--- /dev/null
+// Copyright 2015 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 foo = &mut 1i;
+
+ let &mut x = foo;
+ x += 1; //~ ERROR re-assignment of immutable variable
+
+ // explicitly mut-ify internals
+ let &mut mut x = foo;
+ x += 1;
+
+ // check borrowing is detected successfully
+ let &mut ref x = foo;
+ *foo += 1; //~ ERROR cannot assign to `*foo` because it is borrowed
+}
--- /dev/null
+// 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 foo = &mut 1i;
+
+ // (separate lines to ensure the spans are accurate)
+
+ // SNAP c894171 uncomment this after the next snapshot
+ // NOTE(stage0) just in case tidy doesn't check SNAP's in tests
+ // let &_ // ~ ERROR expected `&mut int`, found `&_`
+ // = foo;
+ let &mut _ = foo;
+
+ let bar = &1i;
+ let &_ = bar;
+ let &mut _ //~ ERROR expected `&int`, found `&mut _`
+ = bar;
+}