Skip to content

Commit 247db70

Browse files
committed
integrate simple notion of borrowing into trans
1 parent 3789960 commit 247db70

File tree

5 files changed

+85
-23
lines changed

5 files changed

+85
-23
lines changed

src/rustc/middle/infer.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@ impl assignment for infer_ctxt {
844844
sub(self).contraregions(r_a, r_b).chain {|_r|
845845
// if successful, add an entry indicating that
846846
// borrowing occurred
847+
#debug["borrowing expression #%?", a_node_id];
847848
self.tcx.borrowings.insert(a_node_id, ());
848849
uok()
849850
}

src/rustc/middle/trans/base.rs

Lines changed: 69 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,8 @@ fn shared_malloc(cx: block, llptr_ty: TypeRef, llsize: ValueRef)
313313
//
314314
// The runtime equivalent is box_body() in "rust_internal.h".
315315
fn opaque_box_body(bcx: block,
316-
body_t: ty::t,
317-
boxptr: ValueRef) -> ValueRef {
316+
body_t: ty::t,
317+
boxptr: ValueRef) -> ValueRef {
318318
let _icx = bcx.insn_ctxt("opaque_box_body");
319319
let ccx = bcx.ccx();
320320
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,
23232323
ret lval_owned(bcx, PointerCast(bcx, elt, T_ptr(llunitty)));
23242324
}
23252325

2326+
fn expr_is_borrowed(bcx: block, e: @ast::expr) -> bool {
2327+
bcx.tcx().borrowings.contains_key(e.id)
2328+
}
2329+
23262330
fn expr_is_lval(bcx: block, e: @ast::expr) -> bool {
23272331
let ccx = bcx.ccx();
23282332
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,
25532557
}
25542558
none { trans_temp_lval(cx, e) }
25552559
};
2560+
let lv = adapt_borrowed_value(lv, arg, e);
25562561
let mut bcx = lv.bcx;
25572562
let mut val = lv.val;
25582563
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,
26112616
ret rslt(bcx, val);
26122617
}
26132618

