Skip to content

Commit 6b6bea9

Browse files
committed
Add boolean constants as part of const_eval
Doesn't exactly eliminate a match check, but simplifies the logic a bit
1 parent 80d129a commit 6b6bea9

File tree

4 files changed

+102
-49
lines changed

4 files changed

+102
-49
lines changed

src/rustc/middle/check_alt.rs

+34-24
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import syntax::ast::*;
22
import syntax::ast_util::{variant_def_ids, dummy_sp, unguarded_pat};
3-
import const_eval::{eval_const_expr, const_val, const_int,
3+
import const_eval::{eval_const_expr, const_val, const_int, const_bool,
44
compare_const_vals};
55
import syntax::codemap::span;
66
import syntax::print::pprust::pat_to_str;
@@ -90,16 +90,19 @@ fn check_exhaustive(tcx: ty::ctxt, sp: span, pats: ~[@pat]) {
9090
useful(ty, ctor) => {
9191
match ty::get(ty).struct {
9292
ty::ty_bool => {
93-
match check ctor {
94-
val(const_int(1i64)) => some(~"true"),
95-
val(const_int(0i64)) => some(~"false")
93+
match ctor {
94+
val(const_bool(true)) => some(~"true"),
95+
val(const_bool(false)) => some(~"false"),
96+
_ => none
9697
}
9798
}
9899
ty::ty_enum(id, _) => {
99-
let vid = match check ctor { variant(id) => id };
100-
match check vec::find(*ty::enum_variants(tcx, id),
100+
let vid = match ctor { variant(id) => id,
101+
_ => fail ~"check_exhaustive: non-variant ctor" };
102+
match vec::find(*ty::enum_variants(tcx, id),
101103
|v| v.id == vid) {
102-
some(v) => some(tcx.sess.str_of(v.name))
104+
some(v) => some(tcx.sess.str_of(v.name)),
105+
none => fail ~"check_exhaustive: bad variant in ctor"
103106
}
104107
}
105108
_ => none
@@ -152,10 +155,10 @@ fn is_useful(tcx: ty::ctxt, m: matrix, v: ~[@pat]) -> useful {
152155
none => {
153156
match ty::get(left_ty).struct {
154157
ty::ty_bool => {
155-
match is_useful_specialized(tcx, m, v, val(const_int(1i64)),
158+
match is_useful_specialized(tcx, m, v, val(const_bool(true)),
156159
0u, left_ty){
157160
not_useful => {
158-
is_useful_specialized(tcx, m, v, val(const_int(0i64)),
161+
is_useful_specialized(tcx, m, v, val(const_bool(false)),
159162
0u, left_ty)
160163
}
161164
u => u
@@ -269,15 +272,16 @@ fn missing_ctor(tcx: ty::ctxt, m: matrix, left_ty: ty::t) -> option<ctor> {
269272
ty::ty_bool => {
270273
let mut true_found = false, false_found = false;
271274
for m.each |r| {
272-
match check pat_ctor_id(tcx, r[0]) {
275+
match pat_ctor_id(tcx, r[0]) {
273276
none => (),
274-
some(val(const_int(1i64))) => true_found = true,
275-
some(val(const_int(0i64))) => false_found = true
277+
some(val(const_bool(true))) => true_found = true,
278+
some(val(const_bool(false))) => false_found = true,
279+
_ => fail ~"impossible case"
276280
}
277281
}
278282
if true_found && false_found { none }
279-
else if true_found { some(val(const_int(0i64))) }
280-
else { some(val(const_int(1i64))) }
283+
else if true_found { some(val(const_bool(false))) }
284+
else { some(val(const_bool(true))) }
281285
}
282286
_ => some(single)
283287
}
@@ -289,9 +293,11 @@ fn ctor_arity(tcx: ty::ctxt, ctor: ctor, ty: ty::t) -> uint {
289293
ty::ty_rec(fs) => fs.len(),
290294
ty::ty_box(_) | ty::ty_uniq(_) => 1u,
291295
ty::ty_enum(eid, _) => {
292-
let id = match check ctor { variant(id) => id };
293-
match check vec::find(*ty::enum_variants(tcx, eid), |v| v.id == id ) {
294-
some(v) => v.args.len()
296+
let id = match ctor { variant(id) => id,
297+
_ => fail ~"impossible case" };
298+
match vec::find(*ty::enum_variants(tcx, eid), |v| v.id == id ) {
299+
some(v) => v.args.len(),
300+
none => fail ~"impossible case"
295301
}
296302
}
297303
ty::ty_class(cid, _) => ty::lookup_class_fields(tcx, cid).len(),
@@ -319,20 +325,22 @@ fn specialize(tcx: ty::ctxt, r: ~[@pat], ctor_id: ctor, arity: uint,
319325
}
320326
}
321327
pat_enum(_, args) => {
322-
match check tcx.def_map.get(r0.id) {
328+
match tcx.def_map.get(r0.id) {
323329
def_variant(_, id) if variant(id) == ctor_id => {
324330
let args = match args {
325331
some(args) => args,
326332
none => vec::from_elem(arity, wild())
327333
};
328334
some(vec::append(args, vec::tail(r)))
329335
}
330-
def_variant(_, _) => none
336+
def_variant(_, _) => none,
337+
_ => none
331338
}
332339
}
333340
pat_rec(flds, _) => {
334-
let ty_flds = match check ty::get(left_ty).struct {
335-
ty::ty_rec(flds) => flds
341+
let ty_flds = match ty::get(left_ty).struct {
342+
ty::ty_rec(flds) => flds,
343+
_ => fail ~"bad type for pat_rec"
336344
};
337345
let args = vec::map(ty_flds, |ty_f| {
338346
match vec::find(flds, |f| f.ident == ty_f.ident ) {
@@ -367,21 +375,23 @@ fn specialize(tcx: ty::ctxt, r: ~[@pat], ctor_id: ctor, arity: uint,
367375
pat_box(a) | pat_uniq(a) => some(vec::append(~[a], vec::tail(r))),
368376
pat_lit(expr) => {
369377
let e_v = eval_const_expr(tcx, expr);
370-
let match_ = match check ctor_id {
378+
let match_ = match ctor_id {
371379
val(v) => compare_const_vals(e_v, v) == 0,
372380
range(c_lo, c_hi) => {
373381
compare_const_vals(c_lo, e_v) >= 0 &&
374382
compare_const_vals(c_hi, e_v) <= 0
375383
}
376-
single => true
384+
single => true,
385+
_ => fail ~"type error"
377386
};
378387
if match_ { some(vec::tail(r)) } else { none }
379388
}
380389
pat_range(lo, hi) => {
381-
let (c_lo, c_hi) = match check ctor_id {
390+
let (c_lo, c_hi) = match ctor_id {
382391
val(v) => (v, v),
383392
range(lo, hi) => (lo, hi),
384393
single => return some(vec::tail(r)),
394+
_ => fail ~"type error"
385395
};
386396
let v_lo = eval_const_expr(tcx, lo),
387397
v_hi = eval_const_expr(tcx, hi);

src/rustc/middle/check_const.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,11 @@ fn check_item_recursion(sess: session, ast_map: ast_map::map,
182182
expr_path(path) => {
183183
match env.def_map.find(e.id) {
184184
some(def_const(def_id)) => {
185-
match check env.ast_map.get(def_id.node) {
185+
match env.ast_map.get(def_id.node) {
186186
ast_map::node_item(it, _) => {
187187
v.visit_item(it, env, v);
188188
}
189+
_ => fail ~"const not bound to an item"
189190
}
190191
}
191192
_ => ()

src/rustc/middle/const_eval.rs

+59-24
Original file line numberDiff line numberDiff line change
@@ -186,30 +186,35 @@ enum const_val {
186186
const_int(i64),
187187
const_uint(u64),
188188
const_str(~str),
189+
const_bool(bool)
189190
}
190191

191192
// FIXME: issue #1417
192193
fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val {
193194
import middle::ty;
194195
fn fromb(b: bool) -> const_val { const_int(b as i64) }
195-
match check e.node {
196+
match e.node {
196197
expr_unary(neg, inner) => {
197-
match check eval_const_expr(tcx, inner) {
198+
match eval_const_expr(tcx, inner) {
198199
const_float(f) => const_float(-f),
199200
const_int(i) => const_int(-i),
200-
const_uint(i) => const_uint(-i)
201+
const_uint(i) => const_uint(-i),
202+
const_str(_) => fail ~"Negate on string",
203+
const_bool(_) => fail ~"Negate on boolean"
201204
}
202205
}
203206
expr_unary(not, inner) => {
204-
match check eval_const_expr(tcx, inner) {
207+
match eval_const_expr(tcx, inner) {
205208
const_int(i) => const_int(!i),
206-
const_uint(i) => const_uint(!i)
209+
const_uint(i) => const_uint(!i),
210+
const_bool(b) => const_bool(!b),
211+
_ => fail ~"Not on float or string"
207212
}
208213
}
209214
expr_binary(op, a, b) => {
210-
match check (eval_const_expr(tcx, a), eval_const_expr(tcx, b)) {
215+
match (eval_const_expr(tcx, a), eval_const_expr(tcx, b)) {
211216
(const_float(a), const_float(b)) => {
212-
match check op {
217+
match op {
213218
add => const_float(a + b),
214219
subtract => const_float(a - b),
215220
mul => const_float(a * b),
@@ -220,11 +225,12 @@ fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val {
220225
le => fromb(a <= b),
221226
ne => fromb(a != b),
222227
ge => fromb(a >= b),
223-
gt => fromb(a > b)
228+
gt => fromb(a > b),
229+
_ => fail ~"Can't do this op on floats"
224230
}
225231
}
226232
(const_int(a), const_int(b)) => {
227-
match check op {
233+
match op {
228234
add => const_int(a + b),
229235
subtract => const_int(a - b),
230236
mul => const_int(a * b),
@@ -244,7 +250,7 @@ fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val {
244250
}
245251
}
246252
(const_uint(a), const_uint(b)) => {
247-
match check op {
253+
match op {
248254
add => const_uint(a + b),
249255
subtract => const_uint(a - b),
250256
mul => const_uint(a * b),
@@ -260,54 +266,74 @@ fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val {
260266
le => fromb(a <= b),
261267
ne => fromb(a != b),
262268
ge => fromb(a >= b),
263-
gt => fromb(a > b)
269+
gt => fromb(a > b),
264270
}
265271
}
266272
// shifts can have any integral type as their rhs
267273
(const_int(a), const_uint(b)) => {
268-
match check op {
274+
match op {
269275
shl => const_int(a << b),
270-
shr => const_int(a >> b)
276+
shr => const_int(a >> b),
277+
_ => fail ~"Can't do this op on an int and uint"
271278
}
272279
}
273280
(const_uint(a), const_int(b)) => {
274-
match check op {
281+
match op {
275282
shl => const_uint(a << b),
276-
shr => const_uint(a >> b)
283+
shr => const_uint(a >> b),
284+
_ => fail ~"Can't do this op on a uint and int"
277285
}
278286
}
287+
(const_bool(a), const_bool(b)) => {
288+
const_bool(match op {
289+
and => a && b,
290+
or => a || b,
291+
bitxor => a ^ b,
292+
bitand => a & b,
293+
bitor => a | b,
294+
eq => a == b,
295+
ne => a != b,
296+
_ => fail ~"Can't do this op on bools"
297+
})
298+
}
299+
_ => fail ~"Bad operands for binary"
279300
}
280301
}
281302
expr_cast(base, _) => {
282303
let ety = ty::expr_ty(tcx, e);
283304
let base = eval_const_expr(tcx, base);
284-
match check ty::get(ety).struct {
305+
match ty::get(ety).struct {
285306
ty::ty_float(_) => {
286-
match check base {
307+
match base {
287308
const_uint(u) => const_float(u as f64),
288309
const_int(i) => const_float(i as f64),
289-
const_float(_) => base
310+
const_float(_) => base,
311+
_ => fail ~"Can't cast float to str"
290312
}
291313
}
292314
ty::ty_uint(_) => {
293-
match check base {
315+
match base {
294316
const_uint(_) => base,
295317
const_int(i) => const_uint(i as u64),
296-
const_float(f) => const_uint(f as u64)
318+
const_float(f) => const_uint(f as u64),
319+
_ => fail ~"Can't cast str to uint"
297320
}
298321
}
299322
ty::ty_int(_) | ty::ty_bool => {
300-
match check base {
323+
match base {
301324
const_uint(u) => const_int(u as i64),
302325
const_int(_) => base,
303-
const_float(f) => const_int(f as i64)
326+
const_float(f) => const_int(f as i64),
327+
_ => fail ~"Can't cast str to int"
304328
}
305329
}
330+
_ => fail ~"Can't cast this type"
306331
}
307332
}
308333
expr_lit(lit) => lit_to_const(lit),
309334
// If we have a vstore, just keep going; it has to be a string
310-
expr_vstore(e, _) => eval_const_expr(tcx, e)
335+
expr_vstore(e, _) => eval_const_expr(tcx, e),
336+
_ => fail ~"Unsupported constant expr"
311337
}
312338
}
313339

@@ -319,7 +345,7 @@ fn lit_to_const(lit: @lit) -> const_val {
319345
lit_int_unsuffixed(n) => const_int(n),
320346
lit_float(n, _) => const_float(option::get(float::from_str(*n)) as f64),
321347
lit_nil => const_int(0i64),
322-
lit_bool(b) => const_int(b as i64)
348+
lit_bool(b) => const_bool(b)
323349
}
324350
}
325351

@@ -361,6 +387,15 @@ fn compare_const_vals(a: const_val, b: const_val) -> int {
361387
1
362388
}
363389
}
390+
(const_bool(a), const_bool(b)) => {
391+
if a == b {
392+
0
393+
} else if a < b {
394+
-1
395+
} else {
396+
1
397+
}
398+
}
364399
_ => fail ~"compare_const_vals: ill-typed comparison"
365400
}
366401
}

src/rustc/middle/ty.rs

+7
Original file line numberDiff line numberDiff line change
@@ -3379,6 +3379,13 @@ fn eval_repeat_count(tcx: ctxt, count_expr: @ast::expr, span: span) -> uint {
33793379
repeat count but found string");
33803380
return 0;
33813381
}
3382+
const_eval::const_bool(_) => {
3383+
tcx.sess.span_err(span,
3384+
~"expected signed or unsigned integer for \
3385+
repeat count but found boolean");
3386+
return 0;
3387+
}
3388+
33823389
}
33833390
}
33843391

0 commit comments

Comments
 (0)