fix issue #6209
This commit is contained in:
parent
15e44381af
commit
f8af2b50ee
@ -1,4 +1,4 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -498,10 +498,27 @@ pub fn specialize(cx: @MatchCheckCtxt,
|
||||
lookup_const_by_id(cx.tcx, did).get();
|
||||
let e_v = eval_const_expr(cx.tcx, const_expr);
|
||||
let match_ = match *ctor_id {
|
||||
val(ref v) => compare_const_vals(&e_v, v) == 0,
|
||||
val(ref v) => {
|
||||
match compare_const_vals(&e_v, v) {
|
||||
Some(val1) => (val1 == 0),
|
||||
None => {
|
||||
cx.tcx.sess.span_err(pat_span,
|
||||
"mismatched types between arms");
|
||||
false
|
||||
}
|
||||
}
|
||||
},
|
||||
range(ref c_lo, ref c_hi) => {
|
||||
compare_const_vals(c_lo, &e_v) >= 0 &&
|
||||
compare_const_vals(c_hi, &e_v) <= 0
|
||||
let m1 = compare_const_vals(c_lo, &e_v),
|
||||
m2 = compare_const_vals(c_hi, &e_v);
|
||||
match (m1, m2) {
|
||||
(Some(val1), Some(val2)) => (val1 >= 0 && val2 <= 0),
|
||||
_ => {
|
||||
cx.tcx.sess.span_err(pat_span,
|
||||
"mismatched types between ranges");
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
single => true,
|
||||
_ => fail!("type error")
|
||||
@ -529,10 +546,26 @@ pub fn specialize(cx: @MatchCheckCtxt,
|
||||
lookup_const_by_id(cx.tcx, did).get();
|
||||
let e_v = eval_const_expr(cx.tcx, const_expr);
|
||||
let match_ = match *ctor_id {
|
||||
val(ref v) => compare_const_vals(&e_v, v) == 0,
|
||||
val(ref v) =>
|
||||
match compare_const_vals(&e_v, v) {
|
||||
Some(val1) => (val1 == 0),
|
||||
None => {
|
||||
cx.tcx.sess.span_err(pat_span,
|
||||
"mismatched types between arms");
|
||||
false
|
||||
}
|
||||
},
|
||||
range(ref c_lo, ref c_hi) => {
|
||||
compare_const_vals(c_lo, &e_v) >= 0 &&
|
||||
compare_const_vals(c_hi, &e_v) <= 0
|
||||
let m1 = compare_const_vals(c_lo, &e_v),
|
||||
m2 = compare_const_vals(c_hi, &e_v);
|
||||
match (m1, m2) {
|
||||
(Some(val1), Some(val2)) => (val1 >= 0 && val2 <= 0),
|
||||
_ => {
|
||||
cx.tcx.sess.span_err(pat_span,
|
||||
"mismatched types between ranges");
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
single => true,
|
||||
_ => fail!("type error")
|
||||
@ -619,10 +652,27 @@ pub fn specialize(cx: @MatchCheckCtxt,
|
||||
pat_lit(expr) => {
|
||||
let e_v = eval_const_expr(cx.tcx, expr);
|
||||
let match_ = match *ctor_id {
|
||||
val(ref v) => compare_const_vals(&e_v, v) == 0,
|
||||
val(ref v) => {
|
||||
match compare_const_vals(&e_v, v) {
|
||||
Some(val1) => val1 == 0,
|
||||
None => {
|
||||
cx.tcx.sess.span_err(pat_span,
|
||||
"mismatched types between arms");
|
||||
false
|
||||
}
|
||||
}
|
||||
},
|
||||
range(ref c_lo, ref c_hi) => {
|
||||
compare_const_vals(c_lo, &e_v) >= 0 &&
|
||||
compare_const_vals(c_hi, &e_v) <= 0
|
||||
let m1 = compare_const_vals(c_lo, &e_v),
|
||||
m2 = compare_const_vals(c_hi, &e_v);
|
||||
match (m1, m2) {
|
||||
(Some(val1), Some(val2)) => (val1 >= 0 && val2 <= 0),
|
||||
_ => {
|
||||
cx.tcx.sess.span_err(pat_span,
|
||||
"mismatched types between ranges");
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
single => true,
|
||||
_ => fail!("type error")
|
||||
@ -638,11 +688,22 @@ pub fn specialize(cx: @MatchCheckCtxt,
|
||||
_ => fail!("type error")
|
||||
};
|
||||
let v_lo = eval_const_expr(cx.tcx, lo),
|
||||
v_hi = eval_const_expr(cx.tcx, hi);
|
||||
let match_ = compare_const_vals(&c_lo, &v_lo) >= 0 &&
|
||||
compare_const_vals(&c_hi, &v_hi) <= 0;
|
||||
if match_ { Some(vec::to_owned(r.tail())) } else { None }
|
||||
}
|
||||
v_hi = eval_const_expr(cx.tcx, hi);
|
||||
|
||||
let m1 = compare_const_vals(&c_lo, &v_lo),
|
||||
m2 = compare_const_vals(&c_hi, &v_hi);
|
||||
match (m1, m2) {
|
||||
(Some(val1), Some(val2)) if val1 >= 0 && val2 <= 0 => {
|
||||
Some(vec::to_owned(r.tail()))
|
||||
},
|
||||
(Some(_), Some(_)) => None,
|
||||
_ => {
|
||||
cx.tcx.sess.span_err(pat_span,
|
||||
"mismatched types between ranges");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
pat_vec(before, slice, after) => {
|
||||
match *ctor_id {
|
||||
vec(_) => {
|
||||
|
@ -420,65 +420,73 @@ pub fn lit_to_const(lit: @lit) -> const_val {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compare_const_vals(a: &const_val, b: &const_val) -> int {
|
||||
pub fn compare_const_vals(a: &const_val, b: &const_val) -> Option<int> {
|
||||
match (a, b) {
|
||||
(&const_int(a), &const_int(b)) => {
|
||||
if a == b {
|
||||
0
|
||||
Some(0)
|
||||
} else if a < b {
|
||||
-1
|
||||
Some(-1)
|
||||
} else {
|
||||
1
|
||||
Some(1)
|
||||
}
|
||||
}
|
||||
(&const_uint(a), &const_uint(b)) => {
|
||||
if a == b {
|
||||
0
|
||||
Some(0)
|
||||
} else if a < b {
|
||||
-1
|
||||
Some(-1)
|
||||
} else {
|
||||
1
|
||||
Some(1)
|
||||
}
|
||||
}
|
||||
(&const_float(a), &const_float(b)) => {
|
||||
if a == b {
|
||||
0
|
||||
Some(0)
|
||||
} else if a < b {
|
||||
-1
|
||||
Some(-1)
|
||||
} else {
|
||||
1
|
||||
Some(1)
|
||||
}
|
||||
}
|
||||
(&const_str(ref a), &const_str(ref b)) => {
|
||||
if (*a) == (*b) {
|
||||
0
|
||||
Some(0)
|
||||
} else if (*a) < (*b) {
|
||||
-1
|
||||
Some(-1)
|
||||
} else {
|
||||
1
|
||||
Some(1)
|
||||
}
|
||||
}
|
||||
(&const_bool(a), &const_bool(b)) => {
|
||||
if a == b {
|
||||
0
|
||||
Some(0)
|
||||
} else if a < b {
|
||||
-1
|
||||
Some(-1)
|
||||
} else {
|
||||
1
|
||||
Some(1)
|
||||
}
|
||||
}
|
||||
_ => fail!("compare_const_vals: ill-typed comparison")
|
||||
_ => {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compare_lit_exprs(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> int {
|
||||
compare_const_vals(&eval_const_expr(tcx, a), &eval_const_expr(tcx, b))
|
||||
pub fn compare_lit_exprs(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> Option<int> {
|
||||
compare_const_vals(&eval_const_expr(tcx, a), &eval_const_expr(tcx, b))
|
||||
}
|
||||
|
||||
pub fn lit_expr_eq(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> bool {
|
||||
compare_lit_exprs(tcx, a, b) == 0
|
||||
pub fn lit_expr_eq(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> Option<bool> {
|
||||
match compare_lit_exprs(tcx, a, b) {
|
||||
Some(val) => Some(val == 0),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lit_eq(a: @lit, b: @lit) -> bool {
|
||||
compare_const_vals(&lit_to_const(a), &lit_to_const(b)) == 0
|
||||
pub fn lit_eq(a: @lit, b: @lit) -> Option<bool> {
|
||||
match compare_const_vals(&lit_to_const(a), &lit_to_const(b)) {
|
||||
Some(val) => Some(val == 0),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
@ -193,48 +193,55 @@ pub enum Opt {
|
||||
|
||||
pub fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
|
||||
match (a, b) {
|
||||
(&lit(a), &lit(b)) => {
|
||||
match (a, b) {
|
||||
(UnitLikeStructLit(a), UnitLikeStructLit(b)) => a == b,
|
||||
_ => {
|
||||
let a_expr;
|
||||
match a {
|
||||
ExprLit(existing_a_expr) => a_expr = existing_a_expr,
|
||||
ConstLit(a_const) => {
|
||||
let e = const_eval::lookup_const_by_id(tcx, a_const);
|
||||
a_expr = e.get();
|
||||
(&lit(a), &lit(b)) => {
|
||||
match (a, b) {
|
||||
(UnitLikeStructLit(a), UnitLikeStructLit(b)) => a == b,
|
||||
_ => {
|
||||
let a_expr;
|
||||
match a {
|
||||
ExprLit(existing_a_expr) => a_expr = existing_a_expr,
|
||||
ConstLit(a_const) => {
|
||||
let e = const_eval::lookup_const_by_id(tcx, a_const);
|
||||
a_expr = e.get();
|
||||
}
|
||||
UnitLikeStructLit(_) => {
|
||||
fail!("UnitLikeStructLit should have been handled \
|
||||
above")
|
||||
}
|
||||
}
|
||||
UnitLikeStructLit(_) => {
|
||||
fail!("UnitLikeStructLit should have been handled \
|
||||
above")
|
||||
|
||||
let b_expr;
|
||||
match b {
|
||||
ExprLit(existing_b_expr) => b_expr = existing_b_expr,
|
||||
ConstLit(b_const) => {
|
||||
let e = const_eval::lookup_const_by_id(tcx, b_const);
|
||||
b_expr = e.get();
|
||||
}
|
||||
UnitLikeStructLit(_) => {
|
||||
fail!("UnitLikeStructLit should have been handled \
|
||||
above")
|
||||
}
|
||||
}
|
||||
|
||||
match const_eval::compare_lit_exprs(tcx, a_expr, b_expr) {
|
||||
Some(val1) => val1 == 0,
|
||||
None => fail!("compare_list_exprs: type mismatch"),
|
||||
}
|
||||
}
|
||||
|
||||
let b_expr;
|
||||
match b {
|
||||
ExprLit(existing_b_expr) => b_expr = existing_b_expr,
|
||||
ConstLit(b_const) => {
|
||||
let e = const_eval::lookup_const_by_id(tcx, b_const);
|
||||
b_expr = e.get();
|
||||
}
|
||||
UnitLikeStructLit(_) => {
|
||||
fail!("UnitLikeStructLit should have been handled \
|
||||
above")
|
||||
}
|
||||
}
|
||||
|
||||
const_eval::compare_lit_exprs(tcx, a_expr, b_expr) == 0
|
||||
}
|
||||
}
|
||||
}
|
||||
(&range(a1, a2), &range(b1, b2)) => {
|
||||
const_eval::compare_lit_exprs(tcx, a1, b1) == 0 &&
|
||||
const_eval::compare_lit_exprs(tcx, a2, b2) == 0
|
||||
}
|
||||
(&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,
|
||||
_ => false
|
||||
(&range(a1, a2), &range(b1, b2)) => {
|
||||
let m1 = const_eval::compare_lit_exprs(tcx, a1, b1);
|
||||
let m2 = const_eval::compare_lit_exprs(tcx, a2, b2);
|
||||
match (m1, m2) {
|
||||
(Some(val1), Some(val2)) => (val1 == 0 && val2 == 0),
|
||||
_ => fail!("compare_list_exprs: type mismatch"),
|
||||
}
|
||||
}
|
||||
(&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,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -408,8 +408,18 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) {
|
||||
// no-op
|
||||
} else if !ty::type_is_numeric(b_ty) {
|
||||
tcx.sess.span_err(pat.span, "non-numeric type used in range");
|
||||
} else if !valid_range_bounds(fcx.ccx, begin, end) {
|
||||
tcx.sess.span_err(begin.span, "lower range bound must be less than upper");
|
||||
} else {
|
||||
match valid_range_bounds(fcx.ccx, begin, end) {
|
||||
Some(false) => {
|
||||
tcx.sess.span_err(begin.span,
|
||||
"lower range bound must be less than upper");
|
||||
},
|
||||
None => {
|
||||
tcx.sess.span_err(begin.span,
|
||||
"mismatched types in range");
|
||||
},
|
||||
_ => { },
|
||||
}
|
||||
}
|
||||
fcx.write_ty(pat.id, b_ty);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -1044,8 +1044,11 @@ pub fn check_lit(fcx: @mut FnCtxt, lit: @ast::lit) -> ty::t {
|
||||
pub fn valid_range_bounds(ccx: @mut CrateCtxt,
|
||||
from: @ast::expr,
|
||||
to: @ast::expr)
|
||||
-> bool {
|
||||
const_eval::compare_lit_exprs(ccx.tcx, from, to) <= 0
|
||||
-> Option<bool> {
|
||||
match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
|
||||
Some(val) => Some(val <= 0),
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_expr_has_type(
|
||||
|
6
src/test/compile-fail/match-ill-type1.rs
Normal file
6
src/test/compile-fail/match-ill-type1.rs
Normal file
@ -0,0 +1,6 @@
|
||||
fn main() {
|
||||
match 1 {
|
||||
1..2u => 1, //~ ERROR mismatched types in range
|
||||
_ => 2,
|
||||
};
|
||||
}
|
7
src/test/compile-fail/match-ill-type2.rs
Normal file
7
src/test/compile-fail/match-ill-type2.rs
Normal file
@ -0,0 +1,7 @@
|
||||
fn main() {
|
||||
match 1 {
|
||||
1 => 1, //~ ERROR mismatched types between arms
|
||||
2u => 1,
|
||||
_ => 2,
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user