]> git.lizzy.rs Git - rust.git/commitdiff
Implement vector destructuring from tail
authorSeo Sanghyeon <sanxiyn@gmail.com>
Tue, 26 Feb 2013 18:58:46 +0000 (03:58 +0900)
committerSeo Sanghyeon <sanxiyn@gmail.com>
Mon, 11 Mar 2013 10:01:51 +0000 (19:01 +0900)
17 files changed:
src/librustc/middle/borrowck/gather_loans.rs
src/librustc/middle/check_match.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/trans/_match.rs
src/librustc/middle/typeck/check/_match.rs
src/librustc/middle/typeck/check/regionck.rs
src/libsyntax/ast.rs
src/libsyntax/ast_util.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/test/compile-fail/alt-vec-invalid-2.rs [deleted file]
src/test/compile-fail/alt-vec-invalid.rs
src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
src/test/run-pass/vec-matching-fold.rs [new file with mode: 0644]
src/test/run-pass/vec-matching.rs

index 94c266ab44fcb296c8e2056f270e500feed36ebb..6e998864def57e658e0366e9509a0e89de9904b6 100644 (file)
@@ -617,17 +617,17 @@ fn gather_pat(@mut self,
                 }
               }
 
-              ast::pat_vec(_, Some(tail_pat)) => {
-                  // The `tail_pat` here creates a slice into the
+              ast::pat_vec(_, Some(slice_pat), _) => {
+                  // The `slice_pat` here creates a slice into the
                   // original vector.  This is effectively a borrow of
                   // the elements of the vector being matched.
 
-                  let tail_ty = self.tcx().ty(tail_pat);
-                  let (tail_mutbl, tail_r) =
-                      self.vec_slice_info(tail_pat, tail_ty);
+                  let slice_ty = self.tcx().ty(slice_pat);
+                  let (slice_mutbl, slice_r) =
+                      self.vec_slice_info(slice_pat, slice_ty);
                   let mcx = self.bccx.mc_ctxt();
-                  let cmt_index = mcx.cat_index(tail_pat, cmt);
-                  self.guarantee_valid(cmt_index, tail_mutbl, tail_r);
+                  let cmt_index = mcx.cat_index(slice_pat, cmt);
+                  self.guarantee_valid(cmt_index, slice_mutbl, slice_r);
               }
 
               _ => {}
@@ -637,7 +637,7 @@ fn gather_pat(@mut self,
 
     fn vec_slice_info(@mut self,
                       pat: @ast::pat,
-                      tail_ty: ty::t) -> (ast::mutability, ty::Region) {
+                      slice_ty: ty::t) -> (ast::mutability, ty::Region) {
         /*!
          *
          * In a pattern like [a, b, ..c], normally `c` has slice type,
@@ -646,9 +646,9 @@ fn vec_slice_info(@mut self,
          * to recurse through rptrs.
          */
 
-        match ty::get(tail_ty).sty {
-            ty::ty_evec(tail_mt, ty::vstore_slice(tail_r)) => {
-                (tail_mt.mutbl, tail_r)
+        match ty::get(slice_ty).sty {
+            ty::ty_evec(slice_mt, ty::vstore_slice(slice_r)) => {
+                (slice_mt.mutbl, slice_r)
             }
 
             ty::ty_rptr(_, ref mt) => {
@@ -658,7 +658,7 @@ fn vec_slice_info(@mut self,
             _ => {
                 self.tcx().sess.span_bug(
                     pat.span,
-                    fmt!("Type of tail pattern is not a slice"));
+                    fmt!("Type of slice pattern is not a slice"));
             }
         }
     }
index a60b0332b8fb4d485a60e9b694aea10ddedbfffa..a7fb1506d181b0a65aab9d81308839d9e288e286 100644 (file)
@@ -244,7 +244,9 @@ pub fn is_useful(cx: @MatchCheckCtxt, m: &matrix, v: &[@pat]) -> useful {
               ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
                 let max_len = do m.foldr(0) |r, max_len| {
                   match /*bad*/copy r[0].node {
-                    pat_vec(elems, _) => uint::max(elems.len(), max_len),
+                    pat_vec(before, _, after) => {
+                      uint::max(before.len() + after.len(), max_len)
+                    }
                     _ => max_len
                   }
                 };
@@ -322,10 +324,10 @@ pub fn pat_ctor_id(cx: @MatchCheckCtxt, p: @pat) -> Option<ctor> {
       pat_box(_) | pat_uniq(_) | pat_tup(_) | pat_region(*) => {
         Some(single)
       }
-      pat_vec(elems, tail) => {
-        match tail {
+      pat_vec(before, slice, after) => {
+        match slice {
           Some(_) => None,
-          None => Some(vec(elems.len()))
+          None => Some(vec(before.len() + after.len()))
         }
       }
     }
@@ -393,22 +395,22 @@ pub fn missing_ctor(cx: @MatchCheckCtxt,
       }
       ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
 
-        // Find the lengths and tails of all vector patterns.
+        // Find the lengths and slices of all vector patterns.
         let vec_pat_lens = do m.filter_mapped |r| {
             match r[0].node {
-                pat_vec(ref elems, ref tail) => {
-                    Some((elems.len(), tail.is_some()))
+                pat_vec(ref before, ref slice, ref after) => {
+                    Some((before.len() + after.len(), slice.is_some()))
                 }
                 _ => None
             }
         };
 
         // Sort them by length such that for patterns of the same length,
-        // those with a destructured tail come first.
+        // those with a destructured slice come first.
         let mut sorted_vec_lens = sort::merge_sort(vec_pat_lens,
-            |&(len1, tail1), &(len2, tail2)| {
+            |&(len1, slice1), &(len2, slice2)| {
                 if len1 == len2 {
-                    tail1 > tail2
+                    slice1 > slice2
                 } else {
                     len1 <= len2
                 }
@@ -416,24 +418,24 @@ pub fn missing_ctor(cx: @MatchCheckCtxt,
         );
         vec::dedup(&mut sorted_vec_lens);
 
-        let mut found_tail = false;
+        let mut found_slice = false;
         let mut next = 0;
         let mut missing = None;
-        for sorted_vec_lens.each |&(length, tail)| {
+        for sorted_vec_lens.each |&(length, slice)| {
             if length != next {
                 missing = Some(next);
                 break;
             }
-            if tail {
-                found_tail = true;
+            if slice {
+                found_slice = true;
                 break;
             }
             next += 1;
         }
 
         // We found patterns of all lengths within <0, next), yet there was no
-        // pattern with a tail - therefore, we report vec(next) as missing.
-        if !found_tail {
+        // pattern with a slice - therefore, we report vec(next) as missing.
+        if !found_slice {
             missing = Some(next);
         }
         match missing {
@@ -621,19 +623,25 @@ pub fn specialize(cx: @MatchCheckCtxt,
                     compare_const_vals(c_hi, v_hi) <= 0;
           if match_ { Some(vec::from_slice(r.tail())) } else { None }
       }
-            pat_vec(elems, tail) => {
+            pat_vec(before, slice, after) => {
                 match ctor_id {
                     vec(_) => {
-                        let num_elements = elems.len();
-                        if num_elements < arity && tail.is_some() {
+                        let num_elements = before.len() + after.len();
+                        if num_elements < arity && slice.is_some() {
                             Some(vec::append(
-                                vec::append(elems, vec::from_elem(
-                                    arity - num_elements, wild()
-                                )),
-                                vec::from_slice(r.tail())
+                                vec::concat(&[
+                                    before,
+                                    vec::from_elem(
+                                        arity - num_elements, wild()),
+                                    after
+                                ]),
+                                r.tail()
                             ))
                         } else if num_elements == arity {
-                            Some(vec::append(elems, r.tail()))
+                            Some(vec::append(
+                                vec::append(before, after),
+                                r.tail()
+                            ))
                         } else {
                             None
                         }
index 00cab7961cada0b4238477eec5ab14b3ba682488..85ff970be1cac5912a36b66ea8a836af7657c6bb 100644 (file)
@@ -963,16 +963,19 @@ fn cat_pattern(&self,
             self.cat_pattern(subcmt, subpat, op);
           }
 
-          ast::pat_vec(ref pats, opt_tail_pat) => {
-              for pats.each |pat| {
+          ast::pat_vec(ref before, slice, ref after) => {
+              for before.each |pat| {
                   let elt_cmt = self.cat_index(*pat, cmt);
                   self.cat_pattern(elt_cmt, *pat, op);
               }
-
-              for opt_tail_pat.each |tail_pat| {
-                  let tail_ty = self.tcx.ty(*tail_pat);
-                  let tail_cmt = self.cat_rvalue(*tail_pat, tail_ty);
-                  self.cat_pattern(tail_cmt, *tail_pat, op);
+              for slice.each |slice_pat| {
+                  let slice_ty = self.tcx.ty(*slice_pat);
+                  let slice_cmt = self.cat_rvalue(*slice_pat, slice_ty);
+                  self.cat_pattern(slice_cmt, *slice_pat, op);
+              }
+              for after.each |pat| {
+                  let elt_cmt = self.cat_index(*pat, cmt);
+                  self.cat_pattern(elt_cmt, *pat, op);
               }
           }
 
index 8411064c57aefb26501fad3d5f6462e58a23a152..d4a7c104500ba031f70ecdc883e3e9e3d30af2b0 100644 (file)
@@ -190,7 +190,7 @@ pub enum Opt {
     var(/* disr val */int, @adt::Repr),
     range(@ast::expr, @ast::expr),
     vec_len_eq(uint),
-    vec_len_ge(uint)
+    vec_len_ge(uint, /* slice */uint)
 }
 
 pub fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
@@ -235,7 +235,7 @@ pub fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
       }
       (&var(a, _), &var(b, _)) => a == b,
       (&vec_len_eq(a), &vec_len_eq(b)) => a == b,
-      (&vec_len_ge(a), &vec_len_ge(b)) => a == b,
+      (&vec_len_ge(a, _), &vec_len_ge(b, _)) => a == b,
       _ => false
     }
 }
@@ -273,7 +273,7 @@ pub fn trans_opt(bcx: block, o: &Opt) -> opt_result {
         vec_len_eq(n) => {
             return single_result(rslt(bcx, C_int(ccx, n as int)));
         }
-        vec_len_ge(n) => {
+        vec_len_ge(n, _) => {
             return lower_bound(rslt(bcx, C_int(ccx, n as int)));
         }
     }
@@ -565,18 +565,22 @@ pub fn enter_opt(bcx: block, m: &[@Match/&r], opt: &Opt, col: uint,
                     None
                 }
             }
-            ast::pat_vec(elems, tail) => {
-                match tail {
+            ast::pat_vec(before, slice, after) => {
+                match slice {
                     Some(_) => {
-                        if opt_eq(tcx, &vec_len_ge(elems.len()), opt) {
-                            Some(vec::append_one(elems, tail.get()))
+                        let n = before.len() + after.len();
+                        let i = before.len();
+                        if opt_eq(tcx, &vec_len_ge(n, i), opt) {
+                            Some(vec::concat(
+                                &[before, ~[slice.get()], after]))
                         } else {
                             None
                         }
                     }
                     None => {
-                        if opt_eq(tcx, &vec_len_eq(elems.len()), opt) {
-                            Some(copy elems)
+                        let n = before.len();
+                        if opt_eq(tcx, &vec_len_eq(n), opt) {
+                            Some(copy before)
                         } else {
                             None
                         }
@@ -807,10 +811,11 @@ fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], +val: Opt) {
             ast::pat_range(l1, l2) => {
                 add_to_set(ccx.tcx, &mut found, range(l1, l2));
             }
-            ast::pat_vec(elems, tail) => {
-                let opt = match tail {
-                    None => vec_len_eq(elems.len()),
-                    Some(_) => vec_len_ge(elems.len())
+            ast::pat_vec(before, slice, after) => {
+                let opt = match slice {
+                    None => vec_len_eq(before.len()),
+                    Some(_) => vec_len_ge(before.len() + after.len(),
+                                          before.len())
                 };
                 add_to_set(ccx.tcx, &mut found, opt);
             }
@@ -841,8 +846,9 @@ pub fn extract_variant_args(bcx: block,
 pub fn extract_vec_elems(bcx: block,
                          pat_id: ast::node_id,
                          elem_count: uint,
-                         tail: bool,
-                         val: ValueRef)
+                         slice: Option<uint>,
+                         val: ValueRef,
+                         count: ValueRef)
                       -> ExtractedBlock {
     let _icx = bcx.insn_ctxt("match::extract_vec_elems");
     let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
@@ -850,26 +856,39 @@ pub fn extract_vec_elems(bcx: block,
     let (base, len) = tvec::get_base_and_len(bcx, unboxed, vt.vec_ty);
 
     let mut elems = do vec::from_fn(elem_count) |i| {
-        GEPi(bcx, base, ~[i])
+        match slice {
+            None => GEPi(bcx, base, ~[i]),
+            Some(n) if i < n => GEPi(bcx, base, ~[i]),
+            Some(n) if i > n => {
+                InBoundsGEP(bcx, base, ~[
+                    Sub(bcx, count,
+                        C_int(bcx.ccx(), (elem_count - i) as int))])
+            }
+            _ => unsafe { llvm::LLVMGetUndef(vt.llunit_ty) }
+        }
     };
-    if tail {
-        let tail_offset = Mul(bcx, vt.llunit_size,
-            C_int(bcx.ccx(), elem_count as int)
+    if slice.is_some() {
+        let n = slice.get();
+        let slice_offset = Mul(bcx, vt.llunit_size,
+            C_int(bcx.ccx(), n as int)
+        );
+        let slice_begin = tvec::pointer_add(bcx, base, slice_offset);
+        let slice_len_offset = Mul(bcx, vt.llunit_size,
+            C_int(bcx.ccx(), (elem_count - 1u) as int)
         );
-        let tail_begin = tvec::pointer_add(bcx, base, tail_offset);
-        let tail_len = Sub(bcx, len, tail_offset);
-        let tail_ty = ty::mk_evec(bcx.tcx(),
+        let slice_len = Sub(bcx, len, slice_len_offset);
+        let slice_ty = ty::mk_evec(bcx.tcx(),
             ty::mt {ty: vt.unit_ty, mutbl: ast::m_imm},
             ty::vstore_slice(ty::re_static)
         );
-        let scratch = scratch_datum(bcx, tail_ty, false);
-        Store(bcx, tail_begin,
+        let scratch = scratch_datum(bcx, slice_ty, false);
+        Store(bcx, slice_begin,
             GEPi(bcx, scratch.val, [0u, abi::slice_elt_base])
         );
-        Store(bcx, tail_len,
+        Store(bcx, slice_len,
             GEPi(bcx, scratch.val, [0u, abi::slice_elt_len])
         );
-        elems.push(scratch.val);
+        elems[n] = scratch.val;
         scratch.add_clean(bcx);
     }
 
@@ -1367,7 +1386,7 @@ pub fn compile_submatch(bcx: block,
                 test_val = Load(bcx, val);
                 kind = compare;
             },
-            vec_len_eq(_) | vec_len_ge(_) => {
+            vec_len_eq(*) | vec_len_ge(*) => {
                 let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
                 let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
                 let (_, len) = tvec::get_base_and_len(
@@ -1511,12 +1530,17 @@ pub fn compile_submatch(bcx: block,
                 unpacked = argvals;
                 opt_cx = new_bcx;
             }
-            vec_len_eq(n) | vec_len_ge(n) => {
-                let tail = match *opt {
-                    vec_len_ge(_) => true,
-                    _ => false
+            vec_len_eq(n) | vec_len_ge(n, _) => {
+                let n = match *opt {
+                    vec_len_ge(*) => n + 1u,
+                    _ => n
+                };
+                let slice = match *opt {
+                    vec_len_ge(_, i) => Some(i),
+                    _ => None
                 };
-                let args = extract_vec_elems(opt_cx, pat_id, n, tail, val);
+                let args = extract_vec_elems(opt_cx, pat_id, n, slice,
+                    val, test_val);
                 size = args.vals.len();
                 unpacked = /*bad*/copy args.vals;
                 opt_cx = args.bcx;
index 1da4cbe7c91cc2fe6f3e8a929d8c9233d675ca6b..4b7def26fd559a4f7907aa844625f8eafbd38cde 100644 (file)
@@ -509,7 +509,7 @@ pub fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
           }
         }
       }
-      ast::pat_vec(elts, tail) => {
+      ast::pat_vec(before, slice, after) => {
         let default_region_var =
             fcx.infcx().next_region_var_with_lb(
                 pat.span, pcx.block_region
@@ -538,21 +538,23 @@ pub fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
             );
           }
         };
-        for elts.each |elt| {
+        for before.each |elt| {
             check_pat(pcx, *elt, elt_type.ty);
         }
-        fcx.write_ty(pat.id, expected);
-
-        match tail {
-            Some(tail_pat) => {
+        match slice {
+            Some(slice_pat) => {
                 let slice_ty = ty::mk_evec(tcx,
                     ty::mt {ty: elt_type.ty, mutbl: elt_type.mutbl},
                     ty::vstore_slice(region_var)
                 );
-                check_pat(pcx, tail_pat, slice_ty);
+                check_pat(pcx, slice_pat, slice_ty);
             }
             None => ()
         }
+        for after.each |elt| {
+            check_pat(pcx, *elt, elt_type.ty);
+        }
+        fcx.write_ty(pat.id, expected);
       }
     }
 }
index 818a444a4f38c339aaf8c03d255864570dff9069..55d027549e30cd3d5ec5a878ffc1cec8666ed8b2 100644 (file)
@@ -896,7 +896,7 @@ fn link_ref_bindings_in_pat(
             }
             ast::pat_lit(*) => {}
             ast::pat_range(*) => {}
-            ast::pat_vec(ref ps, ref opt_tail_pat) => {
+            ast::pat_vec(ref before, ref slice, ref after) => {
                 let vec_ty = rcx.resolve_node_type(pat.id);
                 if !ty::type_contains_err(vec_ty) {
                     let vstore = ty::ty_vstore(vec_ty);
@@ -906,11 +906,11 @@ fn link_ref_bindings_in_pat(
                         ty::vstore_box => None
                     };
 
-                    link_ref_bindings_in_pats(rcx, ps, guarantor1);
-
-                    for opt_tail_pat.each |p| {
-                        link_ref_bindings_in_pat(rcx, *p, guarantor);
+                    link_ref_bindings_in_pats(rcx, before, guarantor1);
+                    for slice.each |&p| {
+                        link_ref_bindings_in_pat(rcx, p, guarantor);
                     }
+                    link_ref_bindings_in_pats(rcx, after, guarantor1);
                 }
             }
         }
index 3782208eb851ce97ae7001194a6a10228c01a69d..f3e73823f69b32c235cb95c07f4d3d211ca4940a 100644 (file)
@@ -309,7 +309,9 @@ pub enum pat_ {
     pat_region(@pat), // borrowed pointer pattern
     pat_lit(@expr),
     pat_range(@expr, @expr),
-    pat_vec(~[@pat], Option<@pat>)
+    // [a, b, ..i, y, z] is represented as
+    // pat_vec(~[a, b], Some(i), ~[y, z])
+    pat_vec(~[@pat], Option<@pat>, ~[@pat])
 }
 
 #[auto_encode]
index 686ae3900ff43e4d249f885141cf22ddb3f94419..7b0e72e6e956e6dcdf1d9b36142c3e97762fef06 100644 (file)
@@ -533,12 +533,15 @@ pub fn walk_pat(pat: @pat, it: fn(@pat)) {
         pat_box(s) | pat_uniq(s) | pat_region(s) => {
             walk_pat(s, it)
         }
-        pat_vec(ref elts, ref tail) => {
-            for elts.each |p| {
+        pat_vec(ref before, ref slice, ref after) => {
+            for before.each |p| {
                 walk_pat(*p, it)
             }
-            for tail.each |tail| {
-                walk_pat(*tail, it)
+            for slice.each |p| {
+                walk_pat(*p, it)
+            }
+            for after.each |p| {
+                walk_pat(*p, it)
             }
         }
         pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _, _) |
index b8371c9e8d9623918a26830b0116ab42d3548ddd..2a5fe7887704d89fa3e6a5f8395355bcbd6e738d 100644 (file)
@@ -416,10 +416,11 @@ pub fn noop_fold_pat(p: &pat_, fld: @ast_fold) -> pat_ {
         pat_range(e1, e2) => {
             pat_range(fld.fold_expr(e1), fld.fold_expr(e2))
         },
-        pat_vec(ref elts, ref tail) => {
+        pat_vec(ref before, ref slice, ref after) => {
             pat_vec(
-                elts.map(|x| fld.fold_pat(*x)),
-                tail.map(|tail| fld.fold_pat(*tail))
+                before.map(|x| fld.fold_pat(*x)),
+                slice.map(|x| fld.fold_pat(*x)),
+                after.map(|x| fld.fold_pat(*x))
             )
         }
     }
index adcaa006247fa3e3e2b826ea91d1918e4b2553d5..38cd09abad42b2fcfba9f211c0ab2f1a63a046f3 100644 (file)
@@ -2024,23 +2024,28 @@ fn parse_pats(&self) -> ~[@pat] {
     fn parse_pat_vec_elements(
         &self,
         refutable: bool
-    ) -> (~[@pat], Option<@pat>) {
-        let mut elements = ~[];
-        let mut tail = None;
+    ) -> (~[@pat], Option<@pat>, ~[@pat]) {
+        let mut before = ~[];
+        let mut slice = None;
+        let mut after = ~[];
         let mut first = true;
+        let mut before_slice = true;
 
         while *self.token != token::RBRACKET {
             if first { first = false; }
             else { self.expect(&token::COMMA); }
 
-            let mut is_tail = false;
-            if *self.token == token::DOTDOT {
-                self.bump();
-                is_tail = true;
+            let mut is_slice = false;
+            if before_slice {
+                if *self.token == token::DOTDOT {
+                    self.bump();
+                    is_slice = true;
+                    before_slice = false;
+                }
             }
 
             let subpat = self.parse_pat(refutable);
-            if is_tail {
+            if is_slice {
                 match subpat {
                     @ast::pat { node: pat_wild, _ } => (),
                     @ast::pat { node: pat_ident(_, _, _), _ } => (),
@@ -2048,13 +2053,17 @@ fn parse_pat_vec_elements(
                         span, ~"expected an identifier or `_`"
                     )
                 }
-                tail = Some(subpat);
-                break;
+                slice = Some(subpat);
+            } else {
+                if before_slice {
+                    before.push(subpat);
+                } else {
+                    after.push(subpat);
+                }
             }
-
-            elements.push(subpat);
         }
-        return (elements, tail);
+
+        (before, slice, after)
     }
 
     fn parse_pat_fields(&self, refutable: bool) -> (~[ast::field_pat], bool) {
@@ -2208,10 +2217,11 @@ fn parse_pat(&self, refutable: bool) -> @pat {
           }
           token::LBRACKET => {
             self.bump();
-            let (elements, tail) = self.parse_pat_vec_elements(refutable);
+            let (before, slice, after) =
+                self.parse_pat_vec_elements(refutable);
             hi = self.span.hi;
             self.expect(&token::RBRACKET);
-            pat = ast::pat_vec(elements, tail);
+            pat = ast::pat_vec(before, slice, after);
           }
           copy tok => {
             if !is_ident_or_path(&tok)
index 3744b7a8f6c0382b9ca7a7279db895685264751b..c81c1c8bd0e1a6f070ee318091924ab0c07a8373 100644 (file)
@@ -1609,13 +1609,19 @@ fn print_field(s: @ps, f: ast::field_pat, refutable: bool) {
         word(s.s, ~"..");
         print_expr(s, end);
       }
-      ast::pat_vec(elts, tail) => {
+      ast::pat_vec(before, slice, after) => {
         word(s.s, ~"[");
-        commasep(s, inconsistent, elts, |s, p| print_pat(s, p, refutable));
-        for tail.each |tail| {
-            if vec::len(elts) != 0u { word_space(s, ~","); }
+        do commasep(s, inconsistent, before) |s, p| {
+            print_pat(s, p, refutable);
+        }
+        for slice.each |&p| {
+            if !before.is_empty() { word_space(s, ~","); }
             word(s.s, ~"..");
-            print_pat(s, *tail, refutable);
+            print_pat(s, p, refutable);
+            if !after.is_empty() { word_space(s, ~","); }
+        }
+        do commasep(s, inconsistent, after) |s, p| {
+            print_pat(s, p, refutable);
         }
         word(s.s, ~"]");
       }
index 6048256b90bfeb8d6760c37fd977632d993d6fe7..f04894729bd0c2a5b9d92d9ec29dab7cdc46fb8e 100644 (file)
@@ -287,11 +287,14 @@ pub fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
             (v.visit_expr)(e2, e, v);
         }
         pat_wild => (),
-        pat_vec(ref elts, ref tail) => {
-            for elts.each |elt| {
+        pat_vec(ref before, ref slice, ref after) => {
+            for before.each |elt| {
+                (v.visit_pat)(*elt, e, v);
+            }
+            for slice.each |elt| {
                 (v.visit_pat)(*elt, e, v);
             }
-            for tail.each |tail| {
+            for after.each |tail| {
                 (v.visit_pat)(*tail, e, v);
             }
         }
diff --git a/src/test/compile-fail/alt-vec-invalid-2.rs b/src/test/compile-fail/alt-vec-invalid-2.rs
deleted file mode 100644 (file)
index 4174120..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
-    match ~[] {
-        [_, ..tail, _] => {}, //~ ERROR: expected `]` but found `,`
-        _ => ()
-    }
-}
index b35731c2e4acd211408dfd80930fddc14d9f0f5b..2cf2d5b93b056c5db559089cc0dd392af5d4d092 100644 (file)
@@ -1,7 +1,7 @@
 fn main() {
     let a = ~[];
     match a {
-        [1, ..tail, ..tail] => {}, //~ ERROR: expected `]` but found `,`
+        [1, ..tail, ..tail] => {}, //~ ERROR: unexpected token: `..`
         _ => ()
     }
 }
index cec81d8a6ef5b4c39935f9aefd3a887944e97f92..c8a0dbedd5d95476197f0f010bb7dd5d7912db4c 100644 (file)
@@ -1,15 +1,28 @@
 fn a() -> &[int] {
     let vec = [1, 2, 3, 4];
     let tail = match vec { //~ ERROR illegal borrow
-        [_a, ..tail] => tail,
-        _ => fail!(~"foo")
+        [_, ..tail] => tail,
+        _ => fail!(~"a")
     };
     tail
 }
 
-fn main() {
-    let tail = a();
-    for tail.each |n| {
-        io::println(fmt!("%d", *n));
-    }
+fn b() -> &[int] {
+    let vec = [1, 2, 3, 4];
+    let init = match vec { //~ ERROR illegal borrow
+        [..init, _] => init,
+        _ => fail!(~"b")
+    };
+    init
 }
+
+fn c() -> &[int] {
+    let vec = [1, 2, 3, 4];
+    let slice = match vec { //~ ERROR illegal borrow
+        [_, ..slice, _] => slice,
+        _ => fail!(~"c")
+    };
+    slice
+}
+
+fn main() {}
diff --git a/src/test/run-pass/vec-matching-fold.rs b/src/test/run-pass/vec-matching-fold.rs
new file mode 100644 (file)
index 0000000..1df90bf
--- /dev/null
@@ -0,0 +1,33 @@
+fn foldl<T, U: Copy>(
+    values: &[T],
+    initial: U,
+    function: &fn(partial: U, element: &T) -> U
+) -> U {
+    match values {
+        [head, ..tail] =>
+            foldl(tail, function(initial, &head), function),
+        [] => copy initial
+    }
+}
+
+fn foldr<T, U: Copy>(
+    values: &[T],
+    initial: U,
+    function: &fn(element: &T, partial: U) -> U
+) -> U {
+    match values {
+        [..head, tail] =>
+            foldr(head, function(&tail, initial), function),
+        [] => copy initial
+    }
+}
+
+pub fn main() {
+    let x = [1, 2, 3, 4, 5];
+
+    let product = foldl(x, 1, |a, b| a * *b);
+    fail_unless!(product == 120);
+
+    let sum = foldr(x, 0, |a, b| *a + b);
+    fail_unless!(sum == 15);
+}
index 1cbd0d78c021d44a62a7d6dd7886abf30af71d33..e1243e18f5ffbde1720605d7fd2dd9ab5c5e3312 100644 (file)
@@ -1,33 +1,13 @@
-fn foldl<T, U: Copy>(
-    values: &[T],
-    initial: U,
-    function: &fn(partial: U, element: &T) -> U
-) -> U {
-    match values {
-        [head, ..tail] =>
-            foldl(tail, function(initial, &head), function),
-        _ => copy initial
-    }
-}
-
 pub fn main() {
-    let x = [1, 2, 3, 4, 5];
+    let x = [1];
     match x {
-        [a, b, c, d, e, f] => {
-            ::core::util::unreachable();
-        }
-        [a, b, c, d, e] => {
+        [_, _, _, _, _, .._] => ::core::util::unreachable(),
+        [.._, _, _, _, _] => ::core::util::unreachable(),
+        [_, .._, _, _] => ::core::util::unreachable(),
+        [_, _] => ::core::util::unreachable(),
+        [a] => {
             fail_unless!(a == 1);
-            fail_unless!(b == 2);
-            fail_unless!(c == 3);
-            fail_unless!(d == 4);
-            fail_unless!(e == 5);
-        }
-        _ => {
-            ::core::util::unreachable();
         }
+        [] => ::core::util::unreachable()
     }
-
-    let product = foldl(x, 1, |a, b| a * *b);
-    fail_unless!(product == 120);
 }