Skip to content

Commit 7340824

Browse files
msullivanbrson
authored andcommitted
Fix autoderef of function calls when the function is not an lval.
As it turns out, the correct way to handle this is much simpler than what I did originally. Also add more tests.
1 parent 418aa52 commit 7340824

File tree

3 files changed

+16
-18
lines changed

3 files changed

+16
-18
lines changed

src/comp/middle/trans.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4206,19 +4206,13 @@ fn trans_eager_binop(&@block_ctxt cx, ast::binop op, &ty::t intype,
42064206
}
42074207
}
42084208

4209-
fn autoderef_lval(&@block_ctxt cx, ValueRef v, &ty::t t, bool is_lval)
4210-
-> result_t {
4209+
fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result_t {
42114210
let ValueRef v1 = v;
42124211
let ty::t t1 = t;
42134212
auto ccx = cx.fcx.lcx.ccx;
42144213
while (true) {
42154214
alt (ty::struct(ccx.tcx, t1)) {
42164215
case (ty::ty_box(?mt)) {
4217-
// If we are working with an lval, we want to
4218-
// unconditionally load at the top of the loop
4219-
// to get rid of the extra indirection
4220-
if (is_lval) { v1 = cx.build.Load(v1); }
4221-
42224216
auto body =
42234217
cx.build.GEP(v1,
42244218
~[C_int(0), C_int(abi::box_rc_field_body)]);
@@ -4233,7 +4227,6 @@ fn autoderef_lval(&@block_ctxt cx, ValueRef v, &ty::t t, bool is_lval)
42334227
} else { v1 = body; }
42344228
}
42354229
case (ty::ty_res(?did, ?inner, ?tps)) {
4236-
if (is_lval) { v1 = cx.build.Load(v1); }
42374230
t1 = ty::substitute_type_params(ccx.tcx, tps, inner);
42384231
v1 = cx.build.GEP(v1, ~[C_int(0), C_int(1)]);
42394232
}
@@ -4243,7 +4236,6 @@ fn autoderef_lval(&@block_ctxt cx, ValueRef v, &ty::t t, bool is_lval)
42434236
std::ivec::len(variants.(0).args) != 1u) {
42444237
break;
42454238
}
4246-
if (is_lval) { v1 = cx.build.Load(v1); }
42474239
t1 = ty::substitute_type_params
42484240
(ccx.tcx, tps, variants.(0).args.(0));
42494241
if (!ty::type_has_dynamic_size(ccx.tcx, t1)) {
@@ -4253,18 +4245,11 @@ fn autoderef_lval(&@block_ctxt cx, ValueRef v, &ty::t t, bool is_lval)
42534245
}
42544246
case (_) { break; }
42554247
}
4256-
// But if we aren't working with an lval, we get rid of
4257-
// a layer of indirection at the bottom of the loop so
4258-
// that it is gone when we return...
4259-
if (!is_lval) { v1 = load_if_immediate(cx, v1, t1); }
4248+
v1 = load_if_immediate(cx, v1, t1);
42604249
}
42614250
ret rec(bcx=cx, val=v1, ty=t1);
42624251
}
42634252

4264-
fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result_t {
4265-
ret autoderef_lval(cx, v, t, false);
4266-
}
4267-
42684253
fn trans_binary(&@block_ctxt cx, ast::binop op, &@ast::expr a, &@ast::expr b)
42694254
-> result {
42704255

@@ -5956,7 +5941,8 @@ fn trans_call(&@block_ctxt cx, &@ast::expr f, &option::t[ValueRef] lliterbody,
59565941
}
59575942
case (none) {
59585943
// It's a closure. We have to autoderef.
5959-
auto res = autoderef_lval(bcx, f_res.res.val, fn_ty, true);
5944+
if (f_res.is_mem) { faddr = load_if_immediate(bcx, faddr, fn_ty);}
5945+
auto res = autoderef(bcx, faddr, fn_ty);
59605946
bcx = res.bcx;
59615947
fn_ty = res.ty;
59625948

src/test/run-pass/auto-deref-fn.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ fn main() {
88
assert(f(5) == 6);
99
assert(g(8) == 9);
1010
assert(h(0x1badd00d) == 0x1badd00e);
11+
assert((@add1)(42) == 43);
1112
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// xfail-stage0
2+
tag int_fn { f(fn(int) -> int); }
3+
tag int_box_fn { fb(@fn(int) -> int); }
4+
fn add1(int i) -> int { ret i+1; }
5+
fn main() {
6+
auto g = f(add1);
7+
assert(g(4) == 5);
8+
assert((f(add1))(5) == 6);
9+
assert((@(f(add1)))(5) == 6);
10+
assert((fb(@add1))(7) == 8);
11+
}

0 commit comments

Comments
 (0)