Skip to content

Commit be5537e

Browse files
committed
Be more strict about what constitutes a block expression
Blocks (or statements involving blocks) that end in a semicolon are no longer considered the block-expression of their outer block. This used to be an expression block, but now is a statement block: { if foo { ret 1; } else { ret 10; } } This helps clear up some ambiguities in our grammar.
1 parent e945164 commit be5537e

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

src/comp/syntax/parse/parser.rs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,8 +1571,42 @@ fn parse_source_stmt(p: parser) -> @ast::stmt {
15711571
}
15721572
}
15731573

1574+
fn stmt_is_expr(stmt: @ast::stmt) -> bool {
1575+
fn expr_is_expr(e: @ast::expr) -> bool {
1576+
alt e.node {
1577+
ast::expr_if(_, th, els) | ast::expr_if_check(_, th, els) {
1578+
if option::is_none(els) { false }
1579+
else { !option::is_none(th.node.expr) ||
1580+
expr_is_expr(option::get(els)) }
1581+
}
1582+
ast::expr_alt(_, arms) {
1583+
let found_expr = false;
1584+
for arm in arms {
1585+
if !option::is_none(arm.body.node.expr) { found_expr = true; }
1586+
}
1587+
found_expr
1588+
}
1589+
ast::expr_block(blk) | ast::expr_while(_, blk) |
1590+
ast::expr_for(_, _, blk) | ast::expr_for_each(_, _, blk) |
1591+
ast::expr_do_while(blk, _) {
1592+
!option::is_none(blk.node.expr)
1593+
}
1594+
_ { true }
1595+
}
1596+
}
1597+
1598+
ret alt stmt.node {
1599+
ast::stmt_expr(e, _) { expr_is_expr(e) }
1600+
_ { false }
1601+
};
1602+
}
1603+
15741604
fn stmt_to_expr(stmt: @ast::stmt) -> option::t<@ast::expr> {
1575-
ret alt stmt.node { ast::stmt_expr(e, _) { some(e) } _ { none } };
1605+
ret if stmt_is_expr(stmt) {
1606+
alt stmt.node {
1607+
ast::stmt_expr(e, _) { some(e) }
1608+
}
1609+
} else { none };
15761610
}
15771611

15781612
fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
@@ -1627,10 +1661,6 @@ fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
16271661
}
16281662
}
16291663

1630-
1631-
1632-
1633-
16341664
// We should not be calling this on a cdir.
16351665
ast::stmt_crate_directive(cdir) {
16361666
fail;
@@ -1681,7 +1711,6 @@ fn parse_block_tail(p: parser, lo: uint, s: ast::check_mode) -> ast::blk {
16811711
// Not an expression statement.
16821712
stmts += [stmt];
16831713

1684-
16851714
if p.get_file_type() == SOURCE_FILE &&
16861715
stmt_ends_with_semi(*stmt) {
16871716
expect(p, token::SEMI);

src/test/compile-fail/forgot-ret.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// -*- rust -*-
2-
// error-pattern: mismatched types
2+
// error-pattern: not all control paths return a value
33

44
fn god_exists(a: int) -> bool { be god_exists(a); }
55

src/test/compile-fail/missing-return2.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
// error-pattern: mismatched types
1+
// error-pattern: not all control paths return a value
22

33
fn f() -> int {
4-
54
// Make sure typestate doesn't interpret this alt expression
65
// as the function result
76
alt true { true { } }

0 commit comments

Comments
 (0)