Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue #6209 #6669

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 76 additions & 15 deletions src/librustc/middle/check_match.rs
Original file line number Diff line number Diff line change
@@ -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.
//
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand All @@ -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(_) => {
Expand Down
54 changes: 31 additions & 23 deletions src/librustc/middle/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
77 changes: 42 additions & 35 deletions src/librustc/middle/trans/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
UnitLikeStructLit(_) => {
fail!("UnitLikeStructLit should have been handled \
above")
(&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")
}
}
}

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();
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")
}
}
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"),
}
}

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
}
}

Expand Down
16 changes: 13 additions & 3 deletions src/librustc/middle/typeck/check/_match.rs
Original file line number Diff line number Diff line change
@@ -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.
//
Expand Down Expand Up @@ -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);
}
Expand Down
9 changes: 6 additions & 3 deletions src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -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.
//
Expand Down Expand Up @@ -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(
Expand Down
6 changes: 6 additions & 0 deletions src/test/compile-fail/match-ill-type1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn main() {
match 1 {
1..2u => 1, //~ ERROR mismatched types in range
_ => 2,
};
}
7 changes: 7 additions & 0 deletions src/test/compile-fail/match-ill-type2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn main() {
match 1 {
1 => 1, //~ ERROR mismatched types between arms
2u => 1,
_ => 2,
};
}