diff --git a/src/librustc/middle/borrowck/gather_loans.rs b/src/librustc/middle/borrowck/gather_loans.rs index 94c266ab44fcb..6e998864def57 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -617,17 +617,17 @@ pub impl GatherLoanCtxt { } } - 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 @@ pub impl GatherLoanCtxt { 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 @@ pub impl GatherLoanCtxt { * 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 @@ pub impl GatherLoanCtxt { _ => { 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")); } } } diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index a60b0332b8fb4..a7fb1506d181b 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -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 { 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 } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 00cab7961cada..85ff970be1cac 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -963,16 +963,19 @@ pub impl mem_categorization_ctxt { 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); } } diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 8411064c57aef..d4a7c104500ba 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -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 @@ pub fn get_options(bcx: block, m: &[@Match], col: uint) -> ~[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, + 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; diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 1da4cbe7c91cc..4b7def26fd559 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -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); } } } diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 818a444a4f38c..55d027549e30c 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -896,7 +896,7 @@ pub mod guarantor { } 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 @@ pub mod guarantor { 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); } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 3782208eb851c..f3e73823f69b3 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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] diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 686ae3900ff43..7b0e72e6e956e 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -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(_, _, _) | diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index b8371c9e8d962..2a5fe7887704d 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -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)) ) } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index adcaa006247fa..38cd09abad42b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2024,23 +2024,28 @@ pub impl Parser { 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 @@ pub impl Parser { 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 @@ pub impl Parser { } 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) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3744b7a8f6c03..c81c1c8bd0e1a 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1609,13 +1609,19 @@ pub fn print_pat(s: @ps, &&pat: @ast::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, ~"]"); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 6048256b90bfe..f04894729bd0c 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -287,11 +287,14 @@ pub fn visit_pat(p: @pat, e: E, v: vt) { (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 index 4174120b291c6..0000000000000 --- a/src/test/compile-fail/alt-vec-invalid-2.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn main() { - match ~[] { - [_, ..tail, _] => {}, //~ ERROR: expected `]` but found `,` - _ => () - } -} diff --git a/src/test/compile-fail/alt-vec-invalid.rs b/src/test/compile-fail/alt-vec-invalid.rs index b35731c2e4acd..2cf2d5b93b056 100644 --- a/src/test/compile-fail/alt-vec-invalid.rs +++ b/src/test/compile-fail/alt-vec-invalid.rs @@ -1,7 +1,7 @@ fn main() { let a = ~[]; match a { - [1, ..tail, ..tail] => {}, //~ ERROR: expected `]` but found `,` + [1, ..tail, ..tail] => {}, //~ ERROR: unexpected token: `..` _ => () } } diff --git a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs index cec81d8a6ef5b..c8a0dbedd5d95 100644 --- a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs +++ b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs @@ -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 index 0000000000000..1df90bf681cfb --- /dev/null +++ b/src/test/run-pass/vec-matching-fold.rs @@ -0,0 +1,33 @@ +fn foldl( + 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( + 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); +} diff --git a/src/test/run-pass/vec-matching.rs b/src/test/run-pass/vec-matching.rs index 1cbd0d78c021d..1402dd18fc72d 100644 --- a/src/test/run-pass/vec-matching.rs +++ b/src/test/run-pass/vec-matching.rs @@ -1,33 +1,54 @@ -fn foldl( - 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 a() { + let x = [1]; + match x { + [_, _, _, _, _, .._] => ::core::util::unreachable(), + [.._, _, _, _, _] => ::core::util::unreachable(), + [_, .._, _, _] => ::core::util::unreachable(), + [_, _] => ::core::util::unreachable(), + [a] => { + fail_unless!(a == 1); + } + [] => ::core::util::unreachable() } } -pub fn main() { - let x = [1, 2, 3, 4, 5]; +fn b() { + let x = [1, 2, 3]; match x { - [a, b, c, d, e, f] => { - ::core::util::unreachable(); - } - [a, b, c, d, e] => { + [a, b, ..c] => { fail_unless!(a == 1); fail_unless!(b == 2); + fail_unless!(c == &[3]); + } + _ => fail!() + } + match x { + [..a, b, c] => { + fail_unless!(a == &[1]); + fail_unless!(b == 2); fail_unless!(c == 3); - fail_unless!(d == 4); - fail_unless!(e == 5); } - _ => { - ::core::util::unreachable(); + _ => fail!() + } + match x { + [a, ..b, c] => { + fail_unless!(a == 1); + fail_unless!(b == &[2]); + fail_unless!(c == 3); + } + _ => fail!() + } + match x { + [a, b, c] => { + fail_unless!(a == 1); + fail_unless!(b == 2); + fail_unless!(c == 3); } + _ => fail!() } +} - let product = foldl(x, 1, |a, b| a * *b); - fail_unless!(product == 120); +pub fn main() { + a(); + b(); }