diff --git a/src/comp/middle/tstate/states.rs b/src/comp/middle/tstate/states.rs index af14db2e9c87..6537487b1bb5 100644 --- a/src/comp/middle/tstate/states.rs +++ b/src/comp/middle/tstate/states.rs @@ -17,6 +17,7 @@ import tritv::ttrue; import bitvectors::*; import syntax::ast::*; import syntax::ast_util::*; +import syntax::codemap::span; import middle::ty::expr_ty; import middle::ty::type_is_nil; import middle::ty::type_is_bot; @@ -31,10 +32,28 @@ import util::common::log_stmt; import util::common::log_stmt_err; import util::common::log_expr_err; +fn forbid_upvar(fcx: &fn_ctxt, rhs_id: &node_id, sp: &span, + t: oper_type) { + alt t { + oper_move. { + alt local_node_id_to_def(fcx, rhs_id) { + some(def_upvar(_,_,_)) { + fcx.ccx.tcx.sess.span_err(sp, "Tried to deinitialize a variable \ + declared in a different scope"); + } + _ {} + } + } + _ { /* do nothing */ } + } +} + fn handle_move_or_copy(fcx: &fn_ctxt, post: &poststate, rhs_path: &path, rhs_id: &node_id, instlhs: &inst, init_op: &init_op) { - let rhs_d = local_node_id_to_def_id(fcx, rhs_id); - alt rhs_d { + forbid_upvar(fcx, rhs_id, rhs_path.span, op_to_oper_ty(init_op)); + + let rhs_d_id = local_node_id_to_def_id(fcx, rhs_id); + alt rhs_d_id { some(rhsid) { // RHS is a local var let instrhs = @@ -110,6 +129,7 @@ fn find_pre_post_state_two(fcx: &fn_ctxt, pres: &prestate, lhs: &@expr, changed = find_pre_post_state_expr(fcx, expr_poststate(fcx.ccx, lhs), rhs) || changed; + forbid_upvar(fcx, rhs.id, rhs.span, ty); let post = tritv_clone(expr_poststate(fcx.ccx, rhs)); diff --git a/src/test/compile-fail/block-deinitializes-upvar.rs b/src/test/compile-fail/block-deinitializes-upvar.rs index da5922036a7a..bc1292021a94 100644 --- a/src/test/compile-fail/block-deinitializes-upvar.rs +++ b/src/test/compile-fail/block-deinitializes-upvar.rs @@ -1,8 +1,11 @@ -// error-pattern:assigning to upvar +// error-pattern:Tried to deinitialize a variable declared in a different fn force(f: &block() -> int) -> int { ret f(); } fn main() { - let x = 5; - let f = lambda () -> int { let y = 6; x <- y; ret 7 }; - assert (force(f) == 7); - log x; + let x = @{x:17, y:2}; + let y = @{x:5, y:5}; + + let f = {|&i| log_err i; x <- y; ret 7; }; + assert (f(5) == 7); + log_err x; + log_err y; }