Skip to content

Commit 1d3e84c

Browse files
committed
auto merge of #6669 : yjh0502/rust/fix_6209, r=graydon
Fix issue #6209, and some related issues about constant expression - unmatched type between arms - unmatched type in range
2 parents f517ed0 + f8af2b5 commit 1d3e84c

File tree

7 files changed

+181
-79
lines changed

7 files changed

+181
-79
lines changed

src/librustc/middle/check_match.rs

+76-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -498,10 +498,27 @@ pub fn specialize(cx: @MatchCheckCtxt,
498498
lookup_const_by_id(cx.tcx, did).get();
499499
let e_v = eval_const_expr(cx.tcx, const_expr);
500500
let match_ = match *ctor_id {
501-
val(ref v) => compare_const_vals(&e_v, v) == 0,
501+
val(ref v) => {
502+
match compare_const_vals(&e_v, v) {
503+
Some(val1) => (val1 == 0),
504+
None => {
505+
cx.tcx.sess.span_err(pat_span,
506+
"mismatched types between arms");
507+
false
508+
}
509+
}
510+
},
502511
range(ref c_lo, ref c_hi) => {
503-
compare_const_vals(c_lo, &e_v) >= 0 &&
504-
compare_const_vals(c_hi, &e_v) <= 0
512+
let m1 = compare_const_vals(c_lo, &e_v),
513+
m2 = compare_const_vals(c_hi, &e_v);
514+
match (m1, m2) {
515+
(Some(val1), Some(val2)) => (val1 >= 0 && val2 <= 0),
516+
_ => {
517+
cx.tcx.sess.span_err(pat_span,
518+
"mismatched types between ranges");
519+
false
520+
}
521+
}
505522
}
506523
single => true,
507524
_ => fail!("type error")
@@ -529,10 +546,26 @@ pub fn specialize(cx: @MatchCheckCtxt,
529546
lookup_const_by_id(cx.tcx, did).get();
530547
let e_v = eval_const_expr(cx.tcx, const_expr);
531548
let match_ = match *ctor_id {
532-
val(ref v) => compare_const_vals(&e_v, v) == 0,
549+
val(ref v) =>
550+
match compare_const_vals(&e_v, v) {
551+
Some(val1) => (val1 == 0),
552+
None => {
553+
cx.tcx.sess.span_err(pat_span,
554+
"mismatched types between arms");
555+
false
556+
}
557+
},
533558
range(ref c_lo, ref c_hi) => {
534-
compare_const_vals(c_lo, &e_v) >= 0 &&
535-
compare_const_vals(c_hi, &e_v) <= 0
559+
let m1 = compare_const_vals(c_lo, &e_v),
560+
m2 = compare_const_vals(c_hi, &e_v);
561+
match (m1, m2) {
562+
(Some(val1), Some(val2)) => (val1 >= 0 && val2 <= 0),
563+
_ => {
564+
cx.tcx.sess.span_err(pat_span,
565+
"mismatched types between ranges");
566+
false
567+
}
568+
}
536569
}
537570
single => true,
538571
_ => fail!("type error")
@@ -619,10 +652,27 @@ pub fn specialize(cx: @MatchCheckCtxt,
619652
pat_lit(expr) => {
620653
let e_v = eval_const_expr(cx.tcx, expr);
621654
let match_ = match *ctor_id {
622-
val(ref v) => compare_const_vals(&e_v, v) == 0,
655+
val(ref v) => {
656+
match compare_const_vals(&e_v, v) {
657+
Some(val1) => val1 == 0,
658+
None => {
659+
cx.tcx.sess.span_err(pat_span,
660+
"mismatched types between arms");
661+
false
662+
}
663+
}
664+
},
623665
range(ref c_lo, ref c_hi) => {
624-
compare_const_vals(c_lo, &e_v) >= 0 &&
625-
compare_const_vals(c_hi, &e_v) <= 0
666+
let m1 = compare_const_vals(c_lo, &e_v),
667+
m2 = compare_const_vals(c_hi, &e_v);
668+
match (m1, m2) {
669+
(Some(val1), Some(val2)) => (val1 >= 0 && val2 <= 0),
670+
_ => {
671+
cx.tcx.sess.span_err(pat_span,
672+
"mismatched types between ranges");
673+
false
674+
}
675+
}
626676
}
627677
single => true,
628678
_ => fail!("type error")
@@ -638,11 +688,22 @@ pub fn specialize(cx: @MatchCheckCtxt,
638688
_ => fail!("type error")
639689
};
640690
let v_lo = eval_const_expr(cx.tcx, lo),
641-
v_hi = eval_const_expr(cx.tcx, hi);
642-
let match_ = compare_const_vals(&c_lo, &v_lo) >= 0 &&
643-
compare_const_vals(&c_hi, &v_hi) <= 0;
644-
if match_ { Some(vec::to_owned(r.tail())) } else { None }
645-
}
691+
v_hi = eval_const_expr(cx.tcx, hi);
692+
693+
let m1 = compare_const_vals(&c_lo, &v_lo),
694+
m2 = compare_const_vals(&c_hi, &v_hi);
695+
match (m1, m2) {
696+
(Some(val1), Some(val2)) if val1 >= 0 && val2 <= 0 => {
697+
Some(vec::to_owned(r.tail()))
698+
},
699+
(Some(_), Some(_)) => None,
700+
_ => {
701+
cx.tcx.sess.span_err(pat_span,
702+
"mismatched types between ranges");
703+
None
704+
}
705+
}
706+
}
646707
pat_vec(before, slice, after) => {
647708
match *ctor_id {
648709
vec(_) => {

src/librustc/middle/const_eval.rs

+31-23
Original file line numberDiff line numberDiff line change
@@ -420,65 +420,73 @@ pub fn lit_to_const(lit: @lit) -> const_val {
420420
}
421421
}
422422

423-
pub fn compare_const_vals(a: &const_val, b: &const_val) -> int {
423+
pub fn compare_const_vals(a: &const_val, b: &const_val) -> Option<int> {
424424
match (a, b) {
425425
(&const_int(a), &const_int(b)) => {
426426
if a == b {
427-
0
427+
Some(0)
428428
} else if a < b {
429-
-1
429+
Some(-1)
430430
} else {
431-
1
431+
Some(1)
432432
}
433433
}
434434
(&const_uint(a), &const_uint(b)) => {
435435
if a == b {
436-
0
436+
Some(0)
437437
} else if a < b {
438-
-1
438+
Some(-1)
439439
} else {
440-
1
440+
Some(1)
441441
}
442442
}
443443
(&const_float(a), &const_float(b)) => {
444444
if a == b {
445-
0
445+
Some(0)
446446
} else if a < b {
447-
-1
447+
Some(-1)
448448
} else {
449-
1
449+
Some(1)
450450
}
451451
}
452452
(&const_str(ref a), &const_str(ref b)) => {
453453
if (*a) == (*b) {
454-
0
454+
Some(0)
455455
} else if (*a) < (*b) {
456-
-1
456+
Some(-1)
457457
} else {
458-
1
458+
Some(1)
459459
}
460460
}
461461
(&const_bool(a), &const_bool(b)) => {
462462
if a == b {
463-
0
463+
Some(0)
464464
} else if a < b {
465-
-1
465+
Some(-1)
466466
} else {
467-
1
467+
Some(1)
468468
}
469469
}
470-
_ => fail!("compare_const_vals: ill-typed comparison")
470+
_ => {
471+
None
472+
}
471473
}
472474
}
473475

474-
pub fn compare_lit_exprs(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> int {
475-
compare_const_vals(&eval_const_expr(tcx, a), &eval_const_expr(tcx, b))
476+
pub fn compare_lit_exprs(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> Option<int> {
477+
compare_const_vals(&eval_const_expr(tcx, a), &eval_const_expr(tcx, b))
476478
}
477479

478-
pub fn lit_expr_eq(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> bool {
479-
compare_lit_exprs(tcx, a, b) == 0
480+
pub fn lit_expr_eq(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> Option<bool> {
481+
match compare_lit_exprs(tcx, a, b) {
482+
Some(val) => Some(val == 0),
483+
None => None,
484+
}
480485
}
481486

482-
pub fn lit_eq(a: @lit, b: @lit) -> bool {
483-
compare_const_vals(&lit_to_const(a), &lit_to_const(b)) == 0
487+
pub fn lit_eq(a: @lit, b: @lit) -> Option<bool> {
488+
match compare_const_vals(&lit_to_const(a), &lit_to_const(b)) {
489+
Some(val) => Some(val == 0),
490+
None => None,
491+
}
484492
}

src/librustc/middle/trans/_match.rs

+42-35
Original file line numberDiff line numberDiff line change
@@ -193,48 +193,55 @@ pub enum Opt {
193193

194194
pub fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
195195
match (a, b) {
196-
(&lit(a), &lit(b)) => {
197-
match (a, b) {
198-
(UnitLikeStructLit(a), UnitLikeStructLit(b)) => a == b,
199-
_ => {
200-
let a_expr;
201-
match a {
202-
ExprLit(existing_a_expr) => a_expr = existing_a_expr,
203-
ConstLit(a_const) => {
204-
let e = const_eval::lookup_const_by_id(tcx, a_const);
205-
a_expr = e.get();
206-
}
207-
UnitLikeStructLit(_) => {
208-
fail!("UnitLikeStructLit should have been handled \
209-
above")
196+
(&lit(a), &lit(b)) => {
197+
match (a, b) {
198+
(UnitLikeStructLit(a), UnitLikeStructLit(b)) => a == b,
199+
_ => {
200+
let a_expr;
201+
match a {
202+
ExprLit(existing_a_expr) => a_expr = existing_a_expr,
203+
ConstLit(a_const) => {
204+
let e = const_eval::lookup_const_by_id(tcx, a_const);
205+
a_expr = e.get();
206+
}
207+
UnitLikeStructLit(_) => {
208+
fail!("UnitLikeStructLit should have been handled \
209+
above")
210+
}
210211
}
211-
}
212212

213-
let b_expr;
214-
match b {
215-
ExprLit(existing_b_expr) => b_expr = existing_b_expr,
216-
ConstLit(b_const) => {
217-
let e = const_eval::lookup_const_by_id(tcx, b_const);
218-
b_expr = e.get();
213+
let b_expr;
214+
match b {
215+
ExprLit(existing_b_expr) => b_expr = existing_b_expr,
216+
ConstLit(b_const) => {
217+
let e = const_eval::lookup_const_by_id(tcx, b_const);
218+
b_expr = e.get();
219+
}
220+
UnitLikeStructLit(_) => {
221+
fail!("UnitLikeStructLit should have been handled \
222+
above")
223+
}
219224
}
220-
UnitLikeStructLit(_) => {
221-
fail!("UnitLikeStructLit should have been handled \
222-
above")
225+
226+
match const_eval::compare_lit_exprs(tcx, a_expr, b_expr) {
227+
Some(val1) => val1 == 0,
228+
None => fail!("compare_list_exprs: type mismatch"),
223229
}
224230
}
225-
226-
const_eval::compare_lit_exprs(tcx, a_expr, b_expr) == 0
227231
}
228232
}
229-
}
230-
(&range(a1, a2), &range(b1, b2)) => {
231-
const_eval::compare_lit_exprs(tcx, a1, b1) == 0 &&
232-
const_eval::compare_lit_exprs(tcx, a2, b2) == 0
233-
}
234-
(&var(a, _), &var(b, _)) => a == b,
235-
(&vec_len_eq(a), &vec_len_eq(b)) => a == b,
236-
(&vec_len_ge(a, _), &vec_len_ge(b, _)) => a == b,
237-
_ => false
233+
(&range(a1, a2), &range(b1, b2)) => {
234+
let m1 = const_eval::compare_lit_exprs(tcx, a1, b1);
235+
let m2 = const_eval::compare_lit_exprs(tcx, a2, b2);
236+
match (m1, m2) {
237+
(Some(val1), Some(val2)) => (val1 == 0 && val2 == 0),
238+
_ => fail!("compare_list_exprs: type mismatch"),
239+
}
240+
}
241+
(&var(a, _), &var(b, _)) => a == b,
242+
(&vec_len_eq(a), &vec_len_eq(b)) => a == b,
243+
(&vec_len_ge(a, _), &vec_len_ge(b, _)) => a == b,
244+
_ => false
238245
}
239246
}
240247

src/librustc/middle/typeck/check/_match.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -408,8 +408,18 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
408408
// no-op
409409
} else if !ty::type_is_numeric(b_ty) {
410410
tcx.sess.span_err(pat.span, "non-numeric type used in range");
411-
} else if !valid_range_bounds(fcx.ccx, begin, end) {
412-
tcx.sess.span_err(begin.span, "lower range bound must be less than upper");
411+
} else {
412+
match valid_range_bounds(fcx.ccx, begin, end) {
413+
Some(false) => {
414+
tcx.sess.span_err(begin.span,
415+
"lower range bound must be less than upper");
416+
},
417+
None => {
418+
tcx.sess.span_err(begin.span,
419+
"mismatched types in range");
420+
},
421+
_ => { },
422+
}
413423
}
414424
fcx.write_ty(pat.id, b_ty);
415425
}

src/librustc/middle/typeck/check/mod.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -1044,8 +1044,11 @@ pub fn check_lit(fcx: @mut FnCtxt, lit: @ast::lit) -> ty::t {
10441044
pub fn valid_range_bounds(ccx: @mut CrateCtxt,
10451045
from: @ast::expr,
10461046
to: @ast::expr)
1047-
-> bool {
1048-
const_eval::compare_lit_exprs(ccx.tcx, from, to) <= 0
1047+
-> Option<bool> {
1048+
match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
1049+
Some(val) => Some(val <= 0),
1050+
None => None
1051+
}
10491052
}
10501053

10511054
pub fn check_expr_has_type(
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn main() {
2+
match 1 {
3+
1..2u => 1, //~ ERROR mismatched types in range
4+
_ => 2,
5+
};
6+
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
match 1 {
3+
1 => 1, //~ ERROR mismatched types between arms
4+
2u => 1,
5+
_ => 2,
6+
};
7+
}

0 commit comments

Comments
 (0)