Skip to content

Commit 5d6a74f

Browse files
committed
Only warn about unreachable range patterns when appropriate
Also simplifies the literal-munging, and moves it into ast_util Closes #1170
1 parent 8cc852a commit 5d6a74f

File tree

8 files changed

+59
-231
lines changed

8 files changed

+59
-231
lines changed

src/comp/middle/check_alt.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import syntax::ast::*;
2-
import syntax::ast_util::{variant_def_ids, dummy_sp};
2+
import syntax::ast_util::{variant_def_ids, dummy_sp, compare_lit, lit_eq};
33
import syntax::visit;
44

55
fn check_crate(tcx: ty::ctxt, crate: @crate) {
@@ -66,11 +66,7 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
6666
pat_wild. | pat_bind(_) { ret true; }
6767
pat_lit(la) {
6868
alt b.node {
69-
pat_lit(lb) { ret util::common::lit_eq(la, lb); }
70-
pat_range(beginb, endb) {
71-
ret util::common::lit_type_eq(la, beginb) &&
72-
util::common::lit_in_range(la, beginb, endb);
73-
}
69+
pat_lit(lb) { ret lit_eq(la, lb); }
7470
_ { ret false; }
7571
}
7672
}
@@ -110,12 +106,11 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
110106
pat_range(begina, enda) {
111107
alt b.node {
112108
pat_lit(lb) {
113-
ret util::common::lit_type_eq(lb, begina) &&
114-
util::common::lit_in_range(lb, begina, enda);
109+
ret compare_lit(begina, lb) <= 0 && compare_lit(enda, lb) >= 0;
115110
}
116111
pat_range(beginb, endb) {
117-
ret util::common::lit_type_eq(begina, beginb) &&
118-
util::common::lit_ranges_overlap(begina, enda, beginb, endb);
112+
ret compare_lit(begina, beginb) <= 0 &&
113+
compare_lit(enda, endb) >= 0;
119114
}
120115
_ { ret false; }
121116
}

src/comp/middle/trans_alt.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ import trans_build::*;
77
import trans::{new_sub_block_ctxt, new_scope_block_ctxt, load_if_immediate};
88
import syntax::ast;
99
import syntax::ast_util;
10-
import syntax::ast_util::dummy_sp;
10+
import syntax::ast_util::{dummy_sp, lit_eq};
1111
import syntax::ast::def_id;
1212
import syntax::codemap::span;
13-
import util::common::lit_eq;
1413

1514
import trans_common::*;
1615

src/comp/middle/tstate/auxiliary.rs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import syntax::ast_util::*;
55
import syntax::codemap::span;
66
import syntax::visit;
77
import std::map::{new_int_hash};
8-
import util::common::{lit_eq};
98
import syntax::print::pprust::path_to_str;
109
import tstate::ann::{pre_and_post, pre_and_post_state, empty_ann, prestate,
1110
poststate, precond, postcond,

src/comp/middle/ty.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1443,7 +1443,9 @@ fn arg_eq<T>(eq: fn(T, T) -> bool, a: @sp_constr_arg<T>, b: @sp_constr_arg<T>)
14431443
alt b.node { ast::carg_ident(t) { ret eq(s, t); } _ { ret false; } }
14441444
}
14451445
ast::carg_lit(l) {
1446-
alt b.node { ast::carg_lit(m) { ret lit_eq(l, m); } _ { ret false; } }
1446+
alt b.node {
1447+
ast::carg_lit(m) { ret ast_util::lit_eq(l, m); } _ { ret false; }
1448+
}
14471449
}
14481450
}
14491451
}

src/comp/middle/typeck.rs

+6-21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import syntax::{ast, ast_util};
22
import ast::spanned;
3-
import syntax::ast_util::{local_def, respan, ty_param_kind};
3+
import syntax::ast_util::{local_def, respan, ty_param_kind, lit_is_numeric,
4+
lit_types_match};
45
import syntax::visit;
56
import metadata::csearch;
67
import driver::session;
@@ -1252,24 +1253,7 @@ fn lit_as_float(l: @ast::lit) -> str {
12521253
}
12531254

