allow immut vars to be moved. enforce mut vars after stage0 in std.

This commit is contained in:
Niko Matsakis 2012-03-14 18:28:50 -04:00
parent 6b35875dca
commit e702d20191
3 changed files with 25 additions and 10 deletions

View File

@ -9,6 +9,13 @@
# runtime rather than the runtime from the working directory.
USE_SNAPSHOT_RUNTIME=0
# Do not use --enforce-mut-vars in stage0, for now, as the snapshot
# has an older version of the check.
ENFORCE_MUT_VARS_0=
ENFORCE_MUT_VARS_1=--enforce-mut-vars
ENFORCE_MUT_VARS_2=--enforce-mut-vars
ENFORCE_MUT_VARS_3=--enforce-mut-vars
define TARGET_STAGE_N
$$(TLIB$(1)_T_$(2)_H_$(3))/intrinsics.ll: \
@ -38,7 +45,8 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB): \
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_CORELIB) \
$$(TSREQ$(1)_T_$(2)_H_$(3))
@$$(call E, compile_and_link: $$@)
$$(STAGE$(1)_T_$(2)_H_$(3)) --enforce-mut-vars -o $$@ $$< && touch $$@
$$(STAGE$(1)_T_$(2)_H_$(3)) $$(ENFORCE_MUT_VARS_$(1)) \
-o $$@ $$< && touch $$@
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_RUSTLLVM): \
rustllvm/$(2)/$$(CFG_RUSTLLVM)

View File

@ -339,7 +339,7 @@ fn async_init (
lp: uv_loop,
async_cb: fn~(uv_handle),
after_cb: fn~(uv_handle)) {
let mut msg = msg_async_init(async_cb, after_cb);
let msg = msg_async_init(async_cb, after_cb);
let loop_chan = get_loop_chan_from_uv_loop(lp);
comm::send(loop_chan, msg);
}
@ -363,7 +363,7 @@ fn close(h: uv_handle, cb: fn~()) {
}
fn timer_init(lp: uv_loop, after_cb: fn~(uv_handle)) {
let mut msg = msg_timer_init(after_cb);
let msg = msg_timer_init(after_cb);
let loop_chan = get_loop_chan_from_uv_loop(lp);
comm::send(loop_chan, msg);
}
@ -372,7 +372,7 @@ fn timer_start(the_timer: uv_handle, timeout: u32, repeat:u32,
timer_cb: fn~(uv_handle)) {
alt the_timer {
uv_timer(id, lp) {
let mut msg = msg_timer_start(id, timeout, repeat, timer_cb);
let msg = msg_timer_start(id, timeout, repeat, timer_cb);
let loop_chan = get_loop_chan_from_uv_loop(lp);
comm::send(loop_chan, msg);
}
@ -387,7 +387,7 @@ fn timer_stop(the_timer: uv_handle, after_cb: fn~(uv_handle)) {
alt the_timer {
uv_timer(id, lp) {
let loop_chan = get_loop_chan_from_uv_loop(lp);
let mut msg = msg_timer_stop(id, after_cb);
let msg = msg_timer_stop(id, after_cb);
comm::send(loop_chan, msg);
}
_ {

View File

@ -176,7 +176,7 @@ fn visit_expr(cx: @ctx, ex: @expr, &&e: (), v: visit::vt<()>) {
expr_fn(_, _, _, cap) {
for moved in cap.moves {
let def = cx.tcx.def_map.get(moved.id);
alt is_immutable_def(cx, def) {
alt is_illegal_to_modify_def(cx, def, msg_move_out) {
some(name) { mk_err(cx, moved.span, msg_move_out, moved.name); }
_ { }
}
@ -192,7 +192,7 @@ fn check_lval(cx: @ctx, dest: @expr, msg: msg) {
alt dest.node {
expr_path(p) {
let def = cx.tcx.def_map.get(dest.id);
alt is_immutable_def(cx, def) {
alt is_illegal_to_modify_def(cx, def, msg) {
some(name) { mk_err(cx, dest.span, msg, name); }
_ { }
}
@ -278,7 +278,9 @@ fn check_bind(cx: @ctx, f: @expr, args: [option<@expr>]) {
}
}
fn is_immutable_def(cx: @ctx, def: def) -> option<str> {
// returns some if the def cannot be modified. the kind of modification is
// indicated by `msg`.
fn is_illegal_to_modify_def(cx: @ctx, def: def, msg: msg) -> option<str> {
alt def {
def_fn(_, _) | def_mod(_) | def_native_mod(_) | def_const(_) |
def_use(_) {
@ -295,8 +297,12 @@ fn is_immutable_def(cx: @ctx, def: def) -> option<str> {
let ty = ty::node_id_to_type(cx.tcx, node_id);
let proto = ty::ty_fn_proto(ty);
ret alt proto {
proto_any | proto_block { is_immutable_def(cx, *inner) }
_ { some("upvar") }
proto_any | proto_block {
is_illegal_to_modify_def(cx, *inner, msg)
}
proto_bare | proto_uniq | proto_box {
some("upvar")
}
};
}
@ -304,6 +310,7 @@ fn is_immutable_def(cx: @ctx, def: def) -> option<str> {
// here and then guarantee in the typestate pass that immutable local
// variables are assigned at most once. But this requires a new kind of
// propagation (def. not assigned), so I didn't do that.
def_local(_, false) if msg == msg_move_out { none }
def_local(_, false) if cx.tcx.sess.opts.enforce_mut_vars {
some("immutable local variable")
}