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