12541255
fn valid_range_bounds(l1: @ast::lit, l2: @ast::lit) -> bool {
1255-
alt l1.node {
1256-
ast::lit_float(s1) | ast::lit_mach_float(_, s1) {
1257-
let s2 = lit_as_float(l2);
1258-
let f1 = std::float::from_str(s1);
1259-
let f2 = std::float::from_str(s2);
1260-
ret std::math::min(f1, f2) == f1
1261-
}
1262-
ast::lit_uint(_) | ast::lit_char(_) {
1263-
let u1 = lit_as_uint(l1);
1264-
let u2 = lit_as_uint(l2);
1265-
ret std::math::min(u1, u2) == u1
1266-
}
1267-
_ {
1268-
let i1 = lit_as_int(l1);
1269-
let i2 = lit_as_int(l2);
1270-
ret std::math::min(i1, i2) == i1
1271-
}
1272-
}
1256+
ast_util::compare_lit(l1, l2) <= 0
12731257
}
12741258

12751259
// 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,
12841268
write::ty_only_fixup(fcx, pat.id, typ);
12851269
}
12861270
ast::pat_range(begin, end) {
1287-
if !util::common::lit_is_numeric(begin) ||
1288-
!util::common::lit_is_numeric(end) {
1271+
if !lit_types_match(begin, end) {
1272+
fcx.ccx.tcx.sess.span_err(pat.span, "mismatched types in range");
1273+
} else if !lit_is_numeric(begin) || !lit_is_numeric(end) {
12891274
fcx.ccx.tcx.sess.span_err(pat.span,
12901275
"non-numeric type used in range");
12911276
} else if !valid_range_bounds(begin, end) {

src/comp/syntax/ast_util.rs

+41-1
Original file line numberDiff line numberDiff line change
@@ -232,11 +232,51 @@ fn ret_by_ref(style: ret_style) -> bool {
232232

233233
fn ty_param_kind(tp: ty_param) -> kind { tp.kind }
234234

235+
fn compare_lit(a: @lit, b: @lit) -> int {
236+
fn cmp<T>(a: T, b: T) -> int { a == b ? 0 : a < b ? -1 : 1 }
237+
alt (a.node, b.node) {
238+
(lit_int(a), lit_int(b)) |
239+
(lit_mach_int(_, a), lit_mach_int(_, b)) { cmp(a, b) }
240+
(lit_uint(a), lit_uint(b)) { cmp(a, b) }
241+
(lit_char(a), lit_char(b)) { cmp(a, b) }
242+
(lit_float(a), lit_float(b)) |
243+
(lit_mach_float(_, a), lit_mach_float(_, b)) {
244+
cmp(std::float::from_str(a), std::float::from_str(b))
245+
}
246+
(lit_str(a), lit_str(b)) { cmp(a, b) }
247+
(lit_nil., lit_nil.) { 0 }
248+
(lit_bool(a), lit_bool(b)) { cmp(a, b) }
249+
}
250+
}
251+
252+
fn lit_eq(a: @lit, b: @lit) -> bool { compare_lit(a, b) == 0 }
253+
254+
fn lit_types_match(a: @lit, b: @lit) -> bool {
255+
alt (a.node, b.node) {
256+
(lit_int(_), lit_int(_)) | (lit_uint(_), lit_uint(_)) |
257+
(lit_char(_), lit_char(_)) | (lit_float(_), lit_float(_)) |
258+
(lit_str(_), lit_str(_)) | (lit_nil., lit_nil.) |
259+
(lit_bool(_), lit_bool(_ )) { true }
260+
(lit_mach_int(ta, _), lit_mach_int(tb, _)) |
261+
(lit_mach_float(ta, _), lit_mach_float(tb, _)) { ta == tb }
262+
_ { false }
263+
}
264+
}
265+
266+
fn lit_is_numeric(l: @ast::lit) -> bool {
267+
alt l.node {
268+
ast::lit_int(_) | ast::lit_char(_) | ast::lit_uint(_) |
269+
ast::lit_mach_int(_, _) | ast::lit_float(_) | ast::lit_mach_float(_,_) {
270+
true
271+
}
272+
_ { false }
273+
}
274+
}
275+
235276
// Local Variables:
236277
// mode: rust
237278
// fill-column: 78;
238279
// indent-tabs-mode: nil
239280
// c-basic-offset: 4
240281
// buffer-file-coding-system: utf-8-unix
241282
// End:
242-

src/comp/util/common.rs

-186
Original file line numberDiff line numberDiff line change
@@ -81,192 +81,6 @@ fn local_rhs_span(l: @ast::local, def: span) -> span {
8181
alt l.node.init { some(i) { ret i.expr.span; } _ { ret def; } }
8282
}
8383

84-
fn lit_is_numeric(l: @ast::lit) -> bool {
85-
alt l.node {
86-
ast::lit_int(_) | ast::lit_char(_) | ast::lit_uint(_) |
87-
ast::lit_mach_int(_, _) | ast::lit_float(_) | ast::lit_mach_float(_,_) {
88-
true
89-
}
90-
_ { false }
91-
}
92-
}
93-
94-
fn lit_type_eq(l: @ast::lit, m: @ast::lit) -> bool {
95-
alt l.node {
96-
ast::lit_str(_) {
97-
alt m.node { ast::lit_str(_) { true } _ { false } }
98-
}
99-
ast::lit_char(_) {
100-
alt m.node { ast::lit_char(_) { true } _ { false } }
101-
}
102-
ast::lit_int(_) {
103-
alt m.node { ast::lit_int(_) { true } _ { false } }
104-
}
105-
ast::lit_uint(_) {
106-
alt m.node { ast::lit_uint(_) { true } _ { false } }
107-
}
108-
ast::lit_mach_int(_, _) {
109-
alt m.node { ast::lit_mach_int(_, _) { true } _ { false } }
110-
}
111-
ast::lit_float(_) {
112-
alt m.node { ast::lit_float(_) { true } _ { false } }
113-
}
114-
ast::lit_mach_float(_, _) {
115-
alt m.node { ast::lit_mach_float(_, _) { true } _ { false } }
116-
}
117-
ast::lit_nil. {
118-
alt m.node { ast::lit_nil. { true } _ { false } }
119-
}
120-
ast::lit_bool(_) {
121-
alt m.node { ast::lit_bool(_) { true } _ { false } }
122-
}
123-
}
124-
}
125-
126-
fn lit_in_range(l: @ast::lit, m1: @ast::lit, m2: @ast::lit) -> bool {
127-
alt lits_to_range(m1, m2) {
128-
irange(i1, i2) {
129-
alt l.node {
130-
ast::lit_int(i3) | ast::lit_mach_int(_, i3) {
131-
i3 >= min(i1, i2) && i3 <= max(i1, i2)
132-
}
133-
_ { fail }
134-
}
135-
}
136-
urange(u1, u2) {
137-
alt l.node {
138-
ast::lit_uint(u3) {
139-
u3 >= min(u1, u2) && u3 <= max(u1, u2)
140-
}
141-
_ { fail }
142-
}
143-
}
144-
crange(c1, c2) {
145-
alt l.node {
146-
ast::lit_char(c3) {
147-
(c3 as uint) >= min(c1 as uint, c2 as uint) &&
148-
(c3 as uint) <= max(c1 as uint, c2 as uint)
149-
}
150-
_ { fail }
151-
}
152-
}
153-
frange(f1, f2) {
154-
alt l.node {
155-
ast::lit_float(f3) | ast::lit_mach_float(_, f3) {
156-
std::float::from_str(f3) >= min(f1, f2) &&
157-
std::float::from_str(f3) <= max(f1, f2)
158-
}
159-
_ { fail }
160-
}
161-
}
162-
}
163-
}
164-
165-
fn ranges_overlap<copy T>(a1: T, a2: T, b1: T, b2: T) -> bool {
166-
let min1 = min(a1, a2);
167-
let max1 = max(a1, a2);
168-
let min2 = min(b1, b2);
169-
let max2 = max(b1, b2);
170-
ret (min1 >= min2 && max1 <= max2) || (min1 <= min2 && max1 >= min2) ||
171-
(min1 >= min2 && min1 <= max2) || (max1 >= min2 && max1 <= max2);
172-
}
173-
174-
fn lit_ranges_overlap(a1: @ast::lit, a2: @ast::lit,
175-
b1: @ast::lit, b2: @ast::lit) -> bool {
176-
alt lits_to_range(a1, a2) {
177-
irange(i1, i2) {
178-
alt lits_to_range(b1, b2) {
179-
irange(i3, i4) { ranges_overlap(i1, i2, i3, i4) }
180-
_ { fail }
181-
}
182-
}
183-
urange(u1, u2) {
184-
alt lits_to_range(b1, b2) {
185-
urange(u3, u4) { ranges_overlap(u1, u2, u3, u4) }
186-
_ { fail }
187-
}
188-
}
189-
crange(c1, c2) {
190-
alt lits_to_range(b1, b2) {
191-
crange(c3, c4) { ranges_overlap(c1, c2, c3, c4) }
192-
_ { fail }
193-
}
194-
}
195-
frange(f1, f2) {
196-
alt lits_to_range(b1, b2) {
197-
frange(f3, f4) { ranges_overlap(f1, f2, f3, f4) }
198-
_ { fail }
199-
}
200-
}
201-
}
202-
}
203-
204-
tag range {
205-
irange(int, int);
206-
urange(uint, uint);
207-
crange(char, char);
208-
frange(float, float);
209-
}
210-
211-
fn lits_to_range(l: @ast::lit, r: @ast::lit) -> range {
212-
alt l.node {
213-
ast::lit_int(i1) | ast::lit_mach_int(_, i1) {
214-
alt r.node { ast::lit_int(i2) { irange(i1, i2) } _ { fail } }
215-
}
216-
ast::lit_uint(u1) {
217-
alt r.node { ast::lit_uint(u2) { urange(u1, u2) } _ { fail } }
218-
}
219-
ast::lit_char(c1) {
220-
alt r.node { ast::lit_char(c2) { crange(c1, c2) } _ { fail } }
221-
}
222-
ast::lit_float(f1) | ast::lit_mach_float(_, f1) {
223-
alt r.node { ast::lit_float(f2) | ast::lit_mach_float(_, f2) {
224-
frange(std::float::from_str(f1), std::float::from_str(f2))
225-
}
226-
_ { fail } }
227-
}
228-
_ { fail }
229-
}
230-
}
231-
232-
fn lit_eq(l: @ast::lit, m: @ast::lit) -> bool {
233-
alt l.node {
234-
ast::lit_str(s) {
235-
alt m.node { ast::lit_str(t) { ret s == t } _ { ret false; } }
236-
}
237-
ast::lit_char(c) {
238-
alt m.node { ast::lit_char(d) { ret c == d; } _ { ret false; } }
239-
}
240-
ast::lit_int(i) {
241-
alt m.node { ast::lit_int(j) { ret i == j; } _ { ret false; } }
242-
}
243-
ast::lit_uint(i) {
244-
alt m.node { ast::lit_uint(j) { ret i == j; } _ { ret false; } }
245-
}
246-
ast::lit_mach_int(_, i) {
247-
alt m.node {
248-
ast::lit_mach_int(_, j) { ret i == j; }
249-
_ { ret false; }
250-
}
251-
}
252-
ast::lit_float(s) {
253-
alt m.node { ast::lit_float(t) { ret s == t; } _ { ret false; } }
254-
}
255-
ast::lit_mach_float(_, s) {
256-
alt m.node {
257-
ast::lit_mach_float(_, t) { ret s == t; }
258-
_ { ret false; }
259-
}
260-
}
261-
ast::lit_nil. {
262-
alt m.node { ast::lit_nil. { ret true; } _ { ret false; } }
263-
}
264-
ast::lit_bool(b) {
265-
alt m.node { ast::lit_bool(c) { ret b == c; } _ { ret false; } }
266-
}
267-
}
268-
}
269-
27084
fn is_main_name(path: [ast::ident]) -> bool {
27185
str::eq(option::get(std::vec::last(path)), "main")
27286
}

src/test/compile-fail/alt-range-fail-dominate.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
//error-pattern: unreachable
44
//error-pattern: unreachable
55
//error-pattern: unreachable
6-
//error-pattern: unreachable
76

87
fn main() {
98
alt 5u {
@@ -12,13 +11,13 @@ fn main() {
1211
};
1312

1413
alt 5u {
14+
3u to 6u { }
1515
4u to 6u { }
16-
3u to 5u { }
1716
};
1817

1918
alt 5u {
2019
4u to 6u { }
21-
5u to 7u { }
20+
4u to 6u { }
2221
};
2322

2423
alt 'c' {
@@ -27,12 +26,7 @@ fn main() {
2726
};
2827

2928
alt 1.0 {
30-
-5.0 to 5.0 {}
31-
0.0 to 6.5 {}
32-
};
33-
34-
alt 1.0 {
35-
0.02 {}
3629
0.01 to 6.5 {}
30+
0.02 {}
3731
};
3832
}

0 commit comments

Comments
 (0)