Skip to content

Commit 046c25d

Browse files
committed
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.
1 parent 6369807 commit 046c25d

File tree

3 files changed

+22
-9
lines changed

3 files changed

+22
-9
lines changed

src/comp/front/parser.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import std::either;
99
import std::either::left;
1010
import std::either::right;
1111
import std::map::hashmap;
12+
import token::can_begin_expr;
1213
import driver::session;
1314
import util::common;
1415
import util::common::filename;
@@ -120,7 +121,6 @@ fn new_parser(session::session sess, ast::crate_cfg cfg,
120121
ext::syntax_expander_table());
121122
}
122123

123-
124124
// These are the words that shouldn't be allowed as value identifiers,
125125
// because, if used at the start of a line, they will cause the line to be
126126
// interpreted as a specific kind of statement, which would be confusing.
@@ -841,14 +841,13 @@ fn parse_bottom_expr(&parser p) -> @ast::expr {
841841
lo = ex_ext.span.lo;
842842
ex = ex_ext.node;
843843
} else if (eat_word(p, "fail")) {
844-
alt (p.peek()) {
845-
case (token::SEMI) { ex = ast::expr_fail(none) }
846-
case (token::RBRACE) { ex = ast::expr_fail(none) }
847-
case (_) {
848-
auto e = parse_expr(p);
849-
hi = e.span.hi;
850-
ex = ast::expr_fail(some(e));
851-
}
844+
if (can_begin_expr(p.peek())) {
845+
auto e = parse_expr(p);
846+
hi = e.span.hi;
847+
ex = ast::expr_fail(some(e));
848+
}
849+
else {
850+
ex = ast::expr_fail(none);
852851
}
853852
} else if (eat_word(p, "log")) {
854853
auto e = parse_expr(p);

src/comp/middle/trans.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5682,6 +5682,11 @@ fn trans_args(&@block_ctxt cx, ValueRef llenv, &option::t[ValueRef] llobj,
56825682
auto arg_tys = type_of_explicit_args(cx.fcx.lcx.ccx, cx.sp, args);
56835683
auto i = 0u;
56845684
for (@ast::expr e in es) {
5685+
if (bcx.build.is_terminated()) {
5686+
// This means an earlier arg was divergent.
5687+
// So this arg can't be evaluated.
5688+
break;
5689+
}
56855690
auto r = trans_arg_expr(bcx, args.(i), arg_tys.(i), e);
56865691
bcx = r.bcx;
56875692
llargs += [r.val];

src/test/run-fail/args-fail.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// xfail-stage0
2+
// error-pattern:meep
3+
fn f(int a, int b, @int c) {
4+
fail "moop";
5+
}
6+
7+
fn main() {
8+
f(1, fail "meep", @42);
9+
}

0 commit comments

Comments
 (0)