提交 f1ea2b30 编写于 作者: F Felix S. Klock II

Catch arith-overflow explicitly during `rustc::middle::const_eval`.

This only replaces the conditional arith-overflow asserts with
unconditional errors from the guts of const-eval; it does *not*
attempt to sanely handle such errors e.g. with a nice error message
from `rustc`.  So the same test that led me to add this commit are
still failing, and must be addressed.
上级 faf3bcd7
......@@ -25,6 +25,7 @@
use syntax::ptr::P;
use syntax::{ast_map, ast_util, codemap};
use std::num::wrapping::OverflowingOps;
use std::cmp::Ordering;
use std::collections::hash_map::Entry::Vacant;
use std::{i8, i16, i32, i64};
......@@ -206,6 +207,33 @@ pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val {
}
}
fn checked_add_int(a: i64, b: i64) -> Result<const_val, String> {
let (ret, oflo) = a.overflowing_add(b);
if !oflo { Ok(const_int(ret)) } else { Err(format!("constant arithmetic overflow")) }
}
fn checked_sub_int(a: i64, b: i64) -> Result<const_val, String> {
let (ret, oflo) = a.overflowing_sub(b);
if !oflo { Ok(const_int(ret)) } else { Err(format!("constant arithmetic overflow")) }
}
fn checked_mul_int(a: i64, b: i64) -> Result<const_val, String> {
let (ret, oflo) = a.overflowing_mul(b);
if !oflo { Ok(const_int(ret)) } else { Err(format!("constant arithmetic overflow")) }
}
fn checked_add_uint(a: u64, b: u64) -> Result<const_val, String> {
let (ret, oflo) = a.overflowing_add(b);
if !oflo { Ok(const_uint(ret)) } else { Err(format!("constant arithmetic overflow")) }
}
fn checked_sub_uint(a: u64, b: u64) -> Result<const_val, String> {
let (ret, oflo) = a.overflowing_sub(b);
if !oflo { Ok(const_uint(ret)) } else { Err(format!("constant arithmetic overflow")) }
}
fn checked_mul_uint(a: u64, b: u64) -> Result<const_val, String> {
let (ret, oflo) = a.overflowing_mul(b);
if !oflo { Ok(const_uint(ret)) } else { Err(format!("constant arithmetic overflow")) }
}
pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
e: &Expr,
ty_hint: Option<Ty<'tcx>>)
......@@ -276,9 +304,9 @@ fn fromb(b: bool) -> Result<const_val, String> { Ok(const_int(b as i64)) }
}
};
match op.node {
ast::BiAdd => Ok(const_int(a + b)),
ast::BiSub => Ok(const_int(a - b)),
ast::BiMul => Ok(const_int(a * b)),
ast::BiAdd => checked_add_int(a, b),
ast::BiSub => checked_sub_int(a, b),
ast::BiMul => checked_mul_int(a, b),
ast::BiDiv => {
if b == 0 {
Err("attempted to divide by zero".to_string())
......@@ -312,9 +340,9 @@ fn fromb(b: bool) -> Result<const_val, String> { Ok(const_int(b as i64)) }
}
(Ok(const_uint(a)), Ok(const_uint(b))) => {
match op.node {
ast::BiAdd => Ok(const_uint(a + b)),
ast::BiSub => Ok(const_uint(a - b)),
ast::BiMul => Ok(const_uint(a * b)),
ast::BiAdd => checked_add_uint(a, b),
ast::BiSub => checked_sub_uint(a, b),
ast::BiMul => checked_mul_uint(a, b),
ast::BiDiv if b == 0 => {
Err("attempted to divide by zero".to_string())
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册