about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-11-22 11:49:29 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2011-11-22 11:49:29 +0100
commit5d6a74f020dba8d25c21670bdcf7bdf8744bffaf (patch)
tree177145e47650762e53082f0fb4d24fba8deca76d
parent8cc852af8ce3c7b59c06aaf41b44ff5fe90c4ced (diff)
Only warn about unreachable range patterns when appropriate
Also simplifies the literal-munging, and moves it into ast_util

Closes #1170
-rw-r--r--src/comp/middle/check_alt.rs15
-rw-r--r--src/comp/middle/trans_alt.rs3
-rw-r--r--src/comp/middle/tstate/auxiliary.rs1
-rw-r--r--src/comp/middle/ty.rs4
-rw-r--r--src/comp/middle/typeck.rs27
-rw-r--r--src/comp/syntax/ast_util.rs42
-rw-r--r--src/comp/util/common.rs186
-rw-r--r--src/test/compile-fail/alt-range-fail-dominate.rs12
8 files changed, 59 insertions, 231 deletions
diff --git a/src/comp/middle/check_alt.rs b/src/comp/middle/check_alt.rs
index b79ded04c27..380fcff24b6 100644
--- a/src/comp/middle/check_alt.rs
+++ b/src/comp/middle/check_alt.rs
@@ -1,5 +1,5 @@
 import syntax::ast::*;
-import syntax::ast_util::{variant_def_ids, dummy_sp};
+import syntax::ast_util::{variant_def_ids, dummy_sp, compare_lit, lit_eq};
 import syntax::visit;
 
 fn check_crate(tcx: ty::ctxt, crate: @crate) {
@@ -66,11 +66,7 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
       pat_wild. | pat_bind(_) { ret true; }
       pat_lit(la) {
         alt b.node {
-          pat_lit(lb) { ret util::common::lit_eq(la, lb); }
-          pat_range(beginb, endb) {
-            ret util::common::lit_type_eq(la, beginb) &&
-                util::common::lit_in_range(la, beginb, endb);
-          }
+          pat_lit(lb) { ret lit_eq(la, lb); }
           _ { ret false; }
         }
       }
@@ -110,12 +106,11 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
       pat_range(begina, enda) {
         alt b.node {
           pat_lit(lb) {
-            ret util::common::lit_type_eq(lb, begina) &&
-                util::common::lit_in_range(lb, begina, enda);
+            ret compare_lit(begina, lb) <= 0 && compare_lit(enda, lb) >= 0;
           }
           pat_range(beginb, endb) {
-            ret util::common::lit_type_eq(begina, beginb) &&
-                util::common::lit_ranges_overlap(begina, enda, beginb, endb);
+            ret compare_lit(begina, beginb) <= 0 &&
+                compare_lit(enda, endb) >= 0;
           }
           _ { ret false; }
         }
diff --git a/src/comp/middle/trans_alt.rs b/src/comp/middle/trans_alt.rs
index af0a1890f3e..5b7b7a59294 100644
--- a/src/comp/middle/trans_alt.rs
+++ b/src/comp/middle/trans_alt.rs
@@ -7,10 +7,9 @@ import trans_build::*;
 import trans::{new_sub_block_ctxt, new_scope_block_ctxt, load_if_immediate};
 import syntax::ast;
 import syntax::ast_util;
-import syntax::ast_util::dummy_sp;
+import syntax::ast_util::{dummy_sp, lit_eq};
 import syntax::ast::def_id;
 import syntax::codemap::span;
-import util::common::lit_eq;
 
 import trans_common::*;
 
diff --git a/src/comp/middle/tstate/auxiliary.rs b/src/comp/middle/tstate/auxiliary.rs
index 6e35aabf032..e7c17665628 100644
--- a/src/comp/middle/tstate/auxiliary.rs
+++ b/src/comp/middle/tstate/auxiliary.rs
@@ -5,7 +5,6 @@ import syntax::ast_util::*;
 import syntax::codemap::span;
 import syntax::visit;
 import std::map::{new_int_hash};
-import util::common::{lit_eq};
 import syntax::print::pprust::path_to_str;
 import tstate::ann::{pre_and_post, pre_and_post_state, empty_ann, prestate,
                      poststate, precond, postcond,
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 9471c4e01c5..e950633284f 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -1443,7 +1443,9 @@ fn arg_eq<T>(eq: fn(T, T) -> bool, a: @sp_constr_arg<T>, b: @sp_constr_arg<T>)
         alt b.node { ast::carg_ident(t) { ret eq(s, t); } _ { ret false; } }
       }
       ast::carg_lit(l) {
-        alt b.node { ast::carg_lit(m) { ret lit_eq(l, m); } _ { ret false; } }
+        alt b.node {
+          ast::carg_lit(m) { ret ast_util::lit_eq(l, m); } _ { ret false; }
+        }
       }
     }
 }
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 156c1cf1138..0858833af6d 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -1,6 +1,7 @@
 import syntax::{ast, ast_util};
 import ast::spanned;
