Make _|_ type binopable
But don't actually generate code that does the operation. That means hoisting the check I added in my last commit from trans_compare up into trans_eager_binop (don't generate any code if one operand has type _|_ ). Closes #777
This commit is contained in:
parent
44c93b5fb2
commit
7c34550931
3 changed files with 24 additions and 18 deletions
|
|
@ -2702,8 +2702,6 @@ fn trans_unary(cx: &@block_ctxt, op: ast::unop, e: &@ast::expr,
|
|||
}
|
||||
}
|
||||
|
||||
// Important to get types for both lhs and rhs, because one might be _|_
|
||||
// and the other not.
|
||||
fn trans_compare(cx0: &@block_ctxt, op: ast::binop,
|
||||
lhs0: ValueRef, lhs_t: ty::t, rhs0: ValueRef,
|
||||
rhs_t: ty::t) -> result {
|
||||
|
|
@ -2725,22 +2723,14 @@ fn trans_compare(cx0: &@block_ctxt, op: ast::binop,
|
|||
ast::le. | ast::gt. { llop = C_u8(abi::cmp_glue_op_le); }
|
||||
}
|
||||
|
||||
if (! ty::type_is_bot(bcx_tcx(cx0), rhs_r.ty) &&
|
||||
! ty::type_is_bot(bcx_tcx(cx0), lhs_r.ty)) {
|
||||
let rs = compare(cx, lhs, rhs, rhs_r.ty, llop);
|
||||
let rs = compare(cx, lhs, rhs, rhs_r.ty, llop);
|
||||
|
||||
// Invert the result if necessary.
|
||||
alt op {
|
||||
ast::eq. | ast::lt. | ast::le. { ret rslt(rs.bcx, rs.val); }
|
||||
ast::ne. | ast::ge. | ast::gt. {
|
||||
ret rslt(rs.bcx, rs.bcx.build.Not(rs.val));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If either is bottom, it diverges. So no need to do the
|
||||
// actual comparison.
|
||||
ret rslt(cx, cx.build.Unreachable());
|
||||
// Invert the result if necessary.
|
||||
alt op {
|
||||
ast::eq. | ast::lt. | ast::le. { ret rslt(rs.bcx, rs.val); }
|
||||
ast::ne. | ast::ge. | ast::gt. {
|
||||
ret rslt(rs.bcx, rs.bcx.build.Not(rs.val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3387,6 +3377,14 @@ fn trans_vec_add(cx: &@block_ctxt, t: &ty::t, lhs: ValueRef, rhs: ValueRef) ->
|
|||
// and the other not.
|
||||
fn trans_eager_binop(cx: &@block_ctxt, op: ast::binop, lhs: ValueRef,
|
||||
lhs_t: ty::t, rhs: ValueRef, rhs_t: ty::t) -> result {
|
||||
|
||||
// If either is bottom, it diverges. So no need to do the
|
||||
// operation.
|
||||
if (ty::type_is_bot(bcx_tcx(cx), lhs_t) ||
|
||||
ty::type_is_bot(bcx_tcx(cx), rhs_t)) {
|
||||
ret rslt(cx, cx.build.Unreachable());
|
||||
}
|
||||
|
||||
let is_float = false;
|
||||
let intype = lhs_t;
|
||||
if ty::type_is_bot(bcx_tcx(cx), intype) {
|
||||
|
|
|
|||
|
|
@ -2880,6 +2880,7 @@ fn is_binopable(cx: &ctxt, ty: t, op: ast::binop) -> bool {
|
|||
const tycat_str: int = 4;
|
||||
const tycat_vec: int = 5;
|
||||
const tycat_struct: int = 6;
|
||||
const tycat_bot: int = 7;
|
||||
|
||||
const opcat_add: int = 0;
|
||||
const opcat_sub: int = 1;
|
||||
|
|
@ -2938,6 +2939,7 @@ fn is_binopable(cx: &ctxt, ty: t, op: ast::binop) -> bool {
|
|||
ty_ivec(_) { tycat_vec }
|
||||
ty_rec(_) { tycat_struct }
|
||||
ty_tag(_, _) { tycat_struct }
|
||||
ty_bot. { tycat_bot }
|
||||
_ { tycat_other }
|
||||
}
|
||||
}
|
||||
|
|
@ -2954,11 +2956,13 @@ fn is_binopable(cx: &ctxt, ty: t, op: ast::binop) -> bool {
|
|||
/*float*/
|
||||
/*str*/
|
||||
/*vec*/
|
||||
/*bot*/
|
||||
tbl =
|
||||
[[f, f, f, f, t, t, f, f], [f, f, f, f, t, t, t, t],
|
||||
[t, t, t, t, t, t, t, f], [t, t, t, f, t, t, f, f],
|
||||
[t, f, f, f, t, t, f, f], [t, f, f, f, t, t, f, f],
|
||||
[f, f, f, f, t, t, f, f]]; /*struct*/
|
||||
[f, f, f, f, t, t, f, f],
|
||||
[t, t, t, t, t, t, t, t]]; /*struct*/
|
||||
|
||||
ret tbl.(tycat(cx, ty)).(opcat(op));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue