about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-07-31 19:25:24 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-07-31 19:26:25 -0700
commitb414db041be115d877e5b17bc86ea019420b672c (patch)
treed7e15ba792c8376aaabe9727726de34b03e89baf
parenta841789a41941ad73a57cd9972dfbd5fdff02685 (diff)
downloadrust-b414db041be115d877e5b17bc86ea019420b672c.tar.gz
rust-b414db041be115d877e5b17bc86ea019420b672c.zip
rustc: Parse by-reference pattern bindings with the "ref" keyword
-rw-r--r--src/cargo/cargo.rs18
-rw-r--r--src/libcore/vec.rs4
-rw-r--r--src/libsyntax/ast.rs8
-rw-r--r--src/libsyntax/ast_map.rs2
-rw-r--r--src/libsyntax/ast_util.rs4
-rw-r--r--src/libsyntax/ext/auto_serialize.rs6
-rw-r--r--src/libsyntax/ext/pipes/ast_builder.rs6
-rw-r--r--src/libsyntax/ext/qquote.rs2
-rw-r--r--src/libsyntax/ext/tt/earley_parser.rs2
-rw-r--r--src/libsyntax/fold.rs5
-rw-r--r--src/libsyntax/parse/parser.rs148
-rw-r--r--src/libsyntax/parse/token.rs2
-rw-r--r--src/libsyntax/print/pprust.rs10
-rw-r--r--src/libsyntax/visit.rs2
-rw-r--r--src/rustc/middle/borrowck/gather_loans.rs6
-rw-r--r--src/rustc/middle/check_alt.rs42
-rw-r--r--src/rustc/middle/pat_util.rs4
-rw-r--r--src/rustc/middle/region.rs2
-rw-r--r--src/rustc/middle/resolve3.rs30
-rw-r--r--src/rustc/middle/trans/alt.rs28
-rw-r--r--src/rustc/middle/trans/base.rs2
-rw-r--r--src/rustc/middle/trans/debuginfo.rs2
-rw-r--r--src/rustc/middle/typeck/check.rs6
-rw-r--r--src/rustc/middle/typeck/check/alt.rs4
-rw-r--r--src/rustc/middle/typeck/check/regionck.rs2
25 files changed, 202 insertions, 145 deletions
diff --git a/src/cargo/cargo.rs b/src/cargo/cargo.rs
index d086d083445..e7c661734f4 100644
--- a/src/cargo/cargo.rs
+++ b/src/cargo/cargo.rs
@@ -20,7 +20,7 @@ type package = {
     url: ~str,
     method: ~str,
     description: ~str,
-    ref: option<~str>,
+    reference: option<~str>,
     tags: ~[~str],
     versions: ~[(~str, ~str)]
 };
@@ -497,7 +497,7 @@ fn load_one_source_package(src: source, p: map::hashmap<~str, json::json>) {
         }
     };
 
-    let ref = alt p.find(~"ref") {
+    let reference = alt p.find(~"ref") {
         some(json::string(n)) { some(*n) }
         _ { none }
     };
@@ -530,7 +530,7 @@ fn load_one_source_package(src: source, p: map::hashmap<~str, json::json>) {
         url: url,
         method: method,
         description: description,
-        ref: ref,
+        reference: reference,
         tags: tags,
         versions: ~[]
     };
@@ -815,10 +815,10 @@ fn install_source(c: cargo, path: ~str) {
     }
 }
 
