1212
1313use std;
1414
15+ use rustc_const_math:: { ConstMathErr , Op } ;
1516use rustc_data_structures:: fnv:: FnvHashMap ;
1617
1718use build:: { BlockAnd , BlockAndExtension , Builder } ;
@@ -88,10 +89,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
8889 this. cfg . push_assign ( block, scope_id, expr_span, & is_min,
8990 Rvalue :: BinaryOp ( BinOp :: Eq , arg. clone ( ) , minval) ) ;
9091
91- let ( of_block, ok_block) = this. build_cond_br ( block, expr_span,
92- Operand :: Consume ( is_min) ) ;
93- this. panic ( of_block, "attempted to negate with overflow" , expr_span) ;
94- block = ok_block;
92+ let err = ConstMathErr :: Overflow ( Op :: Neg ) ;
93+ block = this. assert ( block, Operand :: Consume ( is_min) , false ,
94+ AssertMessage :: Math ( err) , expr_span) ;
9595 }
9696 block. and ( Rvalue :: UnaryOp ( op, arg) )
9797 }
@@ -261,27 +261,32 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
261261 let val = result_value. clone ( ) . field ( val_fld, ty) ;
262262 let of = result_value. field ( of_fld, bool_ty) ;
263263
264- let msg = if op == BinOp :: Shl || op == BinOp :: Shr {
265- "shift operation overflowed"
266- } else {
267- "arithmetic operation overflowed"
268- } ;
264+ let err = ConstMathErr :: Overflow ( match op {
265+ BinOp :: Add => Op :: Add ,
266+ BinOp :: Sub => Op :: Sub ,
267+ BinOp :: Mul => Op :: Mul ,
268+ BinOp :: Shl => Op :: Shl ,
269+ BinOp :: Shr => Op :: Shr ,
270+ _ => {
271+ bug ! ( "MIR build_binary_op: {:?} is not checkable" , op)
272+ }
273+ } ) ;
269274
270- let ( of_block , ok_block ) = self . build_cond_br ( block, span , Operand :: Consume ( of) ) ;
271- self . panic ( of_block , msg , span) ;
275+ block = self . assert ( block, Operand :: Consume ( of) , false ,
276+ AssertMessage :: Math ( err ) , span) ;
272277
273- ok_block . and ( Rvalue :: Use ( Operand :: Consume ( val) ) )
278+ block . and ( Rvalue :: Use ( Operand :: Consume ( val) ) )
274279 } else {
275280 if ty. is_integral ( ) && ( op == BinOp :: Div || op == BinOp :: Rem ) {
276281 // Checking division and remainder is more complex, since we 1. always check
277282 // and 2. there are two possible failure cases, divide-by-zero and overflow.
278283
279- let ( zero_msg , overflow_msg ) = if op == BinOp :: Div {
280- ( "attempted to divide by zero" ,
281- "attempted to divide with overflow" )
284+ let ( zero_err , overflow_err ) = if op == BinOp :: Div {
285+ ( ConstMathErr :: DivisionByZero ,
286+ ConstMathErr :: Overflow ( Op :: Div ) )
282287 } else {
283- ( "attempted remainder with a divisor of zero" ,
284- "attempted remainder with overflow" )
288+ ( ConstMathErr :: RemainderByZero ,
289+ ConstMathErr :: Overflow ( Op :: Rem ) )
285290 } ;
286291
287292 // Check for / 0
@@ -290,11 +295,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
290295 self . cfg . push_assign ( block, scope_id, span, & is_zero,
291296 Rvalue :: BinaryOp ( BinOp :: Eq , rhs. clone ( ) , zero) ) ;
292297
293- let ( zero_block, ok_block) = self . build_cond_br ( block, span,
294- Operand :: Consume ( is_zero) ) ;
295- self . panic ( zero_block, zero_msg, span) ;
296-
297- block = ok_block;
298+ block = self . assert ( block, Operand :: Consume ( is_zero) , false ,
299+ AssertMessage :: Math ( zero_err) , span) ;
298300
299301 // We only need to check for the overflow in one case:
300302 // MIN / -1, and only for signed values.
@@ -318,11 +320,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
318320 self . cfg . push_assign ( block, scope_id, span, & of,
319321 Rvalue :: BinaryOp ( BinOp :: BitAnd , is_neg_1, is_min) ) ;
320322
321- let ( of_block, ok_block) = self . build_cond_br ( block, span,
322- Operand :: Consume ( of) ) ;
323- self . panic ( of_block, overflow_msg, span) ;
324-
325- block = ok_block;
323+ block = self . assert ( block, Operand :: Consume ( of) , false ,
324+ AssertMessage :: Math ( overflow_err) , span) ;
326325 }
327326 }
328327
0 commit comments