2619+
fn adapt_borrowed_value(lv: lval_result, arg: ty::arg,
2620+
e: @ast::expr) -> lval_result {
2621+
let bcx = lv.bcx;
2622+
if !expr_is_borrowed(bcx, e) { ret lv; }
2623+
2624+
let e_ty = expr_ty(bcx, e);
2625+
alt ty::get(e_ty).struct {
2626+
ty::ty_box(mt) {
2627+
let box_ptr = {
2628+
alt lv.kind {
2629+
temporary { lv.val }
2630+
owned { Load(bcx, lv.val) }
2631+
owned_imm { lv.val }
2632+
}
2633+
};
2634+
let body_ptr = GEPi(bcx, box_ptr, [0, abi::box_field_body]);
2635+
ret lval_temp(bcx, body_ptr);
2636+
}
2637+
2638+
ty::ty_uniq(_) {
2639+
ret lv; // no change needed at runtime (I think)
2640+
}
2641+
2642+
ty::ty_estr(ty::vstore_box) |
2643+
ty::ty_evec(_, ty::vstore_box) {
2644+
bcx.tcx().sess.span_unimpl(
2645+
e.span, #fmt["borrowing a value of type %s",
2646+
ty_to_str(bcx.tcx(), e_ty)]);
2647+
}
2648+
2649+
ty::ty_estr(ty::vstore_uniq) |
2650+
ty::ty_evec(_, ty::vstore_uniq) {
2651+
bcx.tcx().sess.span_unimpl(
2652+
e.span, #fmt["borrowing a value of type %s",
2653+
ty_to_str(bcx.tcx(), e_ty)]);
2654+
}
2655+
2656+
ty::ty_estr(ty::vstore_fixed(_)) |
2657+
ty::ty_evec(_, ty::vstore_fixed(_)) {
2658+
bcx.tcx().sess.span_unimpl(
2659+
e.span, #fmt["borrowing a value of type %s",
2660+
ty_to_str(bcx.tcx(), e_ty)]);
2661+
}
2662+
2663+
_ {
2664+
bcx.tcx().sess.span_bug(
2665+
e.span, #fmt["cannot borrow a value of type %s",
2666+
ty_to_str(bcx.tcx(), e_ty)]);
2667+
}
2668+
}
2669+
}
2670+
26142671
enum call_args {
26152672
arg_exprs([@ast::expr]),
26162673
arg_vals([ValueRef])
@@ -3006,7 +3063,12 @@ fn trans_expr_save_in(bcx: block, e: @ast::expr, dest: ValueRef)
30063063
fn trans_temp_lval(bcx: block, e: @ast::expr) -> lval_result {
30073064
let _icx = bcx.insn_ctxt("trans_temp_lval");
30083065
let mut bcx = bcx;
3009-
if expr_is_lval(bcx, e) {
3066+
if expr_is_lval(bcx, e) && !expr_is_borrowed(bcx, e) {
3067+
// if the expression is borrowed, then are not actually passing the
3068+
// lvalue itself, but rather an adaptation of it. This is a bit of a
3069+
// hack, though, but it only needs to exist so long as we have
3070+
// reference modes and the like---otherwise, all potentially borrowed
3071+
// things will go directly through trans_expr() as they ought to.
30103072
ret trans_lval(bcx, e);
30113073
} else {
30123074
let ty = expr_ty(bcx, e);
@@ -3047,12 +3109,6 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
30473109
let tcx = bcx.tcx();
30483110
debuginfo::update_source_pos(bcx, e.span);
30493111

3050-
#debug["trans_expr(e=%s,e.id=%d,dest=%s,ty=%s)",
3051-
expr_to_str(e),
3052-
e.id,
3053-
dest_str(bcx.ccx(), dest),
3054-
ty_to_str(tcx, expr_ty(bcx, e))];
3055-
30563112
if expr_is_lval(bcx, e) {
30573113
ret lval_to_dps(bcx, e, dest);
30583114
}
@@ -3264,9 +3320,10 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
32643320
let bcx = trans_expr(bcx, val, save_in(ptr_val));
32653321
store_in_dest(bcx, ptr_val, dest)
32663322
}
3267-
_ { bcx.tcx().sess.span_bug(e.span, "trans_expr reached \
3268-
fall-through case"); }
3269-
3323+
_ {
3324+
bcx.tcx().sess.span_bug(e.span, "trans_expr reached \
3325+
fall-through case");
3326+
}
32703327
}
32713328
}
32723329

src/rustc/middle/ty.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,13 @@ pure fn type_is_boxed(ty: t) -> bool {
875875
}
876876
}
877877

878+
pure fn type_is_region_ptr(ty: t) -> bool {
879+
alt get(ty).struct {
880+
ty_rptr(_, _) { true }
881+
_ { false }
882+
}
883+
}
884+
878885
pure fn type_is_slice(ty: t) -> bool {
879886
alt get(ty).struct {
880887
ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) { true }
@@ -924,7 +931,7 @@ pure fn type_is_scalar(ty: t) -> bool {
924931
// FIXME maybe inline this for speed?
925932
fn type_is_immediate(ty: t) -> bool {
926933
ret type_is_scalar(ty) || type_is_boxed(ty) ||
927-
type_is_unique(ty);
934+
type_is_unique(ty) || type_is_region_ptr(ty);
928935
}
929936

930937
fn type_needs_drop(cx: ctxt, ty: t) -> bool {

src/rustc/middle/typeck.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2581,7 +2581,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
25812581
// A generic function to factor out common logic from call and bind
25822582
// expressions.
25832583
fn check_call_or_bind(
2584-
fcx: @fn_ctxt, sp: span, call_expr_id: ast::node_id, fty: ty::t,
2584+
fcx: @fn_ctxt, sp: span, fty: ty::t,
25852585
args: [option<@ast::expr>]) -> {fty: ty::t, bot: bool} {
25862586

25872587
let fty = universally_quantify_before_call(fcx, region_env(), fty);
@@ -2680,8 +2680,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
26802680
// Call the generic checker.
26812681
let fty = {
26822682
let args_opt = args.map { |arg| some(arg) };
2683-
let r = check_call_or_bind(fcx, sp, call_expr_id,
2684-
fn_ty, args_opt);
2683+
let r = check_call_or_bind(fcx, sp, fn_ty, args_opt);
26852684
bot |= r.bot;
26862685
r.fty
26872686
};
@@ -2762,8 +2761,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
27622761
some(origin) {
27632762
let {fty: method_ty, bot: bot} = {
27642763
let method_ty = fcx.node_ty(callee_id);
2765-
check_call_or_bind(fcx, op_ex.span, op_ex.id,
2766-
method_ty, args)
2764+
check_call_or_bind(fcx, op_ex.span, method_ty, args)
27672765
};
27682766
fcx.ccx.method_map.insert(op_ex.id, origin);
27692767
some((ty::ty_fn_ret(method_ty), bot))
@@ -3194,7 +3192,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
31943192

31953193
let {fty, bot: ccob_bot} = {
31963194
let fn_ty = fcx.expr_ty(f);
3197-
check_call_or_bind(fcx, expr.span, expr.id, fn_ty, args)
3195+
check_call_or_bind(fcx, expr.span, fn_ty, args)
31983196
};
31993197
bot |= ccob_bot;
32003198

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
// xfail-test it don't work yet
2-
31
fn foo(x: &uint) -> uint {
42
*x
53
}
64

75
fn main() {
8-
let p = @3u;
6+
let p = @22u;
97
let r = foo(p);
10-
assert r == 3u;
8+
#debug["r=%u", r];
9+
assert r == 22u;
1110
}

0 commit comments

Comments
 (0)