Move checked arithmetic operators into Int trait

This commit is contained in:
Brendan Zabarauskas 2014-11-10 00:11:28 +11:00
parent 7e57cd843c
commit e51cc089da
20 changed files with 324 additions and 371 deletions

View File

@ -97,7 +97,7 @@ syn keyword rustTrait FromIterator IntoIterator Extend ExactSize
syn keyword rustTrait Iterator DoubleEndedIterator
syn keyword rustTrait RandomAccessIterator CloneableIterator
syn keyword rustTrait OrdIterator MutableDoubleEndedIterator
syn keyword rustTrait Num NumCast CheckedAdd CheckedSub CheckedMul CheckedDiv
syn keyword rustTrait Num NumCast
syn keyword rustTrait Signed Unsigned Primitive Int Float
syn keyword rustTrait FloatMath ToPrimitive FromPrimitive
syn keyword rustTrait Box

View File

@ -132,7 +132,7 @@ impl Drop for Arena {
#[inline]
fn round_up(base: uint, align: uint) -> uint {
(base.checked_add(&(align - 1))).unwrap() & !(align - 1)
(base.checked_add(align - 1)).unwrap() & !(align - 1)
}
// Walk down a chunk, running the destructors for any objects stored
@ -376,8 +376,8 @@ fn calculate_size<T>(capacity: uint) -> uint {
let mut size = mem::size_of::<TypedArenaChunk<T>>();
size = round_up(size, mem::min_align_of::<T>());
let elem_size = mem::size_of::<T>();
let elems_size = elem_size.checked_mul(&capacity).unwrap();
size = size.checked_add(&elems_size).unwrap();
let elems_size = elem_size.checked_mul(capacity).unwrap();
size = size.checked_add(elems_size).unwrap();
size
}
@ -432,7 +432,7 @@ impl<T> TypedArenaChunk<T> {
#[inline]
fn end(&self) -> *const u8 {
unsafe {
let size = mem::size_of::<T>().checked_mul(&self.capacity).unwrap();
let size = mem::size_of::<T>().checked_mul(self.capacity).unwrap();
self.start().offset(size as int)
}
}
@ -481,7 +481,7 @@ impl<T> TypedArena<T> {
fn grow(&self) {
unsafe {
let chunk = *self.first.borrow_mut();
let new_capacity = (*chunk).capacity.checked_mul(&2).unwrap();
let new_capacity = (*chunk).capacity.checked_mul(2).unwrap();
let chunk = TypedArenaChunk::<T>::new(chunk, new_capacity);
self.ptr.set((*chunk).start() as *const T);
self.end.set((*chunk).end() as *const T);

View File

@ -161,7 +161,7 @@ impl<T> Vec<T> {
} else if capacity == 0 {
Vec::new()
} else {
let size = capacity.checked_mul(&mem::size_of::<T>())
let size = capacity.checked_mul(mem::size_of::<T>())
.expect("capacity overflow");
let ptr = unsafe { allocate(size, mem::min_align_of::<T>()) };
Vec { ptr: ptr as *mut T, len: 0, cap: capacity }
@ -601,7 +601,7 @@ impl<T> Vec<T> {
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn reserve(&mut self, additional: uint) {
if self.cap - self.len < additional {
match self.len.checked_add(&additional) {
match self.len.checked_add(additional) {
None => panic!("Vec::reserve: `uint` overflow"),
// if the checked_add
Some(new_cap) => {
@ -638,7 +638,7 @@ impl<T> Vec<T> {
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn reserve_exact(&mut self, additional: uint) {
if self.cap - self.len < additional {
match self.len.checked_add(&additional) {
match self.len.checked_add(additional) {
None => panic!("Vec::reserve: `uint` overflow"),
Some(new_cap) => self.grow_capacity(new_cap)
}
@ -971,7 +971,7 @@ impl<T> Vec<T> {
pub fn push(&mut self, value: T) {
if mem::size_of::<T>() == 0 {
// zero-size types consume no memory, so we can't rely on the address space running out
self.len = self.len.checked_add(&1).expect("length overflow");
self.len = self.len.checked_add(1).expect("length overflow");
unsafe { mem::forget(value); }
return
}
@ -1064,7 +1064,7 @@ impl<T> Vec<T> {
if mem::size_of::<T>() == 0 { return }
if capacity > self.cap {
let size = capacity.checked_mul(&mem::size_of::<T>())
let size = capacity.checked_mul(mem::size_of::<T>())
.expect("capacity overflow");
unsafe {
self.ptr = alloc_or_realloc(self.ptr, self.cap * mem::size_of::<T>(), size);

View File

@ -60,9 +60,9 @@ This `for` loop syntax can be applied to any iterator over any type.
use clone::Clone;
use cmp;
use cmp::{PartialEq, PartialOrd, Ord};
use cmp::{PartialOrd, Ord};
use mem;
use num::{Zero, One, CheckedAdd, CheckedSub, ToPrimitive, Int};
use num::{Zero, One, ToPrimitive, Int};
use ops::{Add, Mul, Sub};
use option::{Option, Some, None};
use uint;
@ -1093,7 +1093,7 @@ impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for Chain<T, U> {
let lower = a_lower.saturating_add(b_lower);
let upper = match (a_upper, b_upper) {
(Some(x), Some(y)) => x.checked_add(&y),
(Some(x), Some(y)) => x.checked_add(y),
_ => None
};
@ -1415,7 +1415,7 @@ impl<A, T: Iterator<A>> Iterator<A> for Peekable<A, T> {
if self.peeked.is_some() {
let lo = lo.saturating_add(1);
let hi = match hi {
Some(x) => x.checked_add(&1),
Some(x) => x.checked_add(1),
None => None
};
(lo, hi)
@ -1680,7 +1680,7 @@ impl<'a, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for FlatMap<'a, A, T,
let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), |it| it.size_hint());
let lo = flo.saturating_add(blo);
match (self.iter.size_hint(), fhi, bhi) {
((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(&b)),
((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
_ => (lo, None)
}
}
@ -1946,7 +1946,7 @@ impl<A: Add<A, A> + PartialOrd + Clone + ToPrimitive> Iterator<A> for Range<A> {
// the i64/u64 might lie within their range.
let bound = match self.state.to_i64() {
Some(a) => {
let sz = self.stop.to_i64().map(|b| b.checked_sub(&a));
let sz = self.stop.to_i64().map(|b| b.checked_sub(a));
match sz {
Some(Some(bound)) => bound.to_uint(),
_ => None,
@ -1954,7 +1954,7 @@ impl<A: Add<A, A> + PartialOrd + Clone + ToPrimitive> Iterator<A> for Range<A> {
},
None => match self.state.to_u64() {
Some(a) => {
let sz = self.stop.to_u64().map(|b| b.checked_sub(&a));
let sz = self.stop.to_u64().map(|b| b.checked_sub(a));
match sz {
Some(Some(bound)) => bound.to_uint(),
_ => None
@ -2024,7 +2024,7 @@ impl<A: Add<A, A> + PartialOrd + Clone + ToPrimitive> Iterator<A> for RangeInclu
} else {
let lo = lo.saturating_add(1);
let hi = match hi {
Some(x) => x.checked_add(&1),
Some(x) => x.checked_add(1),
None => None
};
(lo, hi)
@ -2060,18 +2060,17 @@ pub struct RangeStep<A> {
/// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping.
#[inline]
pub fn range_step<A: CheckedAdd + PartialOrd +
Clone + Zero>(start: A, stop: A, step: A) -> RangeStep<A> {
pub fn range_step<A: Int>(start: A, stop: A, step: A) -> RangeStep<A> {
let rev = step < Zero::zero();
RangeStep{state: start, stop: stop, step: step, rev: rev}
}
impl<A: CheckedAdd + PartialOrd + Clone> Iterator<A> for RangeStep<A> {
impl<A: Int> Iterator<A> for RangeStep<A> {
#[inline]
fn next(&mut self) -> Option<A> {
if (self.rev && self.state > self.stop) || (!self.rev && self.state < self.stop) {
let result = self.state.clone();
match self.state.checked_add(&self.step) {
let result = self.state;
match self.state.checked_add(self.step) {
Some(x) => self.state = x,
None => self.state = self.stop.clone()
}
@ -2094,19 +2093,18 @@ pub struct RangeStepInclusive<A> {
/// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping.
#[inline]
pub fn range_step_inclusive<A: CheckedAdd + PartialOrd + Clone + Zero>(start: A, stop: A,
step: A) -> RangeStepInclusive<A> {
pub fn range_step_inclusive<A: Int>(start: A, stop: A, step: A) -> RangeStepInclusive<A> {
let rev = step < Zero::zero();
RangeStepInclusive{state: start, stop: stop, step: step, rev: rev, done: false}
}
impl<A: CheckedAdd + PartialOrd + Clone + PartialEq> Iterator<A> for RangeStepInclusive<A> {
impl<A: Int> Iterator<A> for RangeStepInclusive<A> {
#[inline]
fn next(&mut self) -> Option<A> {
if !self.done && ((self.rev && self.state >= self.stop) ||
(!self.rev && self.state <= self.stop)) {
let result = self.state.clone();
match self.state.checked_add(&self.step) {
let result = self.state;
match self.state.checked_add(self.step) {
Some(x) => self.state = x,
None => self.done = true
}

View File

@ -348,10 +348,6 @@ trait_impl!(Primitive for uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
/// operators, bit counting methods, and endian conversion functions.
pub trait Int: Primitive
+ Ord
+ CheckedAdd
+ CheckedSub
+ CheckedMul
+ CheckedDiv
+ Bounded
+ Not<Self>
+ BitAnd<Self,Self>
@ -526,11 +522,65 @@ pub trait Int: Primitive
if cfg!(target_endian = "little") { self } else { self.swap_bytes() }
}
/// Adds two numbers, checking for overflow. If overflow occurs, `None` is
/// returned.
///
/// # Example
///
/// ```rust
/// use std::num::Int;
///
/// assert_eq!(5u16.checked_add(65530), Some(65535));
/// assert_eq!(6u16.checked_add(65530), None);
/// ```
fn checked_add(self, other: Self) -> Option<Self>;
/// Subtracts two numbers, checking for underflow. If underflow occurs,
/// `None` is returned.
///
/// # Example
///
/// ```rust
/// use std::num::Int;
///
/// assert_eq!((-127i8).checked_sub(1), Some(-128));
/// assert_eq!((-128i8).checked_sub(1), None);
/// ```
fn checked_sub(self, other: Self) -> Option<Self>;
/// Multiplies two numbers, checking for underflow or overflow. If underflow
/// or overflow occurs, `None` is returned.
///
/// # Example
///
/// ```rust
/// use std::num::Int;
///
/// assert_eq!(5u8.checked_mul(51), Some(255));
/// assert_eq!(5u8.checked_mul(52), None);
/// ```
fn checked_mul(self, other: Self) -> Option<Self>;
/// Divides two numbers, checking for underflow, overflow and division by
/// zero. If underflow occurs, `None` is returned.
///
/// # Example
///
/// ```rust
/// use std::num::Int;
///
/// assert_eq!((-127i8).checked_div(-1), Some(127));
/// assert_eq!((-128i8).checked_div(-1), None);
/// assert_eq!((1i8).checked_div(0), None);
/// ```
#[inline]
fn checked_div(self, other: Self) -> Option<Self>;
/// Saturating addition. Returns `self + other`, saturating at the
/// numeric bounds instead of overflowing.
#[inline]
fn saturating_add(self, other: Self) -> Self {
match self.checked_add(&other) {
match self.checked_add(other) {
Some(x) => x,
None if other >= Zero::zero() => Bounded::max_value(),
None => Bounded::min_value(),
@ -541,7 +591,7 @@ pub trait Int: Primitive
/// numeric bounds instead of overflowing.
#[inline]
fn saturating_sub(self, other: Self) -> Self {
match self.checked_sub(&other) {
match self.checked_sub(other) {
Some(x) => x,
None if other >= Zero::zero() => Bounded::min_value(),
None => Bounded::max_value(),
@ -549,9 +599,22 @@ pub trait Int: Primitive
}
}
macro_rules! checked_op {
($T:ty, $U:ty, $op:path, $x:expr, $y:expr) => {{
let (result, overflowed) = unsafe { $op($x as $U, $y as $U) };
if overflowed { None } else { Some(result as $T) }
}}
}
macro_rules! uint_impl {
($T:ty, $ActualT:ty, $BITS:expr,
$ctpop:path, $ctlz:path, $cttz:path, $bswap:path) => {
($T:ty = $ActualT:ty, $BITS:expr,
$ctpop:path,
$ctlz:path,
$cttz:path,
$bswap:path,
$add_with_overflow:path,
$sub_with_overflow:path,
$mul_with_overflow:path) => {
impl Int for $T {
#[inline]
fn count_ones(self) -> uint { unsafe { $ctpop(self as $ActualT) as uint } }
@ -578,6 +641,29 @@ macro_rules! uint_impl {
#[inline]
fn swap_bytes(self) -> $T { unsafe { $bswap(self as $ActualT) as $T } }
#[inline]
fn checked_add(self, other: $T) -> Option<$T> {
checked_op!($T, $ActualT, $add_with_overflow, self, other)
}
#[inline]
fn checked_sub(self, other: $T) -> Option<$T> {
checked_op!($T, $ActualT, $sub_with_overflow, self, other)
}
#[inline]
fn checked_mul(self, other: $T) -> Option<$T> {
checked_op!($T, $ActualT, $mul_with_overflow, self, other)
}
#[inline]
fn checked_div(self, v: $T) -> Option<$T> {
match v {
0 => None,
v => Some(self / v),
}
}
}
}
}
@ -586,74 +672,145 @@ macro_rules! uint_impl {
/// consistency with the other `bswap` intrinsics.
unsafe fn bswap8(x: u8) -> u8 { x }
uint_impl!(u8, u8, 8,
uint_impl!(u8 = u8, 8,
intrinsics::ctpop8,
intrinsics::ctlz8,
intrinsics::cttz8,
bswap8)
bswap8,
intrinsics::u8_add_with_overflow,
intrinsics::u8_sub_with_overflow,
intrinsics::u8_mul_with_overflow)
uint_impl!(u16, u16, 16,
uint_impl!(u16 = u16, 16,
intrinsics::ctpop16,
intrinsics::ctlz16,
intrinsics::cttz16,
intrinsics::bswap16)
intrinsics::bswap16,
intrinsics::u16_add_with_overflow,
intrinsics::u16_sub_with_overflow,
intrinsics::u16_mul_with_overflow)
uint_impl!(u32, u32, 32,
uint_impl!(u32 = u32, 32,
intrinsics::ctpop32,
intrinsics::ctlz32,
intrinsics::cttz32,
intrinsics::bswap32)
intrinsics::bswap32,
intrinsics::u32_add_with_overflow,
intrinsics::u32_sub_with_overflow,
intrinsics::u32_mul_with_overflow)
uint_impl!(u64, u64, 64,
uint_impl!(u64 = u64, 64,
intrinsics::ctpop64,
intrinsics::ctlz64,
intrinsics::cttz64,
intrinsics::bswap64)
intrinsics::bswap64,
intrinsics::u64_add_with_overflow,
intrinsics::u64_sub_with_overflow,
intrinsics::u64_mul_with_overflow)
#[cfg(target_word_size = "32")]
uint_impl!(uint, u32, 32,
uint_impl!(uint = u32, 32,
intrinsics::ctpop32,
intrinsics::ctlz32,
intrinsics::cttz32,
intrinsics::bswap32)
intrinsics::bswap32,
intrinsics::u32_add_with_overflow,
intrinsics::u32_sub_with_overflow,
intrinsics::u32_mul_with_overflow)
#[cfg(target_word_size = "64")]
uint_impl!(uint, u64, 64,
uint_impl!(uint = u64, 64,
intrinsics::ctpop64,
intrinsics::ctlz64,
intrinsics::cttz64,
intrinsics::bswap64)
intrinsics::bswap64,
intrinsics::u64_add_with_overflow,
intrinsics::u64_sub_with_overflow,
intrinsics::u64_mul_with_overflow)
macro_rules! int_impl {
($T:ty, $U:ty) => {
($T:ty = $ActualT:ty, $UnsignedT:ty,
$add_with_overflow:path,
$sub_with_overflow:path,
$mul_with_overflow:path) => {
impl Int for $T {
#[inline]
fn count_ones(self) -> uint { (self as $U).count_ones() }
fn count_ones(self) -> uint { (self as $UnsignedT).count_ones() }
#[inline]
fn leading_zeros(self) -> uint { (self as $U).leading_zeros() }
fn leading_zeros(self) -> uint { (self as $UnsignedT).leading_zeros() }
#[inline]
fn trailing_zeros(self) -> uint { (self as $U).trailing_zeros() }
fn trailing_zeros(self) -> uint { (self as $UnsignedT).trailing_zeros() }
#[inline]
fn rotate_left(self, n: uint) -> $T { (self as $U).rotate_left(n) as $T }
fn rotate_left(self, n: uint) -> $T { (self as $UnsignedT).rotate_left(n) as $T }
#[inline]
fn rotate_right(self, n: uint) -> $T { (self as $U).rotate_right(n) as $T }
fn rotate_right(self, n: uint) -> $T { (self as $UnsignedT).rotate_right(n) as $T }
#[inline]
fn swap_bytes(self) -> $T { (self as $U).swap_bytes() as $T }
fn swap_bytes(self) -> $T { (self as $UnsignedT).swap_bytes() as $T }
#[inline]
fn checked_add(self, other: $T) -> Option<$T> {
checked_op!($T, $ActualT, $add_with_overflow, self, other)
}
#[inline]
fn checked_sub(self, other: $T) -> Option<$T> {
checked_op!($T, $ActualT, $sub_with_overflow, self, other)
}
#[inline]
fn checked_mul(self, other: $T) -> Option<$T> {
checked_op!($T, $ActualT, $mul_with_overflow, self, other)
}
#[inline]
fn checked_div(self, v: $T) -> Option<$T> {
match v {
0 => None,
-1 if self == Bounded::min_value()
=> None,
v => Some(self / v),
}
}
}
}
}
int_impl!(i8, u8)
int_impl!(i16, u16)
int_impl!(i32, u32)
int_impl!(i64, u64)
#[cfg(target_word_size = "32")] int_impl!(int, u32)
#[cfg(target_word_size = "64")] int_impl!(int, u64)
int_impl!(i8 = i8, u8,
intrinsics::i8_add_with_overflow,
intrinsics::i8_sub_with_overflow,
intrinsics::i8_mul_with_overflow)
int_impl!(i16 = i16, u16,
intrinsics::i16_add_with_overflow,
intrinsics::i16_sub_with_overflow,
intrinsics::i16_mul_with_overflow)
int_impl!(i32 = i32, u32,
intrinsics::i32_add_with_overflow,
intrinsics::i32_sub_with_overflow,
intrinsics::i32_mul_with_overflow)
int_impl!(i64 = i64, u64,
intrinsics::i64_add_with_overflow,
intrinsics::i64_sub_with_overflow,
intrinsics::i64_mul_with_overflow)
#[cfg(target_word_size = "32")]
int_impl!(int = i32, u32,
intrinsics::i32_add_with_overflow,
intrinsics::i32_sub_with_overflow,
intrinsics::i32_mul_with_overflow)
#[cfg(target_word_size = "64")]
int_impl!(int = i64, u64,
intrinsics::i64_add_with_overflow,
intrinsics::i64_sub_with_overflow,
intrinsics::i64_mul_with_overflow)
/// Unsigned integers
pub trait UnsignedInt: Int {
@ -686,7 +843,7 @@ pub trait UnsignedInt: Int {
tmp = tmp | (tmp >> shift);
shift = shift << 1u;
}
tmp.checked_add(&one())
tmp.checked_add(one())
}
}
@ -1184,192 +1341,6 @@ impl_num_cast!(int, to_int)
impl_num_cast!(f32, to_f32)
impl_num_cast!(f64, to_f64)
/// Performs addition that returns `None` instead of wrapping around on overflow.
pub trait CheckedAdd: Add<Self, Self> {
/// Adds two numbers, checking for overflow. If overflow happens, `None` is returned.
///
/// # Example
///
/// ```rust
/// use std::num::CheckedAdd;
/// assert_eq!(5u16.checked_add(&65530), Some(65535));
/// assert_eq!(6u16.checked_add(&65530), None);
/// ```
fn checked_add(&self, v: &Self) -> Option<Self>;
}
macro_rules! checked_impl(
($trait_name:ident, $method:ident, $t:ty, $op:path) => {
impl $trait_name for $t {
#[inline]
fn $method(&self, v: &$t) -> Option<$t> {
unsafe {
let (x, y) = $op(*self, *v);
if y { None } else { Some(x) }
}
}
}
}
)
macro_rules! checked_cast_impl(
($trait_name:ident, $method:ident, $t:ty, $cast:ty, $op:path) => {
impl $trait_name for $t {
#[inline]
fn $method(&self, v: &$t) -> Option<$t> {
unsafe {
let (x, y) = $op(*self as $cast, *v as $cast);
if y { None } else { Some(x as $t) }
}
}
}
}
)
#[cfg(target_word_size = "32")]
checked_cast_impl!(CheckedAdd, checked_add, uint, u32, intrinsics::u32_add_with_overflow)
#[cfg(target_word_size = "64")]
checked_cast_impl!(CheckedAdd, checked_add, uint, u64, intrinsics::u64_add_with_overflow)
checked_impl!(CheckedAdd, checked_add, u8, intrinsics::u8_add_with_overflow)
checked_impl!(CheckedAdd, checked_add, u16, intrinsics::u16_add_with_overflow)
checked_impl!(CheckedAdd, checked_add, u32, intrinsics::u32_add_with_overflow)
checked_impl!(CheckedAdd, checked_add, u64, intrinsics::u64_add_with_overflow)
#[cfg(target_word_size = "32")]
checked_cast_impl!(CheckedAdd, checked_add, int, i32, intrinsics::i32_add_with_overflow)
#[cfg(target_word_size = "64")]
checked_cast_impl!(CheckedAdd, checked_add, int, i64, intrinsics::i64_add_with_overflow)
checked_impl!(CheckedAdd, checked_add, i8, intrinsics::i8_add_with_overflow)
checked_impl!(CheckedAdd, checked_add, i16, intrinsics::i16_add_with_overflow)
checked_impl!(CheckedAdd, checked_add, i32, intrinsics::i32_add_with_overflow)
checked_impl!(CheckedAdd, checked_add, i64, intrinsics::i64_add_with_overflow)
/// Performs subtraction that returns `None` instead of wrapping around on underflow.
pub trait CheckedSub: Sub<Self, Self> {
/// Subtracts two numbers, checking for underflow. If underflow happens, `None` is returned.
///
/// # Example
///
/// ```rust
/// use std::num::CheckedSub;
/// assert_eq!((-127i8).checked_sub(&1), Some(-128));
/// assert_eq!((-128i8).checked_sub(&1), None);
/// ```
fn checked_sub(&self, v: &Self) -> Option<Self>;
}
#[cfg(target_word_size = "32")]
checked_cast_impl!(CheckedSub, checked_sub, uint, u32, intrinsics::u32_sub_with_overflow)
#[cfg(target_word_size = "64")]
checked_cast_impl!(CheckedSub, checked_sub, uint, u64, intrinsics::u64_sub_with_overflow)
checked_impl!(CheckedSub, checked_sub, u8, intrinsics::u8_sub_with_overflow)
checked_impl!(CheckedSub, checked_sub, u16, intrinsics::u16_sub_with_overflow)
checked_impl!(CheckedSub, checked_sub, u32, intrinsics::u32_sub_with_overflow)
checked_impl!(CheckedSub, checked_sub, u64, intrinsics::u64_sub_with_overflow)
#[cfg(target_word_size = "32")]
checked_cast_impl!(CheckedSub, checked_sub, int, i32, intrinsics::i32_sub_with_overflow)
#[cfg(target_word_size = "64")]
checked_cast_impl!(CheckedSub, checked_sub, int, i64, intrinsics::i64_sub_with_overflow)
checked_impl!(CheckedSub, checked_sub, i8, intrinsics::i8_sub_with_overflow)
checked_impl!(CheckedSub, checked_sub, i16, intrinsics::i16_sub_with_overflow)
checked_impl!(CheckedSub, checked_sub, i32, intrinsics::i32_sub_with_overflow)
checked_impl!(CheckedSub, checked_sub, i64, intrinsics::i64_sub_with_overflow)
/// Performs multiplication that returns `None` instead of wrapping around on underflow or
/// overflow.
pub trait CheckedMul: Mul<Self, Self> {
/// Multiplies two numbers, checking for underflow or overflow. If underflow or overflow
/// happens, `None` is returned.
///
/// # Example
///
/// ```rust
/// use std::num::CheckedMul;
/// assert_eq!(5u8.checked_mul(&51), Some(255));
/// assert_eq!(5u8.checked_mul(&52), None);
/// ```
fn checked_mul(&self, v: &Self) -> Option<Self>;
}
#[cfg(target_word_size = "32")]
checked_cast_impl!(CheckedMul, checked_mul, uint, u32, intrinsics::u32_mul_with_overflow)
#[cfg(target_word_size = "64")]
checked_cast_impl!(CheckedMul, checked_mul, uint, u64, intrinsics::u64_mul_with_overflow)
checked_impl!(CheckedMul, checked_mul, u8, intrinsics::u8_mul_with_overflow)
checked_impl!(CheckedMul, checked_mul, u16, intrinsics::u16_mul_with_overflow)
checked_impl!(CheckedMul, checked_mul, u32, intrinsics::u32_mul_with_overflow)
checked_impl!(CheckedMul, checked_mul, u64, intrinsics::u64_mul_with_overflow)
#[cfg(target_word_size = "32")]
checked_cast_impl!(CheckedMul, checked_mul, int, i32, intrinsics::i32_mul_with_overflow)
#[cfg(target_word_size = "64")]
checked_cast_impl!(CheckedMul, checked_mul, int, i64, intrinsics::i64_mul_with_overflow)
checked_impl!(CheckedMul, checked_mul, i8, intrinsics::i8_mul_with_overflow)
checked_impl!(CheckedMul, checked_mul, i16, intrinsics::i16_mul_with_overflow)
checked_impl!(CheckedMul, checked_mul, i32, intrinsics::i32_mul_with_overflow)
checked_impl!(CheckedMul, checked_mul, i64, intrinsics::i64_mul_with_overflow)
/// Performs division that returns `None` instead of panicking on division by zero and instead of
/// wrapping around on underflow and overflow.
pub trait CheckedDiv: Div<Self, Self> {
/// Divides two numbers, checking for underflow, overflow and division by zero. If any of that
/// happens, `None` is returned.
///
/// # Example
///
/// ```rust
/// use std::num::CheckedDiv;
/// assert_eq!((-127i8).checked_div(&-1), Some(127));
/// assert_eq!((-128i8).checked_div(&-1), None);
/// assert_eq!((1i8).checked_div(&0), None);
/// ```
fn checked_div(&self, v: &Self) -> Option<Self>;
}
macro_rules! checkeddiv_int_impl(
($t:ty, $min:expr) => {
impl CheckedDiv for $t {
#[inline]
fn checked_div(&self, v: &$t) -> Option<$t> {
if *v == 0 || (*self == $min && *v == -1) {
None
} else {
Some(*self / *v)
}
}
}
}
)
checkeddiv_int_impl!(int, int::MIN)
checkeddiv_int_impl!(i8, i8::MIN)
checkeddiv_int_impl!(i16, i16::MIN)
checkeddiv_int_impl!(i32, i32::MIN)
checkeddiv_int_impl!(i64, i64::MIN)
macro_rules! checkeddiv_uint_impl(
($($t:ty)*) => ($(
impl CheckedDiv for $t {
#[inline]
fn checked_div(&self, v: &$t) -> Option<$t> {
if *v == 0 {
None
} else {
Some(*self / *v)
}
}
}
)*)
)
checkeddiv_uint_impl!(uint u8 u16 u32 u64)
/// Used for representing the classification of floating point numbers
#[deriving(PartialEq, Show)]
pub enum FPCategory {

View File

@ -51,7 +51,7 @@ pub use cmp::{Ordering, Less, Equal, Greater, Equiv};
pub use iter::{FromIterator, Extend};
pub use iter::{Iterator, DoubleEndedIterator, RandomAccessIterator, CloneableIterator};
pub use iter::{OrdIterator, MutableDoubleEndedIterator, ExactSize};
pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
pub use num::{Num, NumCast};
pub use num::{Signed, Unsigned, Float};
pub use num::{Primitive, Int, ToPrimitive, FromPrimitive};
pub use option::{Option, Some, None};

View File

@ -40,7 +40,7 @@ use cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering, Less, Equal, Greater, Equiv}
use cmp;
use default::Default;
use iter::*;
use num::{CheckedAdd, Int, div_rem};
use num::{Int, div_rem};
use ops;
use option::{None, Option, Some};
use ptr;
@ -1346,7 +1346,7 @@ impl<'a, T> Iterator<&'a [T]> for Windows<'a, T> {
(0, Some(0))
} else {
let x = self.v.len() - self.size;
(x.saturating_add(1), x.checked_add(&1u))
(x.saturating_add(1), x.checked_add(1u))
}
}
}

View File

@ -25,7 +25,7 @@ use iter::{Map, Iterator};
use iter::{DoubleEndedIterator, ExactSize};
use iter::range;
use kinds::Sized;
use num::{CheckedMul, Int};
use num::Int;
use option::{Option, None, Some};
use raw::Repr;
use slice::{mod, SlicePrelude};
@ -750,7 +750,7 @@ impl<'a> Iterator<u16> for Utf16CodeUnits<'a> {
// every char gets either one u16 or two u16,
// so this iterator is between 1 or 2 times as
// long as the underlying iterator.
(low, high.and_then(|n| n.checked_mul(&2)))
(low, high.and_then(|n| n.checked_mul(2)))
}
}

View File

@ -16,7 +16,6 @@ mod tests {
use core::$T_i::*;
use core::int;
use num;
use core::num::CheckedDiv;
#[test]
fn test_overflows() {
@ -152,9 +151,9 @@ mod tests {
#[test]
fn test_signed_checked_div() {
assert!(10i.checked_div(&2) == Some(5));
assert!(5i.checked_div(&0) == None);
assert!(int::MIN.checked_div(&-1) == None);
assert!(10i.checked_div(2) == Some(5));
assert!(5i.checked_div(0) == None);
assert!(int::MIN.checked_div(-1) == None);
}
}

View File

@ -15,7 +15,6 @@ macro_rules! uint_module (($T:ty, $T_i:ident) => (
mod tests {
use core::$T_i::*;
use num;
use core::num::CheckedDiv;
#[test]
fn test_overflows() {
@ -120,8 +119,8 @@ mod tests {
#[test]
fn test_unsigned_checked_div() {
assert!(10u.checked_div(&2) == Some(5));
assert!(5u.checked_div(&0) == None);
assert!(10u.checked_div(2) == Some(5));
assert!(5u.checked_div(0) == None);
}
}
))

View File

@ -126,7 +126,7 @@ impl<'a, T: Clone> WeightedChoice<'a, T> {
// weights so we can binary search. This *could* drop elements
// with weight == 0 as an optimisation.
for item in items.iter_mut() {
running_total = match running_total.checked_add(&item.weight) {
running_total = match running_total.checked_add(item.weight) {
Some(n) => n,
None => panic!("WeightedChoice::new called with a total weight \
larger than a uint can contain")

View File

@ -24,15 +24,13 @@ use middle::trans::type_::Type;
use syntax::abi;
use syntax::ast;
use std::num::CheckedMul;
// LLVM doesn't like objects that are too big. Issue #17913
fn ensure_array_fits_in_address_space(ccx: &CrateContext,
llet: Type,
size: machine::llsize,
scapegoat: ty::t) {
let esz = machine::llsize_of_alloc(ccx, llet);
match esz.checked_mul(&size) {
match esz.checked_mul(size) {
Some(n) if n < ccx.max_obj_size() => {}
_ => { ccx.report_overbig_object(scapegoat) }
}

View File

@ -61,14 +61,14 @@ impl ToBits for u64 {
/// Adds the specified number of bytes to the bit count. panic!() if this would cause numeric
/// overflow.
fn add_bytes_to_bits<T: Int + CheckedAdd + ToBits>(bits: T, bytes: T) -> T {
fn add_bytes_to_bits<T: Int + ToBits>(bits: T, bytes: T) -> T {
let (new_high_bits, new_low_bits) = bytes.to_bits();
if new_high_bits > Zero::zero() {
panic!("numeric overflow occurred.")
}
match bits.checked_add(&new_low_bits) {
match bits.checked_add(new_low_bits) {
Some(x) => return x,
None => panic!("numeric overflow occurred.")
}

View File

@ -609,7 +609,7 @@ impl<'a> PrettyEncoder<'a> {
/// This is safe to set during encoding.
pub fn set_indent<'a>(&mut self, indent: uint) {
// self.indent very well could be 0 so we need to use checked division.
let level = self.curr_indent.checked_div(&self.indent).unwrap_or(0);
let level = self.curr_indent.checked_div(self.indent).unwrap_or(0);
self.indent = indent;
self.curr_indent = level * self.indent;
}

View File

@ -17,7 +17,7 @@ use iter::{Iterator, count};
use kinds::{Sized, marker};
use mem::{min_align_of, size_of};
use mem;
use num::{CheckedAdd, CheckedMul, UnsignedInt};
use num::{Int, UnsignedInt};
use ops::{Deref, DerefMut, Drop};
use option::{Some, None, Option};
use ptr::{RawPtr, copy_nonoverlapping_memory, zero_memory};
@ -604,9 +604,9 @@ impl<K, V> RawTable<K, V> {
vals_size, min_align_of::< V >());
// One check for overflow that covers calculation and rounding of size.
let size_of_bucket = size_of::<u64>().checked_add(&size_of::<K>()).unwrap()
.checked_add(&size_of::<V>()).unwrap();
assert!(size >= capacity.checked_mul(&size_of_bucket)
let size_of_bucket = size_of::<u64>().checked_add(size_of::<K>()).unwrap()
.checked_add(size_of::<V>()).unwrap();
assert!(size >= capacity.checked_mul(size_of_bucket)
.expect("capacity overflow"),
"capacity overflow");

View File

@ -24,7 +24,6 @@ pub use core::num::{Num, div_rem, Zero, zero, One, one};
pub use core::num::{Signed, abs, signum};
pub use core::num::{Unsigned, pow, Bounded};
pub use core::num::{Primitive, Int, UnsignedInt};
pub use core::num::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
pub use core::num::{cast, FromPrimitive, NumCast, ToPrimitive};
pub use core::num::{next_power_of_two, is_power_of_two};
pub use core::num::{checked_next_power_of_two};
@ -636,36 +635,36 @@ mod tests {
#[test]
fn test_checked_add() {
let five_less = uint::MAX - 5;
assert_eq!(five_less.checked_add(&0), Some(uint::MAX - 5));
assert_eq!(five_less.checked_add(&1), Some(uint::MAX - 4));
assert_eq!(five_less.checked_add(&2), Some(uint::MAX - 3));
assert_eq!(five_less.checked_add(&3), Some(uint::MAX - 2));
assert_eq!(five_less.checked_add(&4), Some(uint::MAX - 1));
assert_eq!(five_less.checked_add(&5), Some(uint::MAX));
assert_eq!(five_less.checked_add(&6), None);
assert_eq!(five_less.checked_add(&7), None);
assert_eq!(five_less.checked_add(0), Some(uint::MAX - 5));
assert_eq!(five_less.checked_add(1), Some(uint::MAX - 4));
assert_eq!(five_less.checked_add(2), Some(uint::MAX - 3));
assert_eq!(five_less.checked_add(3), Some(uint::MAX - 2));
assert_eq!(five_less.checked_add(4), Some(uint::MAX - 1));
assert_eq!(five_less.checked_add(5), Some(uint::MAX));
assert_eq!(five_less.checked_add(6), None);
assert_eq!(five_less.checked_add(7), None);
}
#[test]
fn test_checked_sub() {
assert_eq!(5u.checked_sub(&0), Some(5));
assert_eq!(5u.checked_sub(&1), Some(4));
assert_eq!(5u.checked_sub(&2), Some(3));
assert_eq!(5u.checked_sub(&3), Some(2));
assert_eq!(5u.checked_sub(&4), Some(1));
assert_eq!(5u.checked_sub(&5), Some(0));
assert_eq!(5u.checked_sub(&6), None);
assert_eq!(5u.checked_sub(&7), None);
assert_eq!(5u.checked_sub(0), Some(5));
assert_eq!(5u.checked_sub(1), Some(4));
assert_eq!(5u.checked_sub(2), Some(3));
assert_eq!(5u.checked_sub(3), Some(2));
assert_eq!(5u.checked_sub(4), Some(1));
assert_eq!(5u.checked_sub(5), Some(0));
assert_eq!(5u.checked_sub(6), None);
assert_eq!(5u.checked_sub(7), None);
}
#[test]
fn test_checked_mul() {
let third = uint::MAX / 3;
assert_eq!(third.checked_mul(&0), Some(0));
assert_eq!(third.checked_mul(&1), Some(third));
assert_eq!(third.checked_mul(&2), Some(third * 2));
assert_eq!(third.checked_mul(&3), Some(third * 3));
assert_eq!(third.checked_mul(&4), None);
assert_eq!(third.checked_mul(0), Some(0));
assert_eq!(third.checked_mul(1), Some(third));
assert_eq!(third.checked_mul(2), Some(third * 2));
assert_eq!(third.checked_mul(3), Some(third * 3));
assert_eq!(third.checked_mul(4), None);
}
macro_rules! test_next_power_of_two(

View File

@ -601,11 +601,11 @@ pub fn from_str_radix_int<T: Int>(src: &str, radix: uint) -> Option<T> {
Some(x) => x,
None => return None,
};
result = match result.checked_mul(&radix) {
result = match result.checked_mul(radix) {
Some(result) => result,
None => return None,
};
result = match result.checked_add(&x) {
result = match result.checked_add(x) {
Some(result) => result,
None => return None,
};
@ -616,11 +616,11 @@ pub fn from_str_radix_int<T: Int>(src: &str, radix: uint) -> Option<T> {
Some(x) => x,
None => return None,
};
result = match result.checked_mul(&radix) {
result = match result.checked_mul(radix) {
Some(result) => result,
None => return None,
};
result = match result.checked_sub(&x) {
result = match result.checked_sub(x) {
Some(result) => result,
None => return None,
};

View File

@ -67,7 +67,7 @@
#[doc(no_inline)] pub use iter::{Iterator, DoubleEndedIterator};
#[doc(no_inline)] pub use iter::{RandomAccessIterator, CloneableIterator};
#[doc(no_inline)] pub use iter::{OrdIterator, MutableDoubleEndedIterator};
#[doc(no_inline)] pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
#[doc(no_inline)] pub use num::{Num, NumCast};
#[doc(no_inline)] pub use num::{Signed, Unsigned, Primitive, Int, Float};
#[doc(no_inline)] pub use num::{FloatMath, ToPrimitive, FromPrimitive};
#[doc(no_inline)] pub use boxed::Box;

View File

@ -15,8 +15,7 @@
use {fmt, i64};
use ops::{Add, Sub, Mul, Div, Neg};
use option::{Option, Some, None};
use num;
use num::{CheckedAdd, CheckedMul};
use num::Int;
use result::{Result, Ok, Err};
/// The number of nanoseconds in a microsecond.
@ -69,7 +68,7 @@ impl Duration {
/// Fails when the duration is out of bounds.
#[inline]
pub fn weeks(weeks: i64) -> Duration {
let secs = weeks.checked_mul(&SECS_PER_WEEK).expect("Duration::weeks out of bounds");
let secs = weeks.checked_mul(SECS_PER_WEEK).expect("Duration::weeks out of bounds");
Duration::seconds(secs)
}
@ -78,7 +77,7 @@ impl Duration {
/// Fails when the duration is out of bounds.
#[inline]
pub fn days(days: i64) -> Duration {
let secs = days.checked_mul(&SECS_PER_DAY).expect("Duration::days out of bounds");
let secs = days.checked_mul(SECS_PER_DAY).expect("Duration::days out of bounds");
Duration::seconds(secs)
}
@ -87,7 +86,7 @@ impl Duration {
/// Fails when the duration is out of bounds.
#[inline]
pub fn hours(hours: i64) -> Duration {
let secs = hours.checked_mul(&SECS_PER_HOUR).expect("Duration::hours ouf of bounds");
let secs = hours.checked_mul(SECS_PER_HOUR).expect("Duration::hours ouf of bounds");
Duration::seconds(secs)
}
@ -96,7 +95,7 @@ impl Duration {
/// Fails when the duration is out of bounds.
#[inline]
pub fn minutes(minutes: i64) -> Duration {
let secs = minutes.checked_mul(&SECS_PER_MINUTE).expect("Duration::minutes out of bounds");
let secs = minutes.checked_mul(SECS_PER_MINUTE).expect("Duration::minutes out of bounds");
Duration::seconds(secs)
}
@ -191,33 +190,64 @@ impl Duration {
/// Returns the total number of whole microseconds in the duration,
/// or `None` on overflow (exceeding 2^63 microseconds in either direction).
pub fn num_microseconds(&self) -> Option<i64> {
let secs_part = try_opt!(self.num_seconds().checked_mul(&MICROS_PER_SEC));
let secs_part = try_opt!(self.num_seconds().checked_mul(MICROS_PER_SEC));
let nanos_part = self.nanos_mod_sec() / NANOS_PER_MICRO;
secs_part.checked_add(&(nanos_part as i64))
secs_part.checked_add(nanos_part as i64)
}
/// Returns the total number of whole nanoseconds in the duration,
/// or `None` on overflow (exceeding 2^63 nanoseconds in either direction).
pub fn num_nanoseconds(&self) -> Option<i64> {
let secs_part = try_opt!(self.num_seconds().checked_mul(&(NANOS_PER_SEC as i64)));
let secs_part = try_opt!(self.num_seconds().checked_mul(NANOS_PER_SEC as i64));
let nanos_part = self.nanos_mod_sec();
secs_part.checked_add(&(nanos_part as i64))
secs_part.checked_add(nanos_part as i64)
}
}
impl num::Bounded for Duration {
#[inline] fn min_value() -> Duration { MIN }
#[inline] fn max_value() -> Duration { MAX }
}
/// Add two durations, returning `None` if overflow occured.
pub fn checked_add(&self, rhs: &Duration) -> Option<Duration> {
let mut secs = try_opt!(self.secs.checked_add(rhs.secs));
let mut nanos = self.nanos + rhs.nanos;
if nanos >= NANOS_PER_SEC {
nanos -= NANOS_PER_SEC;
secs = try_opt!(secs.checked_add(1));
}
let d = Duration { secs: secs, nanos: nanos };
// Even if d is within the bounds of i64 seconds,
// it might still overflow i64 milliseconds.
if d < MIN || d > MAX { None } else { Some(d) }
}
impl num::Zero for Duration {
/// Subtract two durations, returning `None` if overflow occured.
pub fn checked_sub(&self, rhs: &Duration) -> Option<Duration> {
let mut secs = try_opt!(self.secs.checked_sub(rhs.secs));
let mut nanos = self.nanos - rhs.nanos;
if nanos < 0 {
nanos += NANOS_PER_SEC;
secs = try_opt!(secs.checked_sub(1));
}
let d = Duration { secs: secs, nanos: nanos };
// Even if d is within the bounds of i64 seconds,
// it might still overflow i64 milliseconds.
if d < MIN || d > MAX { None } else { Some(d) }
}
/// The minimum possible `Duration`: `i64::MIN` milliseconds.
#[inline]
fn zero() -> Duration {
pub fn min_value() -> Duration { MIN }
/// The maximum possible `Duration`: `i64::MAX` milliseconds.
#[inline]
pub fn max_value() -> Duration { MAX }
/// A duration where the stored seconds and nanoseconds are equal to zero.
#[inline]
pub fn zero() -> Duration {
Duration { secs: 0, nanos: 0 }
}
/// Returns `true` if the duration equals `Duration::zero()`.
#[inline]
fn is_zero(&self) -> bool {
pub fn is_zero(&self) -> bool {
self.secs == 0 && self.nanos == 0
}
}
@ -245,21 +275,6 @@ impl Add<Duration,Duration> for Duration {
}
}
impl num::CheckedAdd for Duration {
fn checked_add(&self, rhs: &Duration) -> Option<Duration> {
let mut secs = try_opt!(self.secs.checked_add(&rhs.secs));
let mut nanos = self.nanos + rhs.nanos;
if nanos >= NANOS_PER_SEC {
nanos -= NANOS_PER_SEC;
secs = try_opt!(secs.checked_add(&1));
}
let d = Duration { secs: secs, nanos: nanos };
// Even if d is within the bounds of i64 seconds,
// it might still overflow i64 milliseconds.
if d < MIN || d > MAX { None } else { Some(d) }
}
}
impl Sub<Duration,Duration> for Duration {
fn sub(&self, rhs: &Duration) -> Duration {
let mut secs = self.secs - rhs.secs;
@ -272,21 +287,6 @@ impl Sub<Duration,Duration> for Duration {
}
}
impl num::CheckedSub for Duration {
fn checked_sub(&self, rhs: &Duration) -> Option<Duration> {
let mut secs = try_opt!(self.secs.checked_sub(&rhs.secs));
let mut nanos = self.nanos - rhs.nanos;
if nanos < 0 {
nanos += NANOS_PER_SEC;
secs = try_opt!(secs.checked_sub(&1));
}
let d = Duration { secs: secs, nanos: nanos };
// Even if d is within the bounds of i64 seconds,
// it might still overflow i64 milliseconds.
if d < MIN || d > MAX { None } else { Some(d) }
}
}
impl Mul<i32,Duration> for Duration {
fn mul(&self, rhs: &i32) -> Duration {
// Multiply nanoseconds as i64, because it cannot overflow that way.
@ -379,15 +379,12 @@ fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
mod tests {
use super::{Duration, MIN, MAX};
use {i32, i64};
use num::{Zero, CheckedAdd, CheckedSub};
use option::{Some, None};
use to_string::ToString;
#[test]
fn test_duration() {
let d: Duration = Zero::zero();
assert_eq!(d, Zero::zero());
assert!(Duration::seconds(1) != Zero::zero());
assert!(Duration::seconds(1) != Duration::zero());
assert_eq!(Duration::seconds(1) + Duration::seconds(2), Duration::seconds(3));
assert_eq!(Duration::seconds(86399) + Duration::seconds(4),
Duration::days(1) + Duration::seconds(3));
@ -403,8 +400,7 @@ mod tests {
#[test]
fn test_duration_num_days() {
let d: Duration = Zero::zero();
assert_eq!(d.num_days(), 0);
assert_eq!(Duration::zero().num_days(), 0);
assert_eq!(Duration::days(1).num_days(), 1);
assert_eq!(Duration::days(-1).num_days(), -1);
assert_eq!(Duration::seconds(86399).num_days(), 0);
@ -417,8 +413,7 @@ mod tests {
#[test]
fn test_duration_num_seconds() {
let d: Duration = Zero::zero();
assert_eq!(d.num_seconds(), 0);
assert_eq!(Duration::zero().num_seconds(), 0);
assert_eq!(Duration::seconds(1).num_seconds(), 1);
assert_eq!(Duration::seconds(-1).num_seconds(), -1);
assert_eq!(Duration::milliseconds(999).num_seconds(), 0);
@ -429,8 +424,7 @@ mod tests {
#[test]
fn test_duration_num_milliseconds() {
let d: Duration = Zero::zero();
assert_eq!(d.num_milliseconds(), 0);
assert_eq!(Duration::zero().num_milliseconds(), 0);
assert_eq!(Duration::milliseconds(1).num_milliseconds(), 1);
assert_eq!(Duration::milliseconds(-1).num_milliseconds(), -1);
assert_eq!(Duration::microseconds(999).num_milliseconds(), 0);
@ -445,8 +439,7 @@ mod tests {
#[test]
fn test_duration_num_microseconds() {
let d: Duration = Zero::zero();
assert_eq!(d.num_microseconds(), Some(0));
assert_eq!(Duration::zero().num_microseconds(), Some(0));
assert_eq!(Duration::microseconds(1).num_microseconds(), Some(1));
assert_eq!(Duration::microseconds(-1).num_microseconds(), Some(-1));
assert_eq!(Duration::nanoseconds(999).num_microseconds(), Some(0));
@ -470,8 +463,7 @@ mod tests {
#[test]
fn test_duration_num_nanoseconds() {
let d: Duration = Zero::zero();
assert_eq!(d.num_nanoseconds(), Some(0));
assert_eq!(Duration::zero().num_nanoseconds(), Some(0));
assert_eq!(Duration::nanoseconds(1).num_nanoseconds(), Some(1));
assert_eq!(Duration::nanoseconds(-1).num_nanoseconds(), Some(-1));
assert_eq!(Duration::nanoseconds(i64::MAX).num_nanoseconds(), Some(i64::MAX));
@ -504,10 +496,9 @@ mod tests {
#[test]
fn test_duration_mul() {
let d: Duration = Zero::zero();
assert_eq!(d * i32::MAX, d);
assert_eq!(d * i32::MIN, d);
assert_eq!(Duration::nanoseconds(1) * 0, Zero::zero());
assert_eq!(Duration::zero() * i32::MAX, Duration::zero());
assert_eq!(Duration::zero() * i32::MIN, Duration::zero());
assert_eq!(Duration::nanoseconds(1) * 0, Duration::zero());
assert_eq!(Duration::nanoseconds(1) * 1, Duration::nanoseconds(1));
assert_eq!(Duration::nanoseconds(1) * 1_000_000_000, Duration::seconds(1));
assert_eq!(Duration::nanoseconds(1) * -1_000_000_000, -Duration::seconds(1));
@ -522,9 +513,8 @@ mod tests {
#[test]
fn test_duration_div() {
let d: Duration = Zero::zero();
assert_eq!(d / i32::MAX, d);
assert_eq!(d / i32::MIN, d);
assert_eq!(Duration::zero() / i32::MAX, Duration::zero());
assert_eq!(Duration::zero() / i32::MIN, Duration::zero());
assert_eq!(Duration::nanoseconds(123_456_789) / 1, Duration::nanoseconds(123_456_789));
assert_eq!(Duration::nanoseconds(123_456_789) / -1, -Duration::nanoseconds(123_456_789));
assert_eq!(-Duration::nanoseconds(123_456_789) / -1, Duration::nanoseconds(123_456_789));
@ -540,8 +530,7 @@ mod tests {
#[test]
fn test_duration_fmt() {
let d: Duration = Zero::zero();
assert_eq!(d.to_string(), "PT0S".to_string());
assert_eq!(Duration::zero().to_string(), "PT0S".to_string());
assert_eq!(Duration::days(42).to_string(), "P42D".to_string());
assert_eq!(Duration::days(-42).to_string(), "-P42D".to_string());
assert_eq!(Duration::seconds(42).to_string(), "PT42S".to_string());

View File

@ -63,7 +63,7 @@ impl ParseSess {
pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId {
let v = self.node_id.get();
match v.checked_add(&count) {
match v.checked_add(count) {
Some(next) => { self.node_id.set(next); }
None => panic!("Input too large, ran out of node ids!")
}