about summary refs log tree commit diff
path: root/src/comp/syntax/parse/parser.rs
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2011-12-29 12:03:39 -0800
committerNiko Matsakis <niko@alum.mit.edu>2012-01-03 13:13:52 -0800
commit72a3667eb30705826a99bfa2b9478c4037589dbc (patch)
tree52621f52c0d4ac8a0400d0e5c20bb52f999acef3 /src/comp/syntax/parse/parser.rs
parent43a9d50a74096c73f268f0600f6b1287a1cee880 (diff)
downloadrust-72a3667eb30705826a99bfa2b9478c4037589dbc.tar.gz
rust-72a3667eb30705826a99bfa2b9478c4037589dbc.zip
Allow tail expressions even in no_value blocks. Type checker
will guarantee they have unit type.
Diffstat (limited to 'src/comp/syntax/parse/parser.rs')
-rw-r--r--src/comp/syntax/parse/parser.rs40
1 files changed, 14 insertions, 26 deletions
diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs
index 0ce5f8628dc..a1e4ddbe502 100644
--- a/src/comp/syntax/parse/parser.rs
+++ b/src/comp/syntax/parse/parser.rs
@@ -1232,11 +1232,6 @@ fn parse_if_expr_1(p: parser) ->
         let elexpr = parse_else_expr(p);
         els = some(elexpr);
         hi = elexpr.span.hi;
-    } else if !option::is_none(thn.node.expr) {
-        let sp = option::get(thn.node.expr).span;
-        p.span_fatal(sp, "`if` without `else` can not produce a result");
-        //TODO: If a suggestion mechanism appears, suggest that the
-        //user may have forgotten a ';'
     }
     ret {cond: cond, then: thn, els: els, lo: lo, hi: hi};
 }
@@ -1596,32 +1591,29 @@ fn parse_stmt(p: parser) -> @ast::stmt {
 }
 
 fn expr_is_complete(p: parser, e: @ast::expr) -> bool {
+    log(debug, ("expr_is_complete", p.get_restriction(),
+                print::pprust::expr_to_str(e),
+                expr_requires_semi_to_be_stmt(e)));
     ret p.get_restriction() == RESTRICT_STMT_EXPR &&
         !expr_requires_semi_to_be_stmt(e);
 }
 
 fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
     alt e.node {
-      ast::expr_if(_, th, els) | ast::expr_if_check(_, th, els) {
-        if option::is_none(els) { false }
-        else { !option::is_none(th.node.expr) ||
-                  expr_requires_semi_to_be_stmt(option::get(els)) }
+      ast::expr_if(_, _, _) | ast::expr_if_check(_, _, _)
+      | ast::expr_alt(_, _) | ast::expr_block(_)
+      | ast::expr_do_while(_, _) | ast::expr_while(_, _)
+      | ast::expr_for(_, _, _)
+      | ast::expr_call(_, _, true) {
+        false
       }
-      ast::expr_alt(_, arms) {
-        vec::any(arms, {|arm| !option::is_none(arm.body.node.expr)})
-      }
-      ast::expr_block(blk) | ast::expr_while(_, blk) |
-      ast::expr_for(_, _, blk) | ast::expr_do_while(blk, _) {
-        !option::is_none(blk.node.expr)
-      }
-      ast::expr_call(_, _, true) { false }
       _ { true }
     }
 }
 
 fn stmt_to_expr(stmt: @ast::stmt) -> option::t<@ast::expr> {
     alt stmt.node {
-      ast::stmt_expr(e, _) when expr_requires_semi_to_be_stmt(e) { some(e) }
+      ast::stmt_expr(e, _) { some(e) }
       _ { none }
     }
 }
@@ -1655,14 +1647,10 @@ fn parse_block(p: parser) -> ast::blk {
 }
 
 fn parse_block_no_value(p: parser) -> ast::blk {
-    let blk = parse_block(p);
-    if !option::is_none(blk.node.expr) {
-        let sp = option::get(blk.node.expr).span;
-        p.span_fatal(sp, "this block must not have a result");
-        //TODO: If a suggestion mechanism appears, suggest that the
-        //user may have forgotten a ';'
-    }
-    ret blk;
+    // We parse blocks that cannot have a value the same as any other block;
+    // the type checker will make sure that the tail expression (if any) has
+    // unit type.
+    ret parse_block(p);
 }
 
 // Precondition: already parsed the '{' or '#{'