auto merge of #5122 : sanxiyn/rust/vec-match-tail-2, r=nikomatsakis
Incorporated @nikomatsakis's comments from #4748. Fix #4635.
This commit is contained in:
commit
51cdca0bf0
@ -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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<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 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_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 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 args = extract_vec_elems(opt_cx, pat_id, n, tail, val);
|
||||
let slice = match *opt {
|
||||
vec_len_ge(_, i) => Some(i),
|
||||
_ => None
|
||||
};
|
||||
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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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(_, _, _) |
|
||||
|
@ -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))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
let mut is_slice = false;
|
||||
if before_slice {
|
||||
if *self.token == token::DOTDOT {
|
||||
self.bump();
|
||||
is_tail = true;
|
||||
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)
|
||||
|
@ -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, ~"]");
|
||||
}
|
||||
|
@ -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 tail.each |tail| {
|
||||
for slice.each |elt| {
|
||||
(v.visit_pat)(*elt, e, v);
|
||||
}
|
||||
for after.each |tail| {
|
||||
(v.visit_pat)(*tail, e, v);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
fn main() {
|
||||
match ~[] {
|
||||
[_, ..tail, _] => {}, //~ ERROR: expected `]` but found `,`
|
||||
_ => ()
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
fn main() {
|
||||
let a = ~[];
|
||||
match a {
|
||||
[1, ..tail, ..tail] => {}, //~ ERROR: expected `]` but found `,`
|
||||
[1, ..tail, ..tail] => {}, //~ ERROR: unexpected token: `..`
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
@ -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() {}
|
||||
|
33
src/test/run-pass/vec-matching-fold.rs
Normal file
33
src/test/run-pass/vec-matching-fold.rs
Normal file
@ -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);
|
||||
}
|
@ -1,33 +1,54 @@
|
||||
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 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()
|
||||
}
|
||||
}
|
||||
|
||||
fn b() {
|
||||
let x = [1, 2, 3];
|
||||
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!()
|
||||
}
|
||||
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!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let x = [1, 2, 3, 4, 5];
|
||||
match x {
|
||||
[a, b, c, d, e, f] => {
|
||||
::core::util::unreachable();
|
||||
}
|
||||
[a, b, c, d, e] => {
|
||||
fail_unless!(a == 1);
|
||||
fail_unless!(b == 2);
|
||||
fail_unless!(c == 3);
|
||||
fail_unless!(d == 4);
|
||||
fail_unless!(e == 5);
|
||||
}
|
||||
_ => {
|
||||
::core::util::unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
let product = foldl(x, 1, |a, b| a * *b);
|
||||
fail_unless!(product == 120);
|
||||
a();
|
||||
b();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user