Forbid blocks from deinitializing upvars

Move expressions where the RHS is an upvar are now forbidden within
block expressions.
This commit is contained in:
Tim Chevalier 2011-09-06 15:26:57 -07:00
parent efed843b1a
commit 8ab02f7b21
2 changed files with 30 additions and 7 deletions

View file

@ -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));

View file

@ -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;
}