From e51cc089da7f5a067d348ee48f494c5bca662f95 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Mon, 10 Nov 2014 00:11:28 +1100 Subject: [PATCH] Move checked arithmetic operators into Int trait --- src/etc/vim/syntax/rust.vim | 2 +- src/libarena/lib.rs | 10 +- src/libcollections/vec.rs | 10 +- src/libcore/iter.rs | 34 ++- src/libcore/num/mod.rs | 411 +++++++++++++-------------- src/libcore/prelude.rs | 2 +- src/libcore/slice.rs | 4 +- src/libcore/str.rs | 4 +- src/libcoretest/num/int_macros.rs | 7 +- src/libcoretest/num/uint_macros.rs | 5 +- src/librand/distributions/mod.rs | 2 +- src/librustc/middle/trans/type_of.rs | 4 +- src/librustc_back/sha2.rs | 4 +- src/libserialize/json.rs | 2 +- src/libstd/collections/hash/table.rs | 8 +- src/libstd/num/mod.rs | 43 ++- src/libstd/num/strconv.rs | 8 +- src/libstd/prelude.rs | 2 +- src/libstd/time/duration.rs | 131 ++++----- src/libsyntax/parse/mod.rs | 2 +- 20 files changed, 324 insertions(+), 371 deletions(-) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 0ef9734cf2e..7033f493f0f 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -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 diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index fb091ec7f84..1e9ab34b0ac 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -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(capacity: uint) -> uint { let mut size = mem::size_of::>(); size = round_up(size, mem::min_align_of::()); let elem_size = mem::size_of::(); - 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 TypedArenaChunk { #[inline] fn end(&self) -> *const u8 { unsafe { - let size = mem::size_of::().checked_mul(&self.capacity).unwrap(); + let size = mem::size_of::().checked_mul(self.capacity).unwrap(); self.start().offset(size as int) } } @@ -481,7 +481,7 @@ impl TypedArena { 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::::new(chunk, new_capacity); self.ptr.set((*chunk).start() as *const T); self.end.set((*chunk).end() as *const T); diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 3ef7667dd8f..9f51c6d1b5e 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -161,7 +161,7 @@ impl Vec { } else if capacity == 0 { Vec::new() } else { - let size = capacity.checked_mul(&mem::size_of::()) + let size = capacity.checked_mul(mem::size_of::()) .expect("capacity overflow"); let ptr = unsafe { allocate(size, mem::min_align_of::()) }; Vec { ptr: ptr as *mut T, len: 0, cap: capacity } @@ -601,7 +601,7 @@ impl Vec { #[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 Vec { #[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 Vec { pub fn push(&mut self, value: T) { if mem::size_of::() == 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 Vec { if mem::size_of::() == 0 { return } if capacity > self.cap { - let size = capacity.checked_mul(&mem::size_of::()) + let size = capacity.checked_mul(mem::size_of::()) .expect("capacity overflow"); unsafe { self.ptr = alloc_or_realloc(self.ptr, self.cap * mem::size_of::(), size); diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 73d3aef5ee0..0effc4b19dc 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -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, U: Iterator> Iterator for Chain { 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> Iterator for Peekable { 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, B, U: Iterator> Iterator 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 + PartialOrd + Clone + ToPrimitive> Iterator for Range { // 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 + PartialOrd + Clone + ToPrimitive> Iterator for Range { }, 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 + PartialOrd + Clone + ToPrimitive> Iterator 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 { /// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping. #[inline] -pub fn range_step(start: A, stop: A, step: A) -> RangeStep { +pub fn range_step(start: A, stop: A, step: A) -> RangeStep { let rev = step < Zero::zero(); RangeStep{state: start, stop: stop, step: step, rev: rev} } -impl Iterator for RangeStep { +impl Iterator for RangeStep { #[inline] fn next(&mut self) -> Option { 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 { /// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping. #[inline] -pub fn range_step_inclusive(start: A, stop: A, - step: A) -> RangeStepInclusive { +pub fn range_step_inclusive(start: A, stop: A, step: A) -> RangeStepInclusive { let rev = step < Zero::zero(); RangeStepInclusive{state: start, stop: stop, step: step, rev: rev, done: false} } -impl Iterator for RangeStepInclusive { +impl Iterator for RangeStepInclusive { #[inline] fn next(&mut self) -> Option { 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 } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 9726b7b3978..b26e8dd83fe 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -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 + BitAnd @@ -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; + + /// 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; + + /// 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; + + /// 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; + /// 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 { - /// 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; -} - -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 { - /// 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; -} - -#[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 { - /// 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; -} - -#[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 { - /// 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; -} - -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 { diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 17f7a04819f..045aca8aa0a 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -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}; diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index fd01ed69f81..7b223dc501b 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -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)) } } } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 3aee6867fd5..b3bed201598 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -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 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))) } } diff --git a/src/libcoretest/num/int_macros.rs b/src/libcoretest/num/int_macros.rs index 21b8f31dbf0..51af2e2916d 100644 --- a/src/libcoretest/num/int_macros.rs +++ b/src/libcoretest/num/int_macros.rs @@ -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); } } diff --git a/src/libcoretest/num/uint_macros.rs b/src/libcoretest/num/uint_macros.rs index e59e2378ba2..1d3f1718d72 100644 --- a/src/libcoretest/num/uint_macros.rs +++ b/src/libcoretest/num/uint_macros.rs @@ -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); } } )) diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index 7d454e49006..26d5d3fb2f9 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -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") diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index d1b8f767bc8..5e2df42d2d6 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -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) } } diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs index 96a15213c5e..71d6ad791ec 100644 --- a/src/librustc_back/sha2.rs +++ b/src/librustc_back/sha2.rs @@ -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(bits: T, bytes: T) -> T { +fn add_bytes_to_bits(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.") } diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 77313517585..f387b660ed1 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -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; } diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index b39b15b3eb9..dd65a00d110 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -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 RawTable { vals_size, min_align_of::< V >()); // One check for overflow that covers calculation and rounding of size. - let size_of_bucket = size_of::().checked_add(&size_of::()).unwrap() - .checked_add(&size_of::()).unwrap(); - assert!(size >= capacity.checked_mul(&size_of_bucket) + let size_of_bucket = size_of::().checked_add(size_of::()).unwrap() + .checked_add(size_of::()).unwrap(); + assert!(size >= capacity.checked_mul(size_of_bucket) .expect("capacity overflow"), "capacity overflow"); diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index fefde35ea21..2be88e01eed 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -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( diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 088ea89818e..875d03d6c25 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -601,11 +601,11 @@ pub fn from_str_radix_int(src: &str, radix: uint) -> Option { 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(src: &str, radix: uint) -> Option { 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, }; diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index f1090e75127..3c20d205b77 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -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; diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index c3adae8cff8..6afeb76b83f 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -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 { - 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 { - 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 { + 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 { + 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 for Duration { } } -impl num::CheckedAdd for Duration { - fn checked_add(&self, rhs: &Duration) -> Option { - 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 for Duration { fn sub(&self, rhs: &Duration) -> Duration { let mut secs = self.secs - rhs.secs; @@ -272,21 +287,6 @@ impl Sub for Duration { } } -impl num::CheckedSub for Duration { - fn checked_sub(&self, rhs: &Duration) -> Option { - 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 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()); diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 996708b2174..0f364d1ba0b 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -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!") }