Skip to content

Commit 774f36b

Browse files
author
Jakub Wieczorek
committed
Remove further code duplication
1 parent 19e10e3 commit 774f36b

File tree

1 file changed

+56
-137
lines changed

1 file changed

+56
-137
lines changed

src/librustc/middle/check_match.rs

+56-137
Original file line numberDiff line numberDiff line change
@@ -409,24 +409,12 @@ fn missing_ctor(cx: &MatchCheckCtxt,
409409
_ => check_matrix_for_wild(cx, m),
410410
},
411411
ty::ty_enum(eid, _) => {
412-
let mut found = Vec::new();
413-
for r in m.iter() {
414-
let r = pat_ctor_id(cx, *r.get(0));
415-
for id in r.move_iter() {
416-
if !found.contains(&id) {
417-
found.push(id);
418-
}
419-
}
420-
}
412+
let pat_ctors: Vec<ctor> = m
413+
.iter()
414+
.filter_map(|r| pat_ctor_id(cx, *r.get(0)))
415+
.collect();
421416
let variants = ty::enum_variants(cx.tcx, eid);
422-
if found.len() != (*variants).len() {
423-
for v in (*variants).iter() {
424-
if !found.iter().any(|x| x == &(variant(v.id))) {
425-
return Some(variant(v.id));
426-
}
427-
}
428-
fail!();
429-
} else { None }
417+
variants.iter().map(|v| variant(v.id)).find(|c| !pat_ctors.contains(c))
430418
}
431419
ty::ty_nil => None,
432420
ty::ty_bool => {
@@ -567,6 +555,21 @@ fn wild_multi() -> @Pat {
567555
@Pat {id: 0, node: PatWildMulti, span: DUMMY_SP}
568556
}
569557

558+
fn range_covered_by_constructor(ctor_id: &ctor, from: &const_val, to: &const_val) -> Option<bool> {
559+
let (c_from, c_to) = match *ctor_id {
560+
val(ref value) => (value, value),
561+
range(ref from, ref to) => (from, to),
562+
single => return Some(true),
563+
_ => unreachable!()
564+
};
565+
let cmp_from = compare_const_vals(c_from, from);
566+
let cmp_to = compare_const_vals(c_to, to);
567+
match (cmp_from, cmp_to) {
568+
(Some(val1), Some(val2)) => Some(val1 >= 0 && val2 <= 0),
569+
_ => None
570+
}
571+
}
572+
570573
fn specialize(cx: &MatchCheckCtxt,
571574
r: &[@Pat],
572575
ctor_id: &ctor,
@@ -592,41 +595,15 @@ fn specialize(cx: &MatchCheckCtxt,
592595
}
593596
}
594597
Some(DefStatic(did, _)) => {
595-
let const_expr =
596-
lookup_const_by_id(cx.tcx, did).unwrap();
598+
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
597599
let e_v = eval_const_expr(cx.tcx, const_expr);
598-
let match_ = match *ctor_id {
599-
val(ref v) => {
600-
match compare_const_vals(&e_v, v) {
601-
Some(val1) => (val1 == 0),
602-
None => {
603-
cx.tcx.sess.span_err(*pat_span,
604-
"mismatched types between arms");
605-
false
606-
}
607-
}
608-
},
609-
range(ref c_lo, ref c_hi) => {
610-
let m1 = compare_const_vals(c_lo, &e_v);
611-
let m2 = compare_const_vals(c_hi, &e_v);
612-
match (m1, m2) {
613-
(Some(val1), Some(val2)) => {
614-
(val1 >= 0 && val2 <= 0)
615-
}
616-
_ => {
617-
cx.tcx.sess.span_err(*pat_span,
618-
"mismatched types between ranges");
619-
false
620-
}
621-
}
622-
}
623-
single => true,
624-
_ => fail!("type error")
625-
};
626-
if match_ {
627-
Some(vec!())
628-
} else {
629-
None
600+
match range_covered_by_constructor(ctor_id, &e_v, &e_v) {
601+
Some(true) => Some(vec!()),
602+
Some(false) => None,
603+
None => {
604+
cx.tcx.sess.span_err(*pat_span, "mismatched types between arms");
605+
None
606+
}
630607
}
631608
}
632609
_ => {
@@ -638,38 +615,15 @@ fn specialize(cx: &MatchCheckCtxt,
638615
let def = cx.tcx.def_map.borrow().get_copy(pat_id);
639616
match def {
640617
DefStatic(did, _) => {
641-
let const_expr =
642-
lookup_const_by_id(cx.tcx, did).unwrap();
618+
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
643619
let e_v = eval_const_expr(cx.tcx, const_expr);
644-
let match_ = match *ctor_id {
645-
val(ref v) =>
646-
match compare_const_vals(&e_v, v) {
647-
Some(val1) => (val1 == 0),
648-
None => {
649-
cx.tcx.sess.span_err(*pat_span,
650-
"mismatched types between arms");
651-
false
652-
}
653-
},
654-
range(ref c_lo, ref c_hi) => {
655-
let m1 = compare_const_vals(c_lo, &e_v);
656-
let m2 = compare_const_vals(c_hi, &e_v);
657-
match (m1, m2) {
658-
(Some(val1), Some(val2)) => (val1 >= 0 && val2 <= 0),
659-
_ => {
660-
cx.tcx.sess.span_err(*pat_span,
661-
"mismatched types between ranges");
662-
false
663-
}
664-
}
665-
}
666-
single => true,
667-
_ => fail!("type error")
668-
};
669-
if match_ {
670-
Some(vec!())
671-
} else {
672-
None
620+
match range_covered_by_constructor(ctor_id, &e_v, &e_v) {
621+
Some(true) => Some(vec!()),
622+
Some(false) => None,
623+
None => {
624+
cx.tcx.sess.span_err(*pat_span, "mismatched types between arms");
625+
None
626+
}
673627
}
674628
}
675629
DefVariant(_, id, _) if variant(id) != *ctor_id => None,
@@ -720,68 +674,33 @@ fn specialize(cx: &MatchCheckCtxt,
720674

721675
}
722676
&PatTup(ref args) => {
723-
Some(args.iter().map(|x| *x).collect())
677+
Some(args.clone())
724678
}
725679
&PatBox(ref inner) | &PatRegion(ref inner) => {
726680
Some(vec!(inner.clone()))
727681
}
728682
&PatLit(ref expr) => {
729-
let e_v = eval_const_expr(cx.tcx, *expr);
730-
let match_ = match *ctor_id {
731-
val(ref v) => {
732-
match compare_const_vals(&e_v, v) {
733-
Some(val1) => val1 == 0,
734-
None => {
735-
cx.tcx.sess.span_err(*pat_span,
736-
"mismatched types between arms");
737-
false
738-
}
739-
}
740-
},
741-
range(ref c_lo, ref c_hi) => {
742-
let m1 = compare_const_vals(c_lo, &e_v);
743-
let m2 = compare_const_vals(c_hi, &e_v);
744-
match (m1, m2) {
745-
(Some(val1), Some(val2)) => (val1 >= 0 && val2 <= 0),
746-
_ => {
747-
cx.tcx.sess.span_err(*pat_span,
748-
"mismatched types between ranges");
749-
false
750-
}
751-
}
752-
}
753-
single => true,
754-
_ => fail!("type error")
755-
};
756-
if match_ {
757-
Some(vec!())
758-
} else {
683+
let expr_value = eval_const_expr(cx.tcx, *expr);
684+
match range_covered_by_constructor(ctor_id, &expr_value, &expr_value) {
685+
Some(true) => Some(vec!()),
686+
Some(false) => None,
687+
None => {
688+
cx.tcx.sess.span_err(*pat_span, "mismatched types between arms");
759689
None
760-
}
690+
}
691+
}
761692
}
762-
&PatRange(lo, hi) => {
763-
let (c_lo, c_hi) = match *ctor_id {
764-
val(ref v) => (v, v),
765-
range(ref lo, ref hi) => (lo, hi),
766-
single => return Some(vec!()),
767-
_ => fail!("type error")
768-
};
769-
let v_lo = eval_const_expr(cx.tcx, lo);
770-
let v_hi = eval_const_expr(cx.tcx, hi);
771-
772-
let m1 = compare_const_vals(c_lo, &v_lo);
773-
let m2 = compare_const_vals(c_hi, &v_hi);
774-
match (m1, m2) {
775-
(Some(val1), Some(val2)) if val1 >= 0 && val2 <= 0 => {
776-
Some(vec!())
777-
},
778-
(Some(_), Some(_)) => None,
779-
_ => {
780-
cx.tcx.sess.span_err(*pat_span,
781-
"mismatched types between ranges");
782-
None
783-
}
784-
}
693+
&PatRange(ref from, ref to) => {
694+
let from_value = eval_const_expr(cx.tcx, *from);
695+
let to_value = eval_const_expr(cx.tcx, *to);
696+
match range_covered_by_constructor(ctor_id, &from_value, &to_value) {
697+
Some(true) => Some(vec!()),
698+
Some(false) => None,
699+
None => {
700+
cx.tcx.sess.span_err(*pat_span, "mismatched types between arms");
701+
None
702+
}
703+
}
785704
}
786705
&PatVec(ref before, ref slice, ref after) => {
787706
match *ctor_id {

0 commit comments

Comments
 (0)