diff --git a/src/comp/metadata/astencode.rs b/src/comp/metadata/astencode.rs index 002296a656d..167536907ec 100644 --- a/src/comp/metadata/astencode.rs +++ b/src/comp/metadata/astencode.rs @@ -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); diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index a4ef21afe37..6782d06d9de 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -110,7 +110,7 @@ fn visit_expr(cx: @ctx, ex: @ast::expr, sc: scope, v: vt) { 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); } diff --git a/src/comp/middle/check_alt.rs b/src/comp/middle/check_alt.rs index 8bce6ba4a14..5e377e33226 100644 --- a/src/comp/middle/check_alt.rs +++ b/src/comp/middle/check_alt.rs @@ -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 diff --git a/src/comp/middle/last_use.rs b/src/comp/middle/last_use.rs index 111cbde0fa3..a0e8388e824 100644 --- a/src/comp/middle/last_use.rs +++ b/src/comp/middle/last_use.rs @@ -88,7 +88,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt) { 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 { diff --git a/src/comp/middle/trans/base.rs b/src/comp/middle/trans/base.rs index f5f924b5691..618bfcdb89e 100644 --- a/src/comp/middle/trans/base.rs +++ b/src/comp/middle/trans/base.rs @@ -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) { diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index 66781428122..a3fee3a5a75 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -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 { diff --git a/src/comp/middle/tstate/states.rs b/src/comp/middle/tstate/states.rs index 73c7f6a6847..7a7c1cd399a 100644 --- a/src/comp/middle/tstate/states.rs +++ b/src/comp/middle/tstate/states.rs @@ -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); diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index d921fafbf75..aa03940e606 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -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 diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 2ab7059a2a4..deaf70c41fb 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -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), diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index 0ded2bebd62..878b26fa84c 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -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), diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index ad6b47858bc..01f04433908 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -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) { diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index b0ed7ceed00..9cd9cd0503a 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -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); diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs index 29d673f6560..5cf4773101e 100644 --- a/src/comp/syntax/visit.rs +++ b/src/comp/syntax/visit.rs @@ -339,7 +339,7 @@ fn visit_expr(ex: @expr, e: E, v: vt) { 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); } } diff --git a/src/test/run-pass/bind-methods.rs b/src/test/run-pass/bind-methods.rs index d5bcfdcec63..2eb20ed0e9d 100644 --- a/src/test/run-pass/bind-methods.rs +++ b/src/test/run-pass/bind-methods.rs @@ -1,5 +1,3 @@ -// xfail-test - iface foo { fn foo() -> int; fn bar(p: int) -> int;