-import syntax::ast_util::{local_def, respan, ty_param_kind};
+import syntax::ast_util::{local_def, respan, ty_param_kind, lit_is_numeric,
+                          lit_types_match};
 import syntax::visit;
 import metadata::csearch;
 import driver::session;
@@ -1252,24 +1253,7 @@ fn lit_as_float(l: @ast::lit) -> str {
 }
 
 fn valid_range_bounds(l1: @ast::lit, l2: @ast::lit) -> bool {
-    alt l1.node {
-      ast::lit_float(s1) | ast::lit_mach_float(_, s1) {
-        let s2 = lit_as_float(l2);
-        let f1 = std::float::from_str(s1);
-        let f2 = std::float::from_str(s2);
-        ret std::math::min(f1, f2) == f1
-      }
-      ast::lit_uint(_) | ast::lit_char(_) {
-        let u1 = lit_as_uint(l1);
-        let u2 = lit_as_uint(l2);
-        ret std::math::min(u1, u2) == u1
-      }
-      _ {
-        let i1 = lit_as_int(l1);
-        let i2 = lit_as_int(l2);
-        ret std::math::min(i1, i2) == i1
-      }
-    }
+    ast_util::compare_lit(l1, l2) <= 0
 }
 
 // Pattern checking is top-down rather than bottom-up so that bindings get
