rollup merge of #20554: huonw/mut-pattern
Conflicts: src/librustc_typeck/check/_match.rs
This commit is contained in:
commit
bb5e16b4b8
19 changed files with 92 additions and 26 deletions
|
@ -3484,8 +3484,9 @@ fn main() {
|
|||
|
||||
```
|
||||
|
||||
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;
|
||||
|
|
|
@ -230,7 +230,7 @@ impl<F> CharEq for F where F: FnMut(char) -> bool {
|
|||
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]
|
||||
|
|
|
@ -119,7 +119,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
|||
}
|
||||
|
||||
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])
|
||||
|
|
|
@ -473,7 +473,7 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
|
|||
}
|
||||
}
|
||||
|
||||
ty::ty_rptr(_, ty::mt { ty, .. }) => {
|
||||
ty::ty_rptr(_, ty::mt { ty, mutbl }) => {
|
||||
match ty.sty {
|
||||
ty::ty_vec(_, Some(n)) => match ctor {
|
||||
&Single => {
|
||||
|
@ -493,7 +493,7 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
|
|||
|
||||
_ => {
|
||||
assert_eq!(pats_len, 1);
|
||||
ast::PatRegion(pats.nth(0).unwrap())
|
||||
ast::PatRegion(pats.nth(0).unwrap(), mutbl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -860,7 +860,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
|
|||
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) => {
|
||||
|
|
|
@ -1235,8 +1235,10 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
|||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -683,7 +683,7 @@ fn any_uniq_pat(m: &[Match], col: uint) -> bool {
|
|||
}
|
||||
|
||||
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 {
|
||||
|
@ -1725,7 +1725,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -3442,7 +3442,7 @@ fn create_scope_map(cx: &CrateContext,
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -192,12 +192,16 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
|
|||
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 =
|
||||
ty::deref(fcx.infcx().shallow_resolve(expected), true).map(|mt| mt.mutbl)
|
||||
.unwrap_or(ast::MutImmutable);
|
||||
// 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(|mt| mt.mutbl).unwrap_or(ast::MutImmutable);
|
||||
} else {
|
||||
mutbl
|
||||
};
|
||||
|
||||
let mt = ty::mt { ty: inner_ty, mutbl: mutbl };
|
||||
let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
|
||||
|
|
|
@ -2220,7 +2220,7 @@ fn name_from_pat(p: &ast::Pat) -> String {
|
|||
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");
|
||||
|
|
|
@ -572,7 +572,7 @@ pub enum Pat_ {
|
|||
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:
|
||||
|
|
|
@ -633,7 +633,7 @@ pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool where F: FnMut(&Pat) -> bool {
|
|||
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) => {
|
||||
|
|
|
@ -937,7 +937,7 @@ impl<'a> MethodDef<'a> {
|
|||
&**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
|
||||
|
|
|
@ -1257,7 +1257,7 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
|
|||
}
|
||||
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))
|
||||
},
|
||||
|
|
|
@ -3351,11 +3351,16 @@ impl<'a> Parser<'a> {
|
|||
})
|
||||
}
|
||||
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,
|
||||
|
|
|
@ -2082,8 +2082,11 @@ impl<'a> State<'a> {
|
|||
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)),
|
||||
|
|
|
@ -511,7 +511,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
|
|||
}
|
||||
}
|
||||
PatBox(ref subpattern) |
|
||||
PatRegion(ref subpattern) => {
|
||||
PatRegion(ref subpattern, _) => {
|
||||
visitor.visit_pat(&**subpattern)
|
||||
}
|
||||
PatIdent(_, ref pth1, ref optional_subpattern) => {
|
||||
|
|
|
@ -169,7 +169,8 @@ impl<T: FloatMath + FromPrimitive> Stats<T> for [T] {
|
|||
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.
|
||||
|
|
24
src/test/compile-fail/mut-pattern-internal-mutability.rs
Normal file
24
src/test/compile-fail/mut-pattern-internal-mutability.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
// 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
|
||||
}
|
26
src/test/compile-fail/mut-pattern-mismatched.rs
Normal file
26
src/test/compile-fail/mut-pattern-mismatched.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
// 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue