about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-05-30 19:04:52 -0700
committerbors <bors@rust-lang.org>2013-05-30 19:04:52 -0700
commit3869f7a99c54f00d69b19298f215cbc4a84ce5a8 (patch)
treefca2b9d8c111e40604460dedc696cbe0a47b58c7
parent237dce12c934287abd0bbe5a35309b1dc4f0d2c0 (diff)
parentce5fd302702a76e4b65a94128189b0f2d3a22c32 (diff)
auto merge of #6818 : nikomatsakis/rust/irrefut-patterns-refactoring, r=graydon
Various bug fixes and simplifications I did as part of a patch to fix `let` patterns.

r? @catamorphism
-rw-r--r--src/libextra/fun_treemap.rs14
-rw-r--r--src/libextra/getopts.rs46
-rw-r--r--src/libextra/json.rs2
-rw-r--r--src/libextra/list.rs6
-rw-r--r--src/libextra/net_ip.rs2
-rw-r--r--src/libextra/net_tcp.rs2
-rw-r--r--src/libextra/test.rs11
-rw-r--r--src/libextra/time.rs14
-rw-r--r--src/librustc/back/link.rs10
-rw-r--r--src/librustc/driver/driver.rs8
-rw-r--r--src/librustc/metadata/creader.rs6
-rw-r--r--src/librustc/middle/borrowck/gather_loans/mod.rs2
-rw-r--r--src/librustc/middle/check_match.rs1
-rw-r--r--src/librustc/middle/kind.rs14
-rw-r--r--src/librustc/middle/moves.rs6
-rw-r--r--src/librustc/middle/resolve.rs28
-rw-r--r--src/librustc/middle/trans/_match.rs158
-rw-r--r--src/librustc/middle/trans/base.rs21
-rw-r--r--src/librustc/middle/trans/callee.rs5
-rw-r--r--src/librustc/middle/trans/closure.rs4
-rw-r--r--src/librustc/middle/trans/common.rs6
-rw-r--r--src/librustc/middle/trans/datum.rs154
-rw-r--r--src/librustc/middle/trans/debuginfo.rs21
-rw-r--r--src/librustc/middle/trans/expr.rs33
-rw-r--r--src/librustc/middle/trans/foreign.rs20
-rw-r--r--src/librustc/middle/trans/meth.rs4
-rw-r--r--src/librustc/middle/trans/type_use.rs8
-rw-r--r--src/librustc/middle/typeck/check/_match.rs2
-rw-r--r--src/librustc/middle/typeck/coherence.rs2
-rw-r--r--src/libstd/io.rs6
-rw-r--r--src/libstd/option.rs6
-rw-r--r--src/libstd/path.rs8
-rw-r--r--src/libstd/result.rs26
-rw-r--r--src/libsyntax/ast.rs9
-rw-r--r--src/libsyntax/ast_util.rs2
-rw-r--r--src/libsyntax/ext/build.rs2
-rw-r--r--src/libsyntax/ext/deriving/iter_bytes.rs4
-rw-r--r--src/libsyntax/ext/deriving/rand.rs2
-rw-r--r--src/libsyntax/ext/source_util.rs4
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs2
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs12
-rw-r--r--src/libsyntax/parse/mod.rs8
-rw-r--r--src/libsyntax/parse/parser.rs107
-rw-r--r--src/libsyntax/print/pprust.rs3
-rw-r--r--src/test/compile-fail/borrowck-pat-by-value-binding.rs2
-rw-r--r--src/test/compile-fail/noncopyable-match-pattern.rs23
-rw-r--r--src/test/compile-fail/resolve-inconsistent-binding-mode.rs2
-rw-r--r--src/test/run-pass/issue-2804.rs8
-rw-r--r--src/test/run-pass/match-vec-rvalue.rs12
49 files changed, 408 insertions, 450 deletions
diff --git a/src/libextra/fun_treemap.rs b/src/libextra/fun_treemap.rs
index fb9bb0740c5..eb8c27e9902 100644
--- a/src/libextra/fun_treemap.rs
+++ b/src/libextra/fun_treemap.rs
@@ -35,13 +35,13 @@ enum TreeNode<K, V> {
 pub fn init<K, V>() -> Treemap<K, V> { @Empty }
 
 /// Insert a value into the map
-pub fn insert<K:Copy + Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K, v: V) -> Treemap<K, V> {
+pub fn insert<K:Eq + Ord,V>(m: Treemap<K, V>, k: K, v: V) -> Treemap<K, V> {
     @match m {
         @Empty => Node(@k, @v, @Empty, @Empty),
-        @Node(@copy kk, vv, left, right) => cond!(
-            (k <  kk) { Node(@kk, vv, insert(left, k, v), right) }
-            (k == kk) { Node(@kk, @v, left, right)               }
-            _         { Node(@kk, vv, left, insert(right, k, v)) }
+        @Node(kk, vv, left, right) => cond!(
+            (k <  *kk) { Node(kk, vv, insert(left, k, v), right) }
+            (k == *kk) { Node(kk, @v, left, right)               }
+            _          { Node(kk, vv, left, insert(right, k, v)) }
         )
     }
 }
@@ -50,8 +50,8 @@ pub fn insert<K:Copy + Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K, v: V) -> Treemap
 pub fn find<K:Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K) -> Option<V> {
     match *m {
         Empty => None,
-        Node(@ref kk, @copy v, left, right) => cond!(
-            (k == *kk) { Some(v)        }
+        Node(kk, v, left, right) => cond!(
+            (k == *kk) { Some(copy *v)  }
             (k <  *kk) { find(left, k)  }
             _          { find(right, k) }
         )
diff --git a/src/libextra/getopts.rs b/src/libextra/getopts.rs
index 678d795d8f8..eb5699df77f 100644
--- a/src/libextra/getopts.rs
+++ b/src/libextra/getopts.rs
@@ -171,7 +171,7 @@ fn is_arg(arg: &str) -> bool {
 fn name_str(nm: &Name) -> ~str {
     return match *nm {
       Short(ch) => str::from_char(ch),
-      Long(copy s) => s
+      Long(ref s) => copy *s
     };
 }
 
@@ -390,7 +390,7 @@ pub fn opts_present(mm: &Matches, names: &[~str]) -> bool {
  * argument
  */
 pub fn opt_str(mm: &Matches, nm: &str) -> ~str {
-    return match opt_val(mm, nm) { Val(copy s) => s, _ => fail!() };
+    return match opt_val(mm, nm) { Val(s) => s, _ => fail!() };
 }
 
 /**
@@ -402,7 +402,7 @@ pub fn opt_str(mm: &Matches, nm: &str) -> ~str {
 pub fn opts_str(mm: &Matches, names: &[~str]) -> ~str {
     for names.each |nm| {
         match opt_val(mm, *nm) {
-          Val(copy s) => return s,
+          Val(ref s) => return copy *s,
           _ => ()
         }
     }
@@ -419,7 +419,7 @@ pub fn opts_str(mm: &Matches, names: &[~str]) -> ~str {
 pub fn opt_strs(mm: &Matches, nm: &str) -> ~[~str] {
     let mut acc: ~[~str] = ~[];
     for vec::each(opt_vals(mm, nm)) |v| {
-        match *v { Val(copy s) => acc.push(s), _ => () }
+        match *v { Val(ref s) => acc.push(copy *s), _ => () }
     }
     return acc;
 }
@@ -429,7 +429,7 @@ pub fn opt_maybe_str(mm: &Matches, nm: &str) -> Option<~str> {
     let vals = opt_vals(mm, nm);
     if vec::len::<Optval>(vals) == 0u { return None::<~str>; }
     return match vals[0] {
-        Val(copy s) => Some(s),
+        Val(ref s) => Some(copy *s),
         _ => None
     };
 }
@@ -445,7 +445,7 @@ pub fn opt_maybe_str(mm: &Matches, nm: &str) -> Option<~str> {
 pub fn opt_default(mm: &Matches, nm: &str, def: &str) -> Option<~str> {
     let vals = opt_vals(mm, nm);
     if vec::len::<Optval>(vals) == 0u { return None::<~str>; }
-    return match vals[0] { Val(copy s) => Some::<~str>(s),
+    return match vals[0] { Val(ref s) => Some::<~str>(copy *s),
                            _      => Some::<~str>(str::to_owned(def)) }
 }
 
@@ -701,7 +701,7 @@ mod tests {
         let opts = ~[reqopt("test")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, OptionMissing_),
+          Err(f) => check_fail_type(f, OptionMissing_),
           _ => fail!()
         }
     }
@@ -712,7 +712,7 @@ mod tests {
         let opts = ~[reqopt("test")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, ArgumentMissing_),
+          Err(f) => check_fail_type(f, ArgumentMissing_),
           _ => fail!()
         }
     }
@@ -723,7 +723,7 @@ mod tests {
         let opts = ~[reqopt("test")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, OptionDuplicated_),
+          Err(f) => check_fail_type(f, OptionDuplicated_),
           _ => fail!()
         }
     }
@@ -748,7 +748,7 @@ mod tests {
         let opts = ~[reqopt("t")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, OptionMissing_),
+          Err(f) => check_fail_type(f, OptionMissing_),
           _ => fail!()
         }
     }
@@ -759,7 +759,7 @@ mod tests {
         let opts = ~[reqopt("t")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, ArgumentMissing_),
+          Err(f) => check_fail_type(f, ArgumentMissing_),
           _ => fail!()
         }
     }
@@ -770,7 +770,7 @@ mod tests {
         let opts = ~[reqopt("t")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, OptionDuplicated_),
+          Err(f) => check_fail_type(f, OptionDuplicated_),
           _ => fail!()
         }
     }
@@ -808,7 +808,7 @@ mod tests {
         let opts = ~[optopt("test")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, ArgumentMissing_),
+          Err(f) => check_fail_type(f, ArgumentMissing_),
           _ => fail!()
         }
     }
@@ -819,7 +819,7 @@ mod tests {
         let opts = ~[optopt("test")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, OptionDuplicated_),
+          Err(f) => check_fail_type(f, OptionDuplicated_),
           _ => fail!()
         }
     }
@@ -855,7 +855,7 @@ mod tests {
         let opts = ~[optopt("t")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, ArgumentMissing_),
+          Err(f) => check_fail_type(f, ArgumentMissing_),
           _ => fail!()
         }
     }
@@ -866,7 +866,7 @@ mod tests {
         let opts = ~[optopt("t")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, OptionDuplicated_),
+          Err(f) => check_fail_type(f, OptionDuplicated_),
           _ => fail!()
         }
     }
@@ -901,7 +901,7 @@ mod tests {
         let opts = ~[optflag("test")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => {
+          Err(f) => {
             error!(fail_str(copy f));
             check_fail_type(f, UnexpectedArgument_);
           }
@@ -915,7 +915,7 @@ mod tests {
         let opts = ~[optflag("test")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, OptionDuplicated_),
+          Err(f) => check_fail_type(f, OptionDuplicated_),
           _ => fail!()
         }
     }
@@ -963,7 +963,7 @@ mod tests {
         let opts = ~[optflag("t")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, OptionDuplicated_),
+          Err(f) => check_fail_type(f, OptionDuplicated_),
           _ => fail!()
         }
     }
@@ -1066,7 +1066,7 @@ mod tests {
         let opts = ~[optmulti("test")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, ArgumentMissing_),
+          Err(f) => check_fail_type(f, ArgumentMissing_),
           _ => fail!()
         }
     }
@@ -1119,7 +1119,7 @@ mod tests {
         let opts = ~[optmulti("t")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, ArgumentMissing_),
+          Err(f) => check_fail_type(f, ArgumentMissing_),
           _ => fail!()
         }
     }
@@ -1147,7 +1147,7 @@ mod tests {
         let opts = ~[optmulti("t")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, UnrecognizedOption_),
+          Err(f) => check_fail_type(f, UnrecognizedOption_),
           _ => fail!()
         }
     }
@@ -1158,7 +1158,7 @@ mod tests {
         let opts = ~[optmulti("test")];
         let rs = getopts(args, opts);
         match rs {
-          Err(copy f) => check_fail_type(f, UnrecognizedOption_),
+          Err(f) => check_fail_type(f, UnrecognizedOption_),
           _ => fail!()
         }
     }
diff --git a/src/libextra/json.rs b/src/libextra/json.rs
index 48a3288f809..d69548c6f9d 100644
--- a/src/libextra/json.rs
+++ b/src/libextra/json.rs
@@ -1384,7 +1384,7 @@ mod tests {
 
         for items.each |item| {
             match *item {
-                (copy key, copy value) => { d.insert(key, value); },
+                (ref key, ref value) => { d.insert(copy *key, copy *value); },
             }
         };
 
diff --git a/src/libextra/list.rs b/src/libextra/list.rs
index 6f2c8447eca..7a38be8944f 100644
--- a/src/libextra/list.rs
+++ b/src/libextra/list.rs
@@ -104,7 +104,7 @@ pub fn tail<T:Copy>(ls: @List<T>) -> @List<T> {
 /// Returns the first element of a list
 pub fn head<T:Copy>(ls: @List<T>) -> T {
     match *ls {
-      Cons(copy hd, _) => hd,
+      Cons(ref hd, _) => copy *hd,
       // makes me sad
       _ => fail!("head invoked on empty list")
     }
@@ -114,9 +114,9 @@ pub fn head<T:Copy>(ls: @List<T>) -> T {
 pub fn append<T:Copy>(l: @List<T>, m: @List<T>) -> @List<T> {
     match *l {
       Nil => return m,
-      Cons(copy x, xs) => {
+      Cons(ref x, xs) => {
         let rest = append(xs, m);
-        return @Cons(x, rest);
+        return @Cons(copy *x, rest);
       }
     }
 }
diff --git a/src/libextra/net_ip.rs b/src/libextra/net_ip.rs
index 160d06ec20d..ddbf09e40eb 100644
--- a/src/libextra/net_ip.rs
+++ b/src/libextra/net_ip.rs
@@ -278,7 +278,7 @@ pub mod v6 {
     pub fn parse_addr(ip: &str) -> IpAddr {
         match try_parse_addr(ip) {
           result::Ok(addr) => addr,
-          result::Err(copy err_data) => fail!(copy err_data.err_msg)
+          result::Err(err_data) => fail!(copy err_data.err_msg)
         }
     }
     pub fn try_parse_addr(ip: &str) -> result::Result<IpAddr,ParseAddrErr> {
diff --git a/src/libextra/net_tcp.rs b/src/libextra/net_tcp.rs
index c3a0463c2fc..d658ad6551f 100644
--- a/src/libextra/net_tcp.rs
+++ b/src/libextra/net_tcp.rs
@@ -595,7 +595,7 @@ pub fn accept(new_conn: TcpNewConnection)
                 }
                 // UNSAFE LIBUV INTERACTION END
                 match result_po.recv() {
-                    Some(copy err_data) => result::Err(err_data),
+                    Some(err_data) => result::Err(err_data),
                     None => result::Ok(TcpSocket(client_socket_data))
                 }
             }
diff --git a/src/libextra/test.rs b/src/libextra/test.rs
index 59c6a12e036..375b4cd5fb5 100644
--- a/src/libextra/test.rs
+++ b/src/libextra/test.rs
@@ -223,7 +223,7 @@ pub fn run_tests_console(opts: &TestOpts,
           }
           TeWait(ref test) => st.out.write_str(
               fmt!("test %s ... ", test.name.to_str())),
-          TeResult(copy test, result) => {
+          TeResult(test, result) => {
             match st.log_out {
                 Some(f) => write_log(f, copy result, &test),
                 None => ()
@@ -504,9 +504,8 @@ pub fn filter_tests(
     filtered = if opts.filter.is_none() {
         filtered
     } else {
-        let filter_str =
-            match opts.filter {
-          option::Some(copy f) => f,
+        let filter_str = match opts.filter {
+          option::Some(ref f) => copy *f,
           option::None => ~""
         };
 
@@ -866,7 +865,7 @@ mod tests {
     fn first_free_arg_should_be_a_filter() {
         let args = ~[~"progname", ~"filter"];
         let opts = match parse_opts(args) {
-          either::Left(copy o) => o,
+          either::Left(o) => o,
           _ => fail!("Malformed arg in first_free_arg_should_be_a_filter")
         };
         assert!("filter" == (copy opts.filter).get());
@@ -876,7 +875,7 @@ mod tests {
     fn parse_ignored_flag() {
         let args = ~[~"progname", ~"filter", ~"--ignored"];
         let opts = match parse_opts(args) {
-          either::Left(copy o) => o,
+          either::Left(o) => o,
           _ => fail!("Malformed arg in parse_ignored_flag")
         };
         assert!((opts.run_ignored));
diff --git a/src/libextra/time.rs b/src/libextra/time.rs
index e3289d01750..1a3a5db66ae 100644
--- a/src/libextra/time.rs
+++ b/src/libextra/time.rs
@@ -275,10 +275,12 @@ priv fn do_strptime(s: &str, format: &str) -> Result<Tm, ~str> {
         let mut i = 0u;
         let len = strs.len();
         while i < len {
-            let &(needle, value) = &strs[i];
-
-            if match_str(ss, pos, needle) {
-                return Some((value, pos + str::len(needle)));
+            match strs[i] { // can't use let due to stage0 bugs
+                (ref needle, value) => {
+                    if match_str(ss, pos, *needle) {
+                        return Some((value, pos + str::len(*needle)));
+                    }
+                }
             }
             i += 1u;
         }
@@ -1007,7 +1009,7 @@ mod tests {
             == Err(~"Invalid time"));
 
         match strptime("Fri Feb 13 15:31:30 2009", format) {
-          Err(copy e) => fail!(e),
+          Err(e) => fail!(e),
           Ok(ref tm) => {
             assert!(tm.tm_sec == 30_i32);
             assert!(tm.tm_min == 31_i32);
@@ -1027,7 +1029,7 @@ mod tests {
         fn test(s: &str, format: &str) -> bool {
             match strptime(s, format) {
               Ok(ref tm) => tm.strftime(format) == str::to_owned(s),
-              Err(copy e) => fail!(e)
+              Err(e) => fail!(e)
             }
         }
 
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 02c0b19e565..472ce5c926e 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -375,8 +375,8 @@ pub mod write {
 
     pub fn run_ndk(sess: Session, assembly: &Path, object: &Path) {
         let cc_prog: ~str = match &sess.opts.android_cross_path {
-            &Some(copy path) => {
-                fmt!("%s/bin/arm-linux-androideabi-gcc", path)
+            &Some(ref path) => {
+                fmt!("%s/bin/arm-linux-androideabi-gcc", *path)
             }
             &None => {
                 sess.fatal("need Android NDK path for building \
@@ -763,12 +763,12 @@ pub fn link_binary(sess: Session,
     // For win32, there is no cc command,
     // so we add a condition to make it use gcc.
     let cc_prog: ~str = match sess.opts.linker {
-        Some(copy linker) => linker,
+        Some(ref linker) => copy *linker,
         None => {
             if sess.targ_cfg.os == session::os_android {
                 match &sess.opts.android_cross_path {
-                    &Some(copy path) => {
-                        fmt!("%s/bin/arm-linux-androideabi-gcc", path)
+                    &Some(ref path) => {
+                        fmt!("%s/bin/arm-linux-androideabi-gcc", *path)
                     }
                     &None => {
                         sess.fatal("need Android NDK path for linking \
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index b56699927e4..5e33a8f78fe 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -956,8 +956,8 @@ mod test {
     fn test_switch_implies_cfg_test() {
         let matches =
             &match getopts([~"--test"], optgroups()) {
-              Ok(copy m) => m,
-              Err(copy f) => fail!("test_switch_implies_cfg_test: %s", getopts::fail_str(f))
+              Ok(m) => m,
+              Err(f) => fail!("test_switch_implies_cfg_test: %s", getopts::fail_str(f))
             };
         let sessopts = build_session_options(
             @~"rustc", matches, diagnostic::emit);
@@ -972,8 +972,8 @@ mod test {
     fn test_switch_implies_cfg_test_unless_cfg_test() {
         let matches =
             &match getopts([~"--test", ~"--cfg=test"], optgroups()) {
-              Ok(copy m) => m,
-              Err(copy f) => {
+              Ok(m) => m,
+              Err(f) => {
                 fail!("test_switch_implies_cfg_test_unless_cfg_test: %s", getopts::fail_str(f));
               }
             };
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 2c9b3c3a4ef..0e263c78bfe 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -141,10 +141,10 @@ fn visit_crate(e: @mut Env, c: &ast::crate) {
 
 fn visit_view_item(e: @mut Env, i: @ast::view_item) {
     match i.node {
-      ast::view_item_extern_mod(ident, /*bad*/copy meta_items, id) => {
+      ast::view_item_extern_mod(ident, ref meta_items, id) => {
         debug!("resolving extern mod stmt. ident: %?, meta: %?",
-               ident, meta_items);
-        let cnum = resolve_crate(e, ident, meta_items, @~"", i.span);
+               ident, *meta_items);
+        let cnum = resolve_crate(e, ident, copy *meta_items, @~"", i.span);
         cstore::add_extern_mod_stmt_cnum(e.cstore, id, cnum);
       }
       _ => ()
diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs
index c2ae364e54c..552476d25d6 100644
--- a/src/librustc/middle/borrowck/gather_loans/mod.rs
+++ b/src/librustc/middle/borrowck/gather_loans/mod.rs
@@ -623,7 +623,7 @@ pub impl GatherLoanCtxt {
                                              cmt, mutbl, scope_r);
                     }
                   }
-                  ast::bind_by_copy | ast::bind_infer => {
+                  ast::bind_infer => {
                       // No borrows here, but there may be moves
                       if self.bccx.is_move(pat.id) {
                           gather_moves::gather_move_from_pat(
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 58c5ce6f2b5..035d6a5cc45 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -827,7 +827,6 @@ pub fn check_legality_of_move_bindings(cx: @MatchCheckCtxt,
     for pats.each |pat| {
         do pat_bindings(def_map, *pat) |bm, id, span, _path| {
             match bm {
-                bind_by_copy => {}
                 bind_by_ref(_) => {
                     by_ref_span = Some(span);
                 }
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index 6315986d1a6..8493965049e 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -71,7 +71,6 @@ pub fn check_crate(tcx: ty::ctxt,
         current_item: -1
     };
     let visit = visit::mk_vt(@visit::Visitor {
-        visit_arm: check_arm,
         visit_expr: check_expr,
         visit_fn: check_fn,
         visit_ty: check_ty,
@@ -238,19 +237,6 @@ fn check_fn(
     visit::visit_fn(fk, decl, body, sp, fn_id, cx, v);
 }
 
-fn check_arm(a: &arm, cx: Context, v: visit::vt<Context>) {
-    for a.pats.each |p| {
-        do pat_util::pat_bindings(cx.tcx.def_map, *p) |mode, id, span, _pth| {
-            if mode == bind_by_copy {
-                let t = ty::node_id_to_type(cx.tcx, id);
-                let reason = "consider binding with `ref` or `move` instead";
-                check_copy(cx, t, span, reason);
-            }
-        }
-    }
-    visit::visit_arm(a, cx, v);
-}
-
 pub fn check_expr(e: @expr, cx: Context, v: visit::vt<Context>) {
     debug!("kind::check_expr(%s)", expr_to_str(e, cx.tcx.sess.intr()));
 
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index c58ebcd1ee4..d2f6d652773 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -576,14 +576,18 @@ pub impl VisitContext {
 
         do pat_bindings(self.tcx.def_map, pat) |bm, id, _span, _path| {
             let binding_moves = match bm {
-                bind_by_copy => false,
                 bind_by_ref(_) => false,
                 bind_infer => {
                     let pat_ty = ty::node_id_to_type(self.tcx, id);
+                    debug!("pattern %? type is %s",
+                           id, pat_ty.repr(self.tcx));
                     ty::type_moves_by_default(self.tcx, pat_ty)
                 }
             };
 
+            debug!("pattern binding %?: bm=%?, binding_moves=%b",
+                   id, bm, binding_moves);
+
             if binding_moves {
                 self.move_maps.moves_map.insert(id);
             }
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index fa17fa04ed8..23645f7f04a 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -520,12 +520,12 @@ pub impl NameBindings {
                     type_span: Some(sp)
                 });
             }
-            Some(copy type_def) => {
+            Some(type_def) => {
                 self.type_def = Some(TypeNsDef {
                     privacy: privacy,
                     module_def: Some(module_),
                     type_span: Some(sp),
-                    .. type_def
+                    type_def: type_def.type_def
                 });
             }
         }
@@ -577,12 +577,12 @@ pub impl NameBindings {
                     type_span: Some(sp)
                 });
             }
-            Some(copy type_def) => {
+            Some(type_def) => {
                 self.type_def = Some(TypeNsDef {
                     privacy: privacy,
                     type_def: Some(def),
                     type_span: Some(sp),
-                    .. type_def
+                    module_def: type_def.module_def
                 });
             }
         }
@@ -1566,7 +1566,7 @@ pub impl Resolver {
         match def {
           def_mod(def_id) | def_foreign_mod(def_id) => {
             match child_name_bindings.type_def {
-              Some(TypeNsDef { module_def: Some(copy module_def), _ }) => {
+              Some(TypeNsDef { module_def: Some(module_def), _ }) => {
                 debug!("(building reduced graph for external crate) \
                         already created module");
                 module_def.def_id = Some(def_id);
@@ -1745,7 +1745,7 @@ pub impl Resolver {
                                                           NormalModuleKind,
                                                           dummy_sp());
                     }
-                    Some(copy type_ns_def)
+                    Some(type_ns_def)
                             if type_ns_def.module_def.is_none() => {
                         debug!("(building reduced graph for external crate) \
                                 autovivifying missing module def %s",
@@ -1812,7 +1812,7 @@ pub impl Resolver {
                                     let type_module;
                                     match child_name_bindings.type_def {
                                         Some(TypeNsDef {
-                                            module_def: Some(copy module_def),
+                                            module_def: Some(module_def),
                                             _
                                         }) => {
                                             // We already have a module. This
@@ -2445,7 +2445,7 @@ pub impl Resolver {
                         None => {
                             // Continue.
                         }
-                        Some(copy value_target) => {
+                        Some(value_target) => {
                             dest_import_resolution.value_target =
                                 Some(value_target);
                         }
@@ -2454,7 +2454,7 @@ pub impl Resolver {
                         None => {
                             // Continue.
                         }
-                        Some(copy type_target) => {
+                        Some(type_target) => {
                             dest_import_resolution.type_target =
                                 Some(type_target);
                         }
@@ -2566,7 +2566,7 @@ pub impl Resolver {
                     // Check to see whether there are type bindings, and, if
                     // so, whether there is a module within.
                     match target.bindings.type_def {
-                        Some(copy type_def) => {
+                        Some(type_def) => {
                             match type_def.module_def {
                                 None => {
                                     // Not a module.
@@ -5170,12 +5170,6 @@ pub impl Resolver {
                                     descr: &str) {
         match pat_binding_mode {
             bind_infer => {}
-            bind_by_copy => {
-                self.session.span_err(
-                    pat.span,
-                    fmt!("cannot use `copy` binding mode with %s",
-                         descr));
-            }
             bind_by_ref(*) => {
                 self.session.span_err(
                     pat.span,
@@ -5316,7 +5310,7 @@ pub fn resolve_crate(session: Session,
                   -> CrateMap {
     let resolver = @mut Resolver(session, lang_items, crate);
     resolver.resolve();
-    let @Resolver{def_map, export_map2, trait_map, _} = resolver;
+    let Resolver{def_map, export_map2, trait_map, _} = copy *resolver;
     CrateMap {
         def_map: def_map,
         exp_map2: export_map2,
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index ca7ce9c02d1..b142dc1ef28 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -140,6 +140,11 @@
  * the various values we copied explicitly.  Note that guards and moves are
  * just plain incompatible.
  *
+ * Some relevant helper functions that manage bindings:
+ * - `create_bindings_map()`
+ * - `store_non_ref_bindings()`
+ * - `insert_lllocals()`
+ *
  */
 
 use core::prelude::*;
@@ -314,7 +319,6 @@ pub fn variant_opt(bcx: block, pat_id: ast::node_id)
 pub enum TransBindingMode {
     TrByValue(/*ismove:*/ bool, /*llbinding:*/ ValueRef),
     TrByRef,
-    TrByImplicitRef
 }
 
 /**
@@ -670,8 +674,8 @@ pub fn enter_tup<'r>(bcx: block,
     let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
     do enter_match(bcx, dm, m, col, val) |p| {
         match p.node {
-            ast::pat_tup(/*bad*/copy elts) => {
-                Some(elts)
+            ast::pat_tup(ref elts) => {
+                Some(copy *elts)
             }
             _ => {
                 assert_is_binding_or_wild(bcx, p);
@@ -698,7 +702,7 @@ pub fn enter_tuple_struct<'r>(bcx: block,
     let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
     do enter_match(bcx, dm, m, col, val) |p| {
         match p.node {
-            ast::pat_enum(_, Some(/*bad*/copy elts)) => Some(elts),
+            ast::pat_enum(_, Some(ref elts)) => Some(copy *elts),
             _ => {
                 assert_is_binding_or_wild(bcx, p);
                 Some(vec::from_elem(n_elts, dummy))
@@ -881,7 +885,7 @@ fn match_datum(bcx: block, val: ValueRef, pat_id: ast::node_id) -> Datum {
     //! we should just pass around a Datum and be done with it.
 
     let ty = node_id_type(bcx, pat_id);
-    Datum {val: val, ty: ty, mode: datum::ByRef, source: RevokeClean}
+    Datum {val: val, ty: ty, mode: datum::ByRef(RevokeClean)}
 }
 
 
@@ -988,7 +992,7 @@ pub fn root_pats_as_necessary(mut bcx: block,
         let pat_id = br.pats[col].id;
         if pat_id != 0 {
             let datum = Datum {val: val, ty: node_id_type(bcx, pat_id),
-                               mode: ByRef, source: ZeroMem};
+                               mode: ByRef(ZeroMem)};
             bcx = datum.root_and_write_guard(bcx, br.pats[col].span, pat_id, 0);
         }
     }
@@ -1125,10 +1129,10 @@ pub fn compare_values(cx: block,
     }
 }
 
-pub fn store_non_ref_bindings(bcx: block,
-                              data: &ArmData,
-                              opt_temp_cleanups: Option<&mut ~[ValueRef]>)
-    -> block
+fn store_non_ref_bindings(bcx: block,
+                          bindings_map: &BindingsMap,
+                          mut opt_temp_cleanups: Option<&mut ~[ValueRef]>)
+                          -> block
 {
     /*!
      *
@@ -1140,13 +1144,12 @@ pub fn store_non_ref_bindings(bcx: block,
      */
 
     let mut bcx = bcx;
-    let mut opt_temp_cleanups = opt_temp_cleanups;
-    for data.bindings_map.each_value |&binding_info| {
+    for bindings_map.each_value |&binding_info| {
         match binding_info.trmode {
             TrByValue(is_move, lldest) => {
                 let llval = Load(bcx, binding_info.llmatch); // get a T*
                 let datum = Datum {val: llval, ty: binding_info.ty,
-                                   mode: ByRef, source: ZeroMem};
+                                   mode: ByRef(ZeroMem)};
                 bcx = {
                     if is_move {
                         datum.move_to(bcx, INIT, lldest)
@@ -1161,22 +1164,28 @@ pub fn store_non_ref_bindings(bcx: block,
                     temp_cleanups
                 }
             }
-            TrByRef | TrByImplicitRef => {}
+            TrByRef => {}
         }
     }
     return bcx;
 }
 
-pub fn insert_lllocals(bcx: block,
-                       data: &ArmData,
-                       add_cleans: bool) -> block {
+fn insert_lllocals(bcx: block,
+                   bindings_map: &BindingsMap,
+                   binding_mode: IrrefutablePatternBindingMode,
+                   add_cleans: bool) -> block {
     /*!
-     *
      * For each binding in `data.bindings_map`, adds an appropriate entry into
      * the `fcx.lllocals` map.  If add_cleans is true, then adds cleanups for
-     * the bindings. */
+     * the bindings.
+     */
 
-    for data.bindings_map.each_value |&binding_info| {
+    let llmap = match binding_mode {
+        BindLocal => bcx.fcx.lllocals,
+        BindArgument => bcx.fcx.llargs
+    };
+
+    for bindings_map.each_value |&binding_info| {
         let llval = match binding_info.trmode {
             // By value bindings: use the stack slot that we
             // copied/moved the value into
@@ -1192,17 +1201,12 @@ pub fn insert_lllocals(bcx: block,
             TrByRef => {
                 binding_info.llmatch
             }
-
-            // Ugly: for implicit ref, we actually want a T*, but
-            // we have a T**, so we had to load.  This will go away
-            // once implicit refs go away.
-            TrByImplicitRef => {
-                Load(bcx, binding_info.llmatch)
-            }
         };
 
-        bcx.fcx.lllocals.insert(binding_info.id,
-                                local_mem(llval));
+        debug!("binding %? to %s",
+               binding_info.id,
+               val_str(bcx.ccx().tn, llval));
+        llmap.insert(binding_info.id, llval);
     }
     return bcx;
 }
@@ -1223,8 +1227,8 @@ pub fn compile_guard(bcx: block,
 
     let mut bcx = bcx;
     let mut temp_cleanups = ~[];
-    bcx = store_non_ref_bindings(bcx, data, Some(&mut temp_cleanups));
-    bcx = insert_lllocals(bcx, data, false);
+    bcx = store_non_ref_bindings(bcx, &data.bindings_map, Some(&mut temp_cleanups));
+    bcx = insert_lllocals(bcx, &data.bindings_map, BindLocal, false);
 
     let val = unpack_result!(bcx, {
         do with_scope_result(bcx, guard_expr.info(),
@@ -1254,7 +1258,7 @@ pub fn compile_guard(bcx: block,
                 TrByValue(_, llval) => {
                     bcx = glue::drop_ty(bcx, llval, binding_info.ty);
                 }
-                TrByRef | TrByImplicitRef => {}
+                TrByRef => {}
             }
             bcx.fcx.lllocals.remove(&binding_info.id);
         }
@@ -1621,6 +1625,42 @@ pub fn trans_match(bcx: block,
     }
 }
 
+fn create_bindings_map(bcx: block, pat: @ast::pat) -> BindingsMap {
+    // Create the bindings map, which is a mapping from each binding name
+    // to an alloca() that will be the value for that local variable.
+    // Note that we use the names because each binding will have many ids
+    // from the various alternatives.
+    let ccx = bcx.ccx();
+    let tcx = bcx.tcx();
+    let mut bindings_map = HashMap::new();
+    do pat_bindings(tcx.def_map, pat) |bm, p_id, _s, path| {
+        let ident = path_to_ident(path);
+        let variable_ty = node_id_type(bcx, p_id);
+        let llvariable_ty = type_of::type_of(ccx, variable_ty);
+
+        let llmatch, trmode;
+        match bm {
+            ast::bind_infer => {
+                // in this case, the final type of the variable will be T,
+                // but during matching we need to store a *T as explained
+                // above
+                let is_move = ccx.maps.moves_map.contains(&p_id);
+                llmatch = alloca(bcx, T_ptr(llvariable_ty));
+                trmode = TrByValue(is_move, alloca(bcx, llvariable_ty));
+            }
+            ast::bind_by_ref(_) => {
+                llmatch = alloca(bcx, llvariable_ty);
+                trmode = TrByRef;
+            }
+        };
+        bindings_map.insert(ident, BindingInfo {
+            llmatch: llmatch, trmode: trmode,
+            id: p_id, ty: variable_ty
+        });
+    }
+    return bindings_map;
+}
+
 pub fn trans_match_inner(scope_cx: block,
                          discr_expr: @ast::expr,
                          arms: &[ast::arm],
@@ -1637,41 +1677,9 @@ pub fn trans_match_inner(scope_cx: block,
     }
 
     let mut arm_datas = ~[], matches = ~[];
-    for arms.each |arm| {
+    for vec::each(arms) |arm| {
         let body = scope_block(bcx, arm.body.info(), "case_body");
-
-        // Create the bindings map, which is a mapping from each binding name
-        // to an alloca() that will be the value for that local variable.
-        // Note that we use the names because each binding will have many ids
-        // from the various alternatives.
-        let mut bindings_map = HashMap::new();
-        do pat_bindings(tcx.def_map, arm.pats[0]) |bm, p_id, _s, path| {
-            let ident = path_to_ident(path);
-            let variable_ty = node_id_type(bcx, p_id);
-            let llvariable_ty = type_of::type_of(bcx.ccx(), variable_ty);
-
-            let llmatch, trmode;
-            match bm {
-                ast::bind_by_copy | ast::bind_infer => {
-                    // in this case, the final type of the variable will be T,
-                    // but during matching we need to store a *T as explained
-                    // above
-                    let is_move =
-                        scope_cx.ccx().maps.moves_map.contains(&p_id);
-                    llmatch = alloca(bcx, T_ptr(llvariable_ty));
-                    trmode = TrByValue(is_move, alloca(bcx, llvariable_ty));
-                }
-                ast::bind_by_ref(_) => {
-                    llmatch = alloca(bcx, llvariable_ty);
-                    trmode = TrByRef;
-                }
-            };
-            bindings_map.insert(ident, BindingInfo {
-                llmatch: llmatch, trmode: trmode,
-                id: p_id, ty: variable_ty
-            });
-        }
-
+        let bindings_map = create_bindings_map(bcx, arm.pats[0]);
         let arm_data = @ArmData {bodycx: body,
                                  arm: arm,
                                  bindings_map: bindings_map};
@@ -1693,7 +1701,7 @@ pub fn trans_match_inner(scope_cx: block,
             None
         }
     };
-    let lldiscr = discr_datum.to_ref_llval(bcx);
+    let lldiscr = discr_datum.to_zeroable_ref_llval(bcx);
     compile_submatch(bcx, matches, [lldiscr], chk);
 
     let mut arm_cxs = ~[];
@@ -1705,11 +1713,11 @@ pub fn trans_match_inner(scope_cx: block,
         // is just to reduce code space.  See extensive comment at the start
         // of the file for more details.
         if arm_data.arm.guard.is_none() {
-            bcx = store_non_ref_bindings(bcx, *arm_data, None);
+            bcx = store_non_ref_bindings(bcx, &arm_data.bindings_map, None);
         }
 
         // insert bindings into the lllocals map and add cleanups
-        bcx = insert_lllocals(bcx, *arm_data, true);
+        bcx = insert_lllocals(bcx, &arm_data.bindings_map, BindLocal, true);
 
         bcx = controlflow::trans_block(bcx, &arm_data.arm.body, dest);
         bcx = trans_block_cleanups(bcx, block_cleanups(arm_data.bodycx));
@@ -1757,27 +1765,25 @@ pub fn bind_irrefutable_pat(bcx: block,
             if make_copy {
                 let binding_ty = node_id_type(bcx, pat.id);
                 let datum = Datum {val: val, ty: binding_ty,
-                                   mode: ByRef, source: RevokeClean};
+                                   mode: ByRef(RevokeClean)};
                 let scratch = scratch_datum(bcx, binding_ty, false);
                 datum.copy_to_datum(bcx, INIT, scratch);
                 match binding_mode {
                     BindLocal => {
-                        bcx.fcx.lllocals.insert(pat.id,
-                                                local_mem(scratch.val));
+                        bcx.fcx.lllocals.insert(pat.id, scratch.val);
                     }
                     BindArgument => {
-                        bcx.fcx.llargs.insert(pat.id,
-                                              local_mem(scratch.val));
+                        bcx.fcx.llargs.insert(pat.id, scratch.val);
                     }
                 }
                 add_clean(bcx, scratch.val, binding_ty);
             } else {
                 match binding_mode {
                     BindLocal => {
-                        bcx.fcx.lllocals.insert(pat.id, local_mem(val));
+                        bcx.fcx.lllocals.insert(pat.id, val);
                     }
                     BindArgument => {
-                        bcx.fcx.llargs.insert(pat.id, local_mem(val));
+                        bcx.fcx.llargs.insert(pat.id, val);
                     }
                 }
             }
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 6a49ae4cbc6..539dc3e1f00 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -1105,8 +1105,8 @@ pub fn init_local(bcx: block, local: @ast::local) -> block {
         }
     }
 
-    let llptr = match bcx.fcx.lllocals.find(&local.node.id) {
-        Some(&local_mem(v)) => v,
+    let llptr = match bcx.fcx.lllocals.find_copy(&local.node.id) {
+        Some(v) => v,
         _ => {
             bcx.tcx().sess.span_bug(local.span,
                                     "init_local: Someone forgot to document why it's\
@@ -1432,7 +1432,7 @@ pub fn alloc_local(cx: block, local: @ast::local) -> block {
             });
         }
     }
-    cx.fcx.lllocals.insert(local.node.id, local_mem(val));
+    cx.fcx.lllocals.insert(local.node.id, val);
     cx
 }
 
@@ -1726,7 +1726,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
     let mut bcx = bcx;
 
     match fcx.llself {
-      Some(copy slf) => {
+      Some(slf) => {
         // We really should do this regardless of whether self is owned, but
         // it doesn't work right with default method impls yet. (FIXME: #2794)
         if slf.is_owned {
@@ -1768,7 +1768,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
                                           false,
                                           _match::BindArgument);
 
-        fcx.llargs.insert(arg_id, local_mem(llarg));
+        fcx.llargs.insert(arg_id, llarg);
 
         if fcx.ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) {
             debuginfo::create_arg(bcx, args[arg_n], args[arg_n].ty.span);
@@ -1801,7 +1801,7 @@ pub fn build_return_block(fcx: fn_ctxt) {
 pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
     let _icx = fcx.insn_ctxt("tie_up_header_blocks");
     match fcx.llloadenv {
-        Some(copy ll) => {
+        Some(ll) => {
             Br(raw_block(fcx, false, fcx.llstaticallocas), ll);
             Br(raw_block(fcx, false, ll), lltop);
         }
@@ -2004,7 +2004,7 @@ pub fn trans_enum_variant(ccx: @CrateContext,
         // this function as an opaque blob due to the way that type_of()
         // works. So we have to cast to the destination's view of the type.
         let llarg = match fcx.llargs.find(&va.id) {
-            Some(&local_mem(x)) => x,
+            Some(&x) => x,
             _ => fail!("trans_enum_variant: how do we know this works?"),
         };
         let arg_ty = arg_tys[i];
@@ -2074,12 +2074,7 @@ pub fn trans_tuple_struct(ccx: @CrateContext,
                                              fcx.llretptr.get(),
                                              0,
                                              i);
-        let llarg = match fcx.llargs.get_copy(&field.node.id) {
-            local_mem(x) => x,
-            _ => {
-                ccx.tcx.sess.bug("trans_tuple_struct: llarg wasn't local_mem")
-            }
-        };
+        let llarg = fcx.llargs.get_copy(&field.node.id);
         let arg_ty = arg_tys[i];
         memcpy_ty(bcx, lldestptr, llarg, arg_ty);
     }
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 1e6e31e4277..557388cf11c 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -711,8 +711,7 @@ pub fn trans_arg_expr(bcx: block,
                     DatumBlock {bcx: bcx,
                                 datum: Datum {val: scratch,
                                               ty: scratch_ty,
-                                              mode: ByRef,
-                                              source: RevokeClean}}
+                                              mode: ByRef(RevokeClean)}}
                 }
                 _ => {
                     bcx.sess().impossible_case(
@@ -775,7 +774,7 @@ pub fn trans_arg_expr(bcx: block,
 
                         match arg_datum.appropriate_mode() {
                             ByValue => val = Load(bcx, scratch.val),
-                            ByRef => val = scratch.val,
+                            ByRef(_) => val = scratch.val,
                         }
                     }
                 }
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index fa3e6eeb0b6..1a78019f289 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -287,7 +287,7 @@ pub fn build_closure(bcx0: block,
     for include_ret_handle.each |flagptr| {
         // Flag indicating we have returned (a by-ref bool):
         let flag_datum = Datum {val: *flagptr, ty: ty::mk_bool(),
-                                mode: ByRef, source: ZeroMem};
+                                mode: ByRef(ZeroMem)};
         env_vals.push(EnvValue {action: EnvRef,
                                 datum: flag_datum});
 
@@ -299,7 +299,7 @@ pub fn build_closure(bcx0: block,
         };
         let ret_casted = PointerCast(bcx, ret_true, T_ptr(T_nil()));
         let ret_datum = Datum {val: ret_casted, ty: ty::mk_nil(),
-                               mode: ByRef, source: ZeroMem};
+                               mode: ByRef(ZeroMem)};
         env_vals.push(EnvValue {action: EnvRef,
                                 datum: ret_datum});
     }
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index d148dbd2183..a2fa840ad79 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -240,8 +240,6 @@ pub struct ValSelfData {
     is_owned: bool
 }
 
-pub enum local_val { local_mem(ValueRef), local_imm(ValueRef), }
-
 // Here `self_ty` is the real type of the self parameter to this method. It
 // will only be set in the case of default methods.
 pub struct param_substs {
@@ -328,10 +326,10 @@ pub struct fn_ctxt_ {
     has_immediate_return_value: bool,
 
     // Maps arguments to allocas created for them in llallocas.
-    llargs: @mut HashMap<ast::node_id, local_val>,
+    llargs: @mut HashMap<ast::node_id, ValueRef>,
     // Maps the def_ids for local variables to the allocas created for
     // them in llallocas.
-    lllocals: @mut HashMap<ast::node_id, local_val>,
+    lllocals: @mut HashMap<ast::node_id, ValueRef>,
     // Same as above, but for closure upvars
     llupvars: @mut HashMap<ast::node_id, ValueRef>,
 
diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs
index c8b9e3f8f0e..c0403083ce1 100644
--- a/src/librustc/middle/trans/datum.rs
+++ b/src/librustc/middle/trans/datum.rs
@@ -44,15 +44,17 @@
  * # Datum cleanup styles
  *
  * Each datum carries with it an idea of how its value will be cleaned
- * up.  This is important after a move, because we need to know how to
- * cancel the cleanup (since the value has been moved and therefore does
- * not need to be freed).  There are two options:
- *
- * 1. `RevokeClean`: To cancel the cleanup, we invoke `revoke_clean()`.
- *    This is used for temporary rvalues.
- *
- * 2. `ZeroMem`: To cancel the cleanup, we zero out the memory where
- *    the value resides.  This is used for lvalues.
+ * up.  This is primarily determined by the mode: a `ByValue` datum
+ * will always be cleaned up by revoking cleanup using
+ * `revoke_clean()`, because there is no other option. By ref datums
+ * can sometimes be cleaned up via `revoke_clean` (in particular,
+ * by-ref datums that originated from rvalues), but sometimes they
+ * must be zeroed. This is indicated by the `DatumCleanup`
+ * parameter. Note that zeroing a by-ref datum *always works* to
+ * cancel the cleanup, but using `revoke_clean` is preferable since
+ * there is no runtime cost. Some older parts of the code (notably
+ * `match_`, at least at the time of this writing) rely on this and
+ * only use zeroing.
  *
  * # Copying, moving, and storing
  *
@@ -103,7 +105,6 @@ use middle::ty;
 use util::common::indenter;
 use util::ppaux::ty_to_str;
 
-use core::to_bytes;
 use core::uint;
 use syntax::ast;
 use syntax::codemap::span;
@@ -125,12 +126,6 @@ pub struct Datum {
 
     /// Indicates whether this is by-ref or by-value.
     mode: DatumMode,
-
-    /// How did this value originate?  This is particularly important
-    /// if the value is MOVED or prematurely DROPPED, because it
-    /// describes how to cancel the cleanup that was scheduled before.
-    /// See the def'n of the `DatumCleanup` type.
-    source: DatumCleanup
 }
 
 pub struct DatumBlock {
@@ -138,10 +133,13 @@ pub struct DatumBlock {
     datum: Datum,
 }
 
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub enum DatumMode {
-    /// `val` is a pointer to the actual value (and thus has type *T)
-    ByRef,
+    /// `val` is a pointer to the actual value (and thus has type *T).
+    /// The argument indicates how to cancel cleanup of this datum if
+    /// the value is moved elsewhere, which can either be by zeroing
+    /// the memory or by canceling a registered cleanup.
+    ByRef(DatumCleanup),
 
     /// `val` is the actual value (*only used for immediates* like ints, ptrs)
     ByValue,
@@ -149,30 +147,23 @@ pub enum DatumMode {
 
 pub impl DatumMode {
     fn is_by_ref(&self) -> bool {
-        match *self { ByRef => true, ByValue => false }
+        match *self { ByRef(_) => true, ByValue => false }
     }
 
     fn is_by_value(&self) -> bool {
-        match *self { ByRef => false, ByValue => true }
-    }
-}
-
-impl to_bytes::IterBytes for DatumMode {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as uint).iter_bytes(lsb0, f)
+        match *self { ByRef(_) => false, ByValue => true }
     }
 }
 
 /// See `Datum cleanup styles` section at the head of this module.
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub enum DatumCleanup {
     RevokeClean,
     ZeroMem
 }
 
 pub fn immediate_rvalue(val: ValueRef, ty: ty::t) -> Datum {
-    return Datum {val: val, ty: ty,
-                  mode: ByValue, source: RevokeClean};
+    return Datum {val: val, ty: ty, mode: ByValue};
 }
 
 pub fn immediate_rvalue_bcx(bcx: block,
@@ -195,7 +186,7 @@ pub fn scratch_datum(bcx: block, ty: ty::t, zero: bool) -> Datum {
 
     let llty = type_of::type_of(bcx.ccx(), ty);
     let scratch = alloca_maybe_zeroed(bcx, llty, zero);
-    Datum { val: scratch, ty: ty, mode: ByRef, source: RevokeClean }
+    Datum { val: scratch, ty: ty, mode: ByRef(RevokeClean) }
 }
 
 pub fn appropriate_mode(ty: ty::t) -> DatumMode {
@@ -210,7 +201,7 @@ pub fn appropriate_mode(ty: ty::t) -> DatumMode {
     } else if ty::type_is_immediate(ty) {
         ByValue
     } else {
-        ByRef
+        ByRef(RevokeClean)
     }
 }
 
@@ -289,7 +280,7 @@ pub impl Datum {
             ty::type_needs_drop(bcx.tcx(), self.ty)
         {
             match self.mode {
-                ByRef => {
+                ByRef(_) => {
                     let cast = PointerCast(bcx, dst, val_ty(self.val));
                     let cmp = ICmp(bcx, lib::llvm::IntNE, cast, self.val);
                     do with_cond(bcx, cmp) |bcx| {
@@ -324,7 +315,7 @@ pub impl Datum {
             ByValue => {
                 Store(bcx, self.val, dst);
             }
-            ByRef => {
+            ByRef(_) => {
                 memcpy_ty(bcx, dst, self.val, self.ty);
             }
         }
@@ -352,7 +343,7 @@ pub impl Datum {
         }
 
         match self.mode {
-            ByRef => {
+            ByRef(_) => {
                 memcpy_ty(bcx, dst, self.val, self.ty);
             }
             ByValue => {
@@ -367,28 +358,32 @@ pub impl Datum {
 
     fn add_clean(&self, bcx: block) {
         /*!
-         *
          * Schedules this datum for cleanup in `bcx`.  The datum
-         * must be an rvalue. */
+         * must be an rvalue.
+         */
 
-        assert_eq!(self.source, RevokeClean);
         match self.mode {
             ByValue => {
                 add_clean_temp_immediate(bcx, self.val, self.ty);
             }
-            ByRef => {
+            ByRef(RevokeClean) => {
                 add_clean_temp_mem(bcx, self.val, self.ty);
             }
+            ByRef(ZeroMem) => {
+                bcx.tcx().sess.bug(
+                    fmt!("Cannot add clean to a 'zero-mem' datum"));
+            }
         }
     }
 
     fn cancel_clean(&self, bcx: block) {
         if ty::type_needs_drop(bcx.tcx(), self.ty) {
-            match self.source {
-                RevokeClean => {
+            match self.mode {
+                ByValue |
+                ByRef(RevokeClean) => {
                     revoke_clean(bcx, self.val);
                 }
-                ZeroMem => {
+                ByRef(ZeroMem) => {
                     // Lvalues which potentially need to be dropped
                     // must be passed by ref, so that we can zero them
                     // out.
@@ -400,11 +395,10 @@ pub impl Datum {
     }
 
     fn to_str(&self, ccx: &CrateContext) -> ~str {
-        fmt!("Datum { val=%s, ty=%s, mode=%?, source=%? }",
+        fmt!("Datum { val=%s, ty=%s, mode=%? }",
              val_str(ccx.tn, self.val),
              ty_to_str(ccx.tcx, self.ty),
-             self.mode,
-             self.source)
+             self.mode)
     }
 
     fn to_value_datum(&self, bcx: block) -> Datum {
@@ -417,9 +411,9 @@ pub impl Datum {
 
         match self.mode {
             ByValue => *self,
-            ByRef => {
+            ByRef(_) => {
                 Datum {val: self.to_value_llval(bcx), mode: ByValue,
-                       ty: self.ty, source: RevokeClean}
+                       ty: self.ty}
             }
         }
     }
@@ -434,7 +428,7 @@ pub impl Datum {
         } else {
             match self.mode {
                 ByValue => self.val,
-                ByRef => {
+                ByRef(_) => {
                     if ty::type_is_bool(self.ty) {
                         LoadRangeAssert(bcx, self.val, 0, 2, lib::llvm::True)
                     } else {
@@ -447,24 +441,24 @@ pub impl Datum {
 
     fn to_ref_datum(&self, bcx: block) -> Datum {
         /*!
-         *
          * Yields a by-ref form of this datum.  This may involve
          * creation of a temporary stack slot.  The value returned by
          * this function is not separately rooted from this datum, so
-         * it will not live longer than the current datum. */
+         * it will not live longer than the current datum.
+         */
 
         match self.mode {
-            ByRef => *self,
+            ByRef(_) => *self,
             ByValue => {
-                Datum {val: self.to_ref_llval(bcx), mode: ByRef,
-                       ty: self.ty, source: RevokeClean}
+                Datum {val: self.to_ref_llval(bcx), mode: ByRef(RevokeClean),
+                       ty: self.ty}
             }
         }
     }
 
     fn to_ref_llval(&self, bcx: block) -> ValueRef {
         match self.mode {
-            ByRef => self.val,
+            ByRef(_) => self.val,
             ByValue => {
                 if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) {
                     C_null(T_ptr(type_of::type_of(bcx.ccx(), self.ty)))
@@ -477,6 +471,31 @@ pub impl Datum {
         }
     }
 
+    fn to_zeroable_ref_llval(&self, bcx: block) -> ValueRef {
+        /*!
+         * Returns a by-ref llvalue that can be zeroed in order to
+         * cancel cleanup. This is a kind of hokey bridge used
+         * to adapt to the match code. Please don't use it for new code.
+         */
+
+        match self.mode {
+            // All by-ref datums are zeroable, even if we *could* just
+            // cancel the cleanup.
+            ByRef(_) => self.val,
+
+            // By value datums can't be zeroed (where would you store
+            // the zero?) so we have to spill them. Add a temp cleanup
+            // for this spilled value and cancel the cleanup on this
+            // current value.
+            ByValue => {
+                let slot = self.to_ref_llval(bcx);
+                self.cancel_clean(bcx);
+                add_clean_temp_mem(bcx, slot, self.ty);
+                slot
+            }
+        }
+    }
+
     fn appropriate_mode(&self) -> DatumMode {
         /*! See the `appropriate_mode()` function */
 
@@ -490,7 +509,7 @@ pub impl Datum {
 
         match self.appropriate_mode() {
             ByValue => self.to_value_llval(bcx),
-            ByRef => self.to_ref_llval(bcx)
+            ByRef(_) => self.to_ref_llval(bcx)
         }
     }
 
@@ -501,7 +520,7 @@ pub impl Datum {
 
         match self.appropriate_mode() {
             ByValue => self.to_value_datum(bcx),
-            ByRef => self.to_ref_datum(bcx)
+            ByRef(_) => self.to_ref_datum(bcx)
         }
     }
 
@@ -512,9 +531,8 @@ pub impl Datum {
         let base_val = self.to_ref_llval(bcx);
         Datum {
             val: gep(base_val),
-            mode: ByRef,
+            mode: ByRef(source),
             ty: ty,
-            source: source
         }
     }
 
@@ -524,7 +542,7 @@ pub impl Datum {
         }
 
         return match self.mode {
-            ByRef => glue::drop_ty(bcx, self.val, self.ty),
+            ByRef(_) => glue::drop_ty(bcx, self.val, self.ty),
             ByValue => glue::drop_ty_immediate(bcx, self.val, self.ty)
         };
     }
@@ -546,7 +564,7 @@ pub impl Datum {
 
         let ptr = self.to_value_llval(bcx);
         let body = opaque_box_body(bcx, content_ty, ptr);
-        Datum {val: body, ty: content_ty, mode: ByRef, source: ZeroMem}
+        Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)}
     }
 
     fn to_rptr(&self, bcx: block) -> Datum {
@@ -561,8 +579,7 @@ pub impl Datum {
         let llval = self.to_ref_llval(bcx);
         let rptr_ty = ty::mk_imm_rptr(bcx.tcx(), ty::re_static,
                                       self.ty);
-        Datum {val: llval, ty: rptr_ty,
-               mode: ByValue, source: RevokeClean}
+        Datum {val: llval, ty: rptr_ty, mode: ByValue}
     }
 
     fn try_deref(&self,
@@ -606,7 +623,7 @@ pub impl Datum {
                 let repr = adt::represent_type(ccx, self.ty);
                 let ty = ty::subst(ccx.tcx, substs, variants[0].args[0]);
                 return match self.mode {
-                    ByRef => {
+                    ByRef(_) => {
                         // Recast lv.val as a pointer to the newtype
                         // rather than a ptr to the enum type.
                         (
@@ -614,8 +631,7 @@ pub impl Datum {
                                 val: adt::trans_field_ptr(bcx, repr, self.val,
                                                     0, 0),
                                 ty: ty,
-                                mode: ByRef,
-                                source: ZeroMem
+                                mode: ByRef(ZeroMem)
                             }),
                             bcx
                         )
@@ -645,7 +661,7 @@ pub impl Datum {
                 let repr = adt::represent_type(ccx, self.ty);
                 let ty = fields[0].mt.ty;
                 return match self.mode {
-                    ByRef => {
+                    ByRef(_) => {
                         // Recast lv.val as a pointer to the newtype rather
                         // than a pointer to the struct type.
                         // FIXME #6572: This isn't correct for structs with
@@ -655,8 +671,7 @@ pub impl Datum {
                                 val: adt::trans_field_ptr(bcx, repr, self.val,
                                                     0, 0),
                                 ty: ty,
-                                mode: ByRef,
-                                source: ZeroMem
+                                mode: ByRef(ZeroMem)
                             }),
                             bcx
                         )
@@ -683,8 +698,7 @@ pub impl Datum {
             Datum {
                 val: lv.to_value_llval(bcx),
                 ty: ty,
-                mode: ByRef,
-                source: ZeroMem // *p is an lvalue
+                mode: ByRef(ZeroMem)
             }
         }
     }
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index c1661b80cf8..6d78e8e0379 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -864,17 +864,14 @@ pub fn create_local_var(bcx: block, local: @ast::local)
     };
     update_cache(cache, AutoVariableTag, local_var_metadata(mdval));
 
-    let llptr = match bcx.fcx.lllocals.find(&local.node.id) {
-      option::Some(&local_mem(v)) => v,
-      option::Some(_) => {
-        bcx.tcx().sess.span_bug(local.span, "local is bound to something weird");
-      }
-      option::None => {
-        match bcx.fcx.lllocals.get_copy(&local.node.pat.id) {
-          local_imm(v) => v,
-          _ => bcx.tcx().sess.span_bug(local.span, "local is bound to something weird")
+    // FIXME(#6814) Should use `pat_util::pat_bindings` for pats like (a, b) etc
+    let llptr = match bcx.fcx.lllocals.find_copy(&local.node.pat.id) {
+        Some(v) => v,
+        None => {
+            bcx.tcx().sess.span_bug(
+                local.span,
+                fmt!("No entry in lllocals table for %?", local.node.id));
         }
-      }
     };
     let declargs = ~[llmdnode([llptr]), mdnode];
     trans::build::Call(bcx, *cx.intrinsics.get(&~"llvm.dbg.declare"),
@@ -922,9 +919,7 @@ pub fn create_arg(bcx: block, arg: ast::arg, sp: span)
             };
             update_cache(cache, tg, argument_metadata(mdval));
 
-            let llptr = match fcx.llargs.get_copy(&arg.id) {
-              local_mem(v) | local_imm(v) => v,
-            };
+            let llptr = fcx.llargs.get_copy(&arg.id);
             let declargs = ~[llmdnode([llptr]), mdnode];
             trans::build::Call(bcx,
                                *cx.intrinsics.get(&~"llvm.dbg.declare"),
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 99860e60c6b..42ba06aad76 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -247,7 +247,7 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
         // must patchup the type.
         DatumBlock {bcx: bcx,
                     datum: Datum {val: datum.val, ty: adjusted_ty,
-                                  mode: datum.mode, source: datum.source}}
+                                  mode: datum.mode}}
     }
 
     fn auto_slice(bcx: block,
@@ -793,8 +793,7 @@ fn trans_def_datum_unadjusted(bcx: block,
             bcx: bcx,
             datum: Datum {val: llval,
                           ty: rust_ty,
-                          mode: ByValue,
-                          source: RevokeClean}
+                          mode: ByValue}
         };
     }
 }
@@ -920,8 +919,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
             bcx: bcx,
             datum: Datum {val: elt,
                           ty: vt.unit_ty,
-                          mode: ByRef,
-                          source: ZeroMem}
+                          mode: ByRef(ZeroMem)}
         };
     }
 
@@ -988,8 +986,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
                     bcx: bcx,
                     datum: Datum {val: val,
                                   ty: const_ty,
-                                  mode: ByRef,
-                                  source: ZeroMem}
+                                  mode: ByRef(ZeroMem)}
                 }
             }
             _ => {
@@ -1014,8 +1011,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
                     Datum {
                         val: val,
                         ty: local_ty,
-                        mode: ByRef,
-                        source: ZeroMem
+                        mode: ByRef(ZeroMem)
                     }
                 }
                 None => {
@@ -1052,8 +1048,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
             Datum {
                 val: casted_val,
                 ty: self_info.t,
-                mode: ByRef,
-                source: ZeroMem
+                mode: ByRef(ZeroMem)
             }
         }
         _ => {
@@ -1063,26 +1058,22 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
     };
 
     fn take_local(bcx: block,
-                  table: &HashMap<ast::node_id, local_val>,
+                  table: &HashMap<ast::node_id, ValueRef>,
                   nid: ast::node_id) -> Datum {
-        let (v, mode) = match table.find(&nid) {
-            Some(&local_mem(v)) => (v, ByRef),
-            Some(&local_imm(v)) => (v, ByValue),
+        let v = match table.find(&nid) {
+            Some(&v) => v,
             None => {
                 bcx.sess().bug(fmt!(
                     "trans_local_var: no llval for local/arg %? found", nid));
             }
         };
         let ty = node_id_type(bcx, nid);
-
-        debug!("take_local(nid=%?, v=%s, mode=%?, ty=%s)",
-               nid, bcx.val_str(v), mode, bcx.ty_to_str(ty));
-
+        debug!("take_local(nid=%?, v=%s, ty=%s)",
+               nid, bcx.val_str(v), bcx.ty_to_str(ty));
         Datum {
             val: v,
             ty: ty,
-            mode: mode,
-            source: ZeroMem
+            mode: ByRef(ZeroMem)
         }
     }
 }
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index a7a8cd088d2..ae68a28de97 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -692,19 +692,15 @@ pub fn trans_intrinsic(ccx: @CrateContext,
                   fcx.llretptr.get());
         }
         ~"move_val" => {
-            // Create a datum reflecting the value being moved:
-            //
-            // - the datum will be by ref if the value is non-immediate;
-            //
-            // - the datum has a RevokeClean source because, that way,
-            //   the `move_to()` method does not feel compelled to
-            //   zero out the memory where the datum resides.  Zeroing
-            //   is not necessary since, for intrinsics, there is no
-            //   cleanup to concern ourselves with.
+            // Create a datum reflecting the value being moved.
+            // Use `appropriate_mode` so that the datum is by ref
+            // if the value is non-immediate. Note that, with
+            // intrinsics, there are no argument cleanups to
+            // concern ourselves with.
             let tp_ty = substs.tys[0];
             let mode = appropriate_mode(tp_ty);
             let src = Datum {val: get_param(decl, first_real_arg + 1u),
-                             ty: tp_ty, mode: mode, source: RevokeClean};
+                             ty: tp_ty, mode: mode};
             bcx = src.move_to(bcx, DROP_EXISTING,
                               get_param(decl, first_real_arg));
         }
@@ -713,7 +709,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
             let tp_ty = substs.tys[0];
             let mode = appropriate_mode(tp_ty);
             let src = Datum {val: get_param(decl, first_real_arg + 1u),
-                             ty: tp_ty, mode: mode, source: RevokeClean};
+                             ty: tp_ty, mode: mode};
             bcx = src.move_to(bcx, INIT, get_param(decl, first_real_arg));
         }
         ~"min_align_of" => {
@@ -832,7 +828,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
                 }
             });
             let datum = Datum {val: get_param(decl, first_real_arg),
-                               mode: ByRef, ty: fty, source: ZeroMem};
+                               mode: ByRef(ZeroMem), ty: fty};
             let arg_vals = ~[frameaddress_val];
             bcx = trans_call_inner(
                 bcx, None, fty, ty::mk_nil(),
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index 1e43a3c502b..023d931a60b 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -197,7 +197,7 @@ pub fn trans_method_callee(bcx: block,
     // Replace method_self with method_static here.
     let mut origin = mentry.origin;
     match origin {
-        typeck::method_self(copy trait_id, copy method_index) => {
+        typeck::method_self(trait_id, method_index) => {
             // Get the ID of the impl we're inside.
             let impl_def_id = bcx.fcx.impl_id.get();
 
@@ -445,7 +445,7 @@ pub fn method_ty_param_count(ccx: @CrateContext, m_id: ast::def_id,
                                             _, _)) => {
                 m.generics.ty_params.len()
             }
-            copy e => fail!("method_ty_param_count %?", e)
+            ref e => fail!("method_ty_param_count %?", *e)
         }
     } else {
         csearch::get_type_param_count(ccx.sess.cstore, m_id) -
diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs
index ceb229c79bd..77b2586781f 100644
--- a/src/librustc/middle/trans/type_use.rs
+++ b/src/librustc/middle/trans/type_use.rs
@@ -85,8 +85,8 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint)
     }
 
     if fn_id_loc.crate != local_crate {
-        let Context { uses: @uses, _ } = cx;
-        let uses = @uses; // mutability
+        let Context { uses, _ } = cx;
+        let uses = @copy *uses; // freeze
         ccx.type_use_cache.insert(fn_id, uses);
         return uses;
     }
@@ -173,8 +173,8 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint)
                                 ccx.tcx.sess.parse_sess.interner)));
       }
     }
-    let Context { uses: @uses, _ } = cx;
-    let uses = @uses; // mutability
+    let Context { uses, _ } = cx;
+    let uses = @copy *uses; // freeze
     ccx.type_use_cache.insert(fn_id, uses);
     uses
 }
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index e469856f08f..13102093cd6 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -450,7 +450,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
             demand::eqtype(fcx, pat.span, region_ty, typ);
           }
           // otherwise the type of x is the expected type T
-          ast::bind_by_copy | ast::bind_infer => {
+          ast::bind_infer => {
             demand::eqtype(fcx, pat.span, expected, typ);
           }
         }
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index f9aa01c0956..3cb028b811e 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -308,7 +308,7 @@ pub impl CoherenceChecker {
                             implementation =
                                 self.create_impl_from_item(item);
                         }
-                        Some(copy existing_implementation) => {
+                        Some(existing_implementation) => {
                             implementation = existing_implementation;
                         }
                     }
diff --git a/src/libstd/io.rs b/src/libstd/io.rs
index 011c56ac7c1..bfe82a015cd 100644
--- a/src/libstd/io.rs
+++ b/src/libstd/io.rs
@@ -1933,7 +1933,7 @@ mod tests {
     #[test]
     fn file_reader_not_exist() {
         match io::file_reader(&Path("not a file")) {
-          result::Err(copy e) => {
+          result::Err(e) => {
             assert_eq!(e, ~"error opening not a file");
           }
           result::Ok(_) => fail!()
@@ -1974,7 +1974,7 @@ mod tests {
     #[test]
     fn file_writer_bad_name() {
         match io::file_writer(&Path("?/?"), []) {
-          result::Err(copy e) => {
+          result::Err(e) => {
             assert!(str::starts_with(e, "error opening"));
           }
           result::Ok(_) => fail!()
@@ -1984,7 +1984,7 @@ mod tests {
     #[test]
     fn buffered_file_writer_bad_name() {
         match io::buffered_file_writer(&Path("?/?")) {
-          result::Err(copy e) => {
+          result::Err(e) => {
             assert!(str::starts_with(e, "error opening"));
           }
           result::Ok(_) => fail!()
diff --git a/src/libstd/option.rs b/src/libstd/option.rs
index be6ec8c8518..ee6e37aeb78 100644
--- a/src/libstd/option.rs
+++ b/src/libstd/option.rs
@@ -341,7 +341,7 @@ pub impl<T:Copy> Option<T> {
     #[inline(always)]
     fn get(self) -> T {
         match self {
-          Some(copy x) => return x,
+          Some(x) => return x,
           None => fail!("option::get none")
         }
     }
@@ -349,7 +349,7 @@ pub impl<T:Copy> Option<T> {
     /// Returns the contained value or a default
     #[inline(always)]
     fn get_or_default(self, def: T) -> T {
-        match self { Some(copy x) => x, None => def }
+        match self { Some(x) => x, None => def }
     }
 
     /// Applies a function zero or more times until the result is none.
@@ -366,7 +366,7 @@ pub impl<T:Copy + Zero> Option<T> {
     /// Returns the contained value or zero (for this type)
     #[inline(always)]
     fn get_or_zero(self) -> T {
-        match self { Some(copy x) => x, None => Zero::zero() }
+        match self { Some(x) => x, None => Zero::zero() }
     }
 }
 
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 39bd57b3c37..9eb7b54f009 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -774,9 +774,9 @@ impl GenericPath for WindowsPath {
 
         /* if rhs has a host set, then the whole thing wins */
         match other.host {
-            Some(copy host) => {
+            Some(ref host) => {
                 return WindowsPath {
-                    host: Some(host),
+                    host: Some(copy *host),
                     device: copy other.device,
                     is_absolute: true,
                     components: copy other.components,
@@ -787,10 +787,10 @@ impl GenericPath for WindowsPath {
 
         /* if rhs has a device set, then a part wins */
         match other.device {
-            Some(copy device) => {
+            Some(ref device) => {
                 return WindowsPath {
                     host: None,
-                    device: Some(device),
+                    device: Some(copy *device),
                     is_absolute: true,
                     components: copy other.components,
                 };
diff --git a/src/libstd/result.rs b/src/libstd/result.rs
index 4fe92ddb7b6..5b40b09e98e 100644
--- a/src/libstd/result.rs
+++ b/src/libstd/result.rs
@@ -40,7 +40,7 @@ pub enum Result<T, U> {
 #[inline(always)]
 pub fn get<T:Copy,U>(res: &Result<T, U>) -> T {
     match *res {
-      Ok(copy t) => t,
+      Ok(ref t) => copy *t,
       Err(ref the_err) =>
         fail!("get called on error result: %?", *the_err)
     }
@@ -72,7 +72,7 @@ pub fn get_ref<'a, T, U>(res: &'a Result<T, U>) -> &'a T {
 #[inline(always)]
 pub fn get_err<T, U: Copy>(res: &Result<T, U>) -> U {
     match *res {
-      Err(copy u) => u,
+      Err(ref u) => copy *u,
       Ok(_) => fail!("get_err called on ok result")
     }
 }
@@ -102,8 +102,8 @@ pub fn is_err<T, U>(res: &Result<T, U>) -> bool {
 pub fn to_either<T:Copy,U:Copy>(res: &Result<U, T>)
     -> Either<T, U> {
     match *res {
-      Ok(copy res) => either::Right(res),
-      Err(copy fail_) => either::Left(fail_)
+      Ok(ref res) => either::Right(copy *res),
+      Err(ref fail_) => either::Left(copy *fail_)
     }
 }
 
@@ -206,7 +206,7 @@ pub fn map<T, E: Copy, U: Copy>(res: &Result<T, E>, op: &fn(&T) -> U)
   -> Result<U, E> {
     match *res {
       Ok(ref t) => Ok(op(t)),
-      Err(copy e) => Err(e)
+      Err(ref e) => Err(copy *e)
     }
 }
 
@@ -222,7 +222,7 @@ pub fn map<T, E: Copy, U: Copy>(res: &Result<T, E>, op: &fn(&T) -> U)
 pub fn map_err<T:Copy,E,F:Copy>(res: &Result<T, E>, op: &fn(&E) -> F)
   -> Result<T, F> {
     match *res {
-      Ok(copy t) => Ok(t),
+      Ok(ref t) => Ok(copy *t),
       Err(ref e) => Err(op(e))
     }
 }
@@ -304,8 +304,8 @@ pub fn map_vec<T,U:Copy,V:Copy>(
     let mut vs: ~[V] = vec::with_capacity(vec::len(ts));
     for ts.each |t| {
         match op(t) {
-          Ok(copy v) => vs.push(v),
-          Err(copy u) => return Err(u)
+          Ok(v) => vs.push(v),
+          Err(u) => return Err(u)
         }
     }
     return Ok(vs);
@@ -319,8 +319,8 @@ pub fn map_opt<T,U:Copy,V:Copy>(
     match *o_t {
       None => Ok(None),
       Some(ref t) => match op(t) {
-        Ok(copy v) => Ok(Some(v)),
-        Err(copy e) => Err(e)
+        Ok(v) => Ok(Some(v)),
+        Err(e) => Err(e)
       }
     }
 }
@@ -344,8 +344,8 @@ pub fn map_vec2<S,T,U:Copy,V:Copy>(ss: &[S], ts: &[T],
     let mut i = 0u;
     while i < n {
         match op(&ss[i],&ts[i]) {
-          Ok(copy v) => vs.push(v),
-          Err(copy u) => return Err(u)
+          Ok(v) => vs.push(v),
+          Err(u) => return Err(u)
         }
         i += 1u;
     }
@@ -367,7 +367,7 @@ pub fn iter_vec2<S,T,U:Copy>(ss: &[S], ts: &[T],
     while i < n {
         match op(&ss[i],&ts[i]) {
           Ok(()) => (),
-          Err(copy u) => return Err(u)
+          Err(u) => return Err(u)
         }
         i += 1u;
     }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index cdd16e5d890..676a57e38da 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -257,7 +257,6 @@ pub struct field_pat {
 
 #[deriving(Eq, Encodable, Decodable)]
 pub enum binding_mode {
-    bind_by_copy,
     bind_by_ref(mutability),
     bind_infer
 }
@@ -265,13 +264,13 @@ pub enum binding_mode {
 impl to_bytes::IterBytes for binding_mode {
     fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
         match *self {
-          bind_by_copy => 0u8.iter_bytes(lsb0, f),
-
           bind_by_ref(ref m) => {
-              1u8.iter_bytes(lsb0, f) && m.iter_bytes(lsb0, f)
+              0u8.iter_bytes(lsb0, f) && m.iter_bytes(lsb0, f)
           }
 
-          bind_infer => 2u8.iter_bytes(lsb0, f),
+          bind_infer => {
+              1u8.iter_bytes(lsb0, f)
+          }
         }
     }
 }
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index c8cac4ba2d7..deff6dc5ba9 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -233,7 +233,7 @@ pub fn ident_to_path(s: span, i: ident) -> @Path {
 
 pub fn ident_to_pat(id: node_id, s: span, i: ident) -> @pat {
     @ast::pat { id: id,
-                node: pat_ident(bind_by_copy, ident_to_path(s, i), None),
+                node: pat_ident(bind_infer, ident_to_path(s, i), None),
                 span: s }
 }
 
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 2a3c266cfa6..85bebebf0f6 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -560,7 +560,7 @@ impl AstBuilder for @ExtCtxt {
         self.pat(span, ast::pat_lit(expr))
     }
     fn pat_ident(&self, span: span, ident: ast::ident) -> @ast::pat {
-        self.pat_ident_binding_mode(span, ident, ast::bind_by_copy)
+        self.pat_ident_binding_mode(span, ident, ast::bind_infer)
     }
 
     fn pat_ident_binding_mode(&self,
diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs
index 64ce6dfbc19..10fb4b8ecd4 100644
--- a/src/libsyntax/ext/deriving/iter_bytes.rs
+++ b/src/libsyntax/ext/deriving/iter_bytes.rs
@@ -62,11 +62,11 @@ fn iter_bytes_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @
         Struct(ref fs) => {
             fields = fs
         }
-        EnumMatching(copy index, ref variant, ref fs) => {
+        EnumMatching(index, ref variant, ref fs) => {
             // Determine the discriminant. We will feed this value to the byte
             // iteration function.
             let discriminant = match variant.node.disr_expr {
-                Some(copy d)=> d,
+                Some(d)=> d,
                 None => cx.expr_uint(span, index)
             };
 
diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs
index b2e039786ad..54d31de7c50 100644
--- a/src/libsyntax/ext/deriving/rand.rs
+++ b/src/libsyntax/ext/deriving/rand.rs
@@ -119,7 +119,7 @@ fn rand_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr {
                   summary: &Either<uint, ~[ident]>,
                   rand_call: &fn() -> @expr) -> @expr {
         match *summary {
-            Left(copy count) => {
+            Left(count) => {
                 if count == 0 {
                     cx.expr_ident(span, ctor_ident)
                 } else {
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 8a60b239b89..91fad0c22a6 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -58,8 +58,8 @@ pub fn expand_file(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
     base::check_zero_tts(cx, sp, tts, "file!");
 
     let topmost = topmost_expn_info(cx.backtrace().get());
-    let Loc { file: @FileMap { name: filename, _ }, _ } =
-        cx.codemap().lookup_char_pos(topmost.call_site.lo);
+    let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
+    let filename = copy loc.file.name;
     base::MRExpr(cx.expr_str(topmost.call_site, filename))
 }
 
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 183bc2a77c5..ec63b5a7f74 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -423,7 +423,7 @@ pub 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(true)),
+      "pat" => token::nt_pat(p.parse_pat()),
       "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/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index cac963727e3..4a6a070df50 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -207,8 +207,8 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
         } else { /* repeat */
             r.stack.idx = 0u;
             r.repeat_idx[r.repeat_idx.len() - 1u] += 1u;
-            match r.stack.sep {
-              Some(copy tk) => {
+            match copy r.stack.sep {
+              Some(tk) => {
                 r.cur_tok = tk; /* repeat same span, I guess */
                 return ret_val;
               }
@@ -218,8 +218,8 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
     }
     loop { /* because it's easiest, this handles `tt_delim` not starting
     with a `tt_tok`, even though it won't happen */
-        match r.stack.forest[r.stack.idx] {
-          tt_delim(copy tts) => {
+        match copy r.stack.forest[r.stack.idx] {
+          tt_delim(tts) => {
             r.stack = @mut TtFrame {
                 forest: @mut tts,
                 idx: 0u,
@@ -229,13 +229,13 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
             };
             // if this could be 0-length, we'd need to potentially recur here
           }
-          tt_tok(sp, copy tok) => {
+          tt_tok(sp, tok) => {
             r.cur_span = sp;
             r.cur_tok = tok;
             r.stack.idx += 1u;
             return ret_val;
           }
-          tt_seq(sp, copy tts, copy sep, zerok) => {
+          tt_seq(sp, tts, sep, zerok) => {
             let t = tt_seq(sp, copy tts, copy sep, zerok);
             match lockstep_iter_size(&t, r) {
               lis_unconstrained => {
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index eca999231cd..9d5cb131fec 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -485,9 +485,9 @@ mod test {
 
     #[test] fn parse_ident_pat () {
         let parser = string_to_parser(@~"b");
-        assert_eq!(parser.parse_pat(false),
+        assert_eq!(parser.parse_pat(),
                    @ast::pat{id:1, // fixme
-                             node: ast::pat_ident(ast::bind_by_copy,
+                             node: ast::pat_ident(ast::bind_infer,
                                                   @ast::Path{
                                                       span:sp(0,1),
                                                       global:false,
@@ -516,7 +516,7 @@ mod test {
                                                        2),
                                     span:sp(4,7)},
                        pat: @ast::pat{id:1,
-                                      node: ast::pat_ident(ast::bind_by_copy,
+                                      node: ast::pat_ident(ast::bind_infer,
                                                            @ast::Path{
                                                                span:sp(0,1),
                                                                global:false,
@@ -553,7 +553,7 @@ mod test {
                                                 span:sp(10,13)},
                                     pat: @ast::pat{id:1, // fixme
                                                    node: ast::pat_ident(
-                                                       ast::bind_by_copy,
+                                                       ast::bind_infer,
                                                        @ast::Path{
                                                            span:sp(6,7),
                                                            global:false,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 27dfc2c0a46..29f565851b4 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -18,7 +18,7 @@ use ast::{TyBareFn, TyClosure};
 use ast::{RegionTyParamBound, TraitTyParamBound};
 use ast::{provided, public, purity};
 use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer};
-use ast::{bind_by_copy, bitand, bitor, bitxor, blk};
+use ast::{bitand, bitor, bitxor, blk};
 use ast::{blk_check_mode, box};
 use ast::{crate, crate_cfg, decl, decl_item};
 use ast::{decl_local, default_blk, deref, div, enum_def, explicit_self};
@@ -131,11 +131,11 @@ at INTERPOLATED tokens */
 macro_rules! maybe_whole_expr (
     ($p:expr) => (
         match *($p).token {
-            INTERPOLATED(token::nt_expr(copy e)) => {
+            INTERPOLATED(token::nt_expr(e)) => {
                 $p.bump();
                 return e;
             }
-            INTERPOLATED(token::nt_path(copy pt)) => {
+            INTERPOLATED(token::nt_path(pt)) => {
                 $p.bump();
                 return $p.mk_expr(
                     ($p).span.lo,
@@ -150,8 +150,8 @@ macro_rules! maybe_whole_expr (
 
 macro_rules! maybe_whole (
     ($p:expr, $constructor:ident) => (
-        match *($p).token {
-            INTERPOLATED(token::$constructor(copy x)) => {
+        match copy *($p).token {
+            INTERPOLATED(token::$constructor(x)) => {
                 $p.bump();
                 return x;
             }
@@ -159,8 +159,8 @@ macro_rules! maybe_whole (
        }
     );
     (deref $p:expr, $constructor:ident) => (
-        match *($p).token {
-            INTERPOLATED(token::$constructor(copy x)) => {
+        match copy *($p).token {
+            INTERPOLATED(token::$constructor(x)) => {
                 $p.bump();
                 return copy *x;
             }
@@ -168,8 +168,8 @@ macro_rules! maybe_whole (
         }
     );
     (Some $p:expr, $constructor:ident) => (
-        match *($p).token {
-            INTERPOLATED(token::$constructor(copy x)) => {
+        match copy *($p).token {
+            INTERPOLATED(token::$constructor(x)) => {
                 $p.bump();
                 return Some(x);
             }
@@ -177,8 +177,8 @@ macro_rules! maybe_whole (
         }
     );
     (iovi $p:expr, $constructor:ident) => (
-        match *($p).token {
-            INTERPOLATED(token::$constructor(copy x)) => {
+        match copy *($p).token {
+            INTERPOLATED(token::$constructor(x)) => {
                 $p.bump();
                 return iovi_item(x);
             }
@@ -186,8 +186,8 @@ macro_rules! maybe_whole (
         }
     );
     (pair_empty $p:expr, $constructor:ident) => (
-        match *($p).token {
-            INTERPOLATED(token::$constructor(copy x)) => {
+        match copy *($p).token {
+            INTERPOLATED(token::$constructor(x)) => {
                 $p.bump();
                 return (~[], x);
             }
@@ -825,7 +825,7 @@ pub impl Parser {
         let pat = if require_name || self.is_named_argument() {
             self.parse_arg_mode();
             is_mutbl = self.eat_keyword(keywords::Mut);
-            let pat = self.parse_pat(false);
+            let pat = self.parse_pat();
             self.expect(&token::COLON);
             pat
         } else {
@@ -853,7 +853,7 @@ pub impl Parser {
     fn parse_fn_block_arg(&self) -> arg_or_capture_item {
         self.parse_arg_mode();
         let is_mutbl = self.eat_keyword(keywords::Mut);
-        let pat = self.parse_pat(false);
+        let pat = self.parse_pat();
         let t = if self.eat(&token::COLON) {
             self.parse_ty(false)
         } else {
@@ -1992,28 +1992,29 @@ pub impl Parser {
         // them as the lambda arguments
         let e = self.parse_expr_res(RESTRICT_NO_BAR_OR_DOUBLEBAR_OP);
         match e.node {
-            expr_call(f, /*bad*/ copy args, NoSugar) => {
+            expr_call(f, ref args, NoSugar) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
-                let args = vec::append(args, [last_arg]);
+                let args = vec::append(copy *args, [last_arg]);
                 self.mk_expr(lo.lo, block.span.hi, expr_call(f, args, sugar))
             }
-            expr_method_call(f, i, /*bad*/ copy tps,
-                             /*bad*/ copy args, NoSugar) => {
+            expr_method_call(f, i, ref tps, ref args, NoSugar) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
-                let args = vec::append(args, [last_arg]);
+                let args = vec::append(copy *args, [last_arg]);
                 self.mk_expr(lo.lo, block.span.hi,
-                             expr_method_call(f, i, tps, args, sugar))
+                             expr_method_call(f, i, copy *tps,
+                                              args, sugar))
             }
-            expr_field(f, i, /*bad*/ copy tps) => {
+            expr_field(f, i, ref tps) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
                 self.mk_expr(lo.lo, block.span.hi,
-                             expr_method_call(f, i, tps, ~[last_arg], sugar))
+                             expr_method_call(f, i,
+                                              copy *tps, ~[last_arg], sugar))
             }
             expr_path(*) | expr_call(*) | expr_method_call(*) |
                 expr_paren(*) => {
@@ -2162,7 +2163,7 @@ pub impl Parser {
     fn parse_pats(&self) -> ~[@pat] {
         let mut pats = ~[];
         loop {
-            pats.push(self.parse_pat(true));
+            pats.push(self.parse_pat());
             if *self.token == token::BINOP(token::OR) { self.bump(); }
             else { return pats; }
         };
@@ -2170,7 +2171,6 @@ pub impl Parser {
 
     fn parse_pat_vec_elements(
         &self,
-        refutable: bool
     ) -> (~[@pat], Option<@pat>, ~[@pat]) {
         let mut before = ~[];
         let mut slice = None;
@@ -2191,7 +2191,7 @@ pub impl Parser {
                 }
             }
 
-            let subpat = self.parse_pat(refutable);
+            let subpat = self.parse_pat();
             if is_slice {
                 match subpat {
                     @ast::pat { node: pat_wild, _ } => (),
@@ -2214,7 +2214,7 @@ pub impl Parser {
     }
 
     // parse the fields of a struct-like pattern
-    fn parse_pat_fields(&self, refutable: bool) -> (~[ast::field_pat], bool) {
+    fn parse_pat_fields(&self) -> (~[ast::field_pat], bool) {
         let mut fields = ~[];
         let mut etc = false;
         let mut first = true;
@@ -2244,7 +2244,7 @@ pub impl Parser {
             let subpat;
             if *self.token == token::COLON {
                 self.bump();
-                subpat = self.parse_pat(refutable);
+                subpat = self.parse_pat();
             } else {
                 subpat = @ast::pat {
                     id: self.get_id(),
@@ -2257,10 +2257,8 @@ pub impl Parser {
         return (fields, etc);
     }
 
-    // parse a pattern. The 'refutable' argument
-    // appears to control whether the binding_mode
-    // 'bind_infer' or 'bind_by_copy' is used.
-    fn parse_pat(&self, refutable: bool) -> @pat {
+    // parse a pattern.
+    fn parse_pat(&self) -> @pat {
         maybe_whole!(self, nt_pat);
 
         let lo = self.span.lo;
@@ -2272,7 +2270,7 @@ pub impl Parser {
             // parse @pat
           token::AT => {
             self.bump();
-            let sub = self.parse_pat(refutable);
+            let sub = self.parse_pat();
             hi = sub.span.hi;
             // HACK: parse @"..." as a literal of a vstore @str
             pat = match sub.node {
@@ -2295,7 +2293,7 @@ pub impl Parser {
           token::TILDE => {
             // parse ~pat
             self.bump();
-            let sub = self.parse_pat(refutable);
+            let sub = self.parse_pat();
             hi = sub.span.hi;
             // HACK: parse ~"..." as a literal of a vstore ~str
             pat = match sub.node {
@@ -2319,7 +2317,7 @@ pub impl Parser {
               // parse &pat
               let lo = self.span.lo;
               self.bump();
-              let sub = self.parse_pat(refutable);
+              let sub = self.parse_pat();
               hi = sub.span.hi;
               // HACK: parse &"..." as a literal of a borrowed str
               pat = match sub.node {
@@ -2340,7 +2338,7 @@ pub impl Parser {
           }
           token::LBRACE => {
             self.bump();
-            let (_, _) = self.parse_pat_fields(refutable);
+            let (_, _) = self.parse_pat_fields();
             hi = self.span.hi;
             self.bump();
             self.obsolete(*self.span, ObsoleteRecordPattern);
@@ -2358,11 +2356,11 @@ pub impl Parser {
                 let expr = self.mk_expr(lo, hi, expr_lit(lit));
                 pat = pat_lit(expr);
             } else {
-                let mut fields = ~[self.parse_pat(refutable)];
+                let mut fields = ~[self.parse_pat()];
                 if self.look_ahead(1) != token::RPAREN {
                     while *self.token == token::COMMA {
                         self.bump();
-                        fields.push(self.parse_pat(refutable));
+                        fields.push(self.parse_pat());
                     }
                 }
                 if fields.len() == 1 { self.expect(&token::COMMA); }
@@ -2375,7 +2373,7 @@ pub impl Parser {
             // parse [pat,pat,...] as vector pattern
             self.bump();
             let (before, slice, after) =
-                self.parse_pat_vec_elements(refutable);
+                self.parse_pat_vec_elements();
             hi = self.span.hi;
             self.expect(&token::RBRACKET);
             pat = ast::pat_vec(before, slice, after);
@@ -2405,15 +2403,13 @@ pub impl Parser {
             } else if self.eat_keyword(keywords::Ref) {
                 // parse ref pat
                 let mutbl = self.parse_mutability();
-                pat = self.parse_pat_ident(refutable, bind_by_ref(mutbl));
+                pat = self.parse_pat_ident(bind_by_ref(mutbl));
             } else if self.eat_keyword(keywords::Copy) {
                 // parse copy pat
-                pat = self.parse_pat_ident(refutable, bind_by_copy);
+                self.warn("copy keyword in patterns no longer has any effect, \
+                           remove it");
+                pat = self.parse_pat_ident(bind_infer);
             } else {
-                // XXX---refutable match bindings should work same as let
-                let binding_mode =
-                    if refutable {bind_infer} else {bind_by_copy};
-
                 let can_be_enum_or_struct;
                 match self.look_ahead(1) {
                     token::LPAREN | token::LBRACKET | token::LT |
@@ -2434,12 +2430,12 @@ pub impl Parser {
                     let sub;
                     if self.eat(&token::AT) {
                         // parse foo @ pat
-                        sub = Some(self.parse_pat(refutable));
+                        sub = Some(self.parse_pat());
                     } else {
                         // or just foo
                         sub = None;
                     }
-                    pat = pat_ident(binding_mode, name, sub);
+                    pat = pat_ident(bind_infer, name, sub);
                 } else {
                     // parse an enum pat
                     let enum_path = self.parse_path_with_tps(true);
@@ -2447,7 +2443,7 @@ pub impl Parser {
                         token::LBRACE => {
                             self.bump();
                             let (fields, etc) =
-                                self.parse_pat_fields(refutable);
+                                self.parse_pat_fields();
                             self.bump();
                             pat = pat_struct(enum_path, fields, etc);
                         }
@@ -2468,7 +2464,7 @@ pub impl Parser {
                                         seq_sep_trailing_disallowed(
                                             token::COMMA
                                         ),
-                                        |p| p.parse_pat(refutable)
+                                        |p| p.parse_pat()
                                     );
                                     pat = pat_enum(enum_path, Some(args));
                                   }
@@ -2478,7 +2474,7 @@ pub impl Parser {
                                       // it could still be either an enum
                                       // or an identifier pattern, resolve
                                       // will sort it out:
-                                      pat = pat_ident(binding_mode,
+                                      pat = pat_ident(bind_infer,
                                                       enum_path,
                                                       None);
                                   } else {
@@ -2500,7 +2496,6 @@ pub impl Parser {
     // used by the copy foo and ref foo patterns to give a good
     // error message when parsing mistakes like ref foo(a,b)
     fn parse_pat_ident(&self,
-                       refutable: bool,
                        binding_mode: ast::binding_mode)
                        -> ast::pat_ {
         if !is_plain_ident(&*self.token) {
@@ -2510,7 +2505,7 @@ pub impl Parser {
         // why a path here, and not just an identifier?
         let name = self.parse_path_without_tps();
         let sub = if self.eat(&token::AT) {
-            Some(self.parse_pat(refutable))
+            Some(self.parse_pat())
         } else {
             None
         };
@@ -2533,7 +2528,7 @@ pub impl Parser {
     // parse a local variable declaration
     fn parse_local(&self, is_mutbl: bool) -> @local {
         let lo = self.span.lo;
-        let pat = self.parse_pat(false);
+        let pat = self.parse_pat();
         let mut ty = @Ty {
             id: self.get_id(),
             node: ty_infer,
@@ -2760,7 +2755,7 @@ pub impl Parser {
                     match stmt.node {
                         stmt_expr(e, stmt_id) => {
                             // expression without semicolon
-                            match *self.token {
+                            match copy *self.token {
                                 token::SEMI => {
                                     self.bump();
                                     stmts.push(@codemap::spanned {
@@ -2770,7 +2765,7 @@ pub impl Parser {
                                 token::RBRACE => {
                                     expr = Some(e);
                                 }
-                                copy t => {
+                                t => {
                                     if classify::stmt_ends_with_semi(stmt) {
                                         self.fatal(
                                             fmt!(
@@ -2880,7 +2875,7 @@ pub impl Parser {
                 token::MOD_SEP | token::IDENT(*) => {
                     let obsolete_bound = match *self.token {
                         token::MOD_SEP => false,
-                        token::IDENT(copy sid, _) => {
+                        token::IDENT(sid, _) => {
                             match *self.id_to_str(sid) {
                                 ~"send" |
                                 ~"copy" |
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 6a32e535295..f29876b8708 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1537,9 +1537,6 @@ pub fn print_pat(s: @ps, pat: @ast::pat, refutable: bool) {
                       word_nbsp(s, "ref");
                       print_mutability(s, mutbl);
                   }
-                  ast::bind_by_copy => {
-                      word_nbsp(s, "copy");
-                  }
                   ast::bind_infer => {}
               }
           }
diff --git a/src/test/compile-fail/borrowck-pat-by-value-binding.rs b/src/test/compile-fail/borrowck-pat-by-value-binding.rs
index d60ed3d0e37..e77f5245d7d 100644
--- a/src/test/compile-fail/borrowck-pat-by-value-binding.rs
+++ b/src/test/compile-fail/borrowck-pat-by-value-binding.rs
@@ -36,7 +36,7 @@ fn match_const_opt_by_imm_ref(v: &const Option<int>) {
 
 fn match_const_opt_by_value(v: &const Option<int>) {
     match *v {
-      Some(copy i) => process(i),
+      Some(i) => process(i),
       None => ()
     }
 }
diff --git a/src/test/compile-fail/noncopyable-match-pattern.rs b/src/test/compile-fail/noncopyable-match-pattern.rs
deleted file mode 100644
index a7c8950486c..00000000000
--- a/src/test/compile-fail/noncopyable-match-pattern.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2012 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.
-
-use std::unstable;
-
-fn main() {
-    unsafe {
-        let x = Some(unstable::sync::exclusive(false));
-        match x {
-            Some(copy z) => { //~ ERROR copying a value of non-copyable type
-                do z.with |b| { assert!(!*b); }
-            }
-            None => fail!()
-        }
-    }
-}
diff --git a/src/test/compile-fail/resolve-inconsistent-binding-mode.rs b/src/test/compile-fail/resolve-inconsistent-binding-mode.rs
index 33cc934c7b3..65fbbfc6e19 100644
--- a/src/test/compile-fail/resolve-inconsistent-binding-mode.rs
+++ b/src/test/compile-fail/resolve-inconsistent-binding-mode.rs
@@ -14,7 +14,7 @@ enum opts {
 
 fn matcher1(x: opts) {
     match x {
-      a(ref i) | b(copy i) => {} //~ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1
+      a(ref i) | b(i) => {} //~ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1
       c(_) => {}
     }
 }
diff --git a/src/test/run-pass/issue-2804.rs b/src/test/run-pass/issue-2804.rs
index d42d0b5aac0..59ab5018c1d 100644
--- a/src/test/run-pass/issue-2804.rs
+++ b/src/test/run-pass/issue-2804.rs
@@ -25,9 +25,9 @@ fn lookup(table: ~json::Object, key: ~str, default: ~str) -> ~str
 {
     match table.find(&key)
     {
-        option::Some(&extra::json::String(copy s)) =>
+        option::Some(&extra::json::String(ref s)) =>
         {
-            copy s
+            copy *s
         }
         option::Some(value) =>
         {
@@ -45,9 +45,9 @@ fn add_interface(store: int, managed_ip: ~str, data: extra::json::Json) -> (~str
 {
     match &data
     {
-        &extra::json::Object(copy interface) =>
+        &extra::json::Object(ref interface) =>
         {
-            let name = lookup(copy interface, ~"ifDescr", ~"");
+            let name = lookup(copy *interface, ~"ifDescr", ~"");
             let label = fmt!("%s-%s", managed_ip, name);
 
             (label, bool_value(false))
diff --git a/src/test/run-pass/match-vec-rvalue.rs b/src/test/run-pass/match-vec-rvalue.rs
new file mode 100644
index 00000000000..5f68b0e9a69
--- /dev/null
+++ b/src/test/run-pass/match-vec-rvalue.rs
@@ -0,0 +1,12 @@
+// Tests that matching rvalues with drops does not crash.
+
+fn main() {
+    match ~[1, 2, 3] {
+        x => {
+            assert_eq!(x.len(), 3);
+            assert_eq!(x[0], 1);
+            assert_eq!(x[1], 2);
+            assert_eq!(x[2], 3);
+        }
+    }
+}