Support 'alt check' syntax

It is only a way to flag an alt as intentionally non-exhaustive right now.

Issue #1679
This commit is contained in:
Marijn Haverbeke 2012-02-15 09:35:11 +01:00
parent 9f95ccb426
commit 6627890f6b
14 changed files with 29 additions and 29 deletions

View file

@ -293,7 +293,7 @@ impl ast_output for ast_ctxt {
}
}
ast::expr_alt(cond, arms) {
ast::expr_alt(cond, arms, _) {
self.tag(at_expr_node_alt) {||
self.blk(blk);
self.expr(cond);

View file

@ -110,7 +110,7 @@ fn visit_expr(cx: @ctx, ex: @ast::expr, sc: scope, v: vt<scope>) {
check_call(*cx, sc, f, args);
handled = false;
}
ast::expr_alt(input, arms) { check_alt(*cx, input, arms, sc, v); }
ast::expr_alt(input, arms, _) { check_alt(*cx, input, arms, sc, v); }
ast::expr_for(decl, seq, blk) {
v.visit_expr(seq, sc, v);
check_loop(*cx, sc) {|| check_for(*cx, decl, seq, blk, sc, v); }

View file

@ -21,19 +21,21 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) {
fn check_expr(tcx: ty::ctxt, ex: @expr, &&s: (), v: visit::vt<()>) {
visit::visit_expr(ex, s, v);
alt ex.node {
expr_alt(scrut, arms) {
check_arms(tcx, ex.span, scrut,
pat_util::normalize_arms(tcx, arms));
expr_alt(scrut, arms, mode) {
let arms = pat_util::normalize_arms(tcx, arms);
check_arms(tcx, arms);
/* Check for exhaustiveness */
if mode == alt_exhaustive {
let arms = vec::concat(vec::filter_map(arms, unguarded_pat));
check_exhaustive(tcx, ex.span, expr_ty(tcx, scrut), arms);
}
_ { }
}
_ { }
}
}
fn check_arms(tcx: ty::ctxt, sp:span, scrut: @expr, arms: [arm]) {
fn check_arms(tcx: ty::ctxt, arms: [arm]) {
let i = 0;
let scrut_ty = expr_ty(tcx, scrut);
/* (Could both checks be done in a single pass?) */
/* Check for unreachable patterns */
for arm: arm in arms {
for arm_pat: @pat in arm.pats {
@ -55,11 +57,6 @@ fn check_arms(tcx: ty::ctxt, sp:span, scrut: @expr, arms: [arm]) {
}
i += 1;
}
/* Check for exhaustiveness */
check_exhaustive(tcx, sp, scrut_ty,
vec::concat(vec::filter_map(arms, unguarded_pat)));
}
// Precondition: patterns have been normalized

View file

@ -88,7 +88,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
v.visit_expr(coll, cx, v);
visit_block(loop, cx) {|| visit::visit_block(blk, cx, v);}
}
expr_alt(input, arms) {
expr_alt(input, arms, _) {
v.visit_expr(input, cx, v);
let before = cx.current, sets = [];
for arm in arms {

View file

@ -3257,7 +3257,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
ast::expr_if(cond, thn, els) | ast::expr_if_check(cond, thn, els) {
ret trans_if(bcx, cond, thn, els, dest);
}
ast::expr_alt(expr, arms) {
ast::expr_alt(expr, arms, _) {
ret alt::trans_alt(bcx, expr, arms, dest);
}
ast::expr_block(blk) {

View file

@ -447,7 +447,7 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
find_pre_post_loop(fcx, d, index, body, e.id);
}
expr_index(val, sub) { find_pre_post_exprs(fcx, [val, sub], e.id); }
expr_alt(ex, alts) {
expr_alt(ex, alts, _) {
find_pre_post_expr(fcx, ex);
fn do_an_alt(fcx: fn_ctxt, an_alt: arm) -> pre_and_post {
alt an_alt.guard {

View file

@ -552,7 +552,7 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
expr_index(val, sub) {
ret find_pre_post_state_two(fcx, pres, val, sub, e.id, oper_pure);
}
expr_alt(val, alts) {
expr_alt(val, alts, _) {
let changed =
set_prestate_ann(fcx.ccx, e.id, pres) |
find_pre_post_state_expr(fcx, pres, val);

View file

@ -2231,7 +2231,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
check_block_no_value(fcx, body);
write_ty(tcx, id, block_ty(tcx, body));
}
ast::expr_alt(expr, arms) {
ast::expr_alt(expr, arms, _) {
bot = check_expr(fcx, expr);
// Typecheck the patterns first, so that we get types for all the

View file

@ -215,6 +215,8 @@ enum expr_check_mode { claimed_expr, checked_expr, }
type expr = {id: node_id, node: expr_, span: span};
enum alt_mode { alt_check, alt_exhaustive, }
enum expr_ {
expr_vec([@expr], mutability),
expr_rec([field], option<@expr>),
@ -229,7 +231,7 @@ enum expr_ {
expr_while(@expr, blk),
expr_for(@local, @expr, blk),
expr_do_while(blk, @expr),
expr_alt(@expr, [arm]),
expr_alt(@expr, [arm], alt_mode),
expr_fn(proto, fn_decl, blk, @capture_clause),
expr_fn_block(fn_decl, blk),
expr_block(blk),

View file

@ -383,8 +383,8 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
expr_do_while(blk, expr) {
expr_do_while(fld.fold_block(blk), fld.fold_expr(expr))
}
expr_alt(expr, arms) {
expr_alt(fld.fold_expr(expr), vec::map(arms, fld.fold_arm))
expr_alt(expr, arms, mode) {
expr_alt(fld.fold_expr(expr), vec::map(arms, fld.fold_arm), mode)
}
expr_fn(proto, decl, body, captures) {
expr_fn(proto, fold_fn_decl(decl, fld),

View file

@ -1372,6 +1372,8 @@ fn parse_do_while_expr(p: parser) -> @ast::expr {
fn parse_alt_expr(p: parser) -> @ast::expr {
let lo = p.last_span.lo;
let mode = if eat_word(p, "check") { ast::alt_check }
else { ast::alt_exhaustive };
let discriminant = parse_expr(p);
expect(p, token::LBRACE);
let arms: [ast::arm] = [];
@ -1384,7 +1386,7 @@ fn parse_alt_expr(p: parser) -> @ast::expr {
}
let hi = p.span.hi;
p.bump();
ret mk_expr(p, lo, hi, ast::expr_alt(discriminant, arms));
ret mk_expr(p, lo, hi, ast::expr_alt(discriminant, arms, mode));
}
fn parse_expr(p: parser) -> @ast::expr {
@ -1653,7 +1655,7 @@ fn expr_is_complete(p: parser, e: pexpr) -> bool {
fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
alt e.node {
ast::expr_if(_, _, _) | ast::expr_if_check(_, _, _)
| ast::expr_alt(_, _) | ast::expr_block(_)
| ast::expr_alt(_, _, _) | ast::expr_block(_)
| ast::expr_do_while(_, _) | ast::expr_while(_, _)
| ast::expr_for(_, _, _)
| ast::expr_call(_, _, true) {

View file

@ -901,10 +901,11 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
word_space(s, "while");
print_expr(s, expr);
}
ast::expr_alt(expr, arms) {
ast::expr_alt(expr, arms, mode) {
cbox(s, alt_indent_unit);
ibox(s, 4u);
word_nbsp(s, "alt");
if mode == ast::alt_check { word_nbsp(s, "check"); }
print_maybe_parens_discrim(s, expr);
space(s.s);
bopen(s);

View file

@ -339,7 +339,7 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
v.visit_block(b, e, v);
}
expr_do_while(b, x) { v.visit_block(b, e, v); v.visit_expr(x, e, v); }
expr_alt(x, arms) {
expr_alt(x, arms, _) {
v.visit_expr(x, e, v);
for a: arm in arms { v.visit_arm(a, e, v); }
}

View file

@ -1,5 +1,3 @@
// xfail-test
iface foo {
fn foo() -> int;
fn bar(p: int) -> int;