mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-17 01:13:11 +00:00
integrate simple notion of borrowing into trans
This commit is contained in:
parent
378996092e
commit
247db704a9
@ -844,6 +844,7 @@ impl assignment for infer_ctxt {
|
||||
sub(self).contraregions(r_a, r_b).chain {|_r|
|
||||
// if successful, add an entry indicating that
|
||||
// borrowing occurred
|
||||
#debug["borrowing expression #%?", a_node_id];
|
||||
self.tcx.borrowings.insert(a_node_id, ());
|
||||
uok()
|
||||
}
|
||||
|
@ -313,8 +313,8 @@ fn shared_malloc(cx: block, llptr_ty: TypeRef, llsize: ValueRef)
|
||||
//
|
||||
// The runtime equivalent is box_body() in "rust_internal.h".
|
||||
fn opaque_box_body(bcx: block,
|
||||
body_t: ty::t,
|
||||
boxptr: ValueRef) -> ValueRef {
|
||||
body_t: ty::t,
|
||||
boxptr: ValueRef) -> ValueRef {
|
||||
let _icx = bcx.insn_ctxt("opaque_box_body");
|
||||
let ccx = bcx.ccx();
|
||||
let boxptr = PointerCast(bcx, boxptr, T_ptr(T_box_header(ccx)));
|
||||
@ -2323,6 +2323,10 @@ fn trans_index(cx: block, ex: @ast::expr, base: @ast::expr,
|
||||
ret lval_owned(bcx, PointerCast(bcx, elt, T_ptr(llunitty)));
|
||||
}
|
||||
|
||||
fn expr_is_borrowed(bcx: block, e: @ast::expr) -> bool {
|
||||
bcx.tcx().borrowings.contains_key(e.id)
|
||||
}
|
||||
|
||||
fn expr_is_lval(bcx: block, e: @ast::expr) -> bool {
|
||||
let ccx = bcx.ccx();
|
||||
ty::expr_is_lval(ccx.maps.method_map, e)
|
||||
@ -2553,6 +2557,7 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
|
||||
}
|
||||
none { trans_temp_lval(cx, e) }
|
||||
};
|
||||
let lv = adapt_borrowed_value(lv, arg, e);
|
||||
let mut bcx = lv.bcx;
|
||||
let mut val = lv.val;
|
||||
let arg_mode = ty::resolved_mode(ccx.tcx, arg.mode);
|
||||
@ -2611,6 +2616,58 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
|
||||
ret rslt(bcx, val);
|
||||
}
|
||||
|
||||
fn adapt_borrowed_value(lv: lval_result, arg: ty::arg,
|
||||
e: @ast::expr) -> lval_result {
|
||||
let bcx = lv.bcx;
|
||||
if !expr_is_borrowed(bcx, e) { ret lv; }
|
||||
|
||||
let e_ty = expr_ty(bcx, e);
|
||||
alt ty::get(e_ty).struct {
|
||||
ty::ty_box(mt) {
|
||||
let box_ptr = {
|
||||
alt lv.kind {
|
||||
temporary { lv.val }
|
||||
owned { Load(bcx, lv.val) }
|
||||
owned_imm { lv.val }
|
||||
}
|
||||
};
|
||||
let body_ptr = GEPi(bcx, box_ptr, [0, abi::box_field_body]);
|
||||
ret lval_temp(bcx, body_ptr);
|
||||
}
|
||||
|
||||
ty::ty_uniq(_) {
|
||||
ret lv; // no change needed at runtime (I think)
|
||||
}
|
||||
|
||||
ty::ty_estr(ty::vstore_box) |
|
||||
ty::ty_evec(_, ty::vstore_box) {
|
||||
bcx.tcx().sess.span_unimpl(
|
||||
e.span, #fmt["borrowing a value of type %s",
|
||||
ty_to_str(bcx.tcx(), e_ty)]);
|
||||
}
|
||||
|
||||
ty::ty_estr(ty::vstore_uniq) |
|
||||
ty::ty_evec(_, ty::vstore_uniq) {
|
||||
bcx.tcx().sess.span_unimpl(
|
||||
e.span, #fmt["borrowing a value of type %s",
|
||||
ty_to_str(bcx.tcx(), e_ty)]);
|
||||
}
|
||||
|
||||
ty::ty_estr(ty::vstore_fixed(_)) |
|
||||
ty::ty_evec(_, ty::vstore_fixed(_)) {
|
||||
bcx.tcx().sess.span_unimpl(
|
||||
e.span, #fmt["borrowing a value of type %s",
|
||||
ty_to_str(bcx.tcx(), e_ty)]);
|
||||
}
|
||||
|
||||
_ {
|
||||
bcx.tcx().sess.span_bug(
|
||||
e.span, #fmt["cannot borrow a value of type %s",
|
||||
ty_to_str(bcx.tcx(), e_ty)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum call_args {
|
||||
arg_exprs([@ast::expr]),
|
||||
arg_vals([ValueRef])
|
||||
@ -3006,7 +3063,12 @@ fn trans_expr_save_in(bcx: block, e: @ast::expr, dest: ValueRef)
|
||||
fn trans_temp_lval(bcx: block, e: @ast::expr) -> lval_result {
|
||||
let _icx = bcx.insn_ctxt("trans_temp_lval");
|
||||
let mut bcx = bcx;
|
||||
if expr_is_lval(bcx, e) {
|
||||
if expr_is_lval(bcx, e) && !expr_is_borrowed(bcx, e) {
|
||||
// if the expression is borrowed, then are not actually passing the
|
||||
// lvalue itself, but rather an adaptation of it. This is a bit of a
|
||||
// hack, though, but it only needs to exist so long as we have
|
||||
// reference modes and the like---otherwise, all potentially borrowed
|
||||
// things will go directly through trans_expr() as they ought to.
|
||||
ret trans_lval(bcx, e);
|
||||
} else {
|
||||
let ty = expr_ty(bcx, e);
|
||||
@ -3047,12 +3109,6 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
|
||||
let tcx = bcx.tcx();
|
||||
debuginfo::update_source_pos(bcx, e.span);
|
||||
|
||||
#debug["trans_expr(e=%s,e.id=%d,dest=%s,ty=%s)",
|
||||
expr_to_str(e),
|
||||
e.id,
|
||||
dest_str(bcx.ccx(), dest),
|
||||
ty_to_str(tcx, expr_ty(bcx, e))];
|
||||
|
||||
if expr_is_lval(bcx, e) {
|
||||
ret lval_to_dps(bcx, e, dest);
|
||||
}
|
||||
@ -3264,9 +3320,10 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
|
||||
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"); }
|
||||
|
||||
_ {
|
||||
bcx.tcx().sess.span_bug(e.span, "trans_expr reached \
|
||||
fall-through case");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -875,6 +875,13 @@ pure fn type_is_boxed(ty: t) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pure fn type_is_region_ptr(ty: t) -> bool {
|
||||
alt get(ty).struct {
|
||||
ty_rptr(_, _) { true }
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
|
||||
pure fn type_is_slice(ty: t) -> bool {
|
||||
alt get(ty).struct {
|
||||
ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) { true }
|
||||
@ -924,7 +931,7 @@ pure fn type_is_scalar(ty: t) -> bool {
|
||||
// FIXME maybe inline this for speed?
|
||||
fn type_is_immediate(ty: t) -> bool {
|
||||
ret type_is_scalar(ty) || type_is_boxed(ty) ||
|
||||
type_is_unique(ty);
|
||||
type_is_unique(ty) || type_is_region_ptr(ty);
|
||||
}
|
||||
|
||||
fn type_needs_drop(cx: ctxt, ty: t) -> bool {
|
||||
|
@ -2581,7 +2581,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
||||
// A generic function to factor out common logic from call and bind
|
||||
// expressions.
|
||||
fn check_call_or_bind(
|
||||
fcx: @fn_ctxt, sp: span, call_expr_id: ast::node_id, fty: ty::t,
|
||||
fcx: @fn_ctxt, sp: span, fty: ty::t,
|
||||
args: [option<@ast::expr>]) -> {fty: ty::t, bot: bool} {
|
||||
|
||||
let fty = universally_quantify_before_call(fcx, region_env(), fty);
|
||||
@ -2680,8 +2680,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
||||
// Call the generic checker.
|
||||
let fty = {
|
||||
let args_opt = args.map { |arg| some(arg) };
|
||||
let r = check_call_or_bind(fcx, sp, call_expr_id,
|
||||
fn_ty, args_opt);
|
||||
let r = check_call_or_bind(fcx, sp, fn_ty, args_opt);
|
||||
bot |= r.bot;
|
||||
r.fty
|
||||
};
|
||||
@ -2762,8 +2761,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
||||
some(origin) {
|
||||
let {fty: method_ty, bot: bot} = {
|
||||
let method_ty = fcx.node_ty(callee_id);
|
||||
check_call_or_bind(fcx, op_ex.span, op_ex.id,
|
||||
method_ty, args)
|
||||
check_call_or_bind(fcx, op_ex.span, method_ty, args)
|
||||
};
|
||||
fcx.ccx.method_map.insert(op_ex.id, origin);
|
||||
some((ty::ty_fn_ret(method_ty), bot))
|
||||
@ -3194,7 +3192,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
||||
|
||||
let {fty, bot: ccob_bot} = {
|
||||
let fn_ty = fcx.expr_ty(f);
|
||||
check_call_or_bind(fcx, expr.span, expr.id, fn_ty, args)
|
||||
check_call_or_bind(fcx, expr.span, fn_ty, args)
|
||||
};
|
||||
bot |= ccob_bot;
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
// xfail-test it don't work yet
|
||||
|
||||
fn foo(x: &uint) -> uint {
|
||||
*x
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let p = @3u;
|
||||
let p = @22u;
|
||||
let r = foo(p);
|
||||
assert r == 3u;
|
||||
#debug["r=%u", r];
|
||||
assert r == 22u;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user