about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-07-08 18:49:46 -0700
committerbors <bors@rust-lang.org>2013-07-08 18:49:46 -0700
commita48ca3290df992fde2f74ccf5b9f4e36563af8da (patch)
tree816142177cf53d6185626aee592ef837b5e1d93a /src/libsyntax
parent30c8aac677a754e0d4ebc16f261618f15d15a6e2 (diff)
parent0c6d02f391aa668b2ead91e8a4ed545475ac2c90 (diff)
downloadrust-a48ca3290df992fde2f74ccf5b9f4e36563af8da.tar.gz
rust-a48ca3290df992fde2f74ccf5b9f4e36563af8da.zip
auto merge of #7262 : nikomatsakis/rust/ref-bindings-in-irrefut-patterns, r=catamorphism
Correct treatment of irrefutable patterns. The old code was wrong in many, many ways. `ref` bindings didn't work, it sometimes copied when it should have moved, the borrow checker didn't even look at such patterns at all, we weren't consistent about preventing values with destructors from being pulled apart, etc.

Fixes #3224.
Fixes #3225.
Fixes #3255.
Fixes #6225.
Fixes #6386.

r? @catamorphism

Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/deriving/generic.rs36
-rw-r--r--src/libsyntax/ext/pipes/pipec.rs2
-rw-r--r--src/libsyntax/ext/pipes/proto.rs4
-rw-r--r--src/libsyntax/parse/parser.rs2
-rw-r--r--src/libsyntax/print/pprust.rs56
5 files changed, 49 insertions, 51 deletions
diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs
index 01769482d08..3bc16477c80 100644
--- a/src/libsyntax/ext/deriving/generic.rs
+++ b/src/libsyntax/ext/deriving/generic.rs
@@ -519,8 +519,8 @@ impl<'self> MethodDef<'self> {
         // create the generics that aren't for Self
         let fn_generics = self.generics.to_generics(cx, span, type_ident, generics);
 
-        let args = do arg_types.map |&(id, ty)| {
-            cx.arg(span, id, ty)
+        let args = do arg_types.map |pair| {
+            cx.arg(span, pair.first(), pair.second())
         };
 
         let ret_type = self.get_ret_ty(cx, span, generics, type_ident);
@@ -589,7 +589,7 @@ impl<'self> MethodDef<'self> {
 
         // transpose raw_fields
         let fields = match raw_fields {
-            [self_arg, .. rest] => {
+            [ref self_arg, .. rest] => {
                 do self_arg.iter().enumerate().transform |(i, &(opt_id, field))| {
                     let other_fields = do rest.map |l| {
                         match &l[i] {
@@ -738,16 +738,20 @@ impl<'self> MethodDef<'self> {
 
                     let mut enum_matching_fields = vec::from_elem(self_vec.len(), ~[]);
 
-                    for matches_so_far.tail().iter().advance |&(_, _, other_fields)| {
-                        for other_fields.iter().enumerate().advance |(i, &(_, other_field))| {
-                            enum_matching_fields[i].push(other_field);
+                    for matches_so_far.tail().iter().advance |triple| {
+                        match triple {
+                            &(_, _, ref other_fields) => {
+                                for other_fields.iter().enumerate().advance |(i, pair)| {
+                                    enum_matching_fields[i].push(pair.second());
+                                }
+                            }
                         }
                     }
                     let field_tuples =
                         do self_vec.iter()
                            .zip(enum_matching_fields.iter())
-                           .transform |(&(id, self_f), &other)| {
-                        (id, self_f, other)
+                           .transform |(&(id, self_f), other)| {
+                        (id, self_f, copy *other)
                     }.collect();
                     substructure = EnumMatching(variant_index, variant, field_tuples);
                 }
@@ -892,8 +896,8 @@ pub fn create_subpatterns(cx: @ExtCtxt,
                           field_paths: ~[ast::Path],
                           mutbl: ast::mutability)
                    -> ~[@ast::pat] {
-    do field_paths.map |&path| {
-        cx.pat(span, ast::pat_ident(ast::bind_by_ref(mutbl), path, None))
+    do field_paths.map |path| {
+        cx.pat(span, ast::pat_ident(ast::bind_by_ref(mutbl), copy *path, None))
     }
 }
 
@@ -1015,7 +1019,8 @@ left-to-right (`true`) or right-to-left (`false`).
 pub fn cs_fold(use_foldl: bool,
                f: &fn(@ExtCtxt, span,
                       old: @expr,
-                      self_f: @expr, other_fs: &[@expr]) -> @expr,
+                      self_f: @expr,
+                      other_fs: &[@expr]) -> @expr,
                base: @expr,
                enum_nonmatch_f: EnumNonMatchFunc,
                cx: @ExtCtxt, span: span,
@@ -1023,11 +1028,13 @@ pub fn cs_fold(use_foldl: bool,
     match *substructure.fields {
         EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
             if use_foldl {
-                do all_fields.iter().fold(base) |old, &(_, self_f, other_fs)| {
+                do all_fields.iter().fold(base) |old, triple| {
+                    let (_, self_f, other_fs) = copy *triple;
                     f(cx, span, old, self_f, other_fs)
                 }
             } else {
-                do all_fields.rev_iter().fold(base) |old, &(_, self_f, other_fs)| {
+                do all_fields.rev_iter().fold(base) |old, triple| {
+                    let (_, self_f, other_fs) = copy *triple;
                     f(cx, span, old, self_f, other_fs)
                 }
             }
@@ -1059,7 +1066,8 @@ pub fn cs_same_method(f: &fn(@ExtCtxt, span, ~[@expr]) -> @expr,
     match *substructure.fields {
         EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
             // call self_n.method(other_1_n, other_2_n, ...)
-            let called = do all_fields.map |&(_, self_field, other_fields)| {
+            let called = do all_fields.map |triple| {
+                let (_, self_field, other_fields) = copy *triple;
                 cx.expr_method_call(span,
                                     self_field,
                                     substructure.method_ident,
diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs
index 98fc9aa6178..478c0861990 100644
--- a/src/libsyntax/ext/pipes/pipec.rs
+++ b/src/libsyntax/ext/pipes/pipec.rs
@@ -137,7 +137,7 @@ impl gen_send for message {
                 let arg_names = vec::from_fn(tys.len(), |i| "x_" + i.to_str());
 
                 let args_ast: ~[ast::arg] = arg_names.iter().zip(tys.iter())
-                    .transform(|(&n, t)| cx.arg(span, cx.ident_of(n), copy *t)).collect();
+                    .transform(|(n, t)| cx.arg(span, cx.ident_of(*n), copy *t)).collect();
 
                 let args_ast = vec::append(
                     ~[cx.arg(span,
diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs
index 2fe8456c274..75424b60390 100644
--- a/src/libsyntax/ext/pipes/proto.rs
+++ b/src/libsyntax/ext/pipes/proto.rs
@@ -215,8 +215,8 @@ pub fn visit<Tproto, Tstate, Tmessage, V: visitor<Tproto, Tstate, Tmessage>>(
 
     // the copy keywords prevent recursive use of dvec
     let states: ~[Tstate] = do (copy proto.states).iter().transform |&s| {
-        let messages: ~[Tmessage] = do (copy s.messages).iter().transform |&m| {
-            let message(name, span, tys, this, next) = m;
+        let messages: ~[Tmessage] = do (copy s.messages).iter().transform |m| {
+            let message(name, span, tys, this, next) = copy *m;
             visitor.visit_message(name, span, tys, this, next)
         }.collect();
         visitor.visit_state(s, messages)
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index c43b350abdb..8666c84bbef 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -3914,7 +3914,7 @@ impl Parser {
         };
         let full_path = full_path.normalize();
 
-        let maybe_i = do self.sess.included_mod_stack.iter().position |&p| { p == full_path };
+        let maybe_i = do self.sess.included_mod_stack.iter().position |p| { *p == full_path };
         match maybe_i {
             Some(i) => {
                 let stack = &self.sess.included_mod_stack;
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index b545c56778e..c3710853615 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -147,7 +147,7 @@ pub fn ty_to_str(ty: &ast::Ty, intr: @ident_interner) -> ~str {
 }
 
 pub fn pat_to_str(pat: &ast::pat, intr: @ident_interner) -> ~str {
-    to_str(pat, print_irrefutable_pat, intr)
+    to_str(pat, print_pat, intr)
 }
 
 pub fn expr_to_str(e: &ast::expr, intr: @ident_interner) -> ~str {
@@ -1240,7 +1240,7 @@ pub fn print_expr(s: @ps, expr: &ast::expr) {
                 if first {
                     first = false;
                 } else { space(s.s); word_space(s, "|"); }
-                print_refutable_pat(s, *p);
+                print_pat(s, *p);
             }
             space(s.s);
             match arm.guard {
@@ -1434,7 +1434,7 @@ pub fn print_expr(s: @ps, expr: &ast::expr) {
 }
 
 pub fn print_local_decl(s: @ps, loc: &ast::local) {
-    print_irrefutable_pat(s, loc.node.pat);
+    print_pat(s, loc.node.pat);
     match loc.node.ty.node {
       ast::ty_infer => (),
       _ => { word_space(s, ":"); print_type(s, &loc.node.ty); }
@@ -1526,15 +1526,7 @@ pub fn print_bounded_path(s: @ps, path: &ast::Path,
     print_path_(s, path, false, bounds)
 }
 
-pub fn print_irrefutable_pat(s: @ps, pat: &ast::pat) {
-    print_pat(s, pat, false)
-}
-
-pub fn print_refutable_pat(s: @ps, pat: &ast::pat) {
-    print_pat(s, pat, true)
-}
-
-pub fn print_pat(s: @ps, pat: &ast::pat, refutable: bool) {
+pub fn print_pat(s: @ps, pat: &ast::pat) {
     maybe_print_comment(s, pat.span.lo);
     let ann_node = node_pat(s, pat);
     (s.ann.pre)(ann_node);
@@ -1543,20 +1535,18 @@ pub fn print_pat(s: @ps, pat: &ast::pat, refutable: bool) {
     match pat.node {
       ast::pat_wild => word(s.s, "_"),
       ast::pat_ident(binding_mode, ref path, sub) => {
-          if refutable {
-              match binding_mode {
-                  ast::bind_by_ref(mutbl) => {
-                      word_nbsp(s, "ref");
-                      print_mutability(s, mutbl);
-                  }
-                  ast::bind_infer => {}
+          match binding_mode {
+              ast::bind_by_ref(mutbl) => {
+                  word_nbsp(s, "ref");
+                  print_mutability(s, mutbl);
               }
+              ast::bind_infer => {}
           }
           print_path(s, path, true);
           match sub {
               Some(p) => {
                   word(s.s, "@");
-                  print_pat(s, p, refutable);
+                  print_pat(s, p);
               }
               None => ()
           }
@@ -1569,7 +1559,7 @@ pub fn print_pat(s: @ps, pat: &ast::pat, refutable: bool) {
             if !args.is_empty() {
               popen(s);
               commasep(s, inconsistent, *args,
-                       |s, &p| print_pat(s, p, refutable));
+                       |s, &p| print_pat(s, p));
               pclose(s);
             } else { }
           }
@@ -1578,16 +1568,16 @@ pub fn print_pat(s: @ps, pat: &ast::pat, refutable: bool) {
       ast::pat_struct(ref path, ref fields, etc) => {
         print_path(s, path, true);
         word(s.s, "{");
-        fn print_field(s: @ps, f: &ast::field_pat, refutable: bool) {
+        fn print_field(s: @ps, f: &ast::field_pat) {
             cbox(s, indent_unit);
             print_ident(s, f.ident);
             word_space(s, ":");
-            print_pat(s, f.pat, refutable);
+            print_pat(s, f.pat);
             end(s);
         }
         fn get_span(f: &ast::field_pat) -> codemap::span { return f.pat.span; }
         commasep_cmnt(s, consistent, *fields,
-                      |s, f| print_field(s,f,refutable),
+                      |s, f| print_field(s,f),
                       get_span);
         if etc {
             if fields.len() != 0u { word_space(s, ","); }
@@ -1597,7 +1587,7 @@ pub fn print_pat(s: @ps, pat: &ast::pat, refutable: bool) {
       }
       ast::pat_tup(ref elts) => {
         popen(s);
-        commasep(s, inconsistent, *elts, |s, &p| print_pat(s, p, refutable));
+        commasep(s, inconsistent, *elts, |s, &p| print_pat(s, p));
         if elts.len() == 1 {
             word(s.s, ",");
         }
@@ -1605,15 +1595,15 @@ pub fn print_pat(s: @ps, pat: &ast::pat, refutable: bool) {
       }
       ast::pat_box(inner) => {
           word(s.s, "@");
-          print_pat(s, inner, refutable);
+          print_pat(s, inner);
       }
       ast::pat_uniq(inner) => {
           word(s.s, "~");
-          print_pat(s, inner, refutable);
+          print_pat(s, inner);
       }
       ast::pat_region(inner) => {
           word(s.s, "&");
-          print_pat(s, inner, refutable);
+          print_pat(s, inner);
       }
       ast::pat_lit(e) => print_expr(s, e),
       ast::pat_range(begin, end) => {
@@ -1625,16 +1615,16 @@ pub fn print_pat(s: @ps, pat: &ast::pat, refutable: bool) {
       ast::pat_vec(ref before, slice, ref after) => {
         word(s.s, "[");
         do commasep(s, inconsistent, *before) |s, &p| {
-            print_pat(s, p, refutable);
+            print_pat(s, p);
         }
         for slice.iter().advance |&p| {
             if !before.is_empty() { word_space(s, ","); }
             word(s.s, "..");
-            print_pat(s, p, refutable);
+            print_pat(s, p);
             if !after.is_empty() { word_space(s, ","); }
         }
         do commasep(s, inconsistent, *after) |s, &p| {
-            print_pat(s, p, refutable);
+            print_pat(s, p);
         }
         word(s.s, "]");
       }
@@ -1888,7 +1878,7 @@ pub fn print_arg(s: @ps, input: &ast::arg) {
         word_space(s, "mut");
     }
     match input.ty.node {
-      ast::ty_infer => print_irrefutable_pat(s, input.pat),
+      ast::ty_infer => print_pat(s, input.pat),
       _ => {
         match input.pat.node {
             ast::pat_ident(_, ref path, _) if
@@ -1897,7 +1887,7 @@ pub fn print_arg(s: @ps, input: &ast::arg) {
                 // Do nothing.
             }
             _ => {
-                print_irrefutable_pat(s, input.pat);
+                print_pat(s, input.pat);
                 word(s.s, ":");
                 space(s.s);
             }