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.
This commit is contained in:
Michael Sullivan 2011-08-12 16:33:53 -07:00
parent e527140548
commit 0340f32748
3 changed files with 47 additions and 104 deletions

View file

@ -2497,15 +2497,13 @@ fn trans_unary(cx: &@block_ctxt, op: ast::unop, e: &@ast::expr,
alt op {
ast::not. {
let sub = trans_expr(cx, e);
let dr = autoderef(sub.bcx, sub.val, ty::expr_ty(bcx_tcx(cx), e));
ret rslt(dr.bcx, dr.bcx.build.Not(dr.val));
ret rslt(sub.bcx, sub.bcx.build.Not(sub.val));
}
ast::neg. {
let sub = trans_expr(cx, e);
let dr = autoderef(sub.bcx, sub.val, ty::expr_ty(bcx_tcx(cx), e));
if ty::struct(bcx_tcx(cx), e_ty) == ty::ty_float {
ret rslt(dr.bcx, dr.bcx.build.FNeg(dr.val));
} else { ret rslt(dr.bcx, sub.bcx.build.Neg(dr.val)); }
ret rslt(sub.bcx, sub.bcx.build.FNeg(sub.val));
} else { ret rslt(sub.bcx, sub.bcx.build.Neg(sub.val)); }
}
ast::box(_) {
let lv = trans_lval(cx, e);
@ -2532,20 +2530,10 @@ fn trans_unary(cx: &@block_ctxt, op: ast::unop, e: &@ast::expr,
}
}
fn trans_compare(cx0: &@block_ctxt, op: ast::binop,
lhs0: ValueRef, lhs_t: ty::t, rhs0: ValueRef,
rhs_t: ty::t) -> result {
// Autoderef both sides.
let cx = cx0;
let lhs_r = autoderef(cx, lhs0, lhs_t);
let lhs = lhs_r.val;
cx = lhs_r.bcx;
let rhs_r = autoderef(cx, rhs0, rhs_t);
let rhs = rhs_r.val;
cx = rhs_r.bcx;
fn trans_compare(cx: &@block_ctxt, op: ast::binop,
lhs: ValueRef, lhs_t: ty::t, rhs: ValueRef,
rhs_t: ty::t) -> result {
// Determine the operation we need.
let llop;
alt op {
ast::eq. | ast::ne. { llop = C_u8(abi::cmp_glue_op_eq); }
@ -2553,7 +2541,7 @@ fn trans_compare(cx0: &@block_ctxt, op: ast::binop,
ast::le. | ast::gt. { llop = C_u8(abi::cmp_glue_op_le); }
}
let rs = compare(cx, lhs, rhs, rhs_r.ty, llop);
let rs = compare(cx, lhs, rhs, rhs_t, llop);
// Invert the result if necessary.
alt op {
@ -3320,15 +3308,10 @@ fn trans_binary(cx: &@block_ctxt, op: ast::binop, a: &@ast::expr,
alt op {
ast::and. {
// Lazy-eval and
let lhs_expr = trans_expr(cx, a);
let lhs_res =
autoderef(lhs_expr.bcx, lhs_expr.val,
ty::expr_ty(bcx_tcx(cx), a));
let lhs_res = trans_expr(cx, a);
let rhs_cx = new_scope_block_ctxt(cx, "rhs");
let rhs_expr = trans_expr(rhs_cx, b);
let rhs_res =
autoderef(rhs_expr.bcx, rhs_expr.val,
ty::expr_ty(bcx_tcx(cx), b));
let rhs_res = trans_expr(rhs_cx, b);
let lhs_false_cx = new_scope_block_ctxt(cx, "lhs false");
let lhs_false_res = rslt(lhs_false_cx, C_bool(false));
@ -3343,15 +3326,9 @@ fn trans_binary(cx: &@block_ctxt, op: ast::binop, a: &@ast::expr,
}
ast::or. {
// Lazy-eval or
let lhs_expr = trans_expr(cx, a);
let lhs_res =
autoderef(lhs_expr.bcx, lhs_expr.val,
ty::expr_ty(bcx_tcx(cx), a));
let lhs_res = trans_expr(cx, a);
let rhs_cx = new_scope_block_ctxt(cx, "rhs");
let rhs_expr = trans_expr(rhs_cx, b);
let rhs_res =
autoderef(rhs_expr.bcx, rhs_expr.val,
ty::expr_ty(bcx_tcx(cx), b));
let rhs_res = trans_expr(rhs_cx, b);
let lhs_true_cx = new_scope_block_ctxt(cx, "lhs true");
let lhs_true_res = rslt(lhs_true_cx, C_bool(true));
@ -3363,15 +3340,12 @@ fn trans_binary(cx: &@block_ctxt, op: ast::binop, a: &@ast::expr,
}
_ {
// Remaining cases are eager:
let lhs = trans_expr(cx, a);
let rhs = trans_expr(lhs.bcx, b);
let lhs_expr = trans_expr(cx, a);
let lhty = ty::expr_ty(bcx_tcx(cx), a);
let lhs = autoderef(lhs_expr.bcx, lhs_expr.val, lhty);
let rhs_expr = trans_expr(lhs.bcx, b);
let rhty = ty::expr_ty(bcx_tcx(cx), b);
let rhs = autoderef(rhs_expr.bcx, rhs_expr.val, rhty);
ret trans_eager_binop(rhs.bcx, op, lhs.val, lhs.ty, rhs.val, rhs.ty);
ret trans_eager_binop(rhs.bcx, op,
lhs.val, ty::expr_ty(bcx_tcx(cx), a),
rhs.val, ty::expr_ty(bcx_tcx(cx), b));
}
}
}

View file

@ -890,7 +890,6 @@ mod unify {
}
}
tag autoderef_kind { AUTODEREF_OK; NO_AUTODEREF; AUTODEREF_BLOCK_COERCE; }
// FIXME This is almost a duplicate of ty::type_autoderef, with structure_of
// instead of ty::struct.
@ -929,27 +928,8 @@ fn do_autoderef(fcx: &@fn_ctxt, sp: &span, t: &ty::t) -> ty::t {
fail;
}
fn add_boxes(ccx: &@crate_ctxt, n: uint, t: &ty::t) -> ty::t {
let t1 = t;
while n != 0u { t1 = ty::mk_imm_box(ccx.tcx, t1); n -= 1u; }
ret t1;
}
fn count_boxes(fcx: &@fn_ctxt, sp: &span, t: &ty::t) -> uint {
let n = 0u;
let t1 = t;
while true {
alt structure_of(fcx, sp, t1) {
ty::ty_box(inner) { n += 1u; t1 = inner.ty; }
_ { ret n; }
}
}
fail;
}
fn do_fn_block_coerce(fcx: &@fn_ctxt, sp: &span, actual: &ty::t,
expected: &ty::t) -> ty::t {
// fns can be silently coerced to blocks when being used as
// function call or bind arguments, but not the reverse.
// 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};
mod demand {
fn simple(fcx: &@fn_ctxt, sp: &span, expected: &ty::t, actual: &ty::t) ->
ty::t {
ret full(fcx, sp, expected, actual, ~[], NO_AUTODEREF).ty;
full(fcx, sp, expected, actual, ~[], false).ty
}
fn autoderef(fcx: &@fn_ctxt, sp: &span, expected: &ty::t, actual: &ty::t,
adk: autoderef_kind) -> ty::t {
ret full(fcx, sp, expected, actual, ~[], adk).ty;
fn block_coerce(fcx: &@fn_ctxt, sp: &span,
expected: &ty::t, actual: &ty::t) -> ty::t {
full(fcx, sp, expected, actual, ~[], true).ty
}
fn with_substs(fcx: &@fn_ctxt, sp: &span, expected: &ty::t,
actual: &ty::t, ty_param_substs_0: &[ty::t]) ->
ty_param_substs_and_ty {
full(fcx, sp, expected, actual, ty_param_substs_0, false)
}
// Requires that the two types unify, and prints an error message if they
// don't. Returns the unified type and the type parameter substitutions.
fn full(fcx: &@fn_ctxt, sp: &span, expected: &ty::t, actual: &ty::t,
ty_param_substs_0: &[ty::t], adk: autoderef_kind) ->
fn full(fcx: &@fn_ctxt, sp: &span, expected: ty::t, actual: ty::t,
ty_param_substs_0: &[ty::t], do_block_coerece: bool) ->
ty_param_substs_and_ty {
let expected_1 = expected;
let actual_1 = actual;
let implicit_boxes = 0u;
if adk == AUTODEREF_OK {
expected_1 = do_autoderef(fcx, sp, expected_1);
actual_1 = do_autoderef(fcx, sp, actual_1);
implicit_boxes = count_boxes(fcx, sp, actual);
} else if (adk == AUTODEREF_BLOCK_COERCE) {
actual_1 = do_fn_block_coerce(fcx, sp, actual, expected);
if do_block_coerece {
actual = do_fn_block_coerce(fcx, sp, actual, expected);
}
let ty_param_substs: [mutable ty::t] = ~[mutable];
@ -1021,33 +1000,31 @@ mod demand {
}
fn mk_result(fcx: &@fn_ctxt, result_ty: &ty::t,
ty_param_subst_var_ids: &[int], implicit_boxes: uint) ->
ty_param_subst_var_ids: &[int]) ->
ty_param_substs_and_ty {
let result_ty_param_substs: [ty::t] = ~[];
for var_id: int in ty_param_subst_var_ids {
let tp_subst = ty::mk_var(fcx.ccx.tcx, var_id);
result_ty_param_substs += ~[tp_subst];
}
ret {substs: result_ty_param_substs,
ty: add_boxes(fcx.ccx, implicit_boxes, result_ty)};
ret {substs: result_ty_param_substs, ty: result_ty};
}
alt unify::unify(fcx, expected_1, actual_1) {
alt unify::unify(fcx, expected, actual) {
ures_ok(t) {
ret mk_result(fcx, t, ty_param_subst_var_ids, implicit_boxes);
ret mk_result(fcx, t, ty_param_subst_var_ids);
}
ures_err(err) {
let e_err = resolve_type_vars_if_possible(fcx, expected_1);
let a_err = resolve_type_vars_if_possible(fcx, actual_1);
let e_err = resolve_type_vars_if_possible(fcx, expected);
let a_err = resolve_type_vars_if_possible(fcx, actual);
fcx.ccx.tcx.sess.span_err(sp,
"mismatched types: expected " +
ty_to_str(fcx.ccx.tcx, e_err) +
" but found " +
ty_to_str(fcx.ccx.tcx, a_err) + " ("
+ ty::type_err_to_str(err) + ")");
ret mk_result(fcx, expected_1, ty_param_subst_var_ids,
implicit_boxes);
ret mk_result(fcx, expected, ty_param_subst_var_ids);
}
}
}
@ -1379,8 +1356,8 @@ fn check_pat(fcx: &@fn_ctxt, map: &ast::pat_id_map, pat: &@ast::pat,
path_tpot);
let path_tpt =
demand::full(fcx, pat.span, expected, ctor_ty, expected_tps,
NO_AUTODEREF);
demand::with_substs(fcx, pat.span, expected, ctor_ty,
expected_tps);
path_tpot =
{substs: some[[ty::t]](path_tpt.substs), ty: path_tpt.ty};
@ -1604,13 +1581,11 @@ fn check_expr_with_unifier(fcx: &@fn_ctxt, expr: &@ast::expr,
}
// Check the arguments.
let unifier =
bind demand::autoderef(_, _, _, _, AUTODEREF_BLOCK_COERCE);
let i = 0u;
for a_opt: option::t[@ast::expr] in args {
alt a_opt {
some(a) {
bot |= check_expr_with_unifier(fcx, a, unifier,
bot |= check_expr_with_unifier(fcx, a, demand::block_coerce,
arg_tys.(i).ty);
}
none. { }
@ -1776,12 +1751,10 @@ fn check_expr_with_unifier(fcx: &@fn_ctxt, expr: &@ast::expr,
let lhs_t = next_ty_var(fcx);
bot = check_expr_with(fcx, lhs, lhs_t);
let unifier = bind demand::autoderef(_, _, _, _, AUTODEREF_OK);
let rhs_bot = check_expr_with_unifier(fcx, rhs, unifier, lhs_t);
let rhs_bot = check_expr_with(fcx, rhs, lhs_t);
if !ast::lazy_binop(binop) { bot |= rhs_bot; }
let deref_t = do_autoderef(fcx, expr.span, lhs_t);
check_binop_type_compat(fcx, expr.span, deref_t, binop);
check_binop_type_compat(fcx, expr.span, lhs_t, binop);
let t =
alt binop {
@ -1791,7 +1764,7 @@ fn check_expr_with_unifier(fcx: &@fn_ctxt, expr: &@ast::expr,
ast::ne. { ty::mk_bool(tcx) }
ast::ge. { ty::mk_bool(tcx) }
ast::gt. { ty::mk_bool(tcx) }
_ { deref_t }
_ { lhs_t }
};
write::ty_only_fixup(fcx, id, t);
}
@ -1838,8 +1811,7 @@ fn check_expr_with_unifier(fcx: &@fn_ctxt, expr: &@ast::expr,
}
}
ast::neg. {
oper_t = structurally_resolved_type
(fcx, oper.span, do_autoderef(fcx, expr.span, oper_t));
oper_t = structurally_resolved_type(fcx, oper.span, oper_t);
if !(ty::type_is_integral(tcx, oper_t) ||
ty::type_is_fp(tcx, oper_t)) {
tcx.sess.span_fatal(expr.span, "applying unary minus to \

View file

@ -1,7 +1,4 @@
// -*- rust -*-
// error-pattern: binary operation + cannot be applied to type
type clam = {x: @int, y: @int};
type fish = {a: @int};
@ -17,4 +14,4 @@ fn main() {
let answer: int = forty.a + two.a;
log answer;
assert (answer == 42);
}
}