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:
parent
9f95ccb426
commit
6627890f6b
@ -293,7 +293,7 @@ fn expr(expr: ast:expr) {
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_alt(cond, arms) {
|
||||
ast::expr_alt(cond, arms, _) {
|
||||
self.tag(at_expr_node_alt) {||
|
||||
self.blk(blk);
|
||||
self.expr(cond);
|
||||
|
@ -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); }
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -2231,7 +2231,7 @@ fn check_user_unop(fcx: @fn_ctxt, op_str: str, mname: str,
|
||||
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
|
||||
|
@ -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),
|
||||
|
@ -383,8 +383,8 @@ fn fold_field_(field: field, fld: ast_fold) -> field {
|
||||
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),
|
||||
|
@ -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) {
|
||||
|
@ -901,10 +901,11 @@ fn print_opt(s: ps, expr: option<@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);
|
||||
|
@ -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); }
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
// xfail-test
|
||||
|
||||
iface foo {
|
||||
fn foo() -> int;
|
||||
fn bar(p: int) -> int;
|
||||
|
Loading…
Reference in New Issue
Block a user