@@ -1284,8 +1268,9 @@ fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat,
         write::ty_only_fixup(fcx, pat.id, typ);
       }
       ast::pat_range(begin, end) {
-        if !util::common::lit_is_numeric(begin) ||
-           !util::common::lit_is_numeric(end) {
+        if !lit_types_match(begin, end) {
+            fcx.ccx.tcx.sess.span_err(pat.span, "mismatched types in range");
+        } else if !lit_is_numeric(begin) || !lit_is_numeric(end) {
             fcx.ccx.tcx.sess.span_err(pat.span,
                                       "non-numeric type used in range");
         } else if !valid_range_bounds(begin, end) {
diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs
index 2af904bdef0..c68092da90d 100644
--- a/src/comp/syntax/ast_util.rs
+++ b/src/comp/syntax/ast_util.rs
@@ -232,6 +232,47 @@ fn ret_by_ref(style: ret_style) -> bool {
 
 fn ty_param_kind(tp: ty_param) -> kind { tp.kind }
 
+fn compare_lit(a: @lit, b: @lit) -> int {
+    fn cmp<T>(a: T, b: T) -> int { a == b ? 0 : a < b ? -1 : 1 }
+    alt (a.node, b.node) {
+      (lit_int(a), lit_int(b)) |
+      (lit_mach_int(_, a), lit_mach_int(_, b)) { cmp(a, b) }
+      (lit_uint(a), lit_uint(b)) { cmp(a, b) }
+      (lit_char(a), lit_char(b)) { cmp(a, b) }
+      (lit_float(a), lit_float(b)) |
+      (lit_mach_float(_, a), lit_mach_float(_, b)) {
+        cmp(std::float::from_str(a), std::float::from_str(b))
+      }
+      (lit_str(a), lit_str(b)) { cmp(a, b) }
+      (lit_nil., lit_nil.) { 0 }
+      (lit_bool(a), lit_bool(b)) { cmp(a, b) }
+    }
+}
+
+fn lit_eq(a: @lit, b: @lit) -> bool { compare_lit(a, b) == 0 }
+
+fn lit_types_match(a: @lit, b: @lit) -> bool {
+    alt (a.node, b.node) {
+      (lit_int(_), lit_int(_)) | (lit_uint(_), lit_uint(_)) |
+      (lit_char(_), lit_char(_)) | (lit_float(_), lit_float(_)) |
+      (lit_str(_), lit_str(_)) | (lit_nil., lit_nil.) |
+      (lit_bool(_), lit_bool(_ )) { true }
+      (lit_mach_int(ta, _), lit_mach_int(tb, _)) |
+      (lit_mach_float(ta, _), lit_mach_float(tb, _)) { ta == tb }
+      _ { false }
+    }
+}
+
+fn lit_is_numeric(l: @ast::lit) -> bool {
+    alt l.node {
+      ast::lit_int(_) | ast::lit_char(_) | ast::lit_uint(_) |
+      ast::lit_mach_int(_, _) | ast::lit_float(_) | ast::lit_mach_float(_,_) {
+        true
+      }
+      _ { false }
+    }
+}
+
 // Local Variables:
 // mode: rust
 // fill-column: 78;
@@ -239,4 +280,3 @@ fn ty_param_kind(tp: ty_param) -> kind { tp.kind }
 // c-basic-offset: 4
 // buffer-file-coding-system: utf-8-unix
 // End:
-
diff --git a/src/comp/util/common.rs b/src/comp/util/common.rs
index 22c344e6200..f4f6f9cec24 100644
--- a/src/comp/util/common.rs
+++ b/src/comp/util/common.rs
@@ -81,192 +81,6 @@ fn local_rhs_span(l: @ast::local, def: span) -> span {
     alt l.node.init { some(i) { ret i.expr.span; } _ { ret def; } }
 }
 
-fn lit_is_numeric(l: @ast::lit) -> bool {
-    alt l.node {
-      ast::lit_int(_) | ast::lit_char(_) | ast::lit_uint(_) |
-      ast::lit_mach_int(_, _) | ast::lit_float(_) | ast::lit_mach_float(_,_) {
-        true
-      }
-      _ { false }
-    }
-}
-
-fn lit_type_eq(l: @ast::lit, m: @ast::lit) -> bool {
-    alt l.node {
-      ast::lit_str(_) {
-        alt m.node { ast::lit_str(_) { true } _ { false } }
-      }
-      ast::lit_char(_) {
-        alt m.node { ast::lit_char(_) { true } _ { false } }
-      }
-      ast::lit_int(_) {
-        alt m.node { ast::lit_int(_) { true } _ { false } }
-      }
-      ast::lit_uint(_) {
-        alt m.node { ast::lit_uint(_) { true } _ { false } }
-      }
-      ast::lit_mach_int(_, _) {
-        alt m.node { ast::lit_mach_int(_, _) { true } _ { false } }
-      }
-      ast::lit_float(_) {
-        alt m.node { ast::lit_float(_) { true } _ { false } }
-      }
-      ast::lit_mach_float(_, _) {
-        alt m.node { ast::lit_mach_float(_, _) { true } _ { false } }
-      }
-      ast::lit_nil. {
-        alt m.node { ast::lit_nil. { true } _ { false } }
-      }
-      ast::lit_bool(_) {
-        alt m.node { ast::lit_bool(_) { true } _ { false } }
-      }
-    }
-}
-
-fn lit_in_range(l: @ast::lit, m1: @ast::lit, m2: @ast::lit) -> bool {
-    alt lits_to_range(m1, m2) {
-      irange(i1, i2) {
-        alt l.node {
-          ast::lit_int(i3) | ast::lit_mach_int(_, i3) {
-            i3 >= min(i1, i2) && i3 <= max(i1, i2)
-          }
-          _ { fail }
-        }
-      }
-      urange(u1, u2) {
-        alt l.node {
-          ast::lit_uint(u3) {
-            u3 >= min(u1, u2) && u3 <= max(u1, u2)
-          }
-          _ { fail }
-        }
-      }
-      crange(c1, c2) {
-        alt l.node {
-          ast::lit_char(c3) {
-            (c3 as uint) >= min(c1 as uint, c2 as uint) &&
-            (c3 as uint) <= max(c1 as uint, c2 as uint)
-          }
-          _ { fail }
-        }
-      }
-      frange(f1, f2) {
-        alt l.node {
-          ast::lit_float(f3) | ast::lit_mach_float(_, f3) {
-            std::float::from_str(f3) >= min(f1, f2) &&
-            std::float::from_str(f3) <= max(f1, f2)
-          }
-          _ { fail }
-        }
-      }
-    }
-}
-
-fn ranges_overlap<copy T>(a1: T, a2: T, b1: T, b2: T) -> bool {
-    let min1 = min(a1, a2);
-    let max1 = max(a1, a2);
-    let min2 = min(b1, b2);
-    let max2 = max(b1, b2);
-    ret (min1 >= min2 && max1 <= max2) || (min1 <= min2 && max1 >= min2) ||
-        (min1 >= min2 && min1 <= max2) || (max1 >= min2 && max1 <= max2);
-}
-
-fn lit_ranges_overlap(a1: @ast::lit, a2: @ast::lit,
-                      b1: @ast::lit, b2: @ast::lit) -> bool {
-    alt lits_to_range(a1, a2) {
-      irange(i1, i2) {
-        alt lits_to_range(b1, b2) {
-          irange(i3, i4) { ranges_overlap(i1, i2, i3, i4) }
-          _ { fail }
-        }
-      }
-      urange(u1, u2) {
-        alt lits_to_range(b1, b2) {
-          urange(u3, u4) { ranges_overlap(u1, u2, u3, u4) }
-          _ { fail }
-        }
-      }
-      crange(c1, c2) {
-        alt lits_to_range(b1, b2) {
-          crange(c3, c4) { ranges_overlap(c1, c2, c3, c4) }
-          _ { fail }
-        }
-      }
-      frange(f1, f2) {
-        alt lits_to_range(b1, b2) {
-          frange(f3, f4) { ranges_overlap(f1, f2, f3, f4) }
-          _ { fail }
-        }
-      }
-    }
-}
-
-tag range {
-    irange(int, int);
-    urange(uint, uint);
-    crange(char, char);
-    frange(float, float);
-}
-
-fn lits_to_range(l: @ast::lit, r: @ast::lit) -> range {
-    alt l.node {
-      ast::lit_int(i1) | ast::lit_mach_int(_, i1) {
-        alt r.node { ast::lit_int(i2) { irange(i1, i2) } _ { fail } }
-      }
-      ast::lit_uint(u1) {
-        alt r.node { ast::lit_uint(u2) { urange(u1, u2) } _ { fail } }
-      }
-      ast::lit_char(c1) {
-        alt r.node { ast::lit_char(c2) { crange(c1, c2) } _ { fail } }
-      }
-      ast::lit_float(f1) | ast::lit_mach_float(_, f1) {
-        alt r.node { ast::lit_float(f2) | ast::lit_mach_float(_, f2) {
-          frange(std::float::from_str(f1), std::float::from_str(f2))
-        }
-        _ { fail } }
-      }
-      _ { fail }
-    }
-}
-
-fn lit_eq(l: @ast::lit, m: @ast::lit) -> bool {
-    alt l.node {
-      ast::lit_str(s) {
-        alt m.node { ast::lit_str(t) { ret s == t } _ { ret false; } }
-      }
-      ast::lit_char(c) {
-        alt m.node { ast::lit_char(d) { ret c == d; } _ { ret false; } }
-      }
-      ast::lit_int(i) {
-        alt m.node { ast::lit_int(j) { ret i == j; } _ { ret false; } }
-      }
-      ast::lit_uint(i) {
-        alt m.node { ast::lit_uint(j) { ret i == j; } _ { ret false; } }
-      }
-      ast::lit_mach_int(_, i) {
-        alt m.node {
-          ast::lit_mach_int(_, j) { ret i == j; }
-          _ { ret false; }
-        }
-      }
-      ast::lit_float(s) {
-        alt m.node { ast::lit_float(t) { ret s == t; } _ { ret false; } }
-      }
-      ast::lit_mach_float(_, s) {
-        alt m.node {
-          ast::lit_mach_float(_, t) { ret s == t; }
-          _ { ret false; }
-        }
-      }
-      ast::lit_nil. {
-        alt m.node { ast::lit_nil. { ret true; } _ { ret false; } }
-      }
-      ast::lit_bool(b) {
-        alt m.node { ast::lit_bool(c) { ret b == c; } _ { ret false; } }
-      }
-    }
-}
-
 fn is_main_name(path: [ast::ident]) -> bool {
     str::eq(option::get(std::vec::last(path)), "main")
 }
diff --git a/src/test/compile-fail/alt-range-fail-dominate.rs b/src/test/compile-fail/alt-range-fail-dominate.rs
index 51883e8f8dd..38ac1d76d98 100644
--- a/src/test/compile-fail/alt-range-fail-dominate.rs
+++ b/src/test/compile-fail/alt-range-fail-dominate.rs
@@ -3,7 +3,6 @@
 //error-pattern: unreachable
 //error-pattern: unreachable
 //error-pattern: unreachable
-//error-pattern: unreachable
 
 fn main() {
     alt 5u {
@@ -12,13 +11,13 @@ fn main() {
     };
 
     alt 5u {
+      3u to 6u { }
       4u to 6u { }
-      3u to 5u { }
     };
 
     alt 5u {
       4u to 6u { }
-      5u to 7u { }
+      4u to 6u { }
     };
 
     alt 'c' {
@@ -27,12 +26,7 @@ fn main() {
     };
 
     alt 1.0 {
-      -5.0 to 5.0 {}
-      0.0 to 6.5 {}
-    };
-
-    alt 1.0 {
-      0.02 {}
       0.01 to 6.5 {}
+      0.02 {}
     };
 }
\ No newline at end of file