-fn install_git(c: cargo, wd: ~str, url: ~str, ref: option<~str>) {
+fn install_git(c: cargo, wd: ~str, url: ~str, reference: option<~str>) {
     run::program_output(~"git", ~[~"clone", url, wd]);
-    if option::is_some(ref) {
-        let r = option::get(ref);
+    if option::is_some(reference) {
+        let r = option::get(reference);
         os::change_dir(wd);
         run::run_program(~"git", ~[~"checkout", r]);
     }
@@ -855,7 +855,7 @@ fn install_package(c: cargo, src: ~str, wd: ~str, pkg: package) {
     info(fmt!{"installing %s/%s via %s...", src, pkg.name, method});
 
     alt method {
-        ~"git" { install_git(c, wd, url, copy pkg.ref); }
+        ~"git" { install_git(c, wd, url, copy pkg.reference); }
         ~"file" { install_file(c, wd, url); }
         ~"curl" { install_curl(c, wd, copy url); }
         _ {}
@@ -1034,12 +1034,12 @@ fn install_query(c: cargo, wd: ~str, target: ~str) {
         install_file(c, wd, target);
         ret;
     } else if is_git_url(target) {
-        let ref = if c.opts.free.len() >= 4u {
+        let reference = if c.opts.free.len() >= 4u {
             some(c.opts.free[3u])
         } else {
             none
         };
-        install_git(c, wd, target, ref);
+        install_git(c, wd, target, reference);
     } else if !valid_pkg_name(target) && has_archive_extension(target) {
         install_curl(c, wd, target);
         ret;
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index 9698e229d20..04f10a7f23c 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -536,7 +536,7 @@ fn push_slow<T>(&v: ~[const T], +initval: T) {
 
 // Unchecked vector indexing
 #[inline(always)]
-unsafe fn ref<T: copy>(v: &[const T], i: uint) -> T {
+unsafe fn get_ref<T: copy>(v: &[const T], i: uint) -> T {
     as_buf(v, |p, _len| *ptr::offset(p, i))
 }
 
@@ -555,7 +555,7 @@ fn push_all<T: copy>(&v: ~[const T], rhs: &[const T]) {
     reserve(v, v.len() + rhs.len());
 
     for uint::range(0u, rhs.len()) |i| {
-        push(v, unsafe { ref(rhs, i) })
+        push(v, unsafe { get_ref(rhs, i) })
     }
 }
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 8c2b6dc3490..0dede78ffd0 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -146,6 +146,12 @@ type pat = {id: node_id, node: pat_, span: span};
 type field_pat = {ident: ident, pat: @pat};
 
 #[auto_serialize]
+enum binding_mode {
+    bind_by_value,
+    bind_by_ref
+}
+
+#[auto_serialize]
 enum pat_ {
     pat_wild,
     // A pat_ident may either be a new bound variable,
@@ -155,7 +161,7 @@ enum pat_ {
     // which it is. The resolver determines this, and
     // records this pattern's node_id in an auxiliary
     // set (of "pat_idents that refer to nullary enums")
-    pat_ident(@path, option<@pat>),
+    pat_ident(binding_mode, @path, option<@pat>),
     pat_enum(@path, option<~[@pat]>), // "none" means a * pattern where
                                   // we don't bind the fields to names
     pat_rec(~[field_pat], bool),
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index ebe7a7eb36a..4ef4288376c 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -158,7 +158,7 @@ fn map_block(b: blk, cx: ctx, v: vt) {
 fn number_pat(cx: ctx, pat: @pat) {
     do ast_util::walk_pat(pat) |p| {
         alt p.node {
-          pat_ident(_, _) {
+          pat_ident(*) {
             cx.map.insert(p.id, node_local(cx.local_id));
             cx.local_id += 1u;
           }
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 461d237450c..5f46a693f18 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -568,7 +568,7 @@ pure fn is_item_impl(item: @ast::item) -> bool {
 fn walk_pat(pat: @pat, it: fn(@pat)) {
     it(pat);
     alt pat.node {
-      pat_ident(pth, some(p)) { walk_pat(p, it); }
+      pat_ident(_, pth, some(p)) { walk_pat(p, it); }
       pat_rec(fields, _) {
         for fields.each |f| { walk_pat(f.pat, it); }
       }
@@ -576,7 +576,7 @@ fn walk_pat(pat: @pat, it: fn(@pat)) {
         for s.each |p| { walk_pat(p, it); }
       }
       pat_box(s) | pat_uniq(s) { walk_pat(s, it); }
-      pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _)
+      pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _, _)
         | pat_enum(_, _) {}
     }
 }
diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs
index 57b6dc13b8a..90319feb4d2 100644
--- a/src/libsyntax/ext/auto_serialize.rs
+++ b/src/libsyntax/ext/auto_serialize.rs
@@ -228,7 +228,7 @@ impl helpers of ext_ctxt_helpers for ext_ctxt {
         let path = @{span: span, global: false, idents: ~[nm],
                      rp: none, types: ~[]};
         @{id: self.next_id(),
-          node: ast::pat_ident(path, none),
+          node: ast::pat_ident(ast::bind_by_ref, path, none),
           span: span}
     }
 
@@ -834,7 +834,9 @@ fn ser_enum(cx: ext_ctxt, tps: ser_tps_map, e_name: ast::ident,
             // Generate pattern var(v1, v2, v3)
             |pats| {
                 if vec::is_empty(pats) {
-                    ast::pat_ident(cx.path(v_span, ~[v_name]), none)
+                    ast::pat_ident(ast::bind_by_ref,
+                                   cx.path(v_span, ~[v_name]),
+                                   none)
                 } else {
                     ast::pat_enum(cx.path(v_span, ~[v_name]), some(pats))
                 }
diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs
index bb5b35233cd..89c53d16ac5 100644
--- a/src/libsyntax/ext/pipes/ast_builder.rs
+++ b/src/libsyntax/ext/pipes/ast_builder.rs
@@ -116,8 +116,10 @@ impl ast_builder of ext_ctxt_ast_builder for ext_ctxt {
             @{node: {is_mutbl: false,
                      ty: self.ty_infer(),
                      pat: @{id: self.next_id(),
-                            node: ast::pat_ident(
-                                path(ident, self.empty_span()), none),
+                            node: ast::pat_ident(ast::bind_by_ref,
+                                                 path(ident,
+                                                      self.empty_span()),
+                                                 none),
                             span: self.empty_span()},
                      init: some({op: ast::init_move,
                                  expr: e}),
diff --git a/src/libsyntax/ext/qquote.rs b/src/libsyntax/ext/qquote.rs
index 9dcb4da14fa..94753ea88e0 100644
--- a/src/libsyntax/ext/qquote.rs
+++ b/src/libsyntax/ext/qquote.rs
@@ -170,7 +170,7 @@ fn parse_crate(p: parser) -> @ast::crate { p.parse_crate_mod(~[]) }
 fn parse_ty(p: parser) -> @ast::ty { p.parse_ty(false) }
 fn parse_stmt(p: parser) -> @ast::stmt { p.parse_stmt(~[]) }
 fn parse_expr(p: parser) -> @ast::expr { p.parse_expr() }
-fn parse_pat(p: parser) -> @ast::pat { p.parse_pat() }
+fn parse_pat(p: parser) -> @ast::pat { p.parse_pat(true) }
 
 fn parse_item(p: parser) -> @ast::item {
     alt p.parse_item(~[], ast::public) {
diff --git a/src/libsyntax/ext/tt/earley_parser.rs b/src/libsyntax/ext/tt/earley_parser.rs
index c7a2713c26e..bd8fcf552da 100644
--- a/src/libsyntax/ext/tt/earley_parser.rs
+++ b/src/libsyntax/ext/tt/earley_parser.rs
@@ -326,7 +326,7 @@ fn parse_nt(p: parser, name: ~str) -> nonterminal {
       }}
       ~"block" { token::nt_block(p.parse_block()) }
       ~"stmt" { token::nt_stmt(p.parse_stmt(~[])) }
-      ~"pat" { token::nt_pat(p.parse_pat()) }
+      ~"pat" { token::nt_pat(p.parse_pat(true)) }
       ~"expr" { token::nt_expr(p.parse_expr()) }
       ~"ty" { token::nt_ty(p.parse_ty(false /* no need to disambiguate*/)) }
       // this could be handled like a token, since it is one
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 5e533f3f494..7900b5eea15 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -332,8 +332,9 @@ fn noop_fold_arm(a: arm, fld: ast_fold) -> arm {
 fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ {
     ret alt p {
           pat_wild { pat_wild }
-          pat_ident(pth, sub) {
-            pat_ident(fld.fold_path(pth),
+          pat_ident(binding_mode, pth, sub) {
+            pat_ident(binding_mode,
+                      fld.fold_path(pth),
                       option::map(sub, |x| fld.fold_pat(x)))
           }
           pat_lit(e) { pat_lit(fld.fold_expr(e)) }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index aaafbf0ef24..89053c4eb1d 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -15,14 +15,12 @@ import common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed,
 import dvec::{dvec, extensions};
 import vec::{push};
 import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
-             bitand, bitor, bitxor, blk, blk_check_mode, bound_const,
-             bound_copy, bound_send, bound_trait, bound_owned,
-             box, by_copy, by_move,
-             by_mutbl_ref, by_ref, by_val, capture_clause, capture_item,
-             cdir_dir_mod, cdir_src_mod,
-             cdir_view_item, class_immutable,
-             class_member, class_method, class_mutable,
-             crate, crate_cfg, crate_directive, decl,
+             bind_by_ref, bind_by_value, bitand, bitor, bitxor, blk,
+             blk_check_mode, bound_const, bound_copy, bound_send, bound_trait,
+             bound_owned, box, by_copy, by_move, by_mutbl_ref, by_ref, by_val,
+             capture_clause, capture_item, cdir_dir_mod, cdir_src_mod,
+             cdir_view_item, class_immutable, class_member, class_method,
+             class_mutable, crate, crate_cfg, crate_directive, decl,
              decl_item, decl_local, default_blk, deref, div, expl, expr,
              expr_, expr_addr_of, expr_alt, expr_again, expr_assert,
              expr_assign, expr_assign_op, expr_binary, expr_block, expr_break,
@@ -1585,13 +1583,13 @@ class parser {
     fn parse_pats() -> ~[@pat] {
         let mut pats = ~[];
         loop {
-            vec::push(pats, self.parse_pat());
+            vec::push(pats, self.parse_pat(true));
             if self.token == token::BINOP(token::OR) { self.bump(); }
             else { ret pats; }
         };
     }
 
-    fn parse_pat() -> @pat {
+    fn parse_pat(refutable: bool) -> @pat {
         let lo = self.span.lo;
         let mut hi = self.span.hi;
         let mut pat;
@@ -1599,7 +1597,7 @@ class parser {
           token::UNDERSCORE { self.bump(); pat = pat_wild; }
           token::AT {
             self.bump();
-            let sub = self.parse_pat();
+            let sub = self.parse_pat(refutable);
             hi = sub.span.hi;
             // HACK: parse @"..." as a literal of a vstore @str
             pat = alt sub.node {
@@ -1614,7 +1612,7 @@ class parser {
           }
           token::TILDE {
             self.bump();
-            let sub = self.parse_pat();
+            let sub = self.parse_pat(refutable);
             hi = sub.span.hi;
             // HACK: parse ~"..." as a literal of a vstore ~str
             pat = alt sub.node {
@@ -1660,11 +1658,13 @@ class parser {
                 let mut subpat;
                 if self.token == token::COLON {
                     self.bump();
-                    subpat = self.parse_pat();
+                    subpat = self.parse_pat(refutable);
                 } else {
-                    subpat = @{id: self.get_id(),
-                               node: pat_ident(fieldpath, none),
-                               span: mk_sp(lo, hi)};
+                    subpat = @{
+                        id: self.get_id(),
+                        node: pat_ident(bind_by_ref, fieldpath, none),
+                        span: mk_sp(lo, hi)
+                    };
                 }
                 vec::push(fields, {ident: fieldname, pat: subpat});
             }
@@ -1681,10 +1681,10 @@ class parser {
                 let expr = self.mk_expr(lo, hi, expr_lit(lit));
                 pat = pat_lit(expr);
             } else {
-                let mut fields = ~[self.parse_pat()];
+                let mut fields = ~[self.parse_pat(refutable)];
                 while self.token == token::COMMA {
                     self.bump();
-                    vec::push(fields, self.parse_pat());
+                    vec::push(fields, self.parse_pat(refutable));
                 }
                 if vec::len(fields) == 1u { self.expect(token::COMMA); }
                 hi = self.span.hi;
@@ -1704,50 +1704,80 @@ class parser {
                     hi = val.span.hi;
                     pat = pat_lit(val);
                 }
-            } else if is_plain_ident(self.token) &&
-                alt self.look_ahead(1u) {
-                  token::LPAREN | token::LBRACKET | token::LT { false }
-                  _ { true }
-                } {
-                let name = self.parse_value_path();
-                let sub = if self.eat(token::AT) { some(self.parse_pat()) }
-                else { none };
-                pat = pat_ident(name, sub);
             } else {
-                let enum_path = self.parse_path_with_tps(true);
-                hi = enum_path.span.hi;
-                let mut args: ~[@pat] = ~[];
-                let mut star_pat = false;
-                alt self.token {
-                  token::LPAREN {
-                    alt self.look_ahead(1u) {
-                      token::BINOP(token::STAR) {
-                        // This is a "top constructor only" pat
-                        self.bump(); self.bump();
-                        star_pat = true;
-                        self.expect(token::RPAREN);
+                let binding_mode;
+                if self.eat_keyword(~"ref") {
+                    binding_mode = bind_by_ref;
+                } else {
+                    alt self.token {
+                        token::BINOP(token::PLUS) => {
+                            // XXX: Temporary thing pending a snapshot.
+                            self.bump();
+                            binding_mode = bind_by_value;
+                        }
+                        _ if refutable => {
+                            // XXX: Should be bind_by_value, but that's not
+                            // backward compatible.
+                            binding_mode = bind_by_ref;
+                        }
+                        _ => {
+                            binding_mode = bind_by_value;
+                        }
+                    }
+                }
+
+                if is_plain_ident(self.token) &&
+                    alt self.look_ahead(1) {
+                      token::LPAREN | token::LBRACKET | token::LT => {
+                        false
                       }
-                      _ {
-                        args = self.parse_unspanned_seq(
-                            token::LPAREN, token::RPAREN,
-                            seq_sep_trailing_disallowed(token::COMMA),
-                            |p| p.parse_pat());
-                        hi = self.span.hi;
+                      _ => {
+                        true
                       }
+                    } {
+                    let name = self.parse_value_path();
+                    let sub = if self.eat(token::AT) {
+                        some(self.parse_pat(refutable))
+                    }
+                    else { none };
+                    pat = pat_ident(binding_mode, name, sub);
+                } else {
+                    let enum_path = self.parse_path_with_tps(true);
+                    hi = enum_path.span.hi;
+                    let mut args: ~[@pat] = ~[];
+                    let mut star_pat = false;
+                    alt self.token {
+                      token::LPAREN {
+                        alt self.look_ahead(1u) {
+                          token::BINOP(token::STAR) {
+                            // This is a "top constructor only" pat
+                            self.bump(); self.bump();
+                            star_pat = true;
+                            self.expect(token::RPAREN);
+                          }
+                          _ {
+                            args = self.parse_unspanned_seq(
+                                token::LPAREN, token::RPAREN,
+                                seq_sep_trailing_disallowed(token::COMMA),
+                                |p| p.parse_pat(refutable));
+                            hi = self.span.hi;
+                          }
+                        }
+                      }
+                      _ { }
+                    }
+                    // at this point, we're not sure whether it's a enum or a
+                    // bind
+                    if star_pat {
+                        pat = pat_enum(enum_path, none);
+                    }
+                    else if vec::is_empty(args) &&
+                        vec::len(enum_path.idents) == 1u {
+                        pat = pat_ident(binding_mode, enum_path, none);
+                    }
+                    else {
+                        pat = pat_enum(enum_path, some(args));
                     }
-                  }
-                  _ { }
-                }
-                // at this point, we're not sure whether it's a enum or a bind
-                if star_pat {
-                    pat = pat_enum(enum_path, none);
-                }
-                else if vec::is_empty(args) &&
-                    vec::len(enum_path.idents) == 1u {
-                    pat = pat_ident(enum_path, none);
-                }
-                else {
-                    pat = pat_enum(enum_path, some(args));
                 }
             }
           }
@@ -1758,7 +1788,7 @@ class parser {
     fn parse_local(is_mutbl: bool,
                    allow_init: bool) -> @local {
         let lo = self.span.lo;
-        let pat = self.parse_pat();
+        let pat = self.parse_pat(false);
         let mut ty = @{id: self.get_id(),
                        node: ty_infer,
                        span: mk_sp(lo, lo)};
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 1d4e67c5d14..cbea14f3185 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -331,7 +331,7 @@ fn restricted_keyword_table() -> hashmap<~str, ()> {
         ~"new",
         ~"owned",
         ~"pure",
-        ~"ret", ~"return",
+        ~"ref", ~"ret", ~"return",
         ~"struct",
         ~"true", ~"trait", ~"type",
         ~"unchecked", ~"unsafe",
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 41e795fd436..b0ef87a8cca 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1302,11 +1302,15 @@ fn print_pat(s: ps, &&pat: @ast::pat) {
      is that it doesn't matter */
     alt pat.node {
       ast::pat_wild { word(s.s, ~"_"); }
-      ast::pat_ident(path, sub) {
+      ast::pat_ident(binding_mode, path, sub) {
+        alt binding_mode {
+          ast::bind_by_ref => { word_space(s, ~"ref"); }
+          ast::bind_by_value => {}
+        }
         print_path(s, path, true);
         alt sub {
-          some(p) { word(s.s, ~"@"); print_pat(s, p); }
-          none {}
+          some(p) => { word(s.s, ~"@"); print_pat(s, p); }
+          none => {}
         }
       }
       ast::pat_enum(path, args_) {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 050d7e58120..5cf73da1944 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -229,7 +229,7 @@ fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
       pat_box(inner) | pat_uniq(inner) {
         v.visit_pat(inner, e, v);
       }
-      pat_ident(path, inner) {
+      pat_ident(_, path, inner) {
           visit_path(path, e, v);
           do option::iter(inner) |subpat| { v.visit_pat(subpat, e, v)};
       }
diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs
index 4b9015eec67..f08a06f3419 100644
--- a/src/rustc/middle/borrowck/gather_loans.rs
+++ b/src/rustc/middle/borrowck/gather_loans.rs
@@ -473,11 +473,13 @@ impl methods for gather_loan_ctxt {
             }
           }
 
-          ast::pat_ident(_, none) if self.pat_is_variant(pat) {
+          ast::pat_ident(_, _, none) if self.pat_is_variant(pat) {
             // nullary variant
             debug!{"nullary variant"};
           }
-          ast::pat_ident(id, o_pat) {
+          ast::pat_ident(_, id, o_pat) {
+            // XXX: Needs to take by-ref/by-val into account.
+
             // x or x @ p --- `x` must remain valid for the scope of the alt
             debug!{"defines identifier %s", pprust::path_to_str(id)};
 
diff --git a/src/rustc/middle/check_alt.rs b/src/rustc/middle/check_alt.rs
index 4d62f2818ee..4093c0fcc6e 100644
--- a/src/rustc/middle/check_alt.rs
+++ b/src/rustc/middle/check_alt.rs
@@ -71,8 +71,8 @@ fn check_arms(tcx: ty::ctxt, arms: ~[arm]) {
 
 fn raw_pat(p: @pat) -> @pat {
     alt p.node {
-      pat_ident(_, some(s)) { raw_pat(s) }
-      _ { p }
+      pat_ident(_, _, some(s)) => { raw_pat(s) }
+      _ => { p }
     }
 }
 
@@ -199,32 +199,34 @@ fn is_useful_specialized(tcx: ty::ctxt, m: matrix, v: ~[@pat], ctor: ctor,
 fn pat_ctor_id(tcx: ty::ctxt, p: @pat) -> option<ctor> {
     let pat = raw_pat(p);
     alt pat.node {
-      pat_wild { none }
-      pat_ident(_, _) | pat_enum(_, _) {
+      pat_wild => { none }
+      pat_ident(_, _, _) | pat_enum(_, _) => {
         alt tcx.def_map.find(pat.id) {
           some(def_variant(_, id)) { some(variant(id)) }
           _ { none }
         }
       }
-      pat_lit(expr) { some(val(eval_const_expr(tcx, expr))) }
-      pat_range(lo, hi) {
+      pat_lit(expr) => { some(val(eval_const_expr(tcx, expr))) }
+      pat_range(lo, hi) => {
         some(range(eval_const_expr(tcx, lo), eval_const_expr(tcx, hi)))
       }
-      pat_box(_) | pat_uniq(_) | pat_rec(_, _) | pat_tup(_) { some(single) }
+      pat_box(_) | pat_uniq(_) | pat_rec(_, _) | pat_tup(_) => {
+        some(single)
+      }
     }
 }
 
 fn is_wild(tcx: ty::ctxt, p: @pat) -> bool {
     let pat = raw_pat(p);
     alt pat.node {
-      pat_wild { true }
-      pat_ident(_, _) {
+      pat_wild => { true }
+      pat_ident(_, _, _) => {
         alt tcx.def_map.find(pat.id) {
-          some(def_variant(_, _)) { false }
-          _ { true }
+          some(def_variant(_, _)) => { false }
+          _ => { true }
         }
       }
-      _ { false }
+      _ => { false }
     }
 }
 
@@ -296,7 +298,7 @@ fn specialize(tcx: ty::ctxt, r: ~[@pat], ctor_id: ctor, arity: uint,
     alt r0.node {
       pat_wild { some(vec::append(vec::from_elem(arity, wild()),
                                   vec::tail(r))) }
-      pat_ident(_, _) {
+      pat_ident(_, _, _) {
         alt tcx.def_map.find(r0.id) {
           some(def_variant(_, id)) {
             if variant(id) == ctor_id { some(vec::tail(r)) }
@@ -377,26 +379,26 @@ fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
     }
 
     alt pat.node {
-      pat_box(sub) | pat_uniq(sub) | pat_ident(_, some(sub)) {
+      pat_box(sub) | pat_uniq(sub) | pat_ident(_, _, some(sub)) => {
         is_refutable(tcx, sub)
       }
-      pat_wild | pat_ident(_, none) { false }
-      pat_lit(_) | pat_range(_, _) { true }
-      pat_rec(fields, _) {
+      pat_wild | pat_ident(_, _, none) => { false }
+      pat_lit(_) | pat_range(_, _) => { true }
+      pat_rec(fields, _) => {
         for fields.each |it| {
             if is_refutable(tcx, it.pat) { ret true; }
         }
         false
       }
-      pat_tup(elts) {
+      pat_tup(elts) => {
         for elts.each |elt| { if is_refutable(tcx, elt) { ret true; } }
         false
       }
-      pat_enum(_, some(args)) {
+      pat_enum(_, some(args)) => {
         for args.each |p| { if is_refutable(tcx, p) { ret true; } };
         false
       }
-      pat_enum(_,_) { false }
+      pat_enum(_,_) => { false }
     }
 }
 
diff --git a/src/rustc/middle/pat_util.rs b/src/rustc/middle/pat_util.rs
index 4056dc137d7..8415b5e1a32 100644
--- a/src/rustc/middle/pat_util.rs
+++ b/src/rustc/middle/pat_util.rs
@@ -24,7 +24,7 @@ fn pat_id_map(dm: resolve3::DefMap, pat: @pat) -> pat_id_map {
 fn pat_is_variant(dm: resolve3::DefMap, pat: @pat) -> bool {
     alt pat.node {
       pat_enum(_, _) { true }
-      pat_ident(_, none) {
+      pat_ident(_, _, none) {
         alt dm.find(pat.id) {
           some(def_variant(_, _)) { true }
           _ { false }
@@ -38,7 +38,7 @@ fn pat_bindings(dm: resolve3::DefMap, pat: @pat,
                 it: fn(node_id, span, @path)) {
     do walk_pat(pat) |p| {
         alt p.node {
-          pat_ident(pth, _) if !pat_is_variant(dm, p) {
+          pat_ident(_, pth, _) if !pat_is_variant(dm, p) {
             it(p.id, p.span, pth);
           }
           _ {}
diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs
index e6b2209b44a..809fd1c6fd6 100644
--- a/src/rustc/middle/region.rs
+++ b/src/rustc/middle/region.rs
@@ -208,7 +208,7 @@ fn resolve_arm(arm: ast::arm, cx: ctxt, visitor: visit::vt<ctxt>) {
 
 fn resolve_pat(pat: @ast::pat, cx: ctxt, visitor: visit::vt<ctxt>) {
     alt pat.node {
-      ast::pat_ident(path, _) {
+      ast::pat_ident(_, path, _) {
         let defn_opt = cx.def_map.find(pat.id);
         alt defn_opt {
           some(ast::def_variant(_,_)) {
diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs
index b4237d3e841..f66e3925fb0 100644
--- a/src/rustc/middle/resolve3.rs
+++ b/src/rustc/middle/resolve3.rs
@@ -5,11 +5,11 @@ import metadata::cstore::find_use_stmt_cnum;
 import metadata::decoder::{def_like, dl_def, dl_field, dl_impl};
 import middle::lang_items::LanguageItems;
 import middle::lint::{deny, allow, forbid, level, unused_imports, warn};
-import syntax::ast::{_mod, add, arm, bitand, bitor, bitxor, blk, bound_const};
-import syntax::ast::{bound_copy, bound_owned, bound_send, bound_trait};
-import syntax::ast::{capture_clause, class_ctor, class_dtor, class_member};
-import syntax::ast::{class_method, crate, crate_num, decl_item, def, def_arg};
-import syntax::ast::{def_binding, def_class, def_const, def_fn};
+import syntax::ast::{_mod, add, arm, bind_by_value, bitand, bitor, bitxor};
+import syntax::ast::{blk, bound_const, bound_copy, bound_owned, bound_send};
+import syntax::ast::{bound_trait, capture_clause, class_ctor, class_dtor};
+import syntax::ast::{class_member, class_method, crate, crate_num, decl_item};
+import syntax::ast::{def, def_arg, def_binding, def_class, def_const, def_fn};
 import syntax::ast::{def_foreign_mod, def_id, def_local, def_mod};
 import syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param,
                      def_typaram_binder};
@@ -3734,8 +3734,8 @@ class Resolver {
         let pat_id = pattern.id;
         do walk_pat(pattern) |pattern| {
             alt pattern.node {
-                pat_ident(path, _)
-                        if !path.global && path.idents.len() == 1u {
+                pat_ident(_, path, _)
+                        if !path.global && path.idents.len() == 1u => {
 
                     // The meaning of pat_ident with no type parameters
                     // depends on whether an enum variant with that name is in
@@ -3748,14 +3748,14 @@ class Resolver {
                     let atom = (*self.atom_table).intern(path.idents[0]);
 
                     alt self.resolve_enum_variant_or_const(atom) {
-                        FoundEnumVariant(def) if mode == RefutableMode {
+                        FoundEnumVariant(def) if mode == RefutableMode => {
                             debug!{"(resolving pattern) resolving `%s` to \
                                     enum variant",
                                    *path.idents[0]};
 
                             self.record_def(pattern.id, def);
                         }
-                        FoundEnumVariant(_) {
+                        FoundEnumVariant(_) => {
                             self.session.span_err(pattern.span,
                                                   fmt!{"declaration of `%s` \
                                                         shadows an enum \
@@ -3764,13 +3764,13 @@ class Resolver {
                                                             atom_to_str
                                                             (atom)});
                         }
-                        FoundConst {
+                        FoundConst => {
                             self.session.span_err(pattern.span,
                                                   ~"pattern variable \
                                                    conflicts with a constant \
                                                    in scope");
                         }
-                        EnumVariantOrConstNotFound {
+                        EnumVariantOrConstNotFound => {
                             debug!{"(resolving pattern) binding `%s`",
                                    *path.idents[0]};
 
@@ -3836,7 +3836,7 @@ class Resolver {
                     }
                 }
 
-                pat_ident(path, _) | pat_enum(path, _) {
+                pat_ident(_, path, _) | pat_enum(path, _) => {
                     // These two must be enum variants.
                     alt self.resolve_path(path, ValueNS, false, visitor) {
                         some(def @ def_variant(*)) {
@@ -3860,16 +3860,16 @@ class Resolver {
                     }
                 }
 
-                pat_lit(expr) {
+                pat_lit(expr) => {
                     self.resolve_expr(expr, visitor);
                 }
 
-                pat_range(first_expr, last_expr) {
+                pat_range(first_expr, last_expr) => {
                     self.resolve_expr(first_expr, visitor);
                     self.resolve_expr(last_expr, visitor);
                 }
 
-                _ {
+                _ => {
                     // Nothing to do.
                 }
             }
diff --git a/src/rustc/middle/trans/alt.rs b/src/rustc/middle/trans/alt.rs
index ef957e1c75a..b25aa26066f 100644
--- a/src/rustc/middle/trans/alt.rs
+++ b/src/rustc/middle/trans/alt.rs
@@ -79,7 +79,12 @@ fn variant_opt(tcx: ty::ctxt, pat_id: ast::node_id) -> opt {
     core::unreachable();
 }
 
-type bind_map = ~[{ident: ast::ident, val: ValueRef}];
+type bind_map = ~[{
+    ident: ast::ident,
+    val: ValueRef,
+    mode: ast::binding_mode
+}];
+
 fn assoc(key: ast::ident, list: bind_map) -> option<ValueRef> {
     for vec::each(list) |elt| {
         if str::eq(*elt.ident, *key) { ret some(elt.val); }
@@ -98,7 +103,7 @@ type match_ = ~[match_branch];
 fn has_nested_bindings(m: match_, col: uint) -> bool {
     for vec::each(m) |br| {
         alt br.pats[col].node {
-          ast::pat_ident(_, some(_)) { ret true; }
+          ast::pat_ident(_, _, some(_)) { ret true; }
           _ {}
         }
     }
@@ -109,7 +114,7 @@ fn expand_nested_bindings(m: match_, col: uint, val: ValueRef) -> match_ {
     let mut result = ~[];
     for vec::each(m) |br| {
       alt br.pats[col].node {
-          ast::pat_ident(name, some(inner)) {
+          ast::pat_ident(mode, name, some(inner)) {
             let pats = vec::append(
                 vec::slice(br.pats, 0u, col),
                 vec::append(~[inner],
@@ -118,7 +123,8 @@ fn expand_nested_bindings(m: match_, col: uint, val: ValueRef) -> match_ {
                       @{pats: pats,
                         bound: vec::append(
                             br.bound, ~[{ident: path_to_ident(name),
-                                        val: val}])
+                                        val: val,
+                                        mode: mode}])
                                 with *br});
           }
           _ { vec::push(result, br); }
@@ -140,9 +146,11 @@ fn enter_match(dm: DefMap, m: match_, col: uint, val: ValueRef,
                 vec::view(br.pats, col + 1u, br.pats.len()));
             let self = br.pats[col];
             let bound = alt self.node {
-              ast::pat_ident(name, none) if !pat_is_variant(dm, self) {
+              ast::pat_ident(mode, name, none) if !pat_is_variant(dm, self) {
                 vec::append(br.bound,
-                            ~[{ident: path_to_ident(name), val: val}])
+                            ~[{ident: path_to_ident(name),
+                               val: val,
+                               mode: mode}])
               }
               _ { br.bound }
             };
@@ -158,7 +166,7 @@ fn enter_default(dm: DefMap, m: match_, col: uint, val: ValueRef) -> match_ {
     do enter_match(dm, m, col, val) |p| {
         alt p.node {
           ast::pat_wild | ast::pat_rec(_, _) | ast::pat_tup(_) { some(~[]) }
-          ast::pat_ident(_, none) if !pat_is_variant(dm, p) {
+          ast::pat_ident(_, _, none) if !pat_is_variant(dm, p) {
             some(~[])
           }
           _ { none }
@@ -177,7 +185,7 @@ fn enter_opt(tcx: ty::ctxt, m: match_, opt: opt, col: uint,
                      vec::from_elem(variant_size, dummy))) }
             else { none }
           }
-          ast::pat_ident(_, none) if pat_is_variant(tcx.def_map, p) {
+          ast::pat_ident(_, _, none) if pat_is_variant(tcx.def_map, p) {
             if opt_eq(tcx, variant_opt(tcx, p.id), opt) { some(~[]) }
             else { none }
           }
@@ -359,7 +367,7 @@ fn pick_col(m: match_) -> uint {
     fn score(p: @ast::pat) -> uint {
         alt p.node {
           ast::pat_lit(_) | ast::pat_enum(_, _) | ast::pat_range(_, _) { 1u }
-          ast::pat_ident(_, some(p)) { score(p) }
+          ast::pat_ident(_, _, some(p)) { score(p) }
           _ { 0u }
         }
     }
@@ -725,7 +733,7 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
 
     // Necessary since bind_irrefutable_pat is called outside trans_alt
     alt pat.node {
-      ast::pat_ident(_,inner) {
+      ast::pat_ident(_, _,inner) {
         if pat_is_variant(bcx.tcx().def_map, pat) { ret bcx; }
         if make_copy {
             let ty = node_id_type(bcx, pat.id);
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 5960b7657f4..ef92891418a 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -4380,7 +4380,7 @@ fn alloc_local(cx: block, local: @ast::local) -> block {
     let _icx = cx.insn_ctxt(~"alloc_local");
     let t = node_id_type(cx, local.node.id);
     let simple_name = alt local.node.pat.node {
-      ast::pat_ident(pth, none) { some(path_to_ident(pth)) }
+      ast::pat_ident(_, pth, none) { some(path_to_ident(pth)) }
       _ { none }
     };
     let val = alloc_ty(cx, t);
diff --git a/src/rustc/middle/trans/debuginfo.rs b/src/rustc/middle/trans/debuginfo.rs
index 3197dc00884..98e7129abba 100644
--- a/src/rustc/middle/trans/debuginfo.rs
+++ b/src/rustc/middle/trans/debuginfo.rs
@@ -646,7 +646,7 @@ fn create_local_var(bcx: block, local: @ast::local)
     }
 
     let name = alt local.node.pat.node {
-      ast::pat_ident(pth, _) { ast_util::path_to_ident(pth) }
+      ast::pat_ident(_, pth, _) { ast_util::path_to_ident(pth) }
       // FIXME this should be handled (#2533)
       _ { fail ~"no single variable name for local"; }
     };
diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs
index db9084cbad1..d8dd6bf0542 100644
--- a/src/rustc/middle/typeck/check.rs
+++ b/src/rustc/middle/typeck/check.rs
@@ -320,14 +320,14 @@ fn check_fn(ccx: @crate_ctxt,
         // Add pattern bindings.
         let visit_pat = fn@(p: @ast::pat, &&e: (), v: visit::vt<()>) {
             alt p.node {
-              ast::pat_ident(path, _)
-              if !pat_util::pat_is_variant(fcx.ccx.tcx.def_map, p) {
+              ast::pat_ident(_, path, _)
+                  if !pat_util::pat_is_variant(fcx.ccx.tcx.def_map, p) => {
                 assign(p.id, none);
                 debug!{"Pattern binding %s is assigned to %s",
                        *path.idents[0],
                        fcx.locals.get(p.id).to_str()};
               }
-              _ {}
+              _ => {}
             }
             visit::visit_pat(p, e, v);
         };
diff --git a/src/rustc/middle/typeck/check/alt.rs b/src/rustc/middle/typeck/check/alt.rs
index db35398a49c..5cc8a953722 100644
--- a/src/rustc/middle/typeck/check/alt.rs
+++ b/src/rustc/middle/typeck/check/alt.rs
@@ -155,7 +155,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
         }
         fcx.write_ty(pat.id, b_ty);
       }
-      ast::pat_ident(name, sub) if !pat_is_variant(tcx.def_map, pat) {
+      ast::pat_ident(_, name, sub) if !pat_is_variant(tcx.def_map, pat) {
         let vid = lookup_local(fcx, pat.span, pat.id);
         let mut typ = ty::mk_var(tcx, vid);
         demand::suptype(fcx, pat.span, expected, typ);
@@ -171,7 +171,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
           _ {}
         }
       }
-      ast::pat_ident(path, c) {
+      ast::pat_ident(_, path, c) {
         check_pat_variant(pcx, pat, path, some(~[]), expected);
       }
       ast::pat_enum(path, subpats) {
diff --git a/src/rustc/middle/typeck/check/regionck.rs b/src/rustc/middle/typeck/check/regionck.rs
index 06307c1c70c..50e2d5db973 100644
--- a/src/rustc/middle/typeck/check/regionck.rs
+++ b/src/rustc/middle/typeck/check/regionck.rs
@@ -105,7 +105,7 @@ fn visit_local(l: @ast::local, &&rcx: @rcx, v: rvt) {
 fn visit_pat(p: @ast::pat, &&rcx: @rcx, v: rvt) {
     let fcx = rcx.fcx;
     alt p.node {
-      ast::pat_ident(path, _)
+      ast::pat_ident(_, path, _)
       if !pat_util::pat_is_variant(fcx.ccx.tcx.def_map, p) {
         debug!{"visit_pat binding=%s", *path.idents[0]};
         visit_node(p.id, p.span, rcx);