Skip to content

Commit a0ed110

Browse files
committed
---
yaml --- r: 7017 b: refs/heads/master c: 72a3667 h: refs/heads/master i: 7015: 9c35b63 v: v3
1 parent d6d0c19 commit a0ed110

17 files changed

+98
-56
lines changed

[refs]

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 43a9d50a74096c73f268f0600f6b1287a1cee880
2+
refs/heads/master: 72a3667eb30705826a99bfa2b9478c4037589dbc

trunk/src/comp/middle/typeck.rs

+28-13
Original file line numberDiff line numberDiff line change
@@ -1741,7 +1741,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
17411741
let element_ty = demand::simple(fcx, local.span, element_ty,
17421742
ty::mk_var(fcx.ccx.tcx, locid));
17431743
let bot = check_decl_local(fcx, local);
1744-
check_block(fcx, body);
1744+
check_block_no_value(fcx, body);
17451745
// Unify type of decl with element type of the seq
17461746
demand::simple(fcx, local.span,
17471747
ty::node_id_to_type(fcx.ccx.tcx, local.node.id),
@@ -1756,22 +1756,27 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
17561756
fn check_then_else(fcx: @fn_ctxt, thn: ast::blk,
17571757
elsopt: option::t<@ast::expr>, id: ast::node_id,
17581758
_sp: span) -> bool {
1759-
let then_bot = check_block(fcx, thn);
1760-
let els_bot = false;
1761-
let if_t =
1759+
let (if_t, if_bot) =
17621760
alt elsopt {
17631761
some(els) {
1762+
let thn_bot = check_block(fcx, thn);
17641763
let thn_t = block_ty(fcx.ccx.tcx, thn);
1765-
els_bot = check_expr_with(fcx, els, thn_t);
1766-
let elsopt_t = expr_ty(fcx.ccx.tcx, els);
1767-
if !ty::type_is_bot(fcx.ccx.tcx, elsopt_t) {
1768-
elsopt_t
1769-
} else { thn_t }
1764+
let els_bot = check_expr_with(fcx, els, thn_t);
1765+
let els_t = expr_ty(fcx.ccx.tcx, els);
1766+
let if_t = if !ty::type_is_bot(fcx.ccx.tcx, els_t) {
1767+
els_t
1768+
} else {
1769+
thn_t
1770+
};
1771+
(if_t, thn_bot & els_bot)
1772+
}
1773+
none. {
1774+
check_block_no_value(fcx, thn);
1775+
(ty::mk_nil(fcx.ccx.tcx), false)
17701776
}
1771-
none. { ty::mk_nil(fcx.ccx.tcx) }
17721777
};
17731778
write::ty_only_fixup(fcx, id, if_t);
1774-
ret then_bot & els_bot;
1779+
ret if_bot;
17751780
}
17761781

17771782
// Checks the compatibility
@@ -1993,12 +1998,12 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
19931998
}
19941999
ast::expr_while(cond, body) {
19952000
bot = check_expr_with(fcx, cond, ty::mk_bool(tcx));
1996-
check_block(fcx, body);
2001+
check_block_no_value(fcx, body);
19972002
write::ty_only_fixup(fcx, id, ty::mk_nil(tcx));
19982003
}
19992004
ast::expr_do_while(body, cond) {
20002005
bot = check_expr_with(fcx, cond, ty::mk_bool(tcx)) |
2001-
check_block(fcx, body);
2006+
check_block_no_value(fcx, body);
20022007
write::ty_only_fixup(fcx, id, block_ty(tcx, body));
20032008
}
20042009
ast::expr_alt(expr, arms) {
@@ -2490,6 +2495,16 @@ fn check_stmt(fcx: @fn_ctxt, stmt: @ast::stmt) -> bool {
24902495
ret bot;
24912496
}
24922497

2498+
fn check_block_no_value(fcx: @fn_ctxt, blk: ast::blk) -> bool {
2499+
let bot = check_block(fcx, blk);
2500+
if !bot {
2501+
let blkty = ty::node_id_to_monotype(fcx.ccx.tcx, blk.node.id);
2502+
let nilty = ty::mk_nil(fcx.ccx.tcx);
2503+
demand::simple(fcx, blk.span, nilty, blkty);
2504+
}
2505+
ret bot;
2506+
}
2507+
24932508
fn check_block(fcx0: @fn_ctxt, blk: ast::blk) -> bool {
24942509
let fcx = alt blk.node.rules {
24952510
ast::unchecked_blk. { @{purity: ast::impure_fn with *fcx0} }

trunk/src/comp/syntax/parse/eval.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ fn parse_companion_mod(cx: ctx, prefix: str, suffix: option::t<str>)
5656
-> ([@ast::view_item], [@ast::item], [ast::attribute]) {
5757

5858
fn companion_file(prefix: str, suffix: option::t<str>) -> str {
59-
alt suffix {
59+
ret alt suffix {
6060
option::some(s) { fs::connect(prefix, s) }
6161
option::none. { prefix }
62-
} + ".rs"
62+
} + ".rs";
6363
}
6464

6565
fn file_exists(path: str) -> bool {

trunk/src/comp/syntax/parse/parser.rs

+14-26
Original file line numberDiff line numberDiff line change
@@ -1232,11 +1232,6 @@ fn parse_if_expr_1(p: parser) ->
12321232
let elexpr = parse_else_expr(p);
12331233
els = some(elexpr);
12341234
hi = elexpr.span.hi;
1235-
} else if !option::is_none(thn.node.expr) {
1236-
let sp = option::get(thn.node.expr).span;
1237-
p.span_fatal(sp, "`if` without `else` can not produce a result");
1238-
//TODO: If a suggestion mechanism appears, suggest that the
1239-
//user may have forgotten a ';'
12401235
}
12411236
ret {cond: cond, then: thn, els: els, lo: lo, hi: hi};
12421237
}
@@ -1596,32 +1591,29 @@ fn parse_stmt(p: parser) -> @ast::stmt {
15961591
}
15971592

15981593
fn expr_is_complete(p: parser, e: @ast::expr) -> bool {
1594+
log(debug, ("expr_is_complete", p.get_restriction(),
1595+
print::pprust::expr_to_str(e),
1596+
expr_requires_semi_to_be_stmt(e)));
15991597
ret p.get_restriction() == RESTRICT_STMT_EXPR &&
16001598
!expr_requires_semi_to_be_stmt(e);
16011599
}
16021600

16031601
fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
16041602
alt e.node {
1605-
ast::expr_if(_, th, els) | ast::expr_if_check(_, th, els) {
1606-
if option::is_none(els) { false }
1607-
else { !option::is_none(th.node.expr) ||
1608-
expr_requires_semi_to_be_stmt(option::get(els)) }
1603+
ast::expr_if(_, _, _) | ast::expr_if_check(_, _, _)
1604+
| ast::expr_alt(_, _) | ast::expr_block(_)
1605+
| ast::expr_do_while(_, _) | ast::expr_while(_, _)
1606+
| ast::expr_for(_, _, _)
1607+
| ast::expr_call(_, _, true) {
1608+
false
16091609
}
1610-
ast::expr_alt(_, arms) {
1611-
vec::any(arms, {|arm| !option::is_none(arm.body.node.expr)})
1612-
}
1613-
ast::expr_block(blk) | ast::expr_while(_, blk) |
1614-
ast::expr_for(_, _, blk) | ast::expr_do_while(blk, _) {
1615-
!option::is_none(blk.node.expr)
1616-
}
1617-
ast::expr_call(_, _, true) { false }
16181610
_ { true }
16191611
}
16201612
}
16211613

16221614
fn stmt_to_expr(stmt: @ast::stmt) -> option::t<@ast::expr> {
16231615
alt stmt.node {
1624-
ast::stmt_expr(e, _) when expr_requires_semi_to_be_stmt(e) { some(e) }
1616+
ast::stmt_expr(e, _) { some(e) }
16251617
_ { none }
16261618
}
16271619
}
@@ -1655,14 +1647,10 @@ fn parse_block(p: parser) -> ast::blk {
16551647
}
16561648

16571649
fn parse_block_no_value(p: parser) -> ast::blk {
1658-
let blk = parse_block(p);
1659-
if !option::is_none(blk.node.expr) {
1660-
let sp = option::get(blk.node.expr).span;
1661-
p.span_fatal(sp, "this block must not have a result");
1662-
//TODO: If a suggestion mechanism appears, suggest that the
1663-
//user may have forgotten a ';'
1664-
}
1665-
ret blk;
1650+
// We parse blocks that cannot have a value the same as any other block;
1651+
// the type checker will make sure that the tail expression (if any) has
1652+
// unit type.
1653+
ret parse_block(p);
16661654
}
16671655

16681656
// Precondition: already parsed the '{' or '#{'

trunk/src/comp/syntax/print/pprust.rs

+30-2
Original file line numberDiff line numberDiff line change
@@ -558,11 +558,39 @@ fn print_attribute(s: ps, attr: ast::attribute) {
558558
word(s.s, "]");
559559
}
560560

561+
// An expression that begins with a dual-form statement/expression like `{
562+
// ... }-10` would be parsed as `{ ... };-10` unless parentheses are used (ie,
563+
// `({...}-10)`). These parentheses are not, however, preserved by the
564+
// parser. This function specifies whether parentheses must be inserted.
565+
fn stmt_expr_requires_parens(ex: @ast::expr) -> bool {
566+
fn helper(ex: @ast::expr, inner: bool) -> bool {
567+
alt ex.node {
568+
ast::expr_call(subex, _, _) | ast::expr_binary(_, subex, _) {
569+
be helper(subex, true);
570+
}
571+
_ when !inner { ret false; }
572+
_ { ret !parse::parser::expr_requires_semi_to_be_stmt(ex); }
573+
}
574+
}
575+
ret helper(ex, false);
576+
}
577+
561578
fn print_stmt(s: ps, st: ast::stmt) {
562579
maybe_print_comment(s, st.span.lo);
563580
alt st.node {
564-
ast::stmt_decl(decl, _) { print_decl(s, decl); }
565-
ast::stmt_expr(expr, _) { space_if_not_bol(s); print_expr(s, expr); }
581+
ast::stmt_decl(decl, _) {
582+
print_decl(s, decl);
583+
}
584+
ast::stmt_expr(expr, _) {
585+
space_if_not_bol(s);
586+
if stmt_expr_requires_parens(expr) {
587+
popen(s);
588+
print_expr(s, expr);
589+
pclose(s);
590+
} else {
591+
print_expr(s, expr);
592+
}
593+
}
566594
}
567595
if parse::parser::stmt_ends_with_semi(st) { word(s.s, ";"); }
568596
maybe_print_trailing_comment(s, st.span, none::<uint>);

trunk/src/libstd/rope.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ fn iter_chars(rope: rope, it: block(char)) {
443443
loop_chars(rope) {|x|
444444
it(x);
445445
ret true
446-
}
446+
};
447447
}
448448

449449
/*

trunk/src/test/compile-fail/block-must-not-have-result-do.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// error-pattern:this block must not have a result
1+
// error-pattern:mismatched types: expected `()` but found `bool`
22

33
fn main() {
44
do {

trunk/src/test/compile-fail/block-must-not-have-result-for.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// error-pattern:this block must not have a result
1+
// error-pattern:mismatched types: expected `()` but found `bool`
22

33
fn main() {
44
for i in [0] {

trunk/src/test/compile-fail/block-must-not-have-result-res.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// error-pattern:this block must not have a result
1+
// error-pattern:mismatched types: expected `()` but found `bool`
22

33
resource r(i: int) {
44
true

trunk/src/test/compile-fail/block-must-not-have-result-while.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// error-pattern:this block must not have a result
1+
// error-pattern:mismatched types: expected `()` but found `bool`
22

33
fn main() {
44
while true {

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33

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

6-
fn f(a: int) -> int { if god_exists(a) { ret 5; } }
6+
fn f(a: int) -> int { if god_exists(a) { ret 5; }; }
77

88
fn main() { f(12); }

trunk/src/test/compile-fail/if-without-else-result.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// error-pattern:`if` without `else` can not produce a result
1+
// error-pattern:mismatched types: expected `()` but found `bool`
22

33
fn main() {
44
let a = if true { true };

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
fn f() -> int {
44
// Make sure typestate doesn't interpret this alt expression
55
// as the function result
6-
alt true { true { } }
6+
alt true { true { } };
77
}
88

99
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// pp-exact
2+
3+
// Here we check that the parentheses around the body of `wsucc()` are
4+
// preserved. They are needed to disambiguate `{ret n+1}; - 0` from
5+
// `({ret n+1}-0)`.
6+
7+
fn wsucc(n: int) -> int { ({ ret n + 1 } - 0); }
8+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
fn wsucc(n: int) -> int { { ret n + 1 } + 0; }
1+
fn wsucc(n: int) -> int { ({ ret n + 1 } + 0); }
22
fn main() { }
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
fn wsucc(n: int) -> int { { ret n + 1 } == 0; }
1+
fn wsucc(n: int) -> int { ({ ret n + 1 } == 0); }
22
fn main() { }

trunk/src/test/stdtest/os.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ fn test_setenv() {
1414
}
1515

1616
#[test]
17+
#[ignore(reason = "fails periodically on mac")]
1718
fn test_setenv_overwrite() {
1819
setenv("NAME2", "1");
1920
setenv("NAME2", "2");
@@ -23,12 +24,14 @@ fn test_setenv_overwrite() {
2324
// Windows GetEnvironmentVariable requires some extra work to make sure
2425
// the buffer the variable is copied into is the right size
2526
#[test]
27+
#[ignore(reason = "fails periodically on mac")]
2628
fn test_getenv_big() {
2729
let s = "";
2830
let i = 0;
2931
while i < 100 { s += "aaaaaaaaaa"; i += 1; }
30-
setenv("NAME3", s);
31-
assert (getenv("NAME3") == option::some(s));
32+
setenv("test_getenv_big", s);
33+
log(debug, s);
34+
assert (getenv("test_getenv_big") == option::some(s));
3235
}
3336

3437
#[test]

0 commit comments

Comments
 (0)