@@ -27,6 +27,7 @@ use syntax::{ast_map, ast_util, codemap};
2727
2828use std:: cmp:: Ordering ;
2929use std:: collections:: hash_map:: Entry :: Vacant ;
30+ use std:: { i8, i16, i32, i64} ;
3031use std:: rc:: Rc ;
3132
3233fn 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>,
263264 }
264265 }
265266 ( 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+ } ;
266285 match op. node {
267286 ast:: BiAdd => Ok ( const_int ( a + b) ) ,
268287 ast:: BiSub => Ok ( const_int ( a - b) ) ,
269288 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+ }
272297 }
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+ }
277306 }
278- ast:: BiRem => Ok ( const_int ( a % b) ) ,
279307 ast:: BiAnd | ast:: BiBitAnd => Ok ( const_int ( a & b) ) ,
280308 ast:: BiOr | ast:: BiBitOr => Ok ( const_int ( a | b) ) ,
281309 ast:: BiBitXor => Ok ( const_int ( a ^ b) ) ,
0 commit comments