diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 756a7ad1e6b..61a7bdc13f5 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -315,6 +315,17 @@ fn index_native_item(native_mod_index index, @native_item it) { } } +fn is_call_expr(@expr e) -> bool { + alt (e.node) { + case (expr_call(_, _, _)) { + ret true; + } + case (_) { + ret false; + } + } +} + // // Local Variables: // mode: rust diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index a1b519ba7f5..ea4cf12c48c 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1203,7 +1203,13 @@ impure fn parse_stmt(parser p) -> @ast.stmt { case (token.BE) { p.bump(); auto e = parse_expr(p); - ret @spanned(lo, e.span, ast.stmt_be(e)); + // FIXME: Is this the right place for this check? + if /*check*/ (ast.is_call_expr(e)) { + ret @spanned(lo, e.span, ast.stmt_be(e)); + } + else { + p.err("Non-call expression in tail call"); + } } case (token.LET) { diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 499ab027d50..45d54e6a9d0 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3129,7 +3129,10 @@ fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { } fn trans_be(@block_ctxt cx, @ast.expr e) -> result { - // FIXME: So this isn't actually a tail call + // FIXME: This should be a typestate precondition + check ast.is_call_expr(e); + // FIXME: Turn this into a real tail call once + // calling convention issues are settled ret trans_ret(cx, some(e)); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 7a2b0616d2b..4c3903a7139 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1720,18 +1720,12 @@ fn check_stmt(&@fn_ctxt fcx, &@ast.stmt stmt) -> @ast.stmt { } case (ast.stmt_be(?expr)) { - alt (expr.node) { - case (ast.expr_call(_, _, _)) { - auto expr_0 = check_expr(fcx, expr); - auto expr_1 = demand_expr(fcx, fcx.ret_ty, expr_0); - ret @fold.respan[ast.stmt_](stmt.span, - ast.stmt_be(expr_1)); - } - case (_) { - fcx.ccx.sess.err("Non-call expression in tail call"); - fail; - } - } + /* FIXME: prove instead of check */ + check ast.is_call_expr(expr); + auto expr_0 = check_expr(fcx, expr); + auto expr_1 = demand_expr(fcx, fcx.ret_ty, expr_0); + ret @fold.respan[ast.stmt_](stmt.span, + ast.stmt_be(expr_1)); } case (ast.stmt_log(?expr)) { diff --git a/src/test/compile-fail/tail-non-call.rs b/src/test/compile-fail/tail-non-call.rs index 2742d1fe89d..00a451f647a 100644 --- a/src/test/compile-fail/tail-non-call.rs +++ b/src/test/compile-fail/tail-non-call.rs @@ -7,4 +7,4 @@ fn f() -> int { fn main() { auto y = f(); -} \ No newline at end of file +} diff --git a/src/test/compile-fail/tail-typeck.rs b/src/test/compile-fail/tail-typeck.rs index 10b95546f22..64beedb9a99 100644 --- a/src/test/compile-fail/tail-typeck.rs +++ b/src/test/compile-fail/tail-typeck.rs @@ -10,4 +10,4 @@ fn g() -> uint { fn main() { auto y = f(); -} \ No newline at end of file +}