Change convention for specifying referenced argument
It is now 1-based, rather than 0 based. (Seems more natural, and allows 0 to be used to refer to self and maybe to closure.) Also allows non-referenced args to be implicitly copied again. Issue #918
This commit is contained in:
parent
059b31f7a3
commit
d7587c1eda
@ -72,7 +72,9 @@ fn visit_fn(cx: @ctx, f: ast::_fn, _tp: [ast::ty_param], _sp: span,
|
||||
"return implicitly");
|
||||
}
|
||||
let ret_info = alt f.decl.cf {
|
||||
ast::return_ref(mut, n_arg) { by_ref(mut, f.decl.inputs[n_arg].id) }
|
||||
ast::return_ref(mut, n_arg) {
|
||||
by_ref(mut, f.decl.inputs[n_arg - 1u].id)
|
||||
}
|
||||
_ { other }
|
||||
};
|
||||
v.visit_block(f.body, {bs: bs, ret_info: ret_info}, v);
|
||||
@ -220,7 +222,9 @@ fn cant_copy(cx: ctx, b: binding) -> bool {
|
||||
|
||||
fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] {
|
||||
let fty = ty::type_autoderef(cx.tcx, ty::expr_ty(cx.tcx, f));
|
||||
let ret_ref = ast_util::ret_by_ref(ty::ty_fn_ret_style(cx.tcx, fty));
|
||||
let by_ref = alt ty::ty_fn_ret_style(cx.tcx, fty) {
|
||||
ast::return_ref(_, arg_n) { arg_n } _ { 0u }
|
||||
};
|
||||
let arg_ts = ty::ty_fn_args(cx.tcx, fty);
|
||||
let mut_roots: [{arg: uint, node: node_id}] = [];
|
||||
let bindings = [];
|
||||
@ -246,7 +250,9 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] {
|
||||
mutable ok: valid,
|
||||
mutable copied: alt arg_t.mode {
|
||||
ast::by_move. { copied }
|
||||
ast::by_ref. { ret_ref ? not_allowed : not_copied }
|
||||
ast::by_ref. {
|
||||
i + 1u == by_ref ? not_allowed : not_copied
|
||||
}
|
||||
ast::by_mut_ref. { not_allowed }
|
||||
}}];
|
||||
i += 1u;
|
||||
@ -683,7 +689,7 @@ fn expr_root(cx: ctx, ex: @ast::expr, autoderef: bool) ->
|
||||
let fty = ty::type_autoderef(cx.tcx, ty::expr_ty(cx.tcx, f));
|
||||
alt ty::ty_fn_ret_style(cx.tcx, fty) {
|
||||
ast::return_ref(mut, arg_n) {
|
||||
let arg = args[arg_n];
|
||||
let arg = args[arg_n - 1u];
|
||||
let arg_root = expr_root(cx, arg, false);
|
||||
ret {ex: arg_root.ex,
|
||||
ds: @(*arg_root.ds +
|
||||
|
@ -3557,9 +3557,11 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty0: TypeRef,
|
||||
// - create_llargs_for_fn_args.
|
||||
// - new_fn_ctxt
|
||||
// - trans_args
|
||||
fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t<generic_info>,
|
||||
fn trans_args(cx: @block_ctxt, outer_cx: @block_ctxt, llenv: ValueRef,
|
||||
gen: option::t<generic_info>,
|
||||
lliterbody: option::t<ValueRef>, es: [@ast::expr], fn_ty: ty::t)
|
||||
-> {bcx: @block_ctxt,
|
||||
outer_cx: @block_ctxt,
|
||||
args: [ValueRef],
|
||||
retslot: ValueRef,
|
||||
to_zero: [{v: ValueRef, t: ty::t}],
|
||||
@ -3574,7 +3576,8 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t<generic_info>,
|
||||
let ccx = bcx_ccx(cx);
|
||||
let tcx = ccx.tcx;
|
||||
let bcx: @block_ctxt = cx;
|
||||
let by_ref = ast_util::ret_by_ref(ty::ty_fn_ret_style(tcx, fn_ty));
|
||||
let ret_style = ty::ty_fn_ret_style(tcx, fn_ty);
|
||||
let by_ref = ast_util::ret_by_ref(ret_style);
|
||||
// Arg 0: Output pointer.
|
||||
|
||||
// FIXME: test case looks like
|
||||
@ -3583,6 +3586,7 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t<generic_info>,
|
||||
// This means an earlier arg was divergent.
|
||||
// So this arg can't be evaluated.
|
||||
ret {bcx: bcx,
|
||||
outer_cx: outer_cx,
|
||||
args: [],
|
||||
retslot: C_nil(),
|
||||
to_zero: to_zero,
|
||||
@ -3652,13 +3656,18 @@ fn trans_args(cx: @block_ctxt, llenv: ValueRef, gen: option::t<generic_info>,
|
||||
// So this arg can't be evaluated.
|
||||
break;
|
||||
}
|
||||
let r =
|
||||
trans_arg_expr(bcx, args[i], arg_tys[i], to_zero, to_revoke, e);
|
||||
bcx = r.bcx;
|
||||
let is_referenced = alt ret_style {
|
||||
ast::return_ref(_, arg_n) { i + 1u == arg_n }
|
||||
_ { false }
|
||||
};
|
||||
let r = trans_arg_expr(is_referenced ? outer_cx : bcx,
|
||||
args[i], arg_tys[i], to_zero, to_revoke, e);
|
||||
if is_referenced { outer_cx = r.bcx; } else { bcx = r.bcx; }
|
||||
llargs += [r.val];
|
||||
i += 1u;
|
||||
}
|
||||
ret {bcx: bcx,
|
||||
outer_cx: outer_cx,
|
||||
args: llargs,
|
||||
retslot: llretslot,
|
||||
to_zero: to_zero,
|
||||
@ -3675,14 +3684,7 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
|
||||
let fn_ty = ty::type_autoderef(bcx_tcx(in_cx), fn_expr_ty);
|
||||
let by_ref = ast_util::ret_by_ref(ty::ty_fn_ret_style(bcx_tcx(in_cx),
|
||||
fn_ty));
|
||||
// Things that return by reference must put their arguments (FIXME only
|
||||
// the referenced arguments) into the outer scope, so that they are still
|
||||
// alive when the return value is used.
|
||||
let cx = if by_ref { in_cx } else {
|
||||
let cx = new_scope_block_ctxt(in_cx, "call");
|
||||
Br(in_cx, cx.llbb);
|
||||
cx
|
||||
};
|
||||
let cx = new_scope_block_ctxt(in_cx, "call");
|
||||
let f_res = trans_lval_gen(cx, f);
|
||||
let bcx = f_res.res.bcx;
|
||||
|
||||
@ -3710,7 +3712,8 @@ fn trans_call(in_cx: @block_ctxt, f: @ast::expr,
|
||||
|
||||
let ret_ty = ty::node_id_to_type(bcx_tcx(cx), id);
|
||||
let args_res =
|
||||
trans_args(bcx, llenv, f_res.generic, lliterbody, args, fn_ty);
|
||||
trans_args(bcx, in_cx, llenv, f_res.generic, lliterbody, args, fn_ty);
|
||||
Br(args_res.outer_cx, cx.llbb);
|
||||
bcx = args_res.bcx;
|
||||
let llargs = args_res.args;
|
||||
let llretslot = args_res.retslot;
|
||||
|
@ -448,16 +448,19 @@ fn parse_ret_ty(p: parser, n_args: uint) -> (ast::ret_style, @ast::ty) {
|
||||
if n_args == 0u {
|
||||
p.fatal("can not return reference from argument-less fn");
|
||||
}
|
||||
let mut_root = eat(p, token::NOT), arg = 0u;
|
||||
let mut_root = eat(p, token::NOT), arg = 1u;
|
||||
alt p.peek() {
|
||||
token::LIT_INT(val) { p.bump(); arg = val as uint; }
|
||||
_ { if n_args > 1u {
|
||||
p.fatal("must specify referenced parameter");
|
||||
} }
|
||||
}
|
||||
if arg >= n_args {
|
||||
if arg > n_args {
|
||||
p.fatal("referenced argument does not exist");
|
||||
}
|
||||
if arg == 0u {
|
||||
p.fatal("referenced argument can't be 0");
|
||||
}
|
||||
style = ast::return_ref(mut_root, arg);
|
||||
};
|
||||
(style, parse_ty(p, false))
|
||||
|
@ -1,6 +1,6 @@
|
||||
// error-pattern:can not return a reference to the wrong parameter
|
||||
|
||||
fn f(a: int, b: int) -> &1 int {
|
||||
fn f(a: int, b: int) -> &2 int {
|
||||
ret a;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ fn get<@T>(opt: option<T>) -> &T {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mut(a: {mutable x: @int}, _b: int) -> &!0 @int {
|
||||
fn get_mut(a: {mutable x: @int}, _b: int) -> &!1 @int {
|
||||
ret a.x;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user