Skip to content

Commit 0340f32

Browse files
committed
Eliminate autoderef on binops and unary negation.
Autoderef on binops is basically unused, kind of silly, and complicates typechecking. There were only three instances of it in the compiler and the test drivers, two of which were of the form "*foo = foo + 1", which should be written as "*foo += 1" anyways.
1 parent e527140 commit 0340f32

File tree

3 files changed

+47
-104
lines changed

3 files changed

+47
-104
lines changed

src/comp/middle/trans.rs

Lines changed: 17 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,15 +2497,13 @@ fn trans_unary(cx: &@block_ctxt, op: ast::unop, e: &@ast::expr,
24972497
alt op {
24982498
ast::not. {
24992499
let sub = trans_expr(cx, e);
2500-
let dr = autoderef(sub.bcx, sub.val, ty::expr_ty(bcx_tcx(cx), e));
2501-
ret rslt(dr.bcx, dr.bcx.build.Not(dr.val));
2500+
ret rslt(sub.bcx, sub.bcx.build.Not(sub.val));
25022501
}
25032502
ast::neg. {
25042503
let sub = trans_expr(cx, e);
2505-
let dr = autoderef(sub.bcx, sub.val, ty::expr_ty(bcx_tcx(cx), e));
25062504
if ty::struct(bcx_tcx(cx), e_ty) == ty::ty_float {
2507-
ret rslt(dr.bcx, dr.bcx.build.FNeg(dr.val));
2508-
} else { ret rslt(dr.bcx, sub.bcx.build.Neg(dr.val)); }
2505+
ret rslt(sub.bcx, sub.bcx.build.FNeg(sub.val));
2506+
} else { ret rslt(sub.bcx, sub.bcx.build.Neg(sub.val)); }
25092507
}
25102508
ast::box(_) {
25112509
let lv = trans_lval(cx, e);
@@ -2532,28 +2530,18 @@ fn trans_unary(cx: &@block_ctxt, op: ast::unop, e: &@ast::expr,
25322530
}
25332531
}
25342532

2535-
fn trans_compare(cx0: &@block_ctxt, op: ast::binop,
2536-
lhs0: ValueRef, lhs_t: ty::t, rhs0: ValueRef,
2537-
rhs_t: ty::t) -> result {
2538-
// Autoderef both sides.
2539-
2540-
let cx = cx0;
2541-
let lhs_r = autoderef(cx, lhs0, lhs_t);
2542-
let lhs = lhs_r.val;
2543-
cx = lhs_r.bcx;
2544-
let rhs_r = autoderef(cx, rhs0, rhs_t);
2545-
let rhs = rhs_r.val;
2546-
cx = rhs_r.bcx;
2533+
fn trans_compare(cx: &@block_ctxt, op: ast::binop,
2534+
lhs: ValueRef, lhs_t: ty::t, rhs: ValueRef,
2535+
rhs_t: ty::t) -> result {
25472536
// Determine the operation we need.
2548-
25492537
let llop;
25502538
alt op {
25512539
ast::eq. | ast::ne. { llop = C_u8(abi::cmp_glue_op_eq); }
25522540
ast::lt. | ast::ge. { llop = C_u8(abi::cmp_glue_op_lt); }
25532541
ast::le. | ast::gt. { llop = C_u8(abi::cmp_glue_op_le); }
25542542
}
25552543

2556-
let rs = compare(cx, lhs, rhs, rhs_r.ty, llop);
2544+
let rs = compare(cx, lhs, rhs, rhs_t, llop);
25572545

25582546
// Invert the result if necessary.
25592547
alt op {
@@ -3320,15 +3308,10 @@ fn trans_binary(cx: &@block_ctxt, op: ast::binop, a: &@ast::expr,
33203308
alt op {
33213309
ast::and. {
33223310
// Lazy-eval and
3323-
let lhs_expr = trans_expr(cx, a);
3324-
let lhs_res =
3325-
autoderef(lhs_expr.bcx, lhs_expr.val,
3326-
ty::expr_ty(bcx_tcx(cx), a));
3311+
let lhs_res = trans_expr(cx, a);
33273312
let rhs_cx = new_scope_block_ctxt(cx, "rhs");
3328-
let rhs_expr = trans_expr(rhs_cx, b);
3329-
let rhs_res =
3330-
autoderef(rhs_expr.bcx, rhs_expr.val,
3331-
ty::expr_ty(bcx_tcx(cx), b));
3313+
let rhs_res = trans_expr(rhs_cx, b);
3314+
33323315
let lhs_false_cx = new_scope_block_ctxt(cx, "lhs false");
33333316
let lhs_false_res = rslt(lhs_false_cx, C_bool(false));
33343317

@@ -3343,15 +3326,9 @@ fn trans_binary(cx: &@block_ctxt, op: ast::binop, a: &@ast::expr,
33433326
}
33443327
ast::or. {
33453328
// Lazy-eval or
3346-
let lhs_expr = trans_expr(cx, a);
3347-
let lhs_res =
3348-
autoderef(lhs_expr.bcx, lhs_expr.val,
3349-
ty::expr_ty(bcx_tcx(cx), a));
3329+
let lhs_res = trans_expr(cx, a);
33503330
let rhs_cx = new_scope_block_ctxt(cx, "rhs");
3351-
let rhs_expr = trans_expr(rhs_cx, b);
3352-
let rhs_res =
3353-
autoderef(rhs_expr.bcx, rhs_expr.val,
3354-
ty::expr_ty(bcx_tcx(cx), b));
3331+
let rhs_res = trans_expr(rhs_cx, b);
33553332
let lhs_true_cx = new_scope_block_ctxt(cx, "lhs true");
33563333
let lhs_true_res = rslt(lhs_true_cx, C_bool(true));
33573334

@@ -3363,15 +3340,12 @@ fn trans_binary(cx: &@block_ctxt, op: ast::binop, a: &@ast::expr,
33633340
}
33643341
_ {
33653342
// Remaining cases are eager:
3343+
let lhs = trans_expr(cx, a);
3344+
let rhs = trans_expr(lhs.bcx, b);
33663345

3367-
let lhs_expr = trans_expr(cx, a);
3368-
let lhty = ty::expr_ty(bcx_tcx(cx), a);
3369-
let lhs = autoderef(lhs_expr.bcx, lhs_expr.val, lhty);
3370-
let rhs_expr = trans_expr(lhs.bcx, b);
3371-
let rhty = ty::expr_ty(bcx_tcx(cx), b);
3372-
let rhs = autoderef(rhs_expr.bcx, rhs_expr.val, rhty);
3373-
3374-
ret trans_eager_binop(rhs.bcx, op, lhs.val, lhs.ty, rhs.val, rhs.ty);
3346+
ret trans_eager_binop(rhs.bcx, op,
3347+
lhs.val, ty::expr_ty(bcx_tcx(cx), a),
3348+
rhs.val, ty::expr_ty(bcx_tcx(cx), b));
33753349
}
33763350
}
33773351
}

src/comp/middle/typeck.rs

Lines changed: 28 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,6 @@ mod unify {
890890
}
891891
}
892892

893-
tag autoderef_kind { AUTODEREF_OK; NO_AUTODEREF; AUTODEREF_BLOCK_COERCE; }
894893

895894
// FIXME This is almost a duplicate of ty::type_autoderef, with structure_of
896895
// instead of ty::struct.
@@ -929,27 +928,8 @@ fn do_autoderef(fcx: &@fn_ctxt, sp: &span, t: &ty::t) -> ty::t {
929928
fail;
930929
}
931930

932-
fn add_boxes(ccx: &@crate_ctxt, n: uint, t: &ty::t) -> ty::t {
933-
let t1 = t;
934-
while n != 0u { t1 = ty::mk_imm_box(ccx.tcx, t1); n -= 1u; }
935-
ret t1;
936-
}
937-
938-
fn count_boxes(fcx: &@fn_ctxt, sp: &span, t: &ty::t) -> uint {
939-
let n = 0u;
940-
let t1 = t;
941-
while true {
942-
alt structure_of(fcx, sp, t1) {
943-
ty::ty_box(inner) { n += 1u; t1 = inner.ty; }
944-
_ { ret n; }
945-
}
946-
}
947-
fail;
948-
}
949-
950931
fn do_fn_block_coerce(fcx: &@fn_ctxt, sp: &span, actual: &ty::t,
951932
expected: &ty::t) -> ty::t {
952-
953933
// fns can be silently coerced to blocks when being used as
954934
// function call or bind arguments, but not the reverse.
955935
// If our actual type is a fn and our expected type is a block,
@@ -986,27 +966,26 @@ type ty_param_substs_and_ty = {substs: [ty::t], ty: ty::t};
986966
mod demand {
987967
fn simple(fcx: &@fn_ctxt, sp: &span, expected: &ty::t, actual: &ty::t) ->
988968
ty::t {
989-
ret full(fcx, sp, expected, actual, ~[], NO_AUTODEREF).ty;
969+
full(fcx, sp, expected, actual, ~[], false).ty
970+
}
971+
fn block_coerce(fcx: &@fn_ctxt, sp: &span,
972+
expected: &ty::t, actual: &ty::t) -> ty::t {
973+
full(fcx, sp, expected, actual, ~[], true).ty
990974
}
991-
fn autoderef(fcx: &@fn_ctxt, sp: &span, expected: &ty::t, actual: &ty::t,
992-
adk: autoderef_kind) -> ty::t {
993-
ret full(fcx, sp, expected, actual, ~[], adk).ty;
975+
976+
fn with_substs(fcx: &@fn_ctxt, sp: &span, expected: &ty::t,
977+
actual: &ty::t, ty_param_substs_0: &[ty::t]) ->
978+
ty_param_substs_and_ty {
979+
full(fcx, sp, expected, actual, ty_param_substs_0, false)
994980
}
995981

996982
// Requires that the two types unify, and prints an error message if they
997983
// don't. Returns the unified type and the type parameter substitutions.
998-
fn full(fcx: &@fn_ctxt, sp: &span, expected: &ty::t, actual: &ty::t,
999-
ty_param_substs_0: &[ty::t], adk: autoderef_kind) ->
984+
fn full(fcx: &@fn_ctxt, sp: &span, expected: ty::t, actual: ty::t,
985+
ty_param_substs_0: &[ty::t], do_block_coerece: bool) ->
1000986
ty_param_substs_and_ty {
1001-
let expected_1 = expected;
1002-
let actual_1 = actual;
1003-
let implicit_boxes = 0u;
1004-
if adk == AUTODEREF_OK {
1005-
expected_1 = do_autoderef(fcx, sp, expected_1);
1006-
actual_1 = do_autoderef(fcx, sp, actual_1);
1007-
implicit_boxes = count_boxes(fcx, sp, actual);
1008-
} else if (adk == AUTODEREF_BLOCK_COERCE) {
1009-
actual_1 = do_fn_block_coerce(fcx, sp, actual, expected);
987+
if do_block_coerece {
988+
actual = do_fn_block_coerce(fcx, sp, actual, expected);
1010989
}
1011990

1012991
let ty_param_substs: [mutable ty::t] = ~[mutable];
@@ -1021,33 +1000,31 @@ mod demand {
10211000
}
10221001

10231002
fn mk_result(fcx: &@fn_ctxt, result_ty: &ty::t,
1024-
ty_param_subst_var_ids: &[int], implicit_boxes: uint) ->
1003+
ty_param_subst_var_ids: &[int]) ->
10251004
ty_param_substs_and_ty {
10261005
let result_ty_param_substs: [ty::t] = ~[];
10271006
for var_id: int in ty_param_subst_var_ids {
10281007
let tp_subst = ty::mk_var(fcx.ccx.tcx, var_id);
10291008
result_ty_param_substs += ~[tp_subst];
10301009
}
1031-
ret {substs: result_ty_param_substs,
1032-
ty: add_boxes(fcx.ccx, implicit_boxes, result_ty)};
1010+
ret {substs: result_ty_param_substs, ty: result_ty};
10331011
}
10341012

10351013

1036-
alt unify::unify(fcx, expected_1, actual_1) {
1014+
alt unify::unify(fcx, expected, actual) {
10371015
ures_ok(t) {
1038-
ret mk_result(fcx, t, ty_param_subst_var_ids, implicit_boxes);
1016+
ret mk_result(fcx, t, ty_param_subst_var_ids);
10391017
}
10401018
ures_err(err) {
1041-
let e_err = resolve_type_vars_if_possible(fcx, expected_1);
1042-
let a_err = resolve_type_vars_if_possible(fcx, actual_1);
1019+
let e_err = resolve_type_vars_if_possible(fcx, expected);
1020+
let a_err = resolve_type_vars_if_possible(fcx, actual);
10431021
fcx.ccx.tcx.sess.span_err(sp,
10441022
"mismatched types: expected " +
10451023
ty_to_str(fcx.ccx.tcx, e_err) +
10461024
" but found " +
10471025
ty_to_str(fcx.ccx.tcx, a_err) + " ("
10481026
+ ty::type_err_to_str(err) + ")");
1049-
ret mk_result(fcx, expected_1, ty_param_subst_var_ids,
1050-
implicit_boxes);
1027+
ret mk_result(fcx, expected, ty_param_subst_var_ids);
10511028
}
10521029
}
10531030
}
@@ -1379,8 +1356,8 @@ fn check_pat(fcx: &@fn_ctxt, map: &ast::pat_id_map, pat: &@ast::pat,
13791356
path_tpot);
13801357

13811358
let path_tpt =
1382-
demand::full(fcx, pat.span, expected, ctor_ty, expected_tps,
1383-
NO_AUTODEREF);
1359+
demand::with_substs(fcx, pat.span, expected, ctor_ty,
1360+
expected_tps);
13841361
path_tpot =
13851362
{substs: some[[ty::t]](path_tpt.substs), ty: path_tpt.ty};
13861363

@@ -1604,13 +1581,11 @@ fn check_expr_with_unifier(fcx: &@fn_ctxt, expr: &@ast::expr,
16041581
}
16051582

16061583
// Check the arguments.
1607-
let unifier =
1608-
bind demand::autoderef(_, _, _, _, AUTODEREF_BLOCK_COERCE);
16091584
let i = 0u;
16101585
for a_opt: option::t[@ast::expr] in args {
16111586
alt a_opt {
16121587
some(a) {
1613-
bot |= check_expr_with_unifier(fcx, a, unifier,
1588+
bot |= check_expr_with_unifier(fcx, a, demand::block_coerce,
16141589
arg_tys.(i).ty);
16151590
}
16161591
none. { }
@@ -1776,12 +1751,10 @@ fn check_expr_with_unifier(fcx: &@fn_ctxt, expr: &@ast::expr,
17761751
let lhs_t = next_ty_var(fcx);
17771752
bot = check_expr_with(fcx, lhs, lhs_t);
17781753

1779-
let unifier = bind demand::autoderef(_, _, _, _, AUTODEREF_OK);
1780-
let rhs_bot = check_expr_with_unifier(fcx, rhs, unifier, lhs_t);
1754+
let rhs_bot = check_expr_with(fcx, rhs, lhs_t);
17811755
if !ast::lazy_binop(binop) { bot |= rhs_bot; }
17821756

1783-
let deref_t = do_autoderef(fcx, expr.span, lhs_t);
1784-
check_binop_type_compat(fcx, expr.span, deref_t, binop);
1757+
check_binop_type_compat(fcx, expr.span, lhs_t, binop);
17851758

17861759
let t =
17871760
alt binop {
@@ -1791,7 +1764,7 @@ fn check_expr_with_unifier(fcx: &@fn_ctxt, expr: &@ast::expr,
17911764
ast::ne. { ty::mk_bool(tcx) }
17921765
ast::ge. { ty::mk_bool(tcx) }
17931766
ast::gt. { ty::mk_bool(tcx) }
1794-
_ { deref_t }
1767+
_ { lhs_t }
17951768
};
17961769
write::ty_only_fixup(fcx, id, t);
17971770
}
@@ -1838,8 +1811,7 @@ fn check_expr_with_unifier(fcx: &@fn_ctxt, expr: &@ast::expr,
18381811
}
18391812
}
18401813
ast::neg. {
1841-
oper_t = structurally_resolved_type
1842-
(fcx, oper.span, do_autoderef(fcx, expr.span, oper_t));
1814+
oper_t = structurally_resolved_type(fcx, oper.span, oper_t);
18431815
if !(ty::type_is_integral(tcx, oper_t) ||
18441816
ty::type_is_fp(tcx, oper_t)) {
18451817
tcx.sess.span_fatal(expr.span, "applying unary minus to \

src/test/run-pass/autoderef-full-lval.rs renamed to src/test/compile-fail/autoderef-full-lval.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
2-
3-
4-
// -*- rust -*-
1+
// error-pattern: binary operation + cannot be applied to type
52
type clam = {x: @int, y: @int};
63

74
type fish = {a: @int};
@@ -17,4 +14,4 @@ fn main() {
1714
let answer: int = forty.a + two.a;
1815
log answer;
1916
assert (answer == 42);
20-
}
17+
}

0 commit comments

Comments
 (0)