mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Implement an initial version of placement new.
This commit is contained in:
parent
ba39e277e2
commit
cfcbec3cc3
@ -434,8 +434,8 @@ fn for_each_package(c: cargo, b: fn(source, package)) {
|
||||
|
||||
// Runs all programs in directory <buildpath>
|
||||
fn run_programs(buildpath: str) {
|
||||
let new = os::list_dir(buildpath);
|
||||
for ct: str in new {
|
||||
let newv = os::list_dir(buildpath);
|
||||
for ct: str in newv {
|
||||
run::run_program(ct, []);
|
||||
}
|
||||
}
|
||||
@ -471,9 +471,9 @@ fn install_one_crate(c: cargo, path: str, cf: str) {
|
||||
none { ret; }
|
||||
some(bp) { bp }
|
||||
};
|
||||
let new = os::list_dir(buildpath);
|
||||
let newv = os::list_dir(buildpath);
|
||||
let exec_suffix = os::exe_suffix();
|
||||
for ct: str in new {
|
||||
for ct: str in newv {
|
||||
if (exec_suffix != "" && str::ends_with(ct, exec_suffix)) ||
|
||||
(exec_suffix == "" && !str::starts_with(path::basename(ct),
|
||||
"lib")) {
|
||||
|
@ -488,23 +488,23 @@ fn file_might_not_converge(filename: str) -> bool {
|
||||
fn check_roundtrip_convergence(code: @str, maxIters: uint) {
|
||||
|
||||
let i = 0u;
|
||||
let new = code;
|
||||
let old = code;
|
||||
let newv = code;
|
||||
let oldv = code;
|
||||
|
||||
while i < maxIters {
|
||||
old = new;
|
||||
if content_might_not_converge(*old) { ret; }
|
||||
new = @parse_and_print(old);
|
||||
if old == new { break; }
|
||||
oldv = newv;
|
||||
if content_might_not_converge(*oldv) { ret; }
|
||||
newv = @parse_and_print(oldv);
|
||||
if oldv == newv { break; }
|
||||
i += 1u;
|
||||
}
|
||||
|
||||
if old == new {
|
||||
if oldv == newv {
|
||||
#error("Converged after %u iterations", i);
|
||||
} else {
|
||||
#error("Did not converge after %u iterations!", i);
|
||||
write_file("round-trip-a.rs", *old);
|
||||
write_file("round-trip-b.rs", *new);
|
||||
write_file("round-trip-a.rs", *oldv);
|
||||
write_file("round-trip-b.rs", *newv);
|
||||
run::run_program("diff",
|
||||
["-w", "-u", "round-trip-a.rs",
|
||||
"round-trip-b.rs"]);
|
||||
|
@ -266,30 +266,30 @@ fn normalize(p: path) -> path {
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_os = "freebsd")]
|
||||
fn reabsolute(orig: path, new: path) -> path {
|
||||
fn reabsolute(orig: path, n: path) -> path {
|
||||
if path_is_absolute(orig) {
|
||||
path_sep() + new
|
||||
path_sep() + n
|
||||
} else {
|
||||
new
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "win32")]
|
||||
fn reabsolute(orig: path, new: path) -> path {
|
||||
fn reabsolute(orig: path, newp: path) -> path {
|
||||
if path_is_absolute(orig) && orig[0] == consts::path_sep as u8 {
|
||||
str::from_char(consts::path_sep) + new
|
||||
str::from_char(consts::path_sep) + newp
|
||||
} else {
|
||||
new
|
||||
newp
|
||||
}
|
||||
}
|
||||
|
||||
fn reterminate(orig: path, new: path) -> path {
|
||||
fn reterminate(orig: path, newp: path) -> path {
|
||||
let last = orig[str::len(orig) - 1u];
|
||||
if last == consts::path_sep as u8
|
||||
|| last == consts::path_sep as u8 {
|
||||
ret new + path_sep();
|
||||
ret newp + path_sep();
|
||||
} else {
|
||||
ret new;
|
||||
ret newp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -468,22 +468,22 @@ Concatenate a vector of vectors.
|
||||
Flattens a vector of vectors of T into a single vector of T.
|
||||
"]
|
||||
fn concat<T: copy>(v: [const [const T]]) -> [T] {
|
||||
let mut new: [T] = [];
|
||||
for inner: [T] in v { new += inner; }
|
||||
ret new;
|
||||
let mut r: [T] = [];
|
||||
for inner: [T] in v { r += inner; }
|
||||
ret r;
|
||||
}
|
||||
|
||||
#[doc = "
|
||||
Concatenate a vector of vectors, placing a given separator between each
|
||||
"]
|
||||
fn connect<T: copy>(v: [const [const T]], sep: T) -> [T] {
|
||||
let mut new: [T] = [];
|
||||
let mut r: [T] = [];
|
||||
let mut first = true;
|
||||
for inner: [T] in v {
|
||||
if first { first = false; } else { push(new, sep); }
|
||||
new += inner;
|
||||
if first { first = false; } else { push(r, sep); }
|
||||
r += inner;
|
||||
}
|
||||
ret new;
|
||||
ret r;
|
||||
}
|
||||
|
||||
#[doc = "Reduce a vector from left to right"]
|
||||
|
@ -2308,6 +2308,9 @@ fn resolve_impl_in_expr(e: @env, x: @ast::expr, sc: iscopes, v: vt<iscopes>) {
|
||||
ast::expr_assign_op(_, _, _) | ast::expr_index(_, _) {
|
||||
e.impl_map.insert(x.id, sc);
|
||||
}
|
||||
ast::expr_new(p, _, _) {
|
||||
e.impl_map.insert(p.id, sc);
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
visit::visit_expr(x, sc, v);
|
||||
|
@ -1261,9 +1261,9 @@ fn trans_unary(bcx: block, op: ast::unop, e: @ast::expr,
|
||||
some(origin) {
|
||||
let callee_id = ast_util::op_expr_callee_id(un_expr);
|
||||
let fty = node_id_type(bcx, callee_id);
|
||||
ret trans_call_inner(bcx, fty, {|bcx|
|
||||
ret trans_call_inner(bcx, fty, expr_ty(bcx, un_expr), {|bcx|
|
||||
impl::trans_method_callee(bcx, callee_id, e, origin)
|
||||
}, [], un_expr.id, dest);
|
||||
}, arg_exprs([]), dest);
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
@ -1450,10 +1450,10 @@ fn trans_assign_op(bcx: block, ex: @ast::expr, op: ast::binop,
|
||||
some(origin) {
|
||||
let callee_id = ast_util::op_expr_callee_id(ex);
|
||||
let fty = node_id_type(bcx, callee_id);
|
||||
ret trans_call_inner(bcx, fty, {|bcx|
|
||||
ret trans_call_inner(bcx, fty, expr_ty(bcx, ex), {|bcx|
|
||||
// FIXME provide the already-computed address, not the expr
|
||||
impl::trans_method_callee(bcx, callee_id, dst, origin)
|
||||
}, [src], ex.id, save_in(lhs_res.val));
|
||||
}, arg_exprs([src]), save_in(lhs_res.val));
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
@ -1561,9 +1561,9 @@ fn trans_binary(bcx: block, op: ast::binop, lhs: @ast::expr,
|
||||
some(origin) {
|
||||
let callee_id = ast_util::op_expr_callee_id(ex);
|
||||
let fty = node_id_type(bcx, callee_id);
|
||||
ret trans_call_inner(bcx, fty, {|bcx|
|
||||
ret trans_call_inner(bcx, fty, expr_ty(bcx, ex), {|bcx|
|
||||
impl::trans_method_callee(bcx, callee_id, lhs, origin)
|
||||
}, [rhs], ex.id, dest);
|
||||
}, arg_exprs([rhs]), dest);
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
@ -2498,6 +2498,10 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
|
||||
ret rslt(bcx, val);
|
||||
}
|
||||
|
||||
enum call_args {
|
||||
arg_exprs([@ast::expr]),
|
||||
arg_vals([ValueRef])
|
||||
}
|
||||
|
||||
// NB: must keep 4 fns in sync:
|
||||
//
|
||||
@ -2505,12 +2509,12 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
|
||||
// - create_llargs_for_fn_args.
|
||||
// - new_fn_ctxt
|
||||
// - trans_args
|
||||
fn trans_args(cx: block, llenv: ValueRef, es: [@ast::expr], fn_ty: ty::t,
|
||||
fn trans_args(cx: block, llenv: ValueRef, args: call_args, fn_ty: ty::t,
|
||||
dest: dest, generic_intrinsic: bool)
|
||||
-> {bcx: block, args: [ValueRef], retslot: ValueRef} {
|
||||
|
||||
let temp_cleanups = [];
|
||||
let args = ty::ty_fn_args(fn_ty);
|
||||
let arg_tys = ty::ty_fn_args(fn_ty);
|
||||
let llargs: [ValueRef] = [];
|
||||
|
||||
let ccx = cx.ccx();
|
||||
@ -2546,13 +2550,21 @@ fn trans_args(cx: block, llenv: ValueRef, es: [@ast::expr], fn_ty: ty::t,
|
||||
// First we figure out the caller's view of the types of the arguments.
|
||||
// This will be needed if this is a generic call, because the callee has
|
||||
// to cast her view of the arguments to the caller's view.
|
||||
let arg_tys = type_of_explicit_args(ccx, args);
|
||||
let i = 0u;
|
||||
for e: @ast::expr in es {
|
||||
let r = trans_arg_expr(bcx, args[i], arg_tys[i], e, temp_cleanups);
|
||||
bcx = r.bcx;
|
||||
llargs += [r.val];
|
||||
i += 1u;
|
||||
alt args {
|
||||
arg_exprs(es) {
|
||||
let llarg_tys = type_of_explicit_args(ccx, arg_tys);
|
||||
let i = 0u;
|
||||
for e: @ast::expr in es {
|
||||
let r = trans_arg_expr(bcx, arg_tys[i], llarg_tys[i],
|
||||
e, temp_cleanups);
|
||||
bcx = r.bcx;
|
||||
llargs += [r.val];
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
arg_vals(vs) {
|
||||
llargs += vs;
|
||||
}
|
||||
}
|
||||
|
||||
// now that all arguments have been successfully built, we can revoke any
|
||||
@ -2568,15 +2580,15 @@ fn trans_args(cx: block, llenv: ValueRef, es: [@ast::expr], fn_ty: ty::t,
|
||||
}
|
||||
|
||||
fn trans_call(in_cx: block, f: @ast::expr,
|
||||
args: [@ast::expr], id: ast::node_id, dest: dest)
|
||||
args: call_args, id: ast::node_id, dest: dest)
|
||||
-> block {
|
||||
trans_call_inner(in_cx, expr_ty(in_cx, f),
|
||||
{|cx| trans_callee(cx, f)}, args, id, dest)
|
||||
trans_call_inner(in_cx, expr_ty(in_cx, f), node_id_type(in_cx, id),
|
||||
{|cx| trans_callee(cx, f)}, args, dest)
|
||||
}
|
||||
|
||||
fn trans_call_inner(in_cx: block, fn_expr_ty: ty::t,
|
||||
fn trans_call_inner(in_cx: block, fn_expr_ty: ty::t, ret_ty: ty::t,
|
||||
get_callee: fn(block) -> lval_maybe_callee,
|
||||
args: [@ast::expr], id: ast::node_id, dest: dest)
|
||||
args: call_args, dest: dest)
|
||||
-> block {
|
||||
with_scope(in_cx, "call") {|cx|
|
||||
let f_res = get_callee(cx);
|
||||
@ -2603,9 +2615,10 @@ fn trans_call_inner(in_cx: block, fn_expr_ty: ty::t,
|
||||
}
|
||||
};
|
||||
|
||||
let ret_ty = node_id_type(bcx, id);
|
||||
let args_res = trans_args(bcx, llenv, args, fn_expr_ty, dest,
|
||||
option::is_some(f_res.tds));
|
||||
let args_res = {
|
||||
trans_args(bcx, llenv, args, fn_expr_ty, dest,
|
||||
option::is_some(f_res.tds))
|
||||
};
|
||||
bcx = args_res.bcx;
|
||||
let llargs = args_res.args;
|
||||
option::may(f_res.tds) {|vals|
|
||||
@ -2923,7 +2936,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
|
||||
}
|
||||
ast::expr_cast(val, _) { ret trans_cast(bcx, val, e.id, dest); }
|
||||
ast::expr_call(f, args, _) {
|
||||
ret trans_call(bcx, f, args, e.id, dest);
|
||||
ret trans_call(bcx, f, arg_exprs(args), e.id, dest);
|
||||
}
|
||||
ast::expr_field(base, _, _) {
|
||||
if dest == ignore { ret trans_expr(bcx, base, ignore); }
|
||||
@ -2937,9 +2950,9 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
|
||||
let origin = bcx.ccx().maps.method_map.get(e.id);
|
||||
let callee_id = ast_util::op_expr_callee_id(e);
|
||||
let fty = node_id_type(bcx, callee_id);
|
||||
ret trans_call_inner(bcx, fty, {|bcx|
|
||||
ret trans_call_inner(bcx, fty, expr_ty(bcx, e), {|bcx|
|
||||
impl::trans_method_callee(bcx, callee_id, base, origin)
|
||||
}, [idx], e.id, dest);
|
||||
}, arg_exprs([idx]), dest);
|
||||
}
|
||||
|
||||
// These return nothing
|
||||
@ -3037,6 +3050,45 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
|
||||
assert dest == ignore;
|
||||
ret trans_assign_op(bcx, e, op, dst, src);
|
||||
}
|
||||
ast::expr_new(pool, alloc_id, val) {
|
||||
// First, call pool->alloc(sz, align) to get back a void*. Then, cast
|
||||
// this memory to the required type and evaluate value into it.
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
// Allocate space for the ptr that will be returned from
|
||||
// `pool.alloc()`:
|
||||
let ptr_ty = expr_ty(bcx, e);
|
||||
let {bcx, val: ptr_ptr_val} = alloc_ty(bcx, ptr_ty);
|
||||
|
||||
#debug["ptr_ty = %s", ty_to_str(tcx, ptr_ty)];
|
||||
#debug["ptr_ptr_val = %s", val_str(ccx.tn, ptr_ptr_val)];
|
||||
|
||||
let void_ty = ty::mk_ptr(tcx, {ty: ty::mk_nil(tcx),
|
||||
mutbl: ast::m_imm});
|
||||
let voidval = {
|
||||
let llvoid_ty = type_of(ccx, void_ty);
|
||||
PointerCast(bcx, ptr_ptr_val, T_ptr(llvoid_ty))
|
||||
};
|
||||
|
||||
#debug["voidval = %s", val_str(ccx.tn, voidval)];
|
||||
|
||||
let llval_ty = type_of(ccx, expr_ty(bcx, val));
|
||||
let args = [llsize_of(ccx, llval_ty), llalign_of(ccx, llval_ty)];
|
||||
let origin = bcx.ccx().maps.method_map.get(alloc_id);
|
||||
let bcx = trans_call_inner(
|
||||
bcx,
|
||||
node_id_type(bcx, alloc_id),
|
||||
void_ty,
|
||||
{|bcx| impl::trans_method_callee(bcx, alloc_id, pool, origin) },
|
||||
arg_vals(args),
|
||||
save_in(voidval));
|
||||
|
||||
#debug["dest = %s", dest_str(ccx, dest)];
|
||||
let ptr_val = Load(bcx, ptr_ptr_val);
|
||||
#debug["ptr_val = %s", val_str(ccx.tn, ptr_val)];
|
||||
let bcx = trans_expr(bcx, val, save_in(ptr_val));
|
||||
store_in_dest(bcx, ptr_val, dest)
|
||||
}
|
||||
_ { bcx.tcx().sess.span_bug(e.span, "trans_expr reached \
|
||||
fall-through case"); }
|
||||
|
||||
|
@ -111,27 +111,28 @@ fn classify_ty(ty: TypeRef) -> [x86_64_reg_class] {
|
||||
}
|
||||
}
|
||||
|
||||
fn unify(cls: [mut x86_64_reg_class], i: uint,
|
||||
new: x86_64_reg_class) {
|
||||
if cls[i] == new {
|
||||
fn unify(cls: [mut x86_64_reg_class],
|
||||
i: uint,
|
||||
newv: x86_64_reg_class) {
|
||||
if cls[i] == newv {
|
||||
ret;
|
||||
} else if cls[i] == no_class {
|
||||
cls[i] = new;
|
||||
} else if new == no_class {
|
||||
cls[i] = newv;
|
||||
} else if newv == no_class {
|
||||
ret;
|
||||
} else if cls[i] == memory_class || new == memory_class {
|
||||
} else if cls[i] == memory_class || newv == memory_class {
|
||||
cls[i] = memory_class;
|
||||
} else if cls[i] == integer_class || new == integer_class {
|
||||
} else if cls[i] == integer_class || newv == integer_class {
|
||||
cls[i] = integer_class;
|
||||
} else if cls[i] == x87_class ||
|
||||
cls[i] == x87up_class ||
|
||||
cls[i] == complex_x87_class ||
|
||||
new == x87_class ||
|
||||
new == x87up_class ||
|
||||
new == complex_x87_class {
|
||||
newv == x87_class ||
|
||||
newv == x87up_class ||
|
||||
newv == complex_x87_class {
|
||||
cls[i] = memory_class;
|
||||
} else {
|
||||
cls[i] = new;
|
||||
cls[i] = newv;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,6 +168,9 @@ fn mark_for_expr(cx: ctx, e: @expr) {
|
||||
expr_log(_, _, val) {
|
||||
node_type_needs(cx, use_tydesc, val.id);
|
||||
}
|
||||
expr_new(_, _, v) {
|
||||
node_type_needs(cx, use_repr, v.id);
|
||||
}
|
||||
expr_for(_, _, _) | expr_do_while(_, _) | expr_alt(_, _, _) |
|
||||
expr_block(_) | expr_if(_, _, _) | expr_while(_, _) |
|
||||
expr_fail(_) | expr_break | expr_cont | expr_unary(_, _) |
|
||||
|
@ -183,14 +183,14 @@ fn set_poststate(a: ts_ann, p: poststate) -> bool {
|
||||
|
||||
|
||||
// Set all the bits in p that are set in new
|
||||
fn extend_prestate(p: prestate, new: poststate) -> bool {
|
||||
ret tritv_union(p, new);
|
||||
fn extend_prestate(p: prestate, newv: poststate) -> bool {
|
||||
ret tritv_union(p, newv);
|
||||
}
|
||||
|
||||
|
||||
// Set all the bits in p that are set in new
|
||||
fn extend_poststate(p: poststate, new: poststate) -> bool {
|
||||
ret tritv_union(p, new);
|
||||
fn extend_poststate(p: poststate, newv: poststate) -> bool {
|
||||
ret tritv_union(p, newv);
|
||||
}
|
||||
|
||||
// Sets the given bit in p to "don't care"
|
||||
|
@ -709,8 +709,8 @@ fn find_instances(_fcx: fn_ctxt, subst: subst, c: constraint) ->
|
||||
for d: pred_args in *descs {
|
||||
if args_mention(d.node.args, find_in_subst_bool, subst) {
|
||||
let old_bit_num = d.node.bit_num;
|
||||
let new = replace(subst, d);
|
||||
alt find_instance_(new, *descs) {
|
||||
let newv = replace(subst, d);
|
||||
alt find_instance_(newv, *descs) {
|
||||
some(d1) { rslt += [{from: old_bit_num, to: d1}]; }
|
||||
_ { }
|
||||
}
|
||||
@ -753,7 +753,7 @@ fn replace(subst: subst, d: pred_args) -> [constr_arg_general_<inst>] {
|
||||
alt c.node {
|
||||
carg_ident(p) {
|
||||
alt find_in_subst(p.node, subst) {
|
||||
some(new) { rslt += [carg_ident(new)]; }
|
||||
some(newv) { rslt += [carg_ident(newv)]; }
|
||||
_ { rslt += [c.node]; }
|
||||
}
|
||||
}
|
||||
|
@ -325,6 +325,9 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
|
||||
clear_pp(rslt);
|
||||
handle_var(fcx, rslt, e.id, path_to_ident(p));
|
||||
}
|
||||
expr_new(p, _, v) {
|
||||
find_pre_post_exprs(fcx, [p, v], e.id);
|
||||
}
|
||||
expr_log(_, lvl, arg) {
|
||||
find_pre_post_exprs(fcx, [lvl, arg], e.id);
|
||||
}
|
||||
|
@ -355,6 +355,9 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
|
||||
let num_constrs = num_constraints(fcx.enclosing);
|
||||
|
||||
alt e.node {
|
||||
expr_new(p, _, v) {
|
||||
ret find_pre_post_state_two(fcx, pres, p, v, e.id, oper_pure);
|
||||
}
|
||||
expr_vec(elts, _) {
|
||||
ret find_pre_post_state_exprs(fcx, pres, e.id,
|
||||
vec::from_elem(vec::len(elts),
|
||||
|
@ -155,8 +155,8 @@ fn trit_and(a: trit, b: trit) -> trit {
|
||||
// a and b were both dont_care
|
||||
}
|
||||
|
||||
fn change(changed: bool, old: trit, new: trit) -> bool {
|
||||
changed || new != old
|
||||
fn change(changed: bool, old: trit, newv: trit) -> bool {
|
||||
changed || newv != old
|
||||
}
|
||||
|
||||
fn tritv_difference(p1: t, p2: t) -> bool {
|
||||
@ -166,9 +166,9 @@ fn tritv_difference(p1: t, p2: t) -> bool {
|
||||
let changed = false;
|
||||
while i < sz {
|
||||
let old = tritv_get(p1, i);
|
||||
let new = trit_minus(old, tritv_get(p2, i));
|
||||
changed = change(changed, old, new);
|
||||
tritv_set(i, p1, new);
|
||||
let newv = trit_minus(old, tritv_get(p2, i));
|
||||
changed = change(changed, old, newv);
|
||||
tritv_set(i, p1, newv);
|
||||
i += 1u;
|
||||
}
|
||||
ret changed;
|
||||
@ -181,9 +181,9 @@ fn tritv_union(p1: t, p2: t) -> bool {
|
||||
let changed = false;
|
||||
while i < sz {
|
||||
let old = tritv_get(p1, i);
|
||||
let new = trit_or(old, tritv_get(p2, i));
|
||||
changed = change(changed, old, new);
|
||||
tritv_set(i, p1, new);
|
||||
let newv = trit_or(old, tritv_get(p2, i));
|
||||
changed = change(changed, old, newv);
|
||||
tritv_set(i, p1, newv);
|
||||
i += 1u;
|
||||
}
|
||||
ret changed;
|
||||
@ -196,9 +196,9 @@ fn tritv_intersect(p1: t, p2: t) -> bool {
|
||||
let changed = false;
|
||||
while i < sz {
|
||||
let old = tritv_get(p1, i);
|
||||
let new = trit_and(old, tritv_get(p2, i));
|
||||
changed = change(changed, old, new);
|
||||
tritv_set(i, p1, new);
|
||||
let newv = trit_and(old, tritv_get(p2, i));
|
||||
changed = change(changed, old, newv);
|
||||
tritv_set(i, p1, newv);
|
||||
i += 1u;
|
||||
}
|
||||
ret changed;
|
||||
|
@ -1888,6 +1888,12 @@ fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr,
|
||||
origin: method_origin,
|
||||
self_sub: option<self_subst>}> {
|
||||
let tcx = fcx.ccx.tcx;
|
||||
|
||||
#debug["lookup_method_inner: expr=%s name=%s ty=%s",
|
||||
expr_to_str(expr),
|
||||
name,
|
||||
ty_to_str(fcx.ccx.tcx, ty)];
|
||||
|
||||
// First, see whether this is an interface-bounded parameter
|
||||
alt ty::get(ty).struct {
|
||||
ty::ty_param(n, did) {
|
||||
@ -2870,6 +2876,51 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::expr_new(p, alloc_id, v) {
|
||||
bot |= check_expr(fcx, p);
|
||||
bot |= check_expr(fcx, v);
|
||||
|
||||
let p_ty = expr_ty(tcx, p);
|
||||
|
||||
alt lookup_method(fcx, p, alloc_id, "alloc", p_ty, []) {
|
||||
some(origin) {
|
||||
fcx.ccx.method_map.insert(alloc_id, origin);
|
||||
|
||||
// Check that the alloc() method has the expected type, which
|
||||
// should be fn(sz: uint, align: uint) -> *().
|
||||
let expected_ty = {
|
||||
let ty_uint = ty::mk_uint(tcx);
|
||||
let ty_nilp = ty::mk_ptr(tcx, {ty: ty::mk_nil(tcx),
|
||||
mutbl: ast::m_imm});
|
||||
let m = ast::expl(ty::default_arg_mode_for_ty(ty_uint));
|
||||
ty::mk_fn(tcx, {proto: ast::proto_any,
|
||||
inputs: [{mode: m, ty: ty_uint},
|
||||
{mode: m, ty: ty_uint}],
|
||||
output: ty_nilp,
|
||||
ret_style: ast::return_val,
|
||||
constraints: []})
|
||||
};
|
||||
|
||||
demand::simple(fcx, expr.span,
|
||||
expected_ty, node_id_to_type(tcx, alloc_id));
|
||||
}
|
||||
|
||||
none {
|
||||
let t_err = resolve_type_vars_if_possible(fcx, p_ty);
|
||||
let msg = #fmt["no `alloc()` method found for type `%s`",
|
||||
ty_to_str(tcx, t_err)];
|
||||
tcx.sess.span_err(expr.span, msg);
|
||||
}
|
||||
}
|
||||
|
||||
// The region value must have a type like &r.T. The resulting
|
||||
// memory will be allocated into the region `r`.
|
||||
let pool_region = region_of(fcx, p);
|
||||
let v_ty = expr_ty(tcx, v);
|
||||
let res_ty = ty::mk_rptr(tcx, pool_region, {ty: v_ty,
|
||||
mutbl: ast::m_imm});
|
||||
write_ty(tcx, expr.id, res_ty);
|
||||
}
|
||||
}
|
||||
if bot { write_ty(tcx, expr.id, ty::mk_bot(tcx)); }
|
||||
|
||||
|
@ -325,6 +325,10 @@ enum expr_ {
|
||||
expr_be(@expr),
|
||||
expr_log(int, @expr, @expr),
|
||||
|
||||
expr_new(/* arena */ @expr,
|
||||
/* id for the alloc() call */ node_id,
|
||||
/* value */ @expr),
|
||||
|
||||
/* just an assert, no significance to typestate */
|
||||
expr_assert(@expr),
|
||||
|
||||
|
@ -382,6 +382,11 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
|
||||
let fold_mac = bind fold_mac_(_, fld);
|
||||
|
||||
ret alt e {
|
||||
expr_new(p, i, v) {
|
||||
expr_new(fld.fold_expr(p),
|
||||
fld.new_id(i),
|
||||
fld.fold_expr(v))
|
||||
}
|
||||
expr_vec(exprs, mutt) {
|
||||
expr_vec(fld.map_exprs(fld.fold_expr, exprs), mutt)
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ fn bad_expr_word_table() -> hashmap<str, ()> {
|
||||
"enum", "export", "fail", "fn", "for", "if", "iface",
|
||||
"impl", "import", "let", "log", "loop", "mod", "mut",
|
||||
"mutable", "native", "pure", "resource", "ret", "trait",
|
||||
"type", "unchecked", "unsafe", "while"] {
|
||||
"type", "unchecked", "unsafe", "while", "new"] {
|
||||
words.insert(word, ());
|
||||
}
|
||||
words
|
||||
@ -852,6 +852,13 @@ fn parse_bottom_expr(p: parser) -> pexpr {
|
||||
let blk = parse_block_tail(p, lo, ast::default_blk);
|
||||
ret mk_pexpr(p, blk.span.lo, blk.span.hi, ast::expr_block(blk));
|
||||
}
|
||||
} else if eat_word(p, "new") {
|
||||
expect(p, token::LPAREN);
|
||||
let r = parse_expr(p);
|
||||
expect(p, token::RPAREN);
|
||||
let v = parse_expr(p);
|
||||
ret mk_pexpr(p, lo, p.span.hi,
|
||||
ast::expr_new(r, p.get_id(), v));
|
||||
} else if eat_word(p, "if") {
|
||||
ret pexpr(parse_if_expr(p));
|
||||
} else if eat_word(p, "for") {
|
||||
|
@ -1089,6 +1089,13 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
||||
word_nbsp(s, "assert");
|
||||
print_expr(s, expr);
|
||||
}
|
||||
ast::expr_new(p, _, v) {
|
||||
word_nbsp(s, "new");
|
||||
popen(s);
|
||||
print_expr(s, p);
|
||||
pclose(s);
|
||||
print_expr(s, v);
|
||||
}
|
||||
ast::expr_mac(m) { print_mac(s, m); }
|
||||
}
|
||||
s.ann.post(ann_node);
|
||||
|
@ -315,6 +315,10 @@ fn visit_mac<E>(m: mac, e: E, v: vt<E>) {
|
||||
|
||||
fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
|
||||
alt ex.node {
|
||||
expr_new(pool, _, val) {
|
||||
v.visit_expr(pool, e, v);
|
||||
v.visit_expr(val, e, v);
|
||||
}
|
||||
expr_vec(es, _) { visit_exprs(es, e, v); }
|
||||
expr_rec(flds, base) {
|
||||
for f: field in flds { v.visit_expr(f.node.expr, e, v); }
|
||||
|
15
src/test/compile-fail/placement-new-bad-method-type.rs
Normal file
15
src/test/compile-fail/placement-new-bad-method-type.rs
Normal file
@ -0,0 +1,15 @@
|
||||
import libc, unsafe;
|
||||
|
||||
enum malloc_pool = ();
|
||||
|
||||
impl methods for malloc_pool {
|
||||
fn alloc(sz: int, align: int) -> *() {
|
||||
fail;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let p = &malloc_pool(());
|
||||
let x = new(*p) 4u;
|
||||
//!^ ERROR mismatched types: expected `fn(uint, uint) -> *()`
|
||||
}
|
@ -21,7 +21,7 @@ fn request_task(c: chan<ctx>) {
|
||||
req = recv(p);
|
||||
}
|
||||
|
||||
fn new() -> ctx {
|
||||
fn new_cx() -> ctx {
|
||||
let p = port();
|
||||
let ch = chan(p);
|
||||
let t = task::spawn {|| request_task(ch); };
|
||||
@ -31,7 +31,7 @@ fn new() -> ctx {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cx = new();
|
||||
let cx = new_cx();
|
||||
|
||||
let p = port::<bool>();
|
||||
send(cx, close(chan(p)));
|
||||
|
21
src/test/run-pass/placement-new-leaky.rs
Normal file
21
src/test/run-pass/placement-new-leaky.rs
Normal file
@ -0,0 +1,21 @@
|
||||
import libc, unsafe;
|
||||
|
||||
enum malloc_pool = ();
|
||||
|
||||
impl methods for malloc_pool {
|
||||
fn alloc(sz: uint, align: uint) -> *() {
|
||||
unsafe {
|
||||
unsafe::reinterpret_cast(libc::malloc(sz))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let p = &malloc_pool(());
|
||||
let x = new(*p) 4u;
|
||||
io::print(#fmt["%u", *x]);
|
||||
assert *x == 4u;
|
||||
unsafe {
|
||||
libc::free(unsafe::reinterpret_cast(x));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user