Disallow binding by-mut-ref and by-move arguments
Fix bug in bound by-copy arguments. Closes #1261
This commit is contained in:
parent
d28e0c0c0a
commit
03a6e54212
|
@ -150,6 +150,7 @@ fn visit_decl(cx: @ctx, d: @decl, &&e: (), v: visit::vt<()>) {
|
|||
fn visit_expr(cx: @ctx, ex: @expr, &&e: (), v: visit::vt<()>) {
|
||||
alt ex.node {
|
||||
expr_call(f, args, _) { check_call(cx, f, args); }
|
||||
expr_bind(f, args) { check_bind(cx, f, args); }
|
||||
expr_swap(lhs, rhs) {
|
||||
check_lval(cx, lhs, msg_assign);
|
||||
check_lval(cx, rhs, msg_assign);
|
||||
|
@ -230,6 +231,30 @@ fn check_call(cx: @ctx, f: @expr, args: [@expr]) {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_bind(cx: @ctx, f: @expr, args: [option::t<@expr>]) {
|
||||
let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f));
|
||||
let i = 0u;
|
||||
for arg in args {
|
||||
alt arg {
|
||||
some(expr) {
|
||||
alt (alt arg_ts[i].mode {
|
||||
by_mut_ref. { some("by mutable reference") }
|
||||
by_move. { some("by move") }
|
||||
_ { none }
|
||||
}) {
|
||||
some(name) {
|
||||
cx.tcx.sess.span_err(
|
||||
expr.span, "can not bind an argument passed " + name);
|
||||
}
|
||||
none. {}
|
||||
}
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
|
||||
fn is_immutable_def(def: def) -> option::t<str> {
|
||||
alt def {
|
||||
def_fn(_, _) | def_mod(_) | def_native_mod(_) | def_const(_) |
|
||||
|
|
|
@ -3462,6 +3462,12 @@ fn trans_bind_thunk(cx: @local_ctxt, sp: span, incoming_fty: ty::t,
|
|||
bcx = bound_arg.bcx;
|
||||
let val = bound_arg.val;
|
||||
if out_arg.mode == ast::by_val { val = Load(bcx, val); }
|
||||
if out_arg.mode == ast::by_copy {
|
||||
let {bcx: cx, val: alloc} = alloc_ty(bcx, out_arg.ty);
|
||||
bcx = memmove_ty(cx, alloc, val, out_arg.ty);
|
||||
bcx = take_ty(bcx, alloc, out_arg.ty);
|
||||
val = alloc;
|
||||
}
|
||||
// If the type is parameterized, then we need to cast the
|
||||
// type we actually have to the parameterized out type.
|
||||
if ty::type_contains_params(cx.ccx.tcx, out_arg.ty) {
|
||||
|
|
|
@ -288,7 +288,7 @@ fn spawn_inner<send T>(-data: T, f: fn(T),
|
|||
notify: option<comm::chan<task_notification>>)
|
||||
-> task unsafe {
|
||||
|
||||
fn wrapper<send T>(-data: *u8, f: fn(T)) unsafe {
|
||||
fn wrapper<send T>(data: *u8, f: fn(T)) unsafe {
|
||||
let data: ~T = unsafe::reinterpret_cast(data);
|
||||
f(*data);
|
||||
}
|
||||
|
|
|
@ -112,12 +112,12 @@ mod map_reduce {
|
|||
|
||||
send(out, chan(p));
|
||||
|
||||
let ref_count = 0;
|
||||
let is_done = false;
|
||||
let state = @{mutable ref_count: 0, mutable is_done: false};
|
||||
|
||||
fn get(p: port<reduce_proto>, &ref_count: int, &is_done: bool) ->
|
||||
option<int> {
|
||||
while !is_done || ref_count > 0 {
|
||||
fn get(p: port<reduce_proto>, state: @{mutable ref_count: int,
|
||||
mutable is_done: bool})
|
||||
-> option<int> {
|
||||
while !state.is_done || state.ref_count > 0 {
|
||||
alt recv(p) {
|
||||
emit_val(v) {
|
||||
// log_err #fmt("received %d", v);
|
||||
|
@ -125,16 +125,16 @@ mod map_reduce {
|
|||
}
|
||||
done. {
|
||||
// log_err "all done";
|
||||
is_done = true;
|
||||
state.is_done = true;
|
||||
}
|
||||
ref. { ref_count += 1; }
|
||||
release. { ref_count -= 1; }
|
||||
ref. { state.ref_count += 1; }
|
||||
release. { state.ref_count -= 1; }
|
||||
}
|
||||
}
|
||||
ret none;
|
||||
}
|
||||
|
||||
reduce(key, bind get(p, ref_count, is_done));
|
||||
reduce(key, bind get(p, state));
|
||||
}
|
||||
|
||||
fn map_reduce(-inputs: [str]) {
|
||||
|
|
|
@ -39,8 +39,8 @@ fn traverse_in_order() {
|
|||
insert(m, 2, ());
|
||||
insert(m, 1, ());
|
||||
|
||||
let n = 0;
|
||||
fn t(&n: int, &&k: int, &&_v: ()) { assert (n == k); n += 1; }
|
||||
let n = @mutable 0;
|
||||
fn t(n: @mutable int, &&k: int, &&_v: ()) { assert (*n == k); *n += 1; }
|
||||
traverse(m, bind t(n, _, _));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue