Skip to content

Commit ab78b4d

Browse files
committed
---
yaml --- r: 4358 b: refs/heads/master c: 731797d h: refs/heads/master v: v3
1 parent 19ca9bf commit ab78b4d

File tree

6 files changed

+50
-19
lines changed

6 files changed

+50
-19
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: 430a28bb495fc5702970eacbd8427d965502775e
2+
refs/heads/master: 731797d075e8bd9d0e3d21c917c3c7028278a7d4

trunk/src/comp/middle/trans.rs

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,7 +1707,7 @@ fn compare_scalar_types(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
17071707
}
17081708
}
17091709
ty::ty_type. {
1710-
trans_fail(cx, none[span], "attempt to compare values of type type");
1710+
trans_fail(cx, none, "attempt to compare values of type type");
17111711

17121712
// This is a bit lame, because we return a dummy block to the
17131713
// caller that's actually unreachable, but I don't think it
@@ -2702,15 +2702,18 @@ fn trans_unary(cx: &@block_ctxt, op: ast::unop, e: &@ast::expr,
27022702
}
27032703
}
27042704

2705-
fn trans_compare(cx0: &@block_ctxt, op: ast::binop, t0: &ty::t,
2706-
lhs0: ValueRef, rhs0: ValueRef) -> result {
2705+
// Important to get types for both lhs and rhs, because one might be _|_
2706+
// and the other not.
2707+
fn trans_compare(cx0: &@block_ctxt, op: ast::binop,
2708+
lhs0: ValueRef, lhs_t: ty::t, rhs0: ValueRef,
2709+
rhs_t: ty::t) -> result {
27072710
// Autoderef both sides.
27082711

27092712
let cx = cx0;
2710-
let lhs_r = autoderef(cx, lhs0, t0);
2713+
let lhs_r = autoderef(cx, lhs0, lhs_t);
27112714
let lhs = lhs_r.val;
27122715
cx = lhs_r.bcx;
2713-
let rhs_r = autoderef(cx, rhs0, t0);
2716+
let rhs_r = autoderef(cx, rhs0, rhs_t);
27142717
let rhs = rhs_r.val;
27152718
cx = rhs_r.bcx;
27162719
// Determine the operation we need.
@@ -2721,15 +2724,23 @@ fn trans_compare(cx0: &@block_ctxt, op: ast::binop, t0: &ty::t,
27212724
ast::lt. | ast::ge. { llop = C_u8(abi::cmp_glue_op_lt); }
27222725
ast::le. | ast::gt. { llop = C_u8(abi::cmp_glue_op_le); }
27232726
}
2724-
let rs = compare(cx, lhs, rhs, rhs_r.ty, llop);
27252727

2728+
if (! ty::type_is_bot(bcx_tcx(cx0), rhs_r.ty) &&
2729+
! ty::type_is_bot(bcx_tcx(cx0), lhs_r.ty)) {
2730+
let rs = compare(cx, lhs, rhs, rhs_r.ty, llop);
27262731

2727-
// Invert the result if necessary.
2728-
alt op {
2729-
ast::eq. | ast::lt. | ast::le. { ret rslt(rs.bcx, rs.val); }
2730-
ast::ne. | ast::ge. | ast::gt. {
2731-
ret rslt(rs.bcx, rs.bcx.build.Not(rs.val));
2732-
}
2732+
// Invert the result if necessary.
2733+
alt op {
2734+
ast::eq. | ast::lt. | ast::le. { ret rslt(rs.bcx, rs.val); }
2735+
ast::ne. | ast::ge. | ast::gt. {
2736+
ret rslt(rs.bcx, rs.bcx.build.Not(rs.val));
2737+
}
2738+
}
2739+
}
2740+
else {
2741+
// If either is bottom, it diverges. So no need to do the
2742+
// actual comparison.
2743+
ret rslt(cx, cx.build.Unreachable());
27332744
}
27342745
}
27352746

@@ -3372,9 +3383,16 @@ fn trans_vec_add(cx: &@block_ctxt, t: &ty::t, lhs: ValueRef, rhs: ValueRef) ->
33723383
ret rslt(bcx, tmp);
33733384
}
33743385

3375-
fn trans_eager_binop(cx: &@block_ctxt, op: ast::binop, intype: &ty::t,
3376-
lhs: ValueRef, rhs: ValueRef) -> result {
3386+
// Important to get types for both lhs and rhs, because one might be _|_
3387+
// and the other not.
3388+
fn trans_eager_binop(cx: &@block_ctxt, op: ast::binop, lhs: ValueRef,
3389+
lhs_t: ty::t, rhs: ValueRef, rhs_t: ty::t) -> result {
33773390
let is_float = false;
3391+
let intype = lhs_t;
3392+
if ty::type_is_bot(bcx_tcx(cx), intype) {
3393+
intype = rhs_t;
3394+
}
3395+
33783396
alt ty::struct(bcx_tcx(cx), intype) {
33793397
ty::ty_float. { is_float = true; }
33803398
_ { is_float = false; }
@@ -3419,7 +3437,7 @@ fn trans_eager_binop(cx: &@block_ctxt, op: ast::binop, intype: &ty::t,
34193437
ast::lsl. { ret rslt(cx, cx.build.Shl(lhs, rhs)); }
34203438
ast::lsr. { ret rslt(cx, cx.build.LShr(lhs, rhs)); }
34213439
ast::asr. { ret rslt(cx, cx.build.AShr(lhs, rhs)); }
3422-
_ { ret trans_compare(cx, op, intype, lhs, rhs); }
3440+
_ { ret trans_compare(cx, op, lhs, lhs_t, rhs, rhs_t); }
34233441
}
34243442
}
34253443

@@ -3525,7 +3543,8 @@ fn trans_binary(cx: &@block_ctxt, op: ast::binop, a: &@ast::expr,
35253543
let rhs_expr = trans_expr(lhs.bcx, b);
35263544
let rhty = ty::expr_ty(bcx_tcx(cx), b);
35273545
let rhs = autoderef(rhs_expr.bcx, rhs_expr.val, rhty);
3528-
ret trans_eager_binop(rhs.bcx, op, lhs.ty, lhs.val, rhs.val);
3546+
3547+
ret trans_eager_binop(rhs.bcx, op, lhs.val, lhs.ty, rhs.val, rhs.ty);
35293548
}
35303549
}
35313550
}
@@ -5206,7 +5225,8 @@ fn trans_expr_out(cx: &@block_ctxt, e: &@ast::expr, output: out_method) ->
52065225
}
52075226
}
52085227
let lhs_val = load_if_immediate(rhs_res.bcx, lhs_res.res.val, t);
5209-
let v = trans_eager_binop(rhs_res.bcx, op, t, lhs_val, rhs_res.val);
5228+
let v = trans_eager_binop(rhs_res.bcx, op, lhs_val, t,
5229+
rhs_res.val, t);
52105230
// FIXME: calculate copy init-ness in typestate.
52115231
// This is always a temporary, so can always be safely moved
52125232
let move_res =

trunk/src/comp/middle/trans_alt.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,8 @@ fn compile_submatch(bcx: @block_ctxt, m: &match, vals: ValueRef[],
360360
let r = trans_opt(bcx, opt);
361361
bcx = r.bcx;
362362
let t = ty::node_id_to_type(ccx.tcx, pat_id);
363-
let eq = trans::trans_compare(bcx, ast::eq, t, test_val, r.val);
363+
let eq = trans::trans_compare(bcx, ast::eq, test_val, t,
364+
r.val, t);
364365
bcx = new_sub_block_ctxt(bcx, "next");
365366
eq.bcx.build.CondBr(eq.val, opt_cx.llbb, bcx.llbb);
366367
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// error-pattern:quux
2+
fn my_err(s: str) -> ! { log_err s; fail "quux"; }
3+
fn main() { 3u == my_err("bye"); }

trunk/src/test/run-fail/binop-fail.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// error-pattern:quux
2+
fn my_err(s: str) -> ! { log_err s; fail "quux"; }
3+
fn main() { my_err("bye") == 3u; }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn wsucc(n: int) -> int {
2+
{ ret n + 1 } == 0;
3+
}
4+
fn main() {}

0 commit comments

Comments
 (0)