@@ -27,6 +27,7 @@ use syntax::{ast_map, ast_util, codemap};
27
27
28
28
use std:: cmp:: Ordering ;
29
29
use std:: collections:: hash_map:: Entry :: Vacant ;
30
+ use std:: { i8, i16, i32, i64} ;
30
31
use std:: rc:: Rc ;
31
32
32
33
fn lookup_const < ' a > ( tcx : & ' a ty:: ctxt , e : & Expr ) -> Option < & ' a Expr > {
@@ -263,19 +264,46 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
263
264
}
264
265
}
265
266
( Ok ( const_int( a) ) , Ok ( const_int( b) ) ) => {
267
+ let is_a_min_value = |& : | {
268
+ let int_ty = match ty:: expr_ty_opt ( tcx, e) . map ( |ty| & ty. sty ) {
269
+ Some ( & ty:: ty_int( int_ty) ) => int_ty,
270
+ _ => return false
271
+ } ;
272
+ let int_ty = if let ast:: TyIs ( _) = int_ty {
273
+ tcx. sess . target . int_type
274
+ } else {
275
+ int_ty
276
+ } ;
277
+ match int_ty {
278
+ ast:: TyI8 => ( a as i8 ) == i8:: MIN ,
279
+ ast:: TyI16 => ( a as i16 ) == i16:: MIN ,
280
+ ast:: TyI32 => ( a as i32 ) == i32:: MIN ,
281
+ ast:: TyI64 => ( a as i64 ) == i64:: MIN ,
282
+ ast:: TyIs ( _) => unreachable ! ( )
283
+ }
284
+ } ;
266
285
match op. node {
267
286
ast:: BiAdd => Ok ( const_int ( a + b) ) ,
268
287
ast:: BiSub => Ok ( const_int ( a - b) ) ,
269
288
ast:: BiMul => Ok ( const_int ( a * b) ) ,
270
- ast:: BiDiv if b == 0 => {
271
- Err ( "attempted to divide by zero" . to_string ( ) )
289
+ ast:: BiDiv => {
290
+ if b == 0 {
291
+ Err ( "attempted to divide by zero" . to_string ( ) )
292
+ } else if b == -1 && is_a_min_value ( ) {
293
+ Err ( "attempted to divide with overflow" . to_string ( ) )
294
+ } else {
295
+ Ok ( const_int ( a / b) )
296
+ }
272
297
}
273
- ast:: BiDiv => Ok ( const_int ( a / b) ) ,
274
- ast:: BiRem if b == 0 => {
275
- Err ( "attempted remainder with a divisor of \
276
- zero". to_string ( ) )
298
+ ast:: BiRem => {
299
+ if b == 0 {
300
+ Err ( "attempted remainder with a divisor of zero" . to_string ( ) )
301
+ } else if b == -1 && is_a_min_value ( ) {
302
+ Err ( "attempted remainder with overflow" . to_string ( ) )
303
+ } else {
304
+ Ok ( const_int ( a % b) )
305
+ }
277
306
}
278
- ast:: BiRem => Ok ( const_int ( a % b) ) ,
279
307
ast:: BiAnd | ast:: BiBitAnd => Ok ( const_int ( a & b) ) ,
280
308
ast:: BiOr | ast:: BiBitOr => Ok ( const_int ( a | b) ) ,
281
309
ast:: BiBitXor => Ok ( const_int ( a ^ b) ) ,
0 commit comments