require a non-semi expr acting as a stmt to have unit return type
This commit is contained in:
parent
37ba5f3b32
commit
f832edc369
@ -318,7 +318,7 @@ fn mk_test_wrapper(cx: test_ctxt,
|
||||
};
|
||||
|
||||
let call_stmt: ast::stmt = nospan(
|
||||
ast::stmt_expr(@call_expr, cx.sess.next_node_id()));
|
||||
ast::stmt_semi(@call_expr, cx.sess.next_node_id()));
|
||||
|
||||
let wrapper_decl: ast::fn_decl = {
|
||||
inputs: [],
|
||||
|
@ -155,7 +155,7 @@ fn visit_block(cx: @ctx, b: ast::blk, sc: scope, v: vt<scope>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::stmt_expr(ex, _) {
|
||||
ast::stmt_expr(ex, _) | ast::stmt_semi(ex, _) {
|
||||
v.visit_expr(ex, sc, v);
|
||||
}
|
||||
}
|
||||
|
@ -4053,7 +4053,9 @@ fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt {
|
||||
debuginfo::update_source_pos(cx, s.span);
|
||||
|
||||
alt s.node {
|
||||
ast::stmt_expr(e, _) { bcx = trans_expr(cx, e, ignore); }
|
||||
ast::stmt_expr(e, _) | ast::stmt_semi(e, _) {
|
||||
bcx = trans_expr(cx, e, ignore);
|
||||
}
|
||||
ast::stmt_decl(d, _) {
|
||||
alt d.node {
|
||||
ast::decl_local(locals) {
|
||||
|
@ -14,14 +14,9 @@ fn collect_ids_block(b: blk, rs: @mutable [node_id]) { *rs += [b.node.id]; }
|
||||
|
||||
fn collect_ids_stmt(s: @stmt, rs: @mutable [node_id]) {
|
||||
alt s.node {
|
||||
stmt_decl(_, id) {
|
||||
stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) {
|
||||
log(debug, "node_id " + int::str(id));
|
||||
log_stmt(*s);;
|
||||
*rs += [id];
|
||||
}
|
||||
stmt_expr(_, id) {
|
||||
log(debug, "node_id " + int::str(id));
|
||||
log_stmt(*s);;
|
||||
log_stmt(*s);
|
||||
*rs += [id];
|
||||
}
|
||||
_ { }
|
||||
|
@ -324,8 +324,9 @@ fn node_id_to_poststate(ccx: crate_ctxt, id: node_id) -> poststate {
|
||||
fn stmt_to_ann(ccx: crate_ctxt, s: stmt) -> ts_ann {
|
||||
#debug("stmt_to_ann");
|
||||
alt s.node {
|
||||
stmt_decl(_, id) { ret node_id_to_ts_ann(ccx, id); }
|
||||
stmt_expr(_, id) { ret node_id_to_ts_ann(ccx, id); }
|
||||
stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) {
|
||||
ret node_id_to_ts_ann(ccx, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -647,7 +647,7 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
|
||||
}
|
||||
}
|
||||
}
|
||||
stmt_expr(e, id) {
|
||||
stmt_expr(e, id) | stmt_semi(e, id) {
|
||||
find_pre_post_expr(fcx, e);
|
||||
copy_pre_post(fcx.ccx, id, e);
|
||||
}
|
||||
|
@ -664,7 +664,7 @@ fn find_pre_post_state_stmt(fcx: fn_ctxt, pres: prestate, s: @stmt) -> bool {
|
||||
}
|
||||
}
|
||||
}
|
||||
stmt_expr(ex, _) {
|
||||
stmt_expr(ex, _) | stmt_semi(ex, _) {
|
||||
let changed =
|
||||
find_pre_post_state_expr(fcx, pres, ex) |
|
||||
set_prestate(stmt_ann, expr_prestate(fcx.ccx, ex)) |
|
||||
|
@ -1660,8 +1660,9 @@ fn expr_is_lval(method_map: typeck::method_map, tcx: ty::ctxt,
|
||||
|
||||
fn stmt_node_id(s: @ast::stmt) -> ast::node_id {
|
||||
alt s.node {
|
||||
ast::stmt_decl(_, id) { ret id; }
|
||||
ast::stmt_expr(_, id) { ret id; }
|
||||
ast::stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) {
|
||||
ret id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2539,7 +2539,14 @@ fn check_stmt(fcx: @fn_ctxt, stmt: @ast::stmt) -> bool {
|
||||
ast::decl_item(_) {/* ignore for now */ }
|
||||
}
|
||||
}
|
||||
ast::stmt_expr(expr, id) { node_id = id; bot = check_expr(fcx, expr); }
|
||||
ast::stmt_expr(expr, id) {
|
||||
node_id = id;
|
||||
bot = check_expr_with(fcx, expr, ty::mk_nil(fcx.ccx.tcx));
|
||||
}
|
||||
ast::stmt_semi(expr, id) {
|
||||
node_id = id;
|
||||
bot = check_expr(fcx, expr);
|
||||
}
|
||||
}
|
||||
write::nil_ty(fcx.ccx.tcx, node_id);
|
||||
ret bot;
|
||||
@ -2567,7 +2574,7 @@ fn check_block(fcx0: @fn_ctxt, blk: ast::blk) -> bool {
|
||||
if bot && !warned &&
|
||||
alt s.node {
|
||||
ast::stmt_decl(@{node: ast::decl_local(_), _}, _) |
|
||||
ast::stmt_expr(_, _) {
|
||||
ast::stmt_expr(_, _) | ast::stmt_semi(_, _) {
|
||||
true
|
||||
}
|
||||
_ { false }
|
||||
|
@ -156,7 +156,12 @@ type stmt = spanned<stmt_>;
|
||||
|
||||
tag stmt_ {
|
||||
stmt_decl(@decl, node_id);
|
||||
|
||||
// expr without trailing semi-colon (must have unit type):
|
||||
stmt_expr(@expr, node_id);
|
||||
|
||||
// expr with trailing semi-colon (may have any type):
|
||||
stmt_semi(@expr, node_id);
|
||||
}
|
||||
|
||||
tag init_op { init_assign; init_move; }
|
||||
|
@ -272,8 +272,9 @@ fn noop_fold_block(b: blk_, fld: ast_fold) -> blk_ {
|
||||
|
||||
fn noop_fold_stmt(s: stmt_, fld: ast_fold) -> stmt_ {
|
||||
ret alt s {
|
||||
stmt_decl(d, nid) { stmt_decl(fld.fold_decl(d), nid) }
|
||||
stmt_expr(e, nid) { stmt_expr(fld.fold_expr(e), nid) }
|
||||
stmt_decl(d, nid) { stmt_decl(fld.fold_decl(d), nid) }
|
||||
stmt_expr(e, nid) { stmt_expr(fld.fold_expr(e), nid) }
|
||||
stmt_semi(e, nid) { stmt_semi(fld.fold_expr(e), nid) }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1639,13 +1639,6 @@ fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn stmt_to_expr(stmt: @ast::stmt) -> option::t<@ast::expr> {
|
||||
alt stmt.node {
|
||||
ast::stmt_expr(e, _) { some(e) }
|
||||
_ { none }
|
||||
}
|
||||
}
|
||||
|
||||
fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
|
||||
alt stmt.node {
|
||||
ast::stmt_decl(d, _) {
|
||||
@ -1657,6 +1650,9 @@ fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
|
||||
ast::stmt_expr(e, _) {
|
||||
ret expr_requires_semi_to_be_stmt(e);
|
||||
}
|
||||
ast::stmt_semi(e, _) {
|
||||
ret false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1695,11 +1691,16 @@ fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
|
||||
}
|
||||
_ {
|
||||
let stmt = parse_stmt(p);
|
||||
alt stmt_to_expr(stmt) {
|
||||
some(e) {
|
||||
alt stmt.node {
|
||||
ast::stmt_expr(e, stmt_id) { // Expression without semicolon:
|
||||
alt p.peek() {
|
||||
token::SEMI. { p.bump(); stmts += [stmt]; }
|
||||
token::RBRACE. { expr = some(e); }
|
||||
token::SEMI. {
|
||||
p.bump();
|
||||
stmts += [@{node: ast::stmt_semi(e, stmt_id) with *stmt}];
|
||||
}
|
||||
token::RBRACE. {
|
||||
expr = some(e);
|
||||
}
|
||||
t {
|
||||
if stmt_ends_with_semi(*stmt) {
|
||||
p.fatal("expected ';' or '}' after expression but \
|
||||
@ -1710,8 +1711,8 @@ fn parse_block_tail(p: parser, lo: uint, s: ast::blk_check_mode) -> ast::blk {
|
||||
}
|
||||
}
|
||||
}
|
||||
none. {
|
||||
// Not an expression statement.
|
||||
|
||||
_ { // All other kinds of statements:
|
||||
stmts += [stmt];
|
||||
|
||||
if stmt_ends_with_semi(*stmt) {
|
||||
|
@ -569,6 +569,11 @@ fn print_stmt(s: ps, st: ast::stmt) {
|
||||
space_if_not_bol(s);
|
||||
print_tl_expr(s, expr);
|
||||
}
|
||||
ast::stmt_semi(expr, _) {
|
||||
space_if_not_bol(s);
|
||||
print_tl_expr(s, expr);
|
||||
word(s.s, ";");
|
||||
}
|
||||
}
|
||||
if parse::parser::stmt_ends_with_semi(st) { word(s.s, ";"); }
|
||||
maybe_print_trailing_comment(s, st.span, none::<uint>);
|
||||
|
@ -262,6 +262,7 @@ fn visit_stmt<E>(s: @stmt, e: E, v: vt<E>) {
|
||||
alt s.node {
|
||||
stmt_decl(d, _) { v.visit_decl(d, e, v); }
|
||||
stmt_expr(ex, _) { v.visit_expr(ex, e, v); }
|
||||
stmt_semi(ex, _) { v.visit_expr(ex, e, v); }
|
||||
}
|
||||
}
|
||||
|
||||
|
13
src/test/compile-fail/block-arg-as-stmt-with-value.rs
Normal file
13
src/test/compile-fail/block-arg-as-stmt-with-value.rs
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
fn compute1() -> float {
|
||||
let v = [0f, 1f, 2f, 3f];
|
||||
|
||||
vec::foldl(0f, v) { |x, y| x + y } - 10f
|
||||
//!^ ERROR mismatched types: expected `()`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = compute1();
|
||||
log(debug, x);
|
||||
assert(y == -4f);
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
|
||||
fn compute1() -> float {
|
||||
let v = [0f, 1f, 2f, 3f];
|
||||
|
||||
// Here the "-10f" parses as a second
|
||||
// statement in tail position:
|
||||
vec::foldl(0f, v) { |x, y| x + y } - 10f
|
||||
}
|
||||
|
||||
fn compute2() -> float {
|
||||
let v = [0f, 1f, 2f, 3f];
|
||||
|
||||
// Here the ret makes this explicit:
|
||||
ret vec::foldl(0f, v) { |x, y| x + y } - 10f;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = compute1();
|
||||
log(debug, x);
|
||||
assert(x == -10f);
|
||||
|
||||
let y = compute2();
|
||||
log(debug, y);
|
||||
assert(y == -4f);
|
||||
}
|
@ -1,21 +1,26 @@
|
||||
fn w_semi(v: [int]) -> int {
|
||||
// the semicolon causes compiler not to
|
||||
// complain about the ignored return value:
|
||||
vec::foldl(0, v) {|x,y| x+y};
|
||||
-10
|
||||
}
|
||||
|
||||
fn wo_paren(v: [int]) -> int {
|
||||
// Perhaps surprising: this is parsed equivalently to w_semi()
|
||||
vec::foldl(0, v) {|x,y| x+y} - 10
|
||||
}
|
||||
|
||||
fn w_paren(v: [int]) -> int {
|
||||
// Here the parentheses force interpretation as an expression:
|
||||
fn w_paren1(v: [int]) -> int {
|
||||
(vec::foldl(0, v) {|x,y| x+y}) - 10
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert wo_paren([0, 1, 2, 3]) == -10;
|
||||
assert w_semi([0, 1, 2, 3]) == -10;
|
||||
assert w_paren([0, 1, 2, 3]) == -4;
|
||||
fn w_paren2(v: [int]) -> int {
|
||||
(vec::foldl(0, v) {|x,y| x+y} - 10)
|
||||
}
|
||||
|
||||
fn w_ret(v: [int]) -> int {
|
||||
ret vec::foldl(0, v) {|x,y| x+y} - 10;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert w_semi([0, 1, 2, 3]) == -10;
|
||||
assert w_paren1([0, 1, 2, 3]) == -4;
|
||||
assert w_paren2([0, 1, 2, 3]) == -4;
|
||||
assert w_ret([0, 1, 2, 3]) == -4;
|
||||
}
|
||||
|
||||
|
11
src/test/run-pass/last-use-in-cap-clause.rs
Normal file
11
src/test/run-pass/last-use-in-cap-clause.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// Make sure #1399 stays fixed
|
||||
|
||||
fn foo() -> lambda() -> int {
|
||||
let k = ~22;
|
||||
let _u = {a: k};
|
||||
ret lambda[move k]() -> int { 22 };
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert foo()() == 22;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user