about summary refs log tree commit diff
path: root/src/comp/middle
diff options
context:
space:
mode:
Diffstat (limited to 'src/comp/middle')
-rw-r--r--src/comp/middle/alias.rs5
-rw-r--r--src/comp/middle/trans.rs14
2 files changed, 15 insertions, 4 deletions
diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs
index 88d4f3b56a5..b4cd16d1ee9 100644
--- a/src/comp/middle/alias.rs
+++ b/src/comp/middle/alias.rs
@@ -255,7 +255,7 @@ fn check_call(cx: ctx, f: @ast::expr, args: [@ast::expr]) -> [binding] {
                        local_id: 0u,
                        unsafe_tys: unsafe_set(root.mut),
                        mutable copied: alt arg_t.mode {
-                         ast::by_move. { copied }
+                         ast::by_move. | ast::by_copy. { copied }
                          ast::by_mut_ref. { not_allowed }
                          _ { i + 1u == by_ref ? not_allowed : not_copied }
                        }}];
@@ -337,6 +337,9 @@ fn check_ret_ref(cx: ctx, sc: scope, mut: bool, arg_node_id: node_id,
                 if arg.mode == ast::by_move {
                     bad = some("a move-mode parameter");
                 }
+                if arg.mode == ast::by_copy {
+                    bad = some("a copy-mode parameter");
+                }
                 if cur_node != arg_node_id {
                     bad = some("the wrong parameter");
                 }
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index d5d2620fa6f..b57953d20a6 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -67,8 +67,7 @@ fn type_of_explicit_args(cx: @crate_ctxt, sp: span, inputs: [ty::arg]) ->
         // that would obviate the need for this check
         check non_ty_var(cx, arg_ty);
         let llty = type_of_inner(cx, sp, arg_ty);
-        if arg.mode == ast::by_val { atys += [llty]; }
-        else { atys += [T_ptr(llty)]; }
+        atys += [arg.mode == ast::by_val ? llty : T_ptr(llty)];
     }
     ret atys;
 }
@@ -3636,6 +3635,15 @@ fn trans_arg_expr(cx: @block_ctxt, arg: ty::arg, lldestty0: TypeRef,
         if arg.mode == ast::by_val && (lv.kind == owned || !imm) {
             val = Load(bcx, val);
         }
+    } else if arg.mode == ast::by_copy {
+        let {bcx: cx, val: alloc} = alloc_ty(bcx, e_ty);
+        bcx = cx;
+        if lv.kind == temporary { revoke_clean(bcx, val); }
+        if lv.kind == owned || !ty::type_is_immediate(ccx.tcx, e_ty) {
+            bcx = memmove_ty(bcx, alloc, val, e_ty);
+        } else { Store(bcx, val, alloc); }
+        val = alloc;
+        if lv.kind != temporary { bcx = take_ty(bcx, val, e_ty); }
     } else if ty::type_is_immediate(ccx.tcx, e_ty) && lv.kind != owned {
         let r = do_spill(bcx, val, e_ty);
         val = r.val;
@@ -4989,7 +4997,7 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
         let argval = alt fcx.llargs.get(id) { local_mem(v) { v } };
         alt arg.mode {
           ast::by_mut_ref. { }
-          ast::by_move. { add_clean(bcx, argval, arg.ty); }
+          ast::by_move. | ast::by_copy. { add_clean(bcx, argval, arg.ty); }
           ast::by_val. {
             if !ty::type_is_immediate(bcx_tcx(bcx), arg.ty) {
                 let {bcx: cx, val: alloc} = alloc_ty(bcx, arg.ty);