Make tag, resource and object constructors take their arguments by copy

Doing something like some([1, 2, 3]) will now no longer create a temporary
copy of the vector. It will also be easier for the kind checker to see that
putting a resource into a data-structure constructor is safe.
This commit is contained in:
Marijn Haverbeke 2011-11-16 13:35:34 +01:00
parent 4e03112141
commit cefff237bf
4 changed files with 18 additions and 40 deletions

View File

@ -3587,8 +3587,8 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
};
// Actually construct the closure
let closure = build_environment
(bcx, lltydescs, env_vals + vec::map(env_expr, bound), true);
let closure = build_environment(bcx, lltydescs, env_vals +
vec::map({|x| env_expr(x)}, bound), true);
bcx = closure.bcx;
// Make thunk
@ -5163,12 +5163,9 @@ fn trans_res_ctor(cx: @local_ctxt, sp: span, dtor: ast::_fn,
let lltop = bcx.llbb;
let arg_t = arg_tys_of_fn(ccx, ctor_id)[0].ty;
let tup_t = ty::mk_tup(ccx.tcx, [ty::mk_int(ccx.tcx), arg_t]);
let arg;
alt fcx.llargs.find(dtor.decl.inputs[0].id) {
some(local_mem(x)) { arg = load_if_immediate(bcx, x, arg_t); }
some(local_imm(x)) { arg = x; }
_ { ccx.sess.span_fatal(sp, "unbound dtor decl in trans_res_ctor"); }
}
let arg = alt fcx.llargs.find(dtor.decl.inputs[0].id) {
some(local_mem(x)) { x }
};
let llretptr = fcx.llretptr;
if ty::type_has_dynamic_size(ccx.tcx, ret_t) {
let llret_t = T_ptr(T_struct([ccx.int_type, llvm::LLVMTypeOf(arg)]));
@ -5177,9 +5174,8 @@ fn trans_res_ctor(cx: @local_ctxt, sp: span, dtor: ast::_fn,
// FIXME: silly checks
check type_is_tup_like(bcx, tup_t);
let dst = GEP_tup_like(bcx, tup_t, llretptr, [0, 1]);
bcx = dst.bcx;
bcx = copy_val(bcx, INIT, dst.val, arg, arg_t);
let {bcx, val: dst} = GEP_tup_like(bcx, tup_t, llretptr, [0, 1]);
bcx = memmove_ty(bcx, dst, arg, arg_t);
check type_is_tup_like(bcx, tup_t);
let flag = GEP_tup_like(bcx, tup_t, llretptr, [0, 0]);
bcx = flag.bcx;
@ -5206,7 +5202,7 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id,
let i = 0u;
for varg: ast::variant_arg in variant.node.args {
fn_args +=
[{mode: ast::by_ref,
[{mode: ast::by_copy,
ty: varg.ty,
ident: "arg" + uint::to_str(i, 10u),
id: varg.id}];
@ -5261,11 +5257,9 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id,
if ty::type_contains_params(bcx_tcx(bcx), arg_ty) {
lldestptr = PointerCast(bcx, lldestptr, val_ty(llarg));
}
llarg = load_if_immediate(bcx, llarg, arg_ty);
bcx = copy_val(bcx, INIT, lldestptr, llarg, arg_ty);
bcx = memmove_ty(bcx, lldestptr, llarg, arg_ty);
i += 1u;
}
bcx = trans_block_cleanups(bcx, find_scope_cx(bcx));
build_return(bcx);
finish_fn(fcx, lltop);
}

View File

@ -41,7 +41,7 @@ fn trans_obj(cx: @local_ctxt, sp: span, ob: ast::_obj, ctor_id: ast::node_id,
// we're creating.
let fn_args: [ast::arg] = [];
for f: ast::obj_field in ob.fields {
fn_args += [{mode: ast::by_ref, ty: f.ty, ident: f.ident,
fn_args += [{mode: ast::by_copy, ty: f.ty, ident: f.ident,
id: f.id}];
}
let fcx = new_fn_ctxt(cx, sp, llctor_decl);
@ -174,28 +174,19 @@ fn trans_obj(cx: @local_ctxt, sp: span, ob: ast::_obj, ctor_id: ast::node_id,
let body_fields =
GEP_tup_like(bcx, body_ty, body, [0, abi::obj_body_elt_fields]);
bcx = body_fields.bcx;
// TODO: can we just get fields_ty out of body_ty instead?
let fields_ty = ty::mk_tup(ccx.tcx, obj_fields);
i = 0;
for f: ast::obj_field in ob.fields {
alt bcx.fcx.llargs.find(f.id) {
some(arg1) {
let arg = alt arg1 {
local_mem(v) { load_if_immediate(bcx, v, arg_tys[i].ty) }
local_imm(v) { v }
};
// TODO: can we just get fields_ty out of body_ty instead?
let fields_ty: ty::t = ty::mk_tup(ccx.tcx, obj_fields);
some(local_mem(arg)) {
// Silly check
check type_is_tup_like(bcx, fields_ty);
let field =
GEP_tup_like(bcx, fields_ty, body_fields.val, [0, i]);
bcx = field.bcx;
bcx = copy_val(bcx, INIT, field.val, arg, arg_tys[i].ty);
bcx = memmove_ty(field.bcx, field.val, arg, arg_tys[i].ty);
i += 1;
}
none. {
bcx_ccx(bcx).sess.span_fatal(f.ty.span,
"internal error in trans_obj");
}
}
}

View File

@ -84,7 +84,6 @@
export mk_uint;
export mk_uniq;
export mk_var;
export mk_iter_body_fn;
export mode;
export mt;
export node_type_table;
@ -587,11 +586,6 @@ fn mk_param(cx: ctxt, n: uint, k: ast::kind) -> t {
fn mk_native(cx: ctxt, did: def_id) -> t { ret gen_ty(cx, ty_native(did)); }
fn mk_iter_body_fn(cx: ctxt, output: t) -> t {
ret mk_fn(cx, ast::proto_block, [{mode: ast::by_ref, ty: output}],
ty::mk_nil(cx), ast::return_val, []);
}
// Returns the one-level-deep type structure of the given type.
pure fn struct(cx: ctxt, typ: t) -> sty { interner::get(*cx.ts, typ).struct }

View File

@ -597,7 +597,7 @@ fn ty_of_obj_ctor(cx: @ctxt, id: ast::ident, ob: ast::_obj,
for f: ast::obj_field in ob.fields {
let g = bind getter(cx, _);
let t_field = ast_ty_to_ty(cx.tcx, g, f.ty);
t_inputs += [{mode: ast::by_ref, ty: t_field}];
t_inputs += [{mode: ast::by_copy, ty: t_field}];
}
let t_fn =
@ -646,8 +646,7 @@ fn ty_of_item(cx: @ctxt, it: @ast::item) -> ty::ty_param_kinds_and_ty {
let t_arg = ty_of_arg(cx, f.decl.inputs[0]);
let t_res =
{kinds: ty_param_kinds(tps),
ty:
ty::mk_res(cx.tcx, local_def(it.id), t_arg.ty,
ty: ty::mk_res(cx.tcx, local_def(it.id), t_arg.ty,
mk_ty_params(cx, tps))};
cx.tcx.tcache.insert(local_def(it.id), t_res);
ret t_res;
@ -708,7 +707,7 @@ fn get_tag_variant_types(cx: @ctxt, tag_id: ast::def_id,
let args: [arg] = [];
for va: ast::variant_arg in variant.node.args {
let arg_ty = ast_ty_to_ty(cx.tcx, f, va.ty);
args += [{mode: ast::by_ref, ty: arg_ty}];
args += [{mode: ast::by_copy, ty: arg_ty}];
}
let tag_t = ty::mk_tag(cx.tcx, tag_id, ty_param_tys);
// FIXME: this will be different for constrained types
@ -785,7 +784,7 @@ fn convert(cx: @ctxt, abi: @mutable option::t<ast::native_abi>,
mk_ty_params(cx, tps));
let t_ctor =
ty::mk_fn(cx.tcx, ast::proto_shared(ast::sugar_normal),
[t_arg], t_res,
[{mode: ast::by_copy with t_arg}], t_res,
ast::return_val, []);
let t_dtor =
ty::mk_fn(cx.tcx, ast::proto_shared(ast::sugar_normal),