diff options
| -rw-r--r-- | src/rustc/driver/driver.rs | 2 | ||||
| -rw-r--r-- | src/rustc/middle/block_use.rs | 4 | ||||
| -rw-r--r-- | src/rustc/middle/check_loop.rs | 17 | ||||
| -rw-r--r-- | src/rustc/middle/trans/base.rs | 37 | ||||
| -rw-r--r-- | src/rustc/middle/trans/closure.rs | 5 | ||||
| -rw-r--r-- | src/rustc/middle/trans/common.rs | 4 | ||||
| -rw-r--r-- | src/rustc/middle/trans/type_use.rs | 2 | ||||
| -rw-r--r-- | src/rustc/middle/tstate/pre_post_conditions.rs | 29 | ||||
| -rw-r--r-- | src/rustc/middle/tstate/states.rs | 19 | ||||
| -rw-r--r-- | src/rustc/middle/typeck.rs | 18 | ||||
| -rw-r--r-- | src/rustc/syntax/ast.rs | 1 | ||||
| -rw-r--r-- | src/rustc/syntax/fold.rs | 1 | ||||
| -rw-r--r-- | src/rustc/syntax/parse/parser.rs | 38 | ||||
| -rw-r--r-- | src/rustc/syntax/print/pprust.rs | 14 | ||||
| -rw-r--r-- | src/rustc/syntax/visit.rs | 10 |
15 files changed, 123 insertions, 78 deletions
diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs index 349c29a6f85..92e88860bbe 100644 --- a/src/rustc/driver/driver.rs +++ b/src/rustc/driver/driver.rs @@ -156,7 +156,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, time(time_passes, "block-use checking", bind middle::block_use::check_crate(ty_cx, crate)); time(time_passes, "loop checking", - bind middle::check_loop::check_crate(sess, crate)); + bind middle::check_loop::check_crate(ty_cx, crate)); time(time_passes, "function usage", bind fn_usage::check_crate_fn_usage(ty_cx, crate)); time(time_passes, "alt checking", diff --git a/src/rustc/middle/block_use.rs b/src/rustc/middle/block_use.rs index c0719e47ad3..de14863368c 100644 --- a/src/rustc/middle/block_use.rs +++ b/src/rustc/middle/block_use.rs @@ -33,6 +33,10 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) { i += 1u; } } + expr_loop_body(body) { + cx.allow_block = true; + v.visit_expr(body, cx, v); + } _ { cx.allow_block = false; visit::visit_expr(ex, cx, v); diff --git a/src/rustc/middle/check_loop.rs b/src/rustc/middle/check_loop.rs index 9f570cb924b..b145ae0d75a 100644 --- a/src/rustc/middle/check_loop.rs +++ b/src/rustc/middle/check_loop.rs @@ -4,7 +4,7 @@ import driver::session::session; type ctx = {in_loop: bool, can_ret: bool}; -fn check_crate(sess: session, crate: @crate) { +fn check_crate(tcx: ty::ctxt, crate: @crate) { visit::visit_crate(*crate, {in_loop: false,can_ret: true}, visit::mk_vt(@{ visit_item: {|i, _cx, v| visit::visit_item(i, {in_loop: false, can_ret: true}, v); @@ -21,28 +21,31 @@ fn check_crate(sess: session, crate: @crate) { expr_fn(_, _, _, _) { visit::visit_expr(e, {in_loop: false, can_ret: true}, v); } - expr_fn_block(fn_decl, blk) { - visit::visit_expr(e, {in_loop: false, can_ret: false}, v); + expr_fn_block(_, b) { + v.visit_block(b, {in_loop: false, can_ret: false}, v); + } + expr_loop_body(@{node: expr_fn_block(_, b), _}) { + v.visit_block(b, {in_loop: true, can_ret: false}, v); } expr_break { if !cx.in_loop { - sess.span_err(e.span, "`break` outside of loop"); + tcx.sess.span_err(e.span, "`break` outside of loop"); } } expr_cont { if !cx.in_loop { - sess.span_err(e.span, "`cont` outside of loop"); + tcx.sess.span_err(e.span, "`cont` outside of loop"); } } expr_ret(oe) { if !cx.can_ret { - sess.span_err(e.span, "`ret` in block function"); + tcx.sess.span_err(e.span, "`ret` in block function"); } visit::visit_expr_opt(oe, cx, v); } expr_be(re) { if !cx.can_ret { - sess.span_err(e.span, "`be` in block function"); + tcx.sess.span_err(e.span, "`be` in block function"); } v.visit_expr(re, cx, v); } diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 808a500814e..e1aeb2abc5e 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -2990,20 +2990,24 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block { } ast::expr_addr_of(_, x) { ret trans_addr_of(bcx, x, dest); } ast::expr_fn(proto, decl, body, cap_clause) { - ret closure::trans_expr_fn( - bcx, proto, decl, body, e.span, e.id, *cap_clause, dest); + ret closure::trans_expr_fn(bcx, proto, decl, body, e.span, e.id, + *cap_clause, false, dest); } ast::expr_fn_block(decl, body) { - alt ty::get(expr_ty(bcx, e)).struct { + alt check ty::get(expr_ty(bcx, e)).struct { ty::ty_fn({proto, _}) { #debug("translating fn_block %s with type %s", expr_to_str(e), ty_to_str(tcx, expr_ty(bcx, e))); - let cap_clause = { copies: [], moves: [] }; - ret closure::trans_expr_fn( - bcx, proto, decl, body, e.span, e.id, cap_clause, dest); + ret closure::trans_expr_fn(bcx, proto, decl, body, e.span, e.id, + {copies: [], moves: []}, false, dest); } - _ { - fail "type of fn block is not a function!"; + } + } + ast::expr_loop_body(b@@{node: ast::expr_fn_block(decl, body), _}) { + alt check ty::get(expr_ty(bcx, e)).struct { + ty::ty_fn({proto, _}) { + ret closure::trans_expr_fn(bcx, proto, decl, body, e.span, b.id, + {copies: [], moves: []}, true, dest); } } } @@ -3375,7 +3379,16 @@ fn trans_break_cont(bcx: block, to_end: bool) } _ {} } - unwind = alt check unwind.parent { parent_some(cx) { cx } }; + unwind = alt unwind.parent { + parent_some(cx) { cx } + // This is a return from a loop body block + parent_none { + Store(bcx, C_bool(!to_end), bcx.fcx.llretptr); + cleanup_and_leave(bcx, none, some(bcx.fcx.llreturn)); + Unreachable(bcx); + ret bcx; + } + }; } cleanup_and_Br(bcx, unwind, target.llbb); Unreachable(bcx); @@ -3895,7 +3908,8 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, ty_self: self_arg, param_substs: option<param_substs>, id: ast::node_id, - maybe_load_env: fn(fn_ctxt)) { + maybe_load_env: fn(fn_ctxt), + finish: fn(block)) { let _icx = ccx.insn_ctxt("trans_closure"); set_uwtable(llfndecl); @@ -3932,6 +3946,7 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, } else { bcx = trans_block(bcx, body, save_in(fcx.llretptr)); } + finish(bcx); cleanup_and_Br(bcx, bcx_top, fcx.llreturn); // Insert the mandatory first few basic blocks before lltop. @@ -3957,7 +3972,7 @@ fn trans_fn(ccx: @crate_ctxt, if ccx.sess.opts.extra_debuginfo { debuginfo::create_function(fcx); } - }); + }, {|_bcx|}); if do_time { let end = time::get_time(); log_fn_time(ccx, path_str(path), start, end); diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs index 09d041429cb..0ac132562fe 100644 --- a/src/rustc/middle/trans/closure.rs +++ b/src/rustc/middle/trans/closure.rs @@ -367,6 +367,7 @@ fn trans_expr_fn(bcx: block, sp: span, id: ast::node_id, cap_clause: ast::capture_clause, + is_loop_body: bool, dest: dest) -> block { let _icx = bcx.insn_ctxt("closure::trans_expr_fn"); if dest == ignore { ret bcx; } @@ -385,6 +386,8 @@ fn trans_expr_fn(bcx: block, trans_closure(ccx, sub_path, decl, body, llfn, no_self, bcx.fcx.param_substs, id, {|fcx| load_environment(fcx, cdata_ty, cap_vars, ck); + }, {|bcx| + if is_loop_body { Store(bcx, C_bool(true), bcx.fcx.llretptr); } }); llbox }; @@ -395,7 +398,7 @@ fn trans_expr_fn(bcx: block, ast::proto_uniq { trans_closure_env(ty::ck_uniq) } ast::proto_bare { trans_closure(ccx, sub_path, decl, body, llfn, no_self, none, - id, {|_fcx|}); + id, {|_fcx|}, {|_bcx|}); C_null(T_opaque_box_ptr(ccx)) } }; diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index f68495b7561..5714ef23a5b 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -718,9 +718,7 @@ fn C_nil() -> ValueRef { } fn C_bool(b: bool) -> ValueRef { - if b { - ret C_integral(T_bool(), 1u64, False); - } else { ret C_integral(T_bool(), 0u64, False); } + C_integral(T_bool(), if b { 1u64 } else { 0u64 }, False) } fn C_i32(i: i32) -> ValueRef { diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index 61b09f0e01c..83d3ad5eb04 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -190,7 +190,7 @@ fn mark_for_expr(cx: ctx, e: @expr) { expr_fail(_) | expr_break | expr_cont | expr_unary(_, _) | expr_lit(_) | expr_assert(_) | expr_check(_, _) | expr_if_check(_, _, _) | expr_mac(_) | expr_addr_of(_, _) | - expr_ret(_) | expr_loop(_) | expr_bind(_, _) {} + expr_ret(_) | expr_loop(_) | expr_bind(_, _) | expr_loop_body(_) {} } } diff --git a/src/rustc/middle/tstate/pre_post_conditions.rs b/src/rustc/middle/tstate/pre_post_conditions.rs index 7ad99e0f5d1..03a03cd0aed 100644 --- a/src/rustc/middle/tstate/pre_post_conditions.rs +++ b/src/rustc/middle/tstate/pre_post_conditions.rs @@ -360,10 +360,6 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) { find_pre_post_exprs(fcx, es, e.id); } expr_tup(elts) { find_pre_post_exprs(fcx, elts, e.id); } - expr_copy(a) { - find_pre_post_expr(fcx, a); - copy_pre_post(fcx.ccx, e.id, a); - } expr_move(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_move); } expr_swap(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_swap); } expr_assign(lhs, rhs) { handle_update(fcx, e, lhs, rhs, oper_assign); } @@ -408,17 +404,10 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) { expr_postcond(fcx.ccx, l)); } else { find_pre_post_exprs(fcx, [l, r], e.id); } } - expr_unary(_, operand) { - find_pre_post_expr(fcx, operand); - copy_pre_post(fcx.ccx, e.id, operand); - } - expr_addr_of(_, operand) { - find_pre_post_expr(fcx, operand); - copy_pre_post(fcx.ccx, e.id, operand); - } - expr_cast(operand, _) { - find_pre_post_expr(fcx, operand); - copy_pre_post(fcx.ccx, e.id, operand); + expr_addr_of(_, x) | expr_cast(x, _) | expr_unary(_, x) | + expr_loop_body(x) | expr_assert(x) | expr_copy(x) { + find_pre_post_expr(fcx, x); + copy_pre_post(fcx.ccx, e.id, x); } expr_while(test, body) { find_pre_post_expr(fcx, test); @@ -512,10 +501,6 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) { then everything is true! */ prestate, false_postcond(num_local_vars)); } - expr_assert(p) { - find_pre_post_expr(fcx, p); - copy_pre_post(fcx.ccx, e.id, p); - } expr_check(_, p) { find_pre_post_expr(fcx, p); copy_pre_post(fcx.ccx, e.id, p); @@ -527,12 +512,6 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) { expr_if_check(p, conseq, maybe_alt) { join_then_else(fcx, p, conseq, maybe_alt, e.id, if_check); } - - - - - - expr_bind(operator, maybe_args) { let mut args = []; let mut cmodes = callee_modes(fcx, operator.id); diff --git a/src/rustc/middle/tstate/states.rs b/src/rustc/middle/tstate/states.rs index 8c7cea6c7c9..c0ebc3a9d36 100644 --- a/src/rustc/middle/tstate/states.rs +++ b/src/rustc/middle/tstate/states.rs @@ -422,7 +422,6 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool { init_assign), elts, return_val); } - expr_copy(a) { ret find_pre_post_state_sub(fcx, pres, a, e.id, none); } expr_move(lhs, rhs) { ret find_pre_post_state_two(fcx, pres, lhs, rhs, e.id, oper_move); } @@ -598,17 +597,10 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool { } ret changed | set_poststate_ann(fcx.ccx, e.id, a_post); } - expr_field(val, _, _) { - ret find_pre_post_state_sub(fcx, pres, val, e.id, none); - } - expr_unary(_, operand) { - ret find_pre_post_state_sub(fcx, pres, operand, e.id, none); - } - expr_addr_of(_, operand) { - ret find_pre_post_state_sub(fcx, pres, operand, e.id, none); - } - expr_cast(operand, _) { - ret find_pre_post_state_sub(fcx, pres, operand, e.id, none); + expr_field(x, _, _) | expr_loop_body(x) | expr_unary(_, x) | + expr_addr_of(_, x) | expr_assert(x) | expr_cast(x, _) | + expr_copy(x) { + ret find_pre_post_state_sub(fcx, pres, x, e.id, none); } expr_fail(maybe_fail_val) { // FIXME Should factor out this code, @@ -622,9 +614,6 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool { option::maybe(maybe_fail_val, false, {|fail_val| find_pre_post_state_expr(fcx, pres, fail_val)}); } - expr_assert(p) { - ret find_pre_post_state_sub(fcx, pres, p, e.id, none); - } expr_check(_, p) { /* predicate p holds after this expression executes */ let c: sp_constr = expr_to_constr(fcx.ccx.tcx, p); diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 3fb2c67509a..86cf9d34815 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -2910,6 +2910,24 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, check_expr_fn_with_unifier(fcx, expr, proto, decl, body, unify, expected); } + ast::expr_loop_body(block) { + let rty = structurally_resolved_type(fcx, expr.span, expected); + let inner_ty = alt check ty::get(rty).struct { + ty::ty_fn(fty) { + demand::simple(fcx, expr.span, fty.output, ty::mk_bool(tcx)); + ty::mk_fn(tcx, {output: ty::mk_nil(tcx) with fty}) + } + }; + check_expr_with(fcx, block, inner_ty); + let block_ty = structurally_resolved_type( + fcx, expr.span, ty::node_id_to_type(tcx, block.id)); + alt check ty::get(block_ty).struct { + ty::ty_fn(fty) { + write_ty(tcx, expr.id, ty::mk_fn(tcx, {output: ty::mk_bool(tcx) + with fty})); + } + } + } ast::expr_block(b) { // If this is an unchecked block, turn off purity-checking bot = check_block(fcx, b); diff --git a/src/rustc/syntax/ast.rs b/src/rustc/syntax/ast.rs index 217977e9658..e657b6a6fe4 100644 --- a/src/rustc/syntax/ast.rs +++ b/src/rustc/syntax/ast.rs @@ -303,6 +303,7 @@ enum expr_ { expr_alt(@expr, [arm], alt_mode), expr_fn(proto, fn_decl, blk, @capture_clause), expr_fn_block(fn_decl, blk), + expr_loop_body(@expr), expr_block(blk), /* diff --git a/src/rustc/syntax/fold.rs b/src/rustc/syntax/fold.rs index 4630b99eda6..3f98ce5c29e 100644 --- a/src/rustc/syntax/fold.rs +++ b/src/rustc/syntax/fold.rs @@ -407,6 +407,7 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ { expr_binary(binop, fld.fold_expr(lhs), fld.fold_expr(rhs)) } expr_unary(binop, ohs) { expr_unary(binop, fld.fold_expr(ohs)) } + expr_loop_body(f) { expr_loop_body(fld.fold_expr(f)) } expr_lit(_) { e } expr_cast(expr, ty) { expr_cast(fld.fold_expr(expr), ty) } expr_addr_of(m, ohs) { expr_addr_of(m, fld.fold_expr(ohs)) } diff --git a/src/rustc/syntax/parse/parser.rs b/src/rustc/syntax/parse/parser.rs index 78d8d2b6133..a898ee840be 100644 --- a/src/rustc/syntax/parse/parser.rs +++ b/src/rustc/syntax/parse/parser.rs @@ -1403,13 +1403,37 @@ fn parse_else_expr(p: parser) -> @ast::expr { } fn parse_for_expr(p: parser) -> @ast::expr { - let lo = p.last_span.lo; - let decl = parse_local(p, false, false); - expect_word(p, "in"); - let seq = parse_expr(p); - let body = parse_block_no_value(p); - let mut hi = body.span.hi; - ret mk_expr(p, lo, hi, ast::expr_for(decl, seq, body)); + let lo = p.last_span; + // FIXME remove this kludge after migration and snapshotting (#1619) + let new_style = alt p.token { + token::IDENT(_, false) { alt p.look_ahead(1u) { + token::DOT | token::LPAREN { true } + _ { false } + } } + token::IDENT(_, true) { true } + _ { false } + }; + if new_style { + let call = parse_expr(p); + alt call.node { + ast::expr_call(f, args, true) { + let b_arg = vec::last(args); + let last = mk_expr(p, b_arg.span.lo, b_arg.span.hi, + ast::expr_loop_body(b_arg)); + @{node: ast::expr_call(f, vec::init(args) + [last], true) + with *call} + } + _ { + p.span_fatal(lo, "`for` must be followed by a block call"); + } + } + } else { + let decl = parse_local(p, false, false); + expect_word(p, "in"); + let seq = parse_expr(p); + let body = parse_block_no_value(p); + mk_expr(p, lo.lo, body.span.hi, ast::expr_for(decl, seq, body)) + } } fn parse_while_expr(p: parser) -> @ast::expr { diff --git a/src/rustc/syntax/print/pprust.rs b/src/rustc/syntax/print/pprust.rs index 071441fe8e8..5d259e9bf4a 100644 --- a/src/rustc/syntax/print/pprust.rs +++ b/src/rustc/syntax/print/pprust.rs @@ -855,9 +855,16 @@ fn print_expr(s: ps, &&expr: @ast::expr) { pclose(s); } ast::expr_call(func, args, has_block) { + let mut base_args = args; + let blk = if has_block { + let blk_arg = vec::pop(base_args); + alt blk_arg.node { + ast::expr_loop_body(_) { word_nbsp(s, "for"); } + _ {} + } + some(blk_arg) + } else { none }; print_expr_parens_if_not_bot(s, func); - let mut base_args = args, blk = none; - if has_block { blk = some(vec::pop(base_args)); } if !has_block || vec::len(base_args) > 0u { popen(s); commasep_exprs(s, inconsistent, base_args); @@ -989,6 +996,9 @@ fn print_expr(s: ps, &&expr: @ast::expr) { print_fn_block_args(s, decl); print_possibly_embedded_block(s, body, block_block_fn, indent_unit); } + ast::expr_loop_body(body) { + print_expr(s, body); + } ast::expr_block(blk) { // containing cbox, will be closed by print-block at } cbox(s, indent_unit); diff --git a/src/rustc/syntax/visit.rs b/src/rustc/syntax/visit.rs index cff35221a8d..7a84052fa90 100644 --- a/src/rustc/syntax/visit.rs +++ b/src/rustc/syntax/visit.rs @@ -338,10 +338,12 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) { for eo: option<@expr> in args { visit_expr_opt(eo, e, v); } } expr_binary(_, a, b) { v.visit_expr(a, e, v); v.visit_expr(b, e, v); } - expr_unary(_, a) { v.visit_expr(a, e, v); } + expr_addr_of(_, x) | expr_unary(_, x) | expr_loop_body(x) | + expr_check(_, x) | expr_assert(x) { + v.visit_expr(x, e, v); + } expr_lit(_) { } expr_cast(x, t) { v.visit_expr(x, e, v); v.visit_ty(t, e, v); } - expr_addr_of(_, x) { v.visit_expr(x, e, v); } expr_if(x, b, eo) { v.visit_expr(x, e, v); v.visit_block(b, e, v); @@ -353,7 +355,7 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) { visit_expr_opt(eo, e, v); } expr_while(x, b) { v.visit_expr(x, e, v); v.visit_block(b, e, v); } - expr_loop(b) { v.visit_block(b, e, v); } + expr_loop(b) { v.visit_block(b, e, v); } expr_for(dcl, x, b) { v.visit_local(dcl, e, v); v.visit_expr(x, e, v); @@ -394,8 +396,6 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) { v.visit_expr(lv, e, v); v.visit_expr(x, e, v); } - expr_check(_, x) { v.visit_expr(x, e, v); } - expr_assert(x) { v.visit_expr(x, e, v); } expr_mac(mac) { visit_mac(mac, e, v); } } } |
