From 046c25dbc0c11dcc467c4ff22b8bfbd853976b5b Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Sun, 3 Jul 2011 10:39:07 -0700 Subject: [PATCH] Handle fail as an argument; parse fail expressions unambiguously An expression like: foo(1, fail, 2) was failing to parse, because the parser was interpreting the comma as the start of an expression that was an argument to fail, rather than recognizing that the fail here has no arguments Fixed this by using can_begin_expr to determine whether the next token after a fail token suggests that this is a nullary fail or a unary fail. In addition, when translating calls, check before translating each argument that the block still isn't terminated. This has the effect that if an argument list includes fail, the back-end won't keep trying to generate code for successive arguments and trip the !*terminated assertion. --- src/comp/front/parser.rs | 17 ++++++++--------- src/comp/middle/trans.rs | 5 +++++ src/test/run-fail/args-fail.rs | 9 +++++++++ 3 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 src/test/run-fail/args-fail.rs diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 2db3fde13efb..c4f368a4a2f4 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -9,6 +9,7 @@ import std::either; import std::either::left; import std::either::right; import std::map::hashmap; +import token::can_begin_expr; import driver::session; import util::common; import util::common::filename; @@ -120,7 +121,6 @@ fn new_parser(session::session sess, ast::crate_cfg cfg, ext::syntax_expander_table()); } - // These are the words that shouldn't be allowed as value identifiers, // because, if used at the start of a line, they will cause the line to be // interpreted as a specific kind of statement, which would be confusing. @@ -841,14 +841,13 @@ fn parse_bottom_expr(&parser p) -> @ast::expr { lo = ex_ext.span.lo; ex = ex_ext.node; } else if (eat_word(p, "fail")) { - alt (p.peek()) { - case (token::SEMI) { ex = ast::expr_fail(none) } - case (token::RBRACE) { ex = ast::expr_fail(none) } - case (_) { - auto e = parse_expr(p); - hi = e.span.hi; - ex = ast::expr_fail(some(e)); - } + if (can_begin_expr(p.peek())) { + auto e = parse_expr(p); + hi = e.span.hi; + ex = ast::expr_fail(some(e)); + } + else { + ex = ast::expr_fail(none); } } else if (eat_word(p, "log")) { auto e = parse_expr(p); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index b41553c385bd..44cab2120a02 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5682,6 +5682,11 @@ fn trans_args(&@block_ctxt cx, ValueRef llenv, &option::t[ValueRef] llobj, auto arg_tys = type_of_explicit_args(cx.fcx.lcx.ccx, cx.sp, args); auto i = 0u; for (@ast::expr e in es) { + if (bcx.build.is_terminated()) { + // This means an earlier arg was divergent. + // So this arg can't be evaluated. + break; + } auto r = trans_arg_expr(bcx, args.(i), arg_tys.(i), e); bcx = r.bcx; llargs += [r.val]; diff --git a/src/test/run-fail/args-fail.rs b/src/test/run-fail/args-fail.rs new file mode 100644 index 000000000000..07f47e0da849 --- /dev/null +++ b/src/test/run-fail/args-fail.rs @@ -0,0 +1,9 @@ +// xfail-stage0 +// error-pattern:meep +fn f(int a, int b, @int c) { + fail "moop"; +} + +fn main() { + f(1, fail "meep", @42); +} \ No newline at end of file