@@ -25,6 +25,7 @@ use syntax::parse::token::InternedString;
25
25
use syntax:: ptr:: P ;
26
26
use syntax:: { ast_map, ast_util, codemap} ;
27
27
28
+ use std:: num:: wrapping:: OverflowingOps ;
28
29
use std:: cmp:: Ordering ;
29
30
use std:: collections:: hash_map:: Entry :: Vacant ;
30
31
use std:: { i8, i16, i32, i64} ;
@@ -206,6 +207,33 @@ pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val {
206
207
}
207
208
}
208
209
210
+ fn checked_add_int ( a : i64 , b : i64 ) -> Result < const_val , String > {
211
+ let ( ret, oflo) = a. overflowing_add ( b) ;
212
+ if !oflo { Ok ( const_int ( ret) ) } else { Err ( format ! ( "constant arithmetic overflow" ) ) }
213
+ }
214
+ fn checked_sub_int ( a : i64 , b : i64 ) -> Result < const_val , String > {
215
+ let ( ret, oflo) = a. overflowing_sub ( b) ;
216
+ if !oflo { Ok ( const_int ( ret) ) } else { Err ( format ! ( "constant arithmetic overflow" ) ) }
217
+ }
218
+ fn checked_mul_int ( a : i64 , b : i64 ) -> Result < const_val , String > {
219
+ let ( ret, oflo) = a. overflowing_mul ( b) ;
220
+ if !oflo { Ok ( const_int ( ret) ) } else { Err ( format ! ( "constant arithmetic overflow" ) ) }
221
+ }
222
+
223
+ fn checked_add_uint ( a : u64 , b : u64 ) -> Result < const_val , String > {
224
+ let ( ret, oflo) = a. overflowing_add ( b) ;
225
+ if !oflo { Ok ( const_uint ( ret) ) } else { Err ( format ! ( "constant arithmetic overflow" ) ) }
226
+ }
227
+ fn checked_sub_uint ( a : u64 , b : u64 ) -> Result < const_val , String > {
228
+ let ( ret, oflo) = a. overflowing_sub ( b) ;
229
+ if !oflo { Ok ( const_uint ( ret) ) } else { Err ( format ! ( "constant arithmetic overflow" ) ) }
230
+ }
231
+ fn checked_mul_uint ( a : u64 , b : u64 ) -> Result < const_val , String > {
232
+ let ( ret, oflo) = a. overflowing_mul ( b) ;
233
+ if !oflo { Ok ( const_uint ( ret) ) } else { Err ( format ! ( "constant arithmetic overflow" ) ) }
234
+ }
235
+
236
+
209
237
pub fn eval_const_expr_partial < ' tcx > ( tcx : & ty:: ctxt < ' tcx > ,
210
238
e : & Expr ,
211
239
ty_hint : Option < Ty < ' tcx > > )
@@ -276,9 +304,9 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
276
304
}
277
305
} ;
278
306
match op. node {
279
- ast:: BiAdd => Ok ( const_int ( a + b ) ) ,
280
- ast:: BiSub => Ok ( const_int ( a - b ) ) ,
281
- ast:: BiMul => Ok ( const_int ( a * b ) ) ,
307
+ ast:: BiAdd => checked_add_int ( a , b ) ,
308
+ ast:: BiSub => checked_sub_int ( a , b ) ,
309
+ ast:: BiMul => checked_mul_int ( a , b ) ,
282
310
ast:: BiDiv => {
283
311
if b == 0 {
284
312
Err ( "attempted to divide by zero" . to_string ( ) )
@@ -312,9 +340,9 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
312
340
}
313
341
( Ok ( const_uint( a) ) , Ok ( const_uint( b) ) ) => {
314
342
match op. node {
315
- ast:: BiAdd => Ok ( const_uint ( a + b ) ) ,
316
- ast:: BiSub => Ok ( const_uint ( a - b ) ) ,
317
- ast:: BiMul => Ok ( const_uint ( a * b ) ) ,
343
+ ast:: BiAdd => checked_add_uint ( a , b ) ,
344
+ ast:: BiSub => checked_sub_uint ( a , b ) ,
345
+ ast:: BiMul => checked_mul_uint ( a , b ) ,
318
346
ast:: BiDiv if b == 0 => {
319
347
Err ( "attempted to divide by zero" . to_string ( ) )
320
348
}
0 commit comments