Skip to content

Commit 4e03112

Browse files
committed
Add a pass-by-copy parameter passing convention
This is intended to solve the problem of how to pass arguments to constructor functions -- you want to move in rvalues, but not have to explicitly copy stuff that is not an rvalue. The by-copy passing convention will ensure the callee gets its own copy of the value. For rvalues, it'll just pass off the value. For lvalues, it'll make a copy. Issue #1177
1 parent 6297fc9 commit 4e03112

File tree

9 files changed

+36
-10
lines changed

9 files changed

+36
-10
lines changed

src/comp/metadata/tydecode.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,9 @@ fn parse_ty_fn(st: @pstate, sd: str_def) ->
379379
let mode = alt peek(st) as char {
380380
'&' { ast::by_mut_ref }
381381
'-' { ast::by_move }
382+
'+' { ast::by_copy }
382383
'=' { ast::by_ref }
383-
'+' { ast::by_val }
384+
'#' { ast::by_val }
384385
};
385386
st.pos += 1u;
386387
inputs += [{mode: mode, ty: parse_ty(st, sd)}];

src/comp/metadata/tyencode.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,9 @@ fn enc_ty_fn(w: io::writer, cx: @ctxt, args: [ty::arg], out: ty::t,
202202
alt arg.mode {
203203
by_mut_ref. { w.write_char('&'); }
204204
by_move. { w.write_char('-'); }
205+
by_copy. { w.write_char('+'); }
205206
by_ref. { w.write_char('='); }
206-
by_val. { w.write_char('+'); }
207+
by_val. { w.write_char('#'); }
207208
}
208209
enc_ty(w, cx, arg.ty);
209210
}

src/comp/middle/alias.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] {
255255
local_id: 0u,
256256
unsafe_tys: unsafe_set(root.mut),
257257
mutable copied: alt arg_t.mode {
258-
ast::by_move. { copied }
258+
ast::by_move. | ast::by_copy. { copied }
259259
ast::by_mut_ref. { not_allowed }
260260
_ { i + 1u == by_ref ? not_allowed : not_copied }
261261
}}];
@@ -337,6 +337,9 @@ fn check_ret_ref(cx: ctx, sc: scope, mut: bool, arg_node_id: node_id,
337337
if arg.mode == ast::by_move {
338338
bad = some("a move-mode parameter");
339339
}
340+
if arg.mode == ast::by_copy {
341+
bad = some("a copy-mode parameter");
342+
}
340343
if cur_node != arg_node_id {
341344
bad = some("the wrong parameter");
342345
}

src/comp/middle/trans.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ fn type_of_explicit_args(cx: @crate_ctxt, sp: span, inputs: [ty::arg]) ->
6767
// that would obviate the need for this check
6868
check non_ty_var(cx, arg_ty);
6969
let llty = type_of_inner(cx, sp, arg_ty);
70-
if arg.mode == ast::by_val { atys += [llty]; }
71-
else { atys += [T_ptr(llty)]; }
70+
atys += [arg.mode == ast::by_val ? llty : T_ptr(llty)];
7271
}
7372
ret atys;
7473
}
@@ -3636,6 +3635,15 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty0: TypeRef,
36363635
if arg.mode == ast::by_val && (lv.kind == owned || !imm) {
36373636
val = Load(bcx, val);
36383637
}
3638+
} else if arg.mode == ast::by_copy {
3639+
let {bcx: cx, val: alloc} = alloc_ty(bcx, e_ty);
3640+
bcx = cx;
3641+
if lv.kind == temporary { revoke_clean(bcx, val); }
3642+
if lv.kind == owned || !ty::type_is_immediate(ccx.tcx, e_ty) {
3643+
bcx = memmove_ty(bcx, alloc, val, e_ty);
3644+
} else { Store(bcx, val, alloc); }
3645+
val = alloc;
3646+
if lv.kind != temporary { bcx = take_ty(bcx, val, e_ty); }
36393647
} else if ty::type_is_immediate(ccx.tcx, e_ty) && lv.kind != owned {
36403648
let r = do_spill(bcx, val, e_ty);
36413649
val = r.val;
@@ -4989,7 +4997,7 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
49894997
let argval = alt fcx.llargs.get(id) { local_mem(v) { v } };
49904998
alt arg.mode {
49914999
ast::by_mut_ref. { }
4992-
ast::by_move. { add_clean(bcx, argval, arg.ty); }
5000+
ast::by_move. | ast::by_copy. { add_clean(bcx, argval, arg.ty); }
49935001
ast::by_val. {
49945002
if !ty::type_is_immediate(bcx_tcx(bcx), arg.ty) {
49955003
let {bcx: cx, val: alloc} = alloc_ty(bcx, arg.ty);

src/comp/syntax/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ tag unop {
144144
deref; not; neg;
145145
}
146146

147-
tag mode { by_ref; by_val; by_mut_ref; by_move; mode_infer; }
147+
tag mode { by_ref; by_val; by_mut_ref; by_move; by_copy; mode_infer; }
148148

149149
type stmt = spanned<stmt_>;
150150

src/comp/syntax/parse/parser.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,10 @@ fn parse_arg_mode(p: parser) -> ast::mode {
573573
if eat(p, token::BINOP(token::AND)) { ast::by_mut_ref }
574574
else if eat(p, token::BINOP(token::MINUS)) { ast::by_move }
575575
else if eat(p, token::ANDAND) { ast::by_ref }
576-
else if eat(p, token::BINOP(token::PLUS)) { ast::by_val }
576+
else if eat(p, token::BINOP(token::PLUS)) {
577+
if eat(p, token::BINOP(token::PLUS)) { ast::by_val }
578+
else { ast::by_copy }
579+
}
577580
else { ast::mode_infer }
578581
}
579582

src/comp/syntax/print/pprust.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1161,7 +1161,8 @@ fn print_arg_mode(s: ps, m: ast::mode) {
11611161
ast::by_mut_ref. { word(s.s, "&"); }
11621162
ast::by_move. { word(s.s, "-"); }
11631163
ast::by_ref. { word(s.s, "&&"); }
1164-
ast::by_val. { word(s.s, "+"); }
1164+
ast::by_val. { word(s.s, "++"); }
1165+
ast::by_copy. { word(s.s, "+"); }
11651166
ast::mode_infer. {}
11661167
}
11671168
}

src/comp/util/ppaux.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ import middle::ast_map;
1212
fn mode_str(m: ty::mode) -> str {
1313
alt m {
1414
ast::by_ref. { "&&" }
15-
ast::by_val. { "+" }
15+
ast::by_val. { "++" }
1616
ast::by_mut_ref. { "&" }
1717
ast::by_move. { "-" }
18+
ast::by_copy. { "+" }
1819
_ { "" }
1920
}
2021
}

src/test/run-pass/pass-by-copy.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn magic(+x: {a: @int}) { log x; }
2+
fn magic2(+x: @int) { log x; }
3+
4+
fn main() {
5+
let a = {a: @10}, b = @10;
6+
magic(a); magic({a: @20});
7+
magic2(b); magic2(@20);
8+
}

0 commit comments

Comments
 (0)