diff options
| author | Michael Sullivan <sully@msully.net> | 2011-07-11 13:12:44 -0500 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2011-07-11 11:38:01 -0700 |
| commit | 7340824cbcce104458d87200119b62dbfe0ef07a (patch) | |
| tree | a545b2b60683d528c357dd5ed039145124bdc843 /src | |
| parent | 418aa525107319a224a3299eae8d9c8fdfe02c13 (diff) | |
| download | rust-7340824cbcce104458d87200119b62dbfe0ef07a.tar.gz rust-7340824cbcce104458d87200119b62dbfe0ef07a.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/comp/middle/trans.rs | 22 | ||||
| -rw-r--r-- | src/test/run-pass/auto-deref-fn.rs | 1 | ||||
| -rw-r--r-- | src/test/run-pass/call-autoderef-tag.rs | 11 |
3 files changed, 16 insertions, 18 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 18a0c50ae76..4fd290389e0 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4206,19 +4206,13 @@ fn trans_eager_binop(&@block_ctxt cx, ast::binop op, &ty::t intype, } } -fn autoderef_lval(&@block_ctxt cx, ValueRef v, &ty::t t, bool is_lval) - -> result_t { +fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result_t { let ValueRef v1 = v; let ty::t t1 = t; auto ccx = cx.fcx.lcx.ccx; while (true) { alt (ty::struct(ccx.tcx, t1)) { case (ty::ty_box(?mt)) { - // If we are working with an lval, we want to - // unconditionally load at the top of the loop - // to get rid of the extra indirection - if (is_lval) { v1 = cx.build.Load(v1); } - auto body = cx.build.GEP(v1, ~[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) } else { v1 = body; } } case (ty::ty_res(?did, ?inner, ?tps)) { - if (is_lval) { v1 = cx.build.Load(v1); } t1 = ty::substitute_type_params(ccx.tcx, tps, inner); v1 = cx.build.GEP(v1, ~[C_int(0), C_int(1)]); } @@ -4243,7 +4236,6 @@ fn autoderef_lval(&@block_ctxt cx, ValueRef v, &ty::t t, bool is_lval) std::ivec::len(variants.(0).args) != 1u) { break; } - if (is_lval) { v1 = cx.build.Load(v1); } t1 = ty::substitute_type_params (ccx.tcx, tps, variants.(0).args.(0)); 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) } case (_) { break; } } - // But if we aren't working with an lval, we get rid of - // a layer of indirection at the bottom of the loop so - // that it is gone when we return... - if (!is_lval) { v1 = load_if_immediate(cx, v1, t1); } + v1 = load_if_immediate(cx, v1, t1); } ret rec(bcx=cx, val=v1, ty=t1); } -fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result_t { - ret autoderef_lval(cx, v, t, false); -} - fn trans_binary(&@block_ctxt cx, ast::binop op, &@ast::expr a, &@ast::expr b) -> result { @@ -5956,7 +5941,8 @@ fn trans_call(&@block_ctxt cx, &@ast::expr f, &option::t[ValueRef] lliterbody, } case (none) { // It's a closure. We have to autoderef. - auto res = autoderef_lval(bcx, f_res.res.val, fn_ty, true); + if (f_res.is_mem) { faddr = load_if_immediate(bcx, faddr, fn_ty);} + auto res = autoderef(bcx, faddr, fn_ty); bcx = res.bcx; fn_ty = res.ty; diff --git a/src/test/run-pass/auto-deref-fn.rs b/src/test/run-pass/auto-deref-fn.rs index 6959e8e109f..8637c7d03d6 100644 --- a/src/test/run-pass/auto-deref-fn.rs +++ b/src/test/run-pass/auto-deref-fn.rs @@ -8,4 +8,5 @@ fn main() { assert(f(5) == 6); assert(g(8) == 9); assert(h(0x1badd00d) == 0x1badd00e); + assert((@add1)(42) == 43); } diff --git a/src/test/run-pass/call-autoderef-tag.rs b/src/test/run-pass/call-autoderef-tag.rs new file mode 100644 index 00000000000..3826b9a409c --- /dev/null +++ b/src/test/run-pass/call-autoderef-tag.rs @@ -0,0 +1,11 @@ +// xfail-stage0 +tag int_fn { f(fn(int) -> int); } +tag int_box_fn { fb(@fn(int) -> int); } +fn add1(int i) -> int { ret i+1; } +fn main() { + auto g = f(add1); + assert(g(4) == 5); + assert((f(add1))(5) == 6); + assert((@(f(add1)))(5) == 6); + assert((fb(@add1))(7) == 8); +} |
