@@ -1707,7 +1707,7 @@ fn compare_scalar_types(cx: @block_ctxt, lhs: ValueRef, rhs: ValueRef,
1707
1707
}
1708
1708
}
1709
1709
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" ) ;
1711
1711
1712
1712
// This is a bit lame, because we return a dummy block to the
1713
1713
// 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,
2702
2702
}
2703
2703
}
2704
2704
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 {
2707
2710
// Autoderef both sides.
2708
2711
2709
2712
let cx = cx0;
2710
- let lhs_r = autoderef ( cx, lhs0, t0 ) ;
2713
+ let lhs_r = autoderef ( cx, lhs0, lhs_t ) ;
2711
2714
let lhs = lhs_r. val ;
2712
2715
cx = lhs_r. bcx ;
2713
- let rhs_r = autoderef ( cx, rhs0, t0 ) ;
2716
+ let rhs_r = autoderef ( cx, rhs0, rhs_t ) ;
2714
2717
let rhs = rhs_r. val ;
2715
2718
cx = rhs_r. bcx ;
2716
2719
// Determine the operation we need.
@@ -2721,15 +2724,23 @@ fn trans_compare(cx0: &@block_ctxt, op: ast::binop, t0: &ty::t,
2721
2724
ast:: lt. | ast:: ge. { llop = C_u8 ( abi:: cmp_glue_op_lt) ; }
2722
2725
ast:: le. | ast:: gt. { llop = C_u8 ( abi:: cmp_glue_op_le) ; }
2723
2726
}
2724
- let rs = compare ( cx, lhs, rhs, rhs_r. ty , llop) ;
2725
2727
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) ;
2726
2731
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 ( ) ) ;
2733
2744
}
2734
2745
}
2735
2746
@@ -3372,9 +3383,16 @@ fn trans_vec_add(cx: &@block_ctxt, t: &ty::t, lhs: ValueRef, rhs: ValueRef) ->
3372
3383
ret rslt( bcx, tmp) ;
3373
3384
}
3374
3385
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 {
3377
3390
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
+
3378
3396
alt ty:: struct ( bcx_tcx ( cx) , intype) {
3379
3397
ty:: ty_float. { is_float = true ; }
3380
3398
_ { is_float = false ; }
@@ -3419,7 +3437,7 @@ fn trans_eager_binop(cx: &@block_ctxt, op: ast::binop, intype: &ty::t,
3419
3437
ast:: lsl. { ret rslt ( cx, cx. build . Shl ( lhs, rhs) ) ; }
3420
3438
ast:: lsr. { ret rslt ( cx, cx. build . LShr ( lhs, rhs) ) ; }
3421
3439
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 ) ; }
3423
3441
}
3424
3442
}
3425
3443
@@ -3525,7 +3543,8 @@ fn trans_binary(cx: &@block_ctxt, op: ast::binop, a: &@ast::expr,
3525
3543
let rhs_expr = trans_expr ( lhs. bcx , b) ;
3526
3544
let rhty = ty:: expr_ty ( bcx_tcx ( cx) , b) ;
3527
3545
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 ) ;
3529
3548
}
3530
3549
}
3531
3550
}
@@ -5206,7 +5225,8 @@ fn trans_expr_out(cx: &@block_ctxt, e: &@ast::expr, output: out_method) ->
5206
5225
}
5207
5226
}
5208
5227
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) ;
5210
5230
// FIXME: calculate copy init-ness in typestate.
5211
5231
// This is always a temporary, so can always be safely moved
5212
5232
let move_res =
0 commit comments