Skip to content

Commit 2789b6a

Browse files
msullivanmarijnh
authored andcommitted
---
yaml --- r: 3521 b: refs/heads/master c: 7b1b5d5 h: refs/heads/master i: 3519: e34a593 v: v3
1 parent cca5847 commit 2789b6a

File tree

6 files changed

+70
-24
lines changed

6 files changed

+70
-24
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: ee45d54a4e14c8ae809b0b6c3111260a3f39ba40
2+
refs/heads/master: 7b1b5d5a8a9aba6a682f95b7c738945be8e1fca2

trunk/src/comp/middle/alias.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ fn def_is_local(&ast::def d, bool objfields_count) -> bool {
663663
}
664664

665665
fn fty_args(&ctx cx, ty::t fty) -> ty::arg[] {
666-
ret alt (ty::struct(*cx.tcx, fty)) {
666+
ret alt (ty::struct(*cx.tcx, ty::type_autoderef(*cx.tcx, fty))) {
667667
case (ty::ty_fn(_, ?args, _, _, _)) { args }
668668
case (ty::ty_native_fn(_, ?args, _)) { args }
669669
};

trunk/src/comp/middle/trans.rs

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4099,12 +4099,18 @@ fn trans_eager_binop(&@block_ctxt cx, ast::binop op, &ty::t intype,
40994099
}
41004100
}
41014101

4102-
fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result {
4102+
fn autoderef_lval(&@block_ctxt cx, ValueRef v, &ty::t t, bool is_lval)
4103+
-> result {
41034104
let ValueRef v1 = v;
41044105
let ty::t t1 = t;
41054106
while (true) {
41064107
alt (ty::struct(cx.fcx.lcx.ccx.tcx, t1)) {
41074108
case (ty::ty_box(?mt)) {
4109+
// If we are working with an lval, we want to
4110+
// unconditionally load at the top of the loop
4111+
// to get rid of the extra indirection
4112+
if (is_lval) { v1 = cx.build.Load(v1); }
4113+
41084114
auto body =
41094115
cx.build.GEP(v1,
41104116
[C_int(0), C_int(abi::box_rc_field_body)]);
@@ -4118,14 +4124,22 @@ fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result {
41184124
auto llty = type_of(cx.fcx.lcx.ccx, cx.sp, mt.ty);
41194125
v1 = cx.build.PointerCast(body, T_ptr(llty));
41204126
} else { v1 = body; }
4121-
v1 = load_if_immediate(cx, v1, t1);
4127+
4128+
// But if we aren't working with an lval, we get rid of
4129+
// a layer of indirection at the bottom of the loop so
4130+
// that it is gone when we return...
4131+
if (!is_lval) { v1 = load_if_immediate(cx, v1, t1); }
41224132
}
41234133
case (_) { break; }
41244134
}
41254135
}
41264136
ret rslt(cx, v1);
41274137
}
41284138

4139+
fn autoderef(&@block_ctxt cx, ValueRef v, &ty::t t) -> result {
4140+
ret autoderef_lval(cx, v, t, false);
4141+
}
4142+
41294143
fn trans_binary(&@block_ctxt cx, ast::binop op, &@ast::expr a, &@ast::expr b)
41304144
-> result {
41314145

@@ -5637,17 +5651,33 @@ fn trans_call(&@block_ctxt cx, &@ast::expr f, &option::t[ValueRef] lliterbody,
56375651
// with trans_call.
56385652

56395653
auto f_res = trans_lval(cx, f);
5654+
let ty::t fn_ty;
5655+
alt (f_res.method_ty) {
5656+
case (some(?meth)) {
5657+
// self-call
5658+
fn_ty = meth;
5659+
}
5660+
case (_) {
5661+
fn_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, f);
5662+
}
5663+
}
5664+
5665+
auto bcx = f_res.res.bcx;
5666+
56405667
auto faddr = f_res.res.val;
56415668
auto llenv = C_null(T_opaque_closure_ptr(cx.fcx.lcx.ccx.tn));
56425669
alt (f_res.llobj) {
56435670
case (some(_)) {
56445671
// It's a vtbl entry.
5645-
faddr = f_res.res.bcx.build.Load(faddr);
5672+
faddr = bcx.build.Load(faddr);
56465673
}
56475674
case (none) {
5648-
// It's a closure.
5649-
auto bcx = f_res.res.bcx;
5650-
auto pair = faddr;
5675+
// It's a closure. We have to autoderef.
5676+
auto res = autoderef_lval(bcx, f_res.res.val, fn_ty, true);
5677+
bcx = res.bcx;
5678+
fn_ty = ty::type_autoderef(bcx.fcx.lcx.ccx.tcx, fn_ty);
5679+
5680+
auto pair = res.val;
56515681
faddr =
56525682
bcx.build.GEP(pair, [C_int(0), C_int(abi::fn_field_code)]);
56535683
faddr = bcx.build.Load(faddr);
@@ -5656,19 +5686,12 @@ fn trans_call(&@block_ctxt cx, &@ast::expr f, &option::t[ValueRef] lliterbody,
56565686
llenv = bcx.build.Load(llclosure);
56575687
}
56585688
}
5659-
let ty::t fn_ty;
5660-
alt (f_res.method_ty) {
5661-
case (some(?meth)) {
5662-
// self-call
5663-
fn_ty = meth;
5664-
}
5665-
case (_) { fn_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, f); }
5666-
}
5689+
56675690
auto ret_ty = ty::node_id_to_type(cx.fcx.lcx.ccx.tcx, id);
56685691
auto args_res =
5669-
trans_args(f_res.res.bcx, llenv, f_res.llobj, f_res.generic,
5692+
trans_args(bcx, llenv, f_res.llobj, f_res.generic,
56705693
lliterbody, args, fn_ty);
5671-
auto bcx = args_res._0;
5694+
bcx = args_res._0;
56725695
auto llargs = args_res._1;
56735696
auto llretslot = args_res._2;
56745697
/*

trunk/src/comp/middle/typeck.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,17 +1336,21 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
13361336
// expressions.
13371337

13381338
fn check_call_or_bind(&@fn_ctxt fcx, &span sp, &@ast::expr f,
1339-
&vec[option::t[@ast::expr]] args) {
1339+
&vec[option::t[@ast::expr]] args, bool is_call) {
13401340
// Check the function.
13411341

13421342
check_expr(fcx, f);
13431343
// Get the function type.
13441344

13451345
auto fty = expr_ty(fcx.ccx.tcx, f);
1346-
// Grab the argument types and the return type.
13471346

1347+
// We want to autoderef calls but not binds
1348+
auto fty_stripped =
1349+
if (is_call) { strip_boxes(fcx, sp, fty) } else { fty };
1350+
1351+
// Grab the argument types and the return type.
13481352
auto arg_tys;
1349-
alt (structure_of(fcx, sp, fty)) {
1353+
alt (structure_of(fcx, sp, fty_stripped)) {
13501354
case (ty::ty_fn(_, ?arg_tys_0, _, _, _)) { arg_tys = arg_tys_0; }
13511355
case (ty::ty_native_fn(_, ?arg_tys_0, _)) { arg_tys = arg_tys_0; }
13521356
case (_) {
@@ -1410,7 +1414,7 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
14101414
}
14111415
// Call the generic checker.
14121416

1413-
check_call_or_bind(fcx, sp, f, args_opt_0);
1417+
check_call_or_bind(fcx, sp, f, args_opt_0, true);
14141418
}
14151419
// A generic function for checking for or for-each loops
14161420

@@ -1806,7 +1810,7 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
18061810
case (ast::expr_bind(?f, ?args)) {
18071811
// Call the generic checker.
18081812

1809-
check_call_or_bind(fcx, expr.span, f, args);
1813+
check_call_or_bind(fcx, expr.span, f, args, false);
18101814
// Pull the argument and return types out.
18111815

18121816
auto proto_1;
@@ -1855,7 +1859,8 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
18551859
// Pull the return type out of the type of the function.
18561860

18571861
auto rt_1;
1858-
auto fty = ty::expr_ty(fcx.ccx.tcx, f);
1862+
auto fty = strip_boxes(fcx, expr.span,
1863+
ty::expr_ty(fcx.ccx.tcx, f));
18591864
alt (structure_of(fcx, expr.span, fty)) {
18601865
case (ty::ty_fn(_, _, ?rt, _, _)) { rt_1 = rt; }
18611866
case (ty::ty_native_fn(_, _, ?rt)) { rt_1 = rt; }
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// error-pattern: mismatched types
2+
3+
fn add1(int i) -> int { ret i+1; }
4+
fn main() {
5+
auto f = @add1;
6+
auto g = bind f(5);
7+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// xfail-stage0
2+
3+
fn add1(int i) -> int { ret i+1; }
4+
fn main() {
5+
auto f = @add1;
6+
auto g = @f;
7+
auto h = @@@add1;
8+
assert(f(5) == 6);
9+
assert(g(8) == 9);
10+
assert(h(0x1badd00d) == 0x1badd00e);
11+
}

0 commit comments

Comments
 (0)