Skip to content

Commit 4b8c271

Browse files
committed
---
yaml --- r: 180117 b: refs/heads/auto c: a0fe12982b77a6fc6ec54b3260d4b9810c55a6c4 h: refs/heads/master i: 180115: b16dd2d v: v3
1 parent 95330cb commit 4b8c271

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
1010
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
1111
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1212
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
13-
refs/heads/auto: 8807eb21c120d58bd3c2f8e68892a07ddb476da5
13+
refs/heads/auto: a0fe12982b77a6fc6ec54b3260d4b9810c55a6c4
1414
refs/heads/servo: af82457af293e2a842ba6b7759b70288da276167
1515
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1616
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336

branches/auto/src/librustc/middle/const_eval.rs

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use syntax::{ast_map, ast_util, codemap};
2727

2828
use std::cmp::Ordering;
2929
use std::collections::hash_map::Entry::Vacant;
30+
use std::{i8, i16, i32, i64};
3031
use std::rc::Rc;
3132

3233
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>,
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

Comments
 (0)