Skip to content

Commit 51cdca0

Browse files
committed
auto merge of #5122 : sanxiyn/rust/vec-match-tail-2, r=nikomatsakis
Incorporated @nikomatsakis's comments from #4748. Fix #4635.
2 parents 58618fb + 070137c commit 51cdca0

17 files changed

+276
-153
lines changed

src/librustc/middle/borrowck/gather_loans.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -617,17 +617,17 @@ pub impl GatherLoanCtxt {
617617
}
618618
}
619619

620-
ast::pat_vec(_, Some(tail_pat)) => {
621-
// The `tail_pat` here creates a slice into the
620+
ast::pat_vec(_, Some(slice_pat), _) => {
621+
// The `slice_pat` here creates a slice into the
622622
// original vector. This is effectively a borrow of
623623
// the elements of the vector being matched.
624624

625-
let tail_ty = self.tcx().ty(tail_pat);
626-
let (tail_mutbl, tail_r) =
627-
self.vec_slice_info(tail_pat, tail_ty);
625+
let slice_ty = self.tcx().ty(slice_pat);
626+
let (slice_mutbl, slice_r) =
627+
self.vec_slice_info(slice_pat, slice_ty);
628628
let mcx = self.bccx.mc_ctxt();
629-
let cmt_index = mcx.cat_index(tail_pat, cmt);
630-
self.guarantee_valid(cmt_index, tail_mutbl, tail_r);
629+
let cmt_index = mcx.cat_index(slice_pat, cmt);
630+
self.guarantee_valid(cmt_index, slice_mutbl, slice_r);
631631
}
632632

633633
_ => {}
@@ -637,7 +637,7 @@ pub impl GatherLoanCtxt {
637637

638638
fn vec_slice_info(@mut self,
639639
pat: @ast::pat,
640-
tail_ty: ty::t) -> (ast::mutability, ty::Region) {
640+
slice_ty: ty::t) -> (ast::mutability, ty::Region) {
641641
/*!
642642
*
643643
* In a pattern like [a, b, ..c], normally `c` has slice type,
@@ -646,9 +646,9 @@ pub impl GatherLoanCtxt {
646646
* to recurse through rptrs.
647647
*/
648648

649-
match ty::get(tail_ty).sty {
650-
ty::ty_evec(tail_mt, ty::vstore_slice(tail_r)) => {
651-
(tail_mt.mutbl, tail_r)
649+
match ty::get(slice_ty).sty {
650+
ty::ty_evec(slice_mt, ty::vstore_slice(slice_r)) => {
651+
(slice_mt.mutbl, slice_r)
652652
}
653653

654654
ty::ty_rptr(_, ref mt) => {
@@ -658,7 +658,7 @@ pub impl GatherLoanCtxt {
658658
_ => {
659659
self.tcx().sess.span_bug(
660660
pat.span,
661-
fmt!("Type of tail pattern is not a slice"));
661+
fmt!("Type of slice pattern is not a slice"));
662662
}
663663
}
664664
}

src/librustc/middle/check_match.rs

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,9 @@ pub fn is_useful(cx: @MatchCheckCtxt, m: &matrix, v: &[@pat]) -> useful {
244244
ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
245245
let max_len = do m.foldr(0) |r, max_len| {
246246
match /*bad*/copy r[0].node {
247-
pat_vec(elems, _) => uint::max(elems.len(), max_len),
247+
pat_vec(before, _, after) => {
248+
uint::max(before.len() + after.len(), max_len)
249+
}
248250
_ => max_len
249251
}
250252
};
@@ -322,10 +324,10 @@ pub fn pat_ctor_id(cx: @MatchCheckCtxt, p: @pat) -> Option<ctor> {
322324
pat_box(_) | pat_uniq(_) | pat_tup(_) | pat_region(*) => {
323325
Some(single)
324326
}
325-
pat_vec(elems, tail) => {
326-
match tail {
327+
pat_vec(before, slice, after) => {
328+
match slice {
327329
Some(_) => None,
328-
None => Some(vec(elems.len()))
330+
None => Some(vec(before.len() + after.len()))
329331
}
330332
}
331333
}
@@ -393,47 +395,47 @@ pub fn missing_ctor(cx: @MatchCheckCtxt,
393395
}
394396
ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
395397
396-
// Find the lengths and tails of all vector patterns.
398+
// Find the lengths and slices of all vector patterns.
397399
let vec_pat_lens = do m.filter_mapped |r| {
398400
match r[0].node {
399-
pat_vec(ref elems, ref tail) => {
400-
Some((elems.len(), tail.is_some()))
401+
pat_vec(ref before, ref slice, ref after) => {
402+
Some((before.len() + after.len(), slice.is_some()))
401403
}
402404
_ => None
403405
}
404406
};
405407
406408
// Sort them by length such that for patterns of the same length,
407-
// those with a destructured tail come first.
409+
// those with a destructured slice come first.
408410
let mut sorted_vec_lens = sort::merge_sort(vec_pat_lens,
409-
|&(len1, tail1), &(len2, tail2)| {
411+
|&(len1, slice1), &(len2, slice2)| {
410412
if len1 == len2 {
411-
tail1 > tail2
413+
slice1 > slice2
412414
} else {
413415
len1 <= len2
414416
}
415417
}
416418
);
417419
vec::dedup(&mut sorted_vec_lens);
418420
419-
let mut found_tail = false;
421+
let mut found_slice = false;
420422
let mut next = 0;
421423
let mut missing = None;
422-
for sorted_vec_lens.each |&(length, tail)| {
424+
for sorted_vec_lens.each |&(length, slice)| {
423425
if length != next {
424426
missing = Some(next);
425427
break;
426428
}
427-
if tail {
428-
found_tail = true;
429+
if slice {
430+
found_slice = true;
429431
break;
430432
}
431433
next += 1;
432434
}
433435
434436
// We found patterns of all lengths within <0, next), yet there was no
435-
// pattern with a tail - therefore, we report vec(next) as missing.
436-
if !found_tail {
437+
// pattern with a slice - therefore, we report vec(next) as missing.
438+
if !found_slice {
437439
missing = Some(next);
438440
}
439441
match missing {
@@ -621,19 +623,25 @@ pub fn specialize(cx: @MatchCheckCtxt,
621623
compare_const_vals(c_hi, v_hi) <= 0;
622624
if match_ { Some(vec::from_slice(r.tail())) } else { None }
623625
}
624-
pat_vec(elems, tail) => {
626+
pat_vec(before, slice, after) => {
625627
match ctor_id {
626628
vec(_) => {
627-
let num_elements = elems.len();
628-
if num_elements < arity && tail.is_some() {
629+
let num_elements = before.len() + after.len();
630+
if num_elements < arity && slice.is_some() {
629631
Some(vec::append(
630-
vec::append(elems, vec::from_elem(
631-
arity - num_elements, wild()
632-
)),
633-
vec::from_slice(r.tail())
632+
vec::concat(&[
633+
before,
634+
vec::from_elem(
635+
arity - num_elements, wild()),
636+
after
637+
]),
638+
r.tail()
634639
))
635640
} else if num_elements == arity {
636-
Some(vec::append(elems, r.tail()))
641+
Some(vec::append(
642+
vec::append(before, after),
643+
r.tail()
644+
))
637645
} else {
638646
None
639647
}

src/librustc/middle/mem_categorization.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -963,16 +963,19 @@ pub impl mem_categorization_ctxt {
963963
self.cat_pattern(subcmt, subpat, op);
964964
}
965965

966-
ast::pat_vec(ref pats, opt_tail_pat) => {
967-
for pats.each |pat| {
966+
ast::pat_vec(ref before, slice, ref after) => {
967+
for before.each |pat| {
968968
let elt_cmt = self.cat_index(*pat, cmt);
969969
self.cat_pattern(elt_cmt, *pat, op);
970970
}
971-
972-
for opt_tail_pat.each |tail_pat| {
973-
let tail_ty = self.tcx.ty(*tail_pat);
974-
let tail_cmt = self.cat_rvalue(*tail_pat, tail_ty);
975-
self.cat_pattern(tail_cmt, *tail_pat, op);
971+
for slice.each |slice_pat| {
972+
let slice_ty = self.tcx.ty(*slice_pat);
973+
let slice_cmt = self.cat_rvalue(*slice_pat, slice_ty);
974+
self.cat_pattern(slice_cmt, *slice_pat, op);
975+
}
976+
for after.each |pat| {
977+
let elt_cmt = self.cat_index(*pat, cmt);
978+
self.cat_pattern(elt_cmt, *pat, op);
976979
}
977980
}
978981

src/librustc/middle/trans/_match.rs

Lines changed: 56 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ pub enum Opt {
190190
var(/* disr val */int, @adt::Repr),
191191
range(@ast::expr, @ast::expr),
192192
vec_len_eq(uint),
193-
vec_len_ge(uint)
193+
vec_len_ge(uint, /* slice */uint)
194194
}
195195

196196
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 {
235235
}
236236
(&var(a, _), &var(b, _)) => a == b,
237237
(&vec_len_eq(a), &vec_len_eq(b)) => a == b,
238-
(&vec_len_ge(a), &vec_len_ge(b)) => a == b,
238+
(&vec_len_ge(a, _), &vec_len_ge(b, _)) => a == b,
239239
_ => false
240240
}
241241
}
@@ -273,7 +273,7 @@ pub fn trans_opt(bcx: block, o: &Opt) -> opt_result {
273273
vec_len_eq(n) => {
274274
return single_result(rslt(bcx, C_int(ccx, n as int)));
275275
}
276-
vec_len_ge(n) => {
276+
vec_len_ge(n, _) => {
277277
return lower_bound(rslt(bcx, C_int(ccx, n as int)));
278278
}
279279
}
@@ -565,18 +565,22 @@ pub fn enter_opt(bcx: block, m: &[@Match/&r], opt: &Opt, col: uint,
565565
None
566566
}
567567
}
568-
ast::pat_vec(elems, tail) => {
569-
match tail {
568+
ast::pat_vec(before, slice, after) => {
569+
match slice {
570570
Some(_) => {
571-
if opt_eq(tcx, &vec_len_ge(elems.len()), opt) {
572-
Some(vec::append_one(elems, tail.get()))
571+
let n = before.len() + after.len();
572+
let i = before.len();
573+
if opt_eq(tcx, &vec_len_ge(n, i), opt) {
574+
Some(vec::concat(
575+
&[before, ~[slice.get()], after]))
573576
} else {
574577
None
575578
}
576579
}
577580
None => {
578-
if opt_eq(tcx, &vec_len_eq(elems.len()), opt) {
579-
Some(copy elems)
581+
let n = before.len();
582+
if opt_eq(tcx, &vec_len_eq(n), opt) {
583+
Some(copy before)
580584
} else {
581585
None
582586
}
@@ -807,10 +811,11 @@ pub fn get_options(bcx: block, m: &[@Match], col: uint) -> ~[Opt] {
807811
ast::pat_range(l1, l2) => {
808812
add_to_set(ccx.tcx, &mut found, range(l1, l2));
809813
}
810-
ast::pat_vec(elems, tail) => {
811-
let opt = match tail {
812-
None => vec_len_eq(elems.len()),
813-
Some(_) => vec_len_ge(elems.len())
814+
ast::pat_vec(before, slice, after) => {
815+
let opt = match slice {
816+
None => vec_len_eq(before.len()),
817+
Some(_) => vec_len_ge(before.len() + after.len(),
818+
before.len())
814819
};
815820
add_to_set(ccx.tcx, &mut found, opt);
816821
}
@@ -841,35 +846,49 @@ pub fn extract_variant_args(bcx: block,
841846
pub fn extract_vec_elems(bcx: block,
842847
pat_id: ast::node_id,
843848
elem_count: uint,
844-
tail: bool,
845-
val: ValueRef)
849+
slice: Option<uint>,
850+
val: ValueRef,
851+
count: ValueRef)
846852
-> ExtractedBlock {
847853
let _icx = bcx.insn_ctxt("match::extract_vec_elems");
848854
let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
849855
let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
850856
let (base, len) = tvec::get_base_and_len(bcx, unboxed, vt.vec_ty);
851857
852858
let mut elems = do vec::from_fn(elem_count) |i| {
853-
GEPi(bcx, base, ~[i])
859+
match slice {
860+
None => GEPi(bcx, base, ~[i]),
861+
Some(n) if i < n => GEPi(bcx, base, ~[i]),
862+
Some(n) if i > n => {
863+
InBoundsGEP(bcx, base, ~[
864+
Sub(bcx, count,
865+
C_int(bcx.ccx(), (elem_count - i) as int))])
866+
}
867+
_ => unsafe { llvm::LLVMGetUndef(vt.llunit_ty) }
868+
}
854869
};
855-
if tail {
856-
let tail_offset = Mul(bcx, vt.llunit_size,
857-
C_int(bcx.ccx(), elem_count as int)
870+
if slice.is_some() {
871+
let n = slice.get();
872+
let slice_offset = Mul(bcx, vt.llunit_size,
873+
C_int(bcx.ccx(), n as int)
874+
);
875+
let slice_begin = tvec::pointer_add(bcx, base, slice_offset);
876+
let slice_len_offset = Mul(bcx, vt.llunit_size,
877+
C_int(bcx.ccx(), (elem_count - 1u) as int)
858878
);
859-
let tail_begin = tvec::pointer_add(bcx, base, tail_offset);
860-
let tail_len = Sub(bcx, len, tail_offset);
861-
let tail_ty = ty::mk_evec(bcx.tcx(),
879+
let slice_len = Sub(bcx, len, slice_len_offset);
880+
let slice_ty = ty::mk_evec(bcx.tcx(),
862881
ty::mt {ty: vt.unit_ty, mutbl: ast::m_imm},
863882
ty::vstore_slice(ty::re_static)
864883
);
865-
let scratch = scratch_datum(bcx, tail_ty, false);
866-
Store(bcx, tail_begin,
884+
let scratch = scratch_datum(bcx, slice_ty, false);
885+
Store(bcx, slice_begin,
867886
GEPi(bcx, scratch.val, [0u, abi::slice_elt_base])
868887
);
869-
Store(bcx, tail_len,
888+
Store(bcx, slice_len,
870889
GEPi(bcx, scratch.val, [0u, abi::slice_elt_len])
871890
);
872-
elems.push(scratch.val);
891+
elems[n] = scratch.val;
873892
scratch.add_clean(bcx);
874893
}
875894
@@ -1367,7 +1386,7 @@ pub fn compile_submatch(bcx: block,
13671386
test_val = Load(bcx, val);
13681387
kind = compare;
13691388
},
1370-
vec_len_eq(_) | vec_len_ge(_) => {
1389+
vec_len_eq(*) | vec_len_ge(*) => {
13711390
let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
13721391
let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
13731392
let (_, len) = tvec::get_base_and_len(
@@ -1511,12 +1530,17 @@ pub fn compile_submatch(bcx: block,
15111530
unpacked = argvals;
15121531
opt_cx = new_bcx;
15131532
}
1514-
vec_len_eq(n) | vec_len_ge(n) => {
1515-
let tail = match *opt {
1516-
vec_len_ge(_) => true,
1517-
_ => false
1533+
vec_len_eq(n) | vec_len_ge(n, _) => {
1534+
let n = match *opt {
1535+
vec_len_ge(*) => n + 1u,
1536+
_ => n
1537+
};
1538+
let slice = match *opt {
1539+
vec_len_ge(_, i) => Some(i),
1540+
_ => None
15181541
};
1519-
let args = extract_vec_elems(opt_cx, pat_id, n, tail, val);
1542+
let args = extract_vec_elems(opt_cx, pat_id, n, slice,
1543+
val, test_val);
15201544
size = args.vals.len();
15211545
unpacked = /*bad*/copy args.vals;
15221546
opt_cx = args.bcx;

0 commit comments

Comments
 (0)