Add core::num::wrapping
and fix overflow errors.
Many of the core rust libraries have places that rely on integer wrapping behaviour. These places have been altered to use the wrapping_* methods: * core:#️⃣:sip - A number of macros * core::str - The `maximal_suffix` method in `TwoWaySearcher` * rustc::util::nodemap - Implementation of FnvHash * rustc_back::sha2 - A number of macros and other places * rand::isaac - Isaac64Rng, changed to use the Wrapping helper type Some places had "benign" underflow. This is when underflow or overflow occurs, but the unspecified value is not used due to other conditions. * collections::bit::Bitv - underflow when `self.nbits` is zero. * collections:#️⃣:{map,table} - Underflow when searching an empty table. Did cause undefined behaviour in this case due to an out-of-bounds ptr::offset based on the underflowed index. However the resulting pointers would never be read from. * syntax::ext::deriving::encodable - Underflow when calculating the index of the last field in a variant with no fields. These cases were altered to avoid the underflow, often by moving the underflowing operation to a place where underflow could not happen. There was one case that relied on the fact that unsigned arithmetic and two's complement arithmetic are identical with wrapping semantics. This was changed to use the wrapping_* methods. Finally, the calculation of variant discriminants could overflow if the preceeding discriminant was `U64_MAX`. The logic in `rustc::middle::ty` for this was altered to avoid the overflow completely, while the remaining places were changed to use wrapping methods. This is because `rustc::middle::ty::enum_variants` now throws an error when the calculated discriminant value overflows a `u64`. This behaviour can be triggered by the following code: ``` enum Foo { A = U64_MAX, B } ``` This commit also implements the remaining integer operators for Wrapped<T>.
This commit is contained in:
parent
cdfff9db35
commit
1246d4067f
19 changed files with 286 additions and 95 deletions
|
@ -818,11 +818,11 @@ impl BitVec {
|
||||||
let full_value = if value { !0 } else { 0 };
|
let full_value = if value { !0 } else { 0 };
|
||||||
|
|
||||||
// Correct the old tail word, setting or clearing formerly unused bits
|
// Correct the old tail word, setting or clearing formerly unused bits
|
||||||
let old_last_word = blocks_for_bits(self.nbits) - 1;
|
let num_cur_blocks = blocks_for_bits(self.nbits);
|
||||||
if self.nbits % u32::BITS as usize > 0 {
|
if self.nbits % u32::BITS as usize > 0 {
|
||||||
let mask = mask_for_bits(self.nbits);
|
let mask = mask_for_bits(self.nbits);
|
||||||
if value {
|
if value {
|
||||||
self.storage[old_last_word] |= !mask;
|
self.storage[num_cur_blocks - 1] |= !mask;
|
||||||
} else {
|
} else {
|
||||||
// Extra bits are already zero by invariant.
|
// Extra bits are already zero by invariant.
|
||||||
}
|
}
|
||||||
|
@ -830,7 +830,7 @@ impl BitVec {
|
||||||
|
|
||||||
// Fill in words after the old tail word
|
// Fill in words after the old tail word
|
||||||
let stop_idx = cmp::min(self.storage.len(), new_nblocks);
|
let stop_idx = cmp::min(self.storage.len(), new_nblocks);
|
||||||
for idx in old_last_word + 1..stop_idx {
|
for idx in num_cur_blocks..stop_idx {
|
||||||
self.storage[idx] = full_value;
|
self.storage[idx] = full_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
use default::Default;
|
use default::Default;
|
||||||
|
use num::wrapping::WrappingOps;
|
||||||
use super::Hasher;
|
use super::Hasher;
|
||||||
|
|
||||||
/// An implementation of SipHash 2-4.
|
/// An implementation of SipHash 2-4.
|
||||||
|
@ -71,17 +71,17 @@ macro_rules! u8to64_le {
|
||||||
|
|
||||||
macro_rules! rotl {
|
macro_rules! rotl {
|
||||||
($x:expr, $b:expr) =>
|
($x:expr, $b:expr) =>
|
||||||
(($x << $b) | ($x >> (64 - $b)))
|
(($x << $b) | ($x >> (64.wrapping_sub($b))))
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! compress {
|
macro_rules! compress {
|
||||||
($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
|
($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
|
||||||
({
|
({
|
||||||
$v0 += $v1; $v1 = rotl!($v1, 13); $v1 ^= $v0;
|
$v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0;
|
||||||
$v0 = rotl!($v0, 32);
|
$v0 = rotl!($v0, 32);
|
||||||
$v2 += $v3; $v3 = rotl!($v3, 16); $v3 ^= $v2;
|
$v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2;
|
||||||
$v0 += $v3; $v3 = rotl!($v3, 21); $v3 ^= $v0;
|
$v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0;
|
||||||
$v2 += $v1; $v1 = rotl!($v1, 17); $v1 ^= $v2;
|
$v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2;
|
||||||
$v2 = rotl!($v2, 32);
|
$v2 = rotl!($v2, 32);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,9 @@ use option::Option::{self, Some, None};
|
||||||
use result::Result::{self, Ok, Err};
|
use result::Result::{self, Ok, Err};
|
||||||
use str::{FromStr, StrExt};
|
use str::{FromStr, StrExt};
|
||||||
|
|
||||||
|
#[unstable(feature = "core", reason = "may be removed or relocated")]
|
||||||
|
pub mod wrapping;
|
||||||
|
|
||||||
/// A built-in signed or unsigned integer.
|
/// A built-in signed or unsigned integer.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait Int
|
pub trait Int
|
||||||
|
|
153
src/libcore/num/wrapping.rs
Normal file
153
src/libcore/num/wrapping.rs
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
|
use ops::*;
|
||||||
|
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
use intrinsics::{overflowing_add, overflowing_sub, overflowing_mul};
|
||||||
|
|
||||||
|
pub trait WrappingOps {
|
||||||
|
fn wrapping_add(self, rhs: Self) -> Self;
|
||||||
|
fn wrapping_sub(self, rhs: Self) -> Self;
|
||||||
|
fn wrapping_mul(self, rhs: Self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
macro_rules! wrapping_impl {
|
||||||
|
($($t:ty)*) => ($(
|
||||||
|
impl WrappingOps for $t {
|
||||||
|
#[inline(always)]
|
||||||
|
fn wrapping_add(self, rhs: $t) -> $t {
|
||||||
|
unsafe {
|
||||||
|
overflowing_add(self, rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn wrapping_sub(self, rhs: $t) -> $t {
|
||||||
|
unsafe {
|
||||||
|
overflowing_sub(self, rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn wrapping_mul(self, rhs: $t) -> $t {
|
||||||
|
unsafe {
|
||||||
|
overflowing_mul(self, rhs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
|
macro_rules! wrapping_impl {
|
||||||
|
($($t:ty)*) => ($(
|
||||||
|
impl WrappingOps for $t {
|
||||||
|
#[inline(always)]
|
||||||
|
fn wrapping_add(self, rhs: $t) -> $t {
|
||||||
|
self + rhs
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn wrapping_sub(self, rhs: $t) -> $t {
|
||||||
|
self - rhs
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn wrapping_mul(self, rhs: $t) -> $t {
|
||||||
|
self * rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*)
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapping_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }
|
||||||
|
|
||||||
|
#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
|
||||||
|
#[derive(PartialEq,Eq,PartialOrd,Ord,Clone,Copy)]
|
||||||
|
pub struct Wrapping<T>(pub T);
|
||||||
|
|
||||||
|
impl<T:WrappingOps> Add for Wrapping<T> {
|
||||||
|
type Output = Wrapping<T>;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn add(self, other: Wrapping<T>) -> Wrapping<T> {
|
||||||
|
Wrapping(self.0.wrapping_add(other.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:WrappingOps> Sub for Wrapping<T> {
|
||||||
|
type Output = Wrapping<T>;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn sub(self, other: Wrapping<T>) -> Wrapping<T> {
|
||||||
|
Wrapping(self.0.wrapping_sub(other.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:WrappingOps> Mul for Wrapping<T> {
|
||||||
|
type Output = Wrapping<T>;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn mul(self, other: Wrapping<T>) -> Wrapping<T> {
|
||||||
|
Wrapping(self.0.wrapping_mul(other.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:WrappingOps+Not<Output=T>> Not for Wrapping<T> {
|
||||||
|
type Output = Wrapping<T>;
|
||||||
|
|
||||||
|
fn not(self) -> Wrapping<T> {
|
||||||
|
Wrapping(!self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:WrappingOps+BitXor<Output=T>> BitXor for Wrapping<T> {
|
||||||
|
type Output = Wrapping<T>;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn bitxor(self, other: Wrapping<T>) -> Wrapping<T> {
|
||||||
|
Wrapping(self.0 ^ other.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:WrappingOps+BitOr<Output=T>> BitOr for Wrapping<T> {
|
||||||
|
type Output = Wrapping<T>;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn bitor(self, other: Wrapping<T>) -> Wrapping<T> {
|
||||||
|
Wrapping(self.0 | other.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:WrappingOps+BitAnd<Output=T>> BitAnd for Wrapping<T> {
|
||||||
|
type Output = Wrapping<T>;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn bitand(self, other: Wrapping<T>) -> Wrapping<T> {
|
||||||
|
Wrapping(self.0 & other.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:WrappingOps+Shl<uint,Output=T>> Shl<uint> for Wrapping<T> {
|
||||||
|
type Output = Wrapping<T>;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn shl(self, other: uint) -> Wrapping<T> {
|
||||||
|
Wrapping(self.0 << other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:WrappingOps+Shr<uint,Output=T>> Shr<uint> for Wrapping<T> {
|
||||||
|
type Output = Wrapping<T>;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn shr(self, other: uint) -> Wrapping<T> {
|
||||||
|
Wrapping(self.0 >> other)
|
||||||
|
}
|
||||||
|
}
|
|
@ -830,6 +830,7 @@ impl TwoWaySearcher {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn maximal_suffix(arr: &[u8], reversed: bool) -> (usize, usize) {
|
fn maximal_suffix(arr: &[u8], reversed: bool) -> (usize, usize) {
|
||||||
|
use num::wrapping::WrappingOps;
|
||||||
let mut left = -1; // Corresponds to i in the paper
|
let mut left = -1; // Corresponds to i in the paper
|
||||||
let mut right = 0; // Corresponds to j in the paper
|
let mut right = 0; // Corresponds to j in the paper
|
||||||
let mut offset = 1; // Corresponds to k in the paper
|
let mut offset = 1; // Corresponds to k in the paper
|
||||||
|
@ -839,17 +840,17 @@ impl TwoWaySearcher {
|
||||||
let a;
|
let a;
|
||||||
let b;
|
let b;
|
||||||
if reversed {
|
if reversed {
|
||||||
a = arr[left + offset];
|
a = arr[left.wrapping_add(offset)];
|
||||||
b = arr[right + offset];
|
b = arr[right + offset];
|
||||||
} else {
|
} else {
|
||||||
a = arr[right + offset];
|
a = arr[right + offset];
|
||||||
b = arr[left + offset];
|
b = arr[left.wrapping_add(offset)];
|
||||||
}
|
}
|
||||||
if a < b {
|
if a < b {
|
||||||
// Suffix is smaller, period is entire prefix so far.
|
// Suffix is smaller, period is entire prefix so far.
|
||||||
right += offset;
|
right += offset;
|
||||||
offset = 1;
|
offset = 1;
|
||||||
period = right - left;
|
period = right.wrapping_sub(left);
|
||||||
} else if a == b {
|
} else if a == b {
|
||||||
// Advance through repetition of the current period.
|
// Advance through repetition of the current period.
|
||||||
if offset == period {
|
if offset == period {
|
||||||
|
@ -866,7 +867,7 @@ impl TwoWaySearcher {
|
||||||
period = 1;
|
period = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(left + 1, period)
|
(left.wrapping_add(1), period)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
use core::prelude::{PartialOrd};
|
use core::prelude::{PartialOrd};
|
||||||
use core::num::Int;
|
use core::num::Int;
|
||||||
|
use core::num::wrapping::WrappingOps;
|
||||||
|
|
||||||
use Rng;
|
use Rng;
|
||||||
use distributions::{Sample, IndependentSample};
|
use distributions::{Sample, IndependentSample};
|
||||||
|
@ -97,7 +98,7 @@ macro_rules! integer_impl {
|
||||||
// bijection.
|
// bijection.
|
||||||
|
|
||||||
fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
|
fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
|
||||||
let range = high as $unsigned - low as $unsigned;
|
let range = (high as $unsigned).wrapping_sub(low as $unsigned);
|
||||||
let unsigned_max: $unsigned = Int::max_value();
|
let unsigned_max: $unsigned = Int::max_value();
|
||||||
|
|
||||||
// this is the largest number that fits into $unsigned
|
// this is the largest number that fits into $unsigned
|
||||||
|
|
|
@ -304,7 +304,7 @@ impl Isaac64Rng {
|
||||||
fn init(&mut self, use_rsl: bool) {
|
fn init(&mut self, use_rsl: bool) {
|
||||||
macro_rules! init {
|
macro_rules! init {
|
||||||
($var:ident) => (
|
($var:ident) => (
|
||||||
let mut $var = 0x9e3779b97f4a7c13;
|
let mut $var = Wrapping(0x9e3779b97f4a7c13);
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
init!(a); init!(b); init!(c); init!(d);
|
init!(a); init!(b); init!(c); init!(d);
|
||||||
|
@ -312,14 +312,14 @@ impl Isaac64Rng {
|
||||||
|
|
||||||
macro_rules! mix {
|
macro_rules! mix {
|
||||||
() => {{
|
() => {{
|
||||||
a-=e; f^=h>>9; h+=a;
|
a=a-e; f=f^h>>9; h=h+a;
|
||||||
b-=f; g^=a<<9; a+=b;
|
b=b-f; g=g^a<<9; a=a+b;
|
||||||
c-=g; h^=b>>23; b+=c;
|
c=c-g; h=h^b>>23; b=b+c;
|
||||||
d-=h; a^=c<<15; c+=d;
|
d=d-h; a=a^c<<15; c=c+d;
|
||||||
e-=a; b^=d>>14; d+=e;
|
e=e-a; b=b^d>>14; d=d+e;
|
||||||
f-=b; c^=e<<20; e+=f;
|
f=f-b; c=c^e<<20; e=e+f;
|
||||||
g-=c; d^=f>>17; f+=g;
|
g=g-c; d=d^f>>17; f=f+g;
|
||||||
h-=d; e^=g<<14; g+=h;
|
h=h-d; e=e^g<<14; g=g+h;
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,15 +331,15 @@ impl Isaac64Rng {
|
||||||
macro_rules! memloop {
|
macro_rules! memloop {
|
||||||
($arr:expr) => {{
|
($arr:expr) => {{
|
||||||
for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
|
for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
|
||||||
a+=$arr[i ]; b+=$arr[i+1];
|
a=a+Wrapping($arr[i ]); b=b+Wrapping($arr[i+1]);
|
||||||
c+=$arr[i+2]; d+=$arr[i+3];
|
c=c+Wrapping($arr[i+2]); d=d+Wrapping($arr[i+3]);
|
||||||
e+=$arr[i+4]; f+=$arr[i+5];
|
e=e+Wrapping($arr[i+4]); f=f+Wrapping($arr[i+5]);
|
||||||
g+=$arr[i+6]; h+=$arr[i+7];
|
g=g+Wrapping($arr[i+6]); h=h+Wrapping($arr[i+7]);
|
||||||
mix!();
|
mix!();
|
||||||
self.mem[i ]=a; self.mem[i+1]=b;
|
self.mem[i ]=a.0; self.mem[i+1]=b.0;
|
||||||
self.mem[i+2]=c; self.mem[i+3]=d;
|
self.mem[i+2]=c.0; self.mem[i+3]=d.0;
|
||||||
self.mem[i+4]=e; self.mem[i+5]=f;
|
self.mem[i+4]=e.0; self.mem[i+5]=f.0;
|
||||||
self.mem[i+6]=g; self.mem[i+7]=h;
|
self.mem[i+6]=g.0; self.mem[i+7]=h.0;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -349,10 +349,10 @@ impl Isaac64Rng {
|
||||||
} else {
|
} else {
|
||||||
for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
|
for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
|
||||||
mix!();
|
mix!();
|
||||||
self.mem[i ]=a; self.mem[i+1]=b;
|
self.mem[i ]=a.0; self.mem[i+1]=b.0;
|
||||||
self.mem[i+2]=c; self.mem[i+3]=d;
|
self.mem[i+2]=c.0; self.mem[i+3]=d.0;
|
||||||
self.mem[i+4]=e; self.mem[i+5]=f;
|
self.mem[i+4]=e.0; self.mem[i+5]=f.0;
|
||||||
self.mem[i+6]=g; self.mem[i+7]=h;
|
self.mem[i+6]=g.0; self.mem[i+7]=h.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,8 +363,8 @@ impl Isaac64Rng {
|
||||||
fn isaac64(&mut self) {
|
fn isaac64(&mut self) {
|
||||||
self.c += 1;
|
self.c += 1;
|
||||||
// abbreviations
|
// abbreviations
|
||||||
let mut a = self.a;
|
let mut a = Wrapping(self.a);
|
||||||
let mut b = self.b + self.c;
|
let mut b = Wrapping(self.b) + Wrapping(self.c);
|
||||||
const MIDPOINT: uint = RAND_SIZE_64 / 2;
|
const MIDPOINT: uint = RAND_SIZE_64 / 2;
|
||||||
const MP_VEC: [(uint, uint); 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
|
const MP_VEC: [(uint, uint); 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
|
||||||
macro_rules! ind {
|
macro_rules! ind {
|
||||||
|
@ -383,13 +383,13 @@ impl Isaac64Rng {
|
||||||
let mix = if $j == 0 {!mix} else {mix};
|
let mix = if $j == 0 {!mix} else {mix};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let x = *self.mem.get_unchecked(base + mr_offset);
|
let x = Wrapping(*self.mem.get_unchecked(base + mr_offset));
|
||||||
a = mix + *self.mem.get_unchecked(base + m2_offset);
|
a = mix + Wrapping(*self.mem.get_unchecked(base + m2_offset));
|
||||||
let y = ind!(x) + a + b;
|
let y = Wrapping(ind!(x.0)) + a + b;
|
||||||
*self.mem.get_unchecked_mut(base + mr_offset) = y;
|
*self.mem.get_unchecked_mut(base + mr_offset) = y.0;
|
||||||
|
|
||||||
b = ind!(y >> RAND_SIZE_64_LEN) + x;
|
b = Wrapping(ind!(y.0 >> RAND_SIZE_64_LEN)) + x;
|
||||||
*self.rsl.get_unchecked_mut(base + mr_offset) = b;
|
*self.rsl.get_unchecked_mut(base + mr_offset) = b.0;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -401,13 +401,13 @@ impl Isaac64Rng {
|
||||||
let mix = if $j == 0 {!mix} else {mix};
|
let mix = if $j == 0 {!mix} else {mix};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let x = *self.mem.get_unchecked(base + mr_offset);
|
let x = Wrapping(*self.mem.get_unchecked(base + mr_offset));
|
||||||
a = mix + *self.mem.get_unchecked(base + m2_offset);
|
a = mix + Wrapping(*self.mem.get_unchecked(base + m2_offset));
|
||||||
let y = ind!(x) + a + b;
|
let y = Wrapping(ind!(x.0)) + a + b;
|
||||||
*self.mem.get_unchecked_mut(base + mr_offset) = y;
|
*self.mem.get_unchecked_mut(base + mr_offset) = y.0;
|
||||||
|
|
||||||
b = ind!(y >> RAND_SIZE_64_LEN) + x;
|
b = Wrapping(ind!(y.0 >> RAND_SIZE_64_LEN)) + x;
|
||||||
*self.rsl.get_unchecked_mut(base + mr_offset) = b;
|
*self.rsl.get_unchecked_mut(base + mr_offset) = b.0;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -419,8 +419,8 @@ impl Isaac64Rng {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.a = a;
|
self.a = a.0;
|
||||||
self.b = b;
|
self.b = b.0;
|
||||||
self.cnt = RAND_SIZE_64;
|
self.cnt = RAND_SIZE_64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -783,7 +783,7 @@ pub fn get_enum_variants<'tcx>(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::Nod
|
||||||
_ => { /* empty */ }
|
_ => { /* empty */ }
|
||||||
}
|
}
|
||||||
let old_disr_val = disr_val;
|
let old_disr_val = disr_val;
|
||||||
disr_val += 1;
|
disr_val = disr_val.wrapping_add(1);
|
||||||
Rc::new(ty::VariantInfo {
|
Rc::new(ty::VariantInfo {
|
||||||
args: arg_tys,
|
args: arg_tys,
|
||||||
arg_names: arg_names,
|
arg_names: arg_names,
|
||||||
|
|
|
@ -347,7 +347,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
|
||||||
|
|
||||||
ecx.tcx.map.with_path(variant.node.id, |path| encode_path(rbml_w, path));
|
ecx.tcx.map.with_path(variant.node.id, |path| encode_path(rbml_w, path));
|
||||||
rbml_w.end_tag();
|
rbml_w.end_tag();
|
||||||
disr_val += 1;
|
disr_val = disr_val.wrapping_add(1);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,7 +204,9 @@ impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> {
|
||||||
pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId {
|
pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId {
|
||||||
// from_id_range should be non-empty
|
// from_id_range should be non-empty
|
||||||
assert!(!self.from_id_range.empty());
|
assert!(!self.from_id_range.empty());
|
||||||
(id - self.from_id_range.min + self.to_id_range.min)
|
// Use wrapping arithmetic because otherwise it introduces control flow.
|
||||||
|
// Maybe we should just have the control flow? -- aatch
|
||||||
|
(id.wrapping_sub(self.from_id_range.min).wrapping_add(self.to_id_range.min))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates an EXTERNAL def-id, converting the crate number from the one used in the encoded
|
/// Translates an EXTERNAL def-id, converting the crate number from the one used in the encoded
|
||||||
|
|
|
@ -5333,6 +5333,7 @@ pub fn type_is_empty(cx: &ctxt, ty: Ty) -> bool {
|
||||||
|
|
||||||
pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
||||||
-> Rc<Vec<Rc<VariantInfo<'tcx>>>> {
|
-> Rc<Vec<Rc<VariantInfo<'tcx>>>> {
|
||||||
|
use std::num::Int; // For checked_add
|
||||||
memoized(&cx.enum_var_cache, id, |id: ast::DefId| {
|
memoized(&cx.enum_var_cache, id, |id: ast::DefId| {
|
||||||
if ast::LOCAL_CRATE != id.krate {
|
if ast::LOCAL_CRATE != id.krate {
|
||||||
Rc::new(csearch::get_enum_variants(cx, id))
|
Rc::new(csearch::get_enum_variants(cx, id))
|
||||||
|
@ -5349,11 +5350,7 @@ pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
||||||
let mut last_discriminant: Option<Disr> = None;
|
let mut last_discriminant: Option<Disr> = None;
|
||||||
Rc::new(enum_definition.variants.iter().map(|variant| {
|
Rc::new(enum_definition.variants.iter().map(|variant| {
|
||||||
|
|
||||||
let mut discriminant = match last_discriminant {
|
let mut discriminant = INITIAL_DISCRIMINANT_VALUE;
|
||||||
Some(val) => val + 1,
|
|
||||||
None => INITIAL_DISCRIMINANT_VALUE
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(ref e) = variant.node.disr_expr {
|
if let Some(ref e) = variant.node.disr_expr {
|
||||||
// Preserve all values, and prefer signed.
|
// Preserve all values, and prefer signed.
|
||||||
let ty = Some(cx.types.i64);
|
let ty = Some(cx.types.i64);
|
||||||
|
@ -5373,7 +5370,19 @@ pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
||||||
"expected constant: {}", err);
|
"expected constant: {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
} else {
|
||||||
|
if let Some(val) = last_discriminant {
|
||||||
|
if let Some(v) = val.checked_add(1) {
|
||||||
|
discriminant = v
|
||||||
|
} else {
|
||||||
|
cx.sess.span_err(
|
||||||
|
variant.span,
|
||||||
|
&format!("Discriminant overflowed!"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
discriminant = INITIAL_DISCRIMINANT_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
last_discriminant = Some(discriminant);
|
last_discriminant = Some(discriminant);
|
||||||
Rc::new(VariantInfo::from_ast_variant(cx, &**variant,
|
Rc::new(VariantInfo::from_ast_variant(cx, &**variant,
|
||||||
|
|
|
@ -57,7 +57,7 @@ impl Hasher for FnvHasher {
|
||||||
let FnvHasher(mut hash) = *self;
|
let FnvHasher(mut hash) = *self;
|
||||||
for byte in bytes {
|
for byte in bytes {
|
||||||
hash = hash ^ (*byte as u64);
|
hash = hash ^ (*byte as u64);
|
||||||
hash = hash * 0x100000001b3;
|
hash = hash.wrapping_mul(0x100000001b3);
|
||||||
}
|
}
|
||||||
*self = FnvHasher(hash);
|
*self = FnvHasher(hash);
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,17 +347,19 @@ impl Engine256State {
|
||||||
// Sha-512 and Sha-256 use basically the same calculations which are implemented
|
// Sha-512 and Sha-256 use basically the same calculations which are implemented
|
||||||
// by these macros. Inlining the calculations seems to result in better generated code.
|
// by these macros. Inlining the calculations seems to result in better generated code.
|
||||||
macro_rules! schedule_round { ($t:expr) => (
|
macro_rules! schedule_round { ($t:expr) => (
|
||||||
w[$t] = sigma1(w[$t - 2]) + w[$t - 7] + sigma0(w[$t - 15]) + w[$t - 16];
|
w[$t] = sigma1(w[$t - 2]).wrapping_add(w[$t - 7])
|
||||||
)
|
.wrapping_add(sigma0(w[$t - 15])).wrapping_add(w[$t - 16]);
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! sha2_round {
|
macro_rules! sha2_round {
|
||||||
($A:ident, $B:ident, $C:ident, $D:ident,
|
($A:ident, $B:ident, $C:ident, $D:ident,
|
||||||
$E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => (
|
$E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => (
|
||||||
{
|
{
|
||||||
$H += sum1($E) + ch($E, $F, $G) + $K[$t] + w[$t];
|
$H = $H.wrapping_add(sum1($E)).wrapping_add(ch($E, $F, $G))
|
||||||
$D += $H;
|
.wrapping_add($K[$t]).wrapping_add(w[$t]);
|
||||||
$H += sum0($A) + maj($A, $B, $C);
|
$D = $D.wrapping_add($H);
|
||||||
|
$H = $H.wrapping_add(sum0($A)).wrapping_add(maj($A, $B, $C));
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -397,14 +399,14 @@ impl Engine256State {
|
||||||
sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
|
sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.h0 += a;
|
self.h0 = self.h0.wrapping_add(a);
|
||||||
self.h1 += b;
|
self.h1 = self.h1.wrapping_add(b);
|
||||||
self.h2 += c;
|
self.h2 = self.h2.wrapping_add(c);
|
||||||
self.h3 += d;
|
self.h3 = self.h3.wrapping_add(d);
|
||||||
self.h4 += e;
|
self.h4 = self.h4.wrapping_add(e);
|
||||||
self.h5 += f;
|
self.h5 = self.h5.wrapping_add(f);
|
||||||
self.h6 += g;
|
self.h6 = self.h6.wrapping_add(g);
|
||||||
self.h7 += h;
|
self.h7 = self.h7.wrapping_add(h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4554,6 +4554,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
||||||
id: ast::NodeId,
|
id: ast::NodeId,
|
||||||
hint: attr::ReprAttr)
|
hint: attr::ReprAttr)
|
||||||
-> Vec<Rc<ty::VariantInfo<'tcx>>> {
|
-> Vec<Rc<ty::VariantInfo<'tcx>>> {
|
||||||
|
use std::num::Int;
|
||||||
|
|
||||||
let rty = ty::node_id_to_type(ccx.tcx, id);
|
let rty = ty::node_id_to_type(ccx.tcx, id);
|
||||||
let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
|
let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
|
||||||
|
@ -4565,7 +4566,13 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
||||||
// If the discriminant value is specified explicitly in the enum check whether the
|
// If the discriminant value is specified explicitly in the enum check whether the
|
||||||
// initialization expression is valid, otherwise use the last value plus one.
|
// initialization expression is valid, otherwise use the last value plus one.
|
||||||
let mut current_disr_val = match prev_disr_val {
|
let mut current_disr_val = match prev_disr_val {
|
||||||
Some(prev_disr_val) => prev_disr_val + 1,
|
Some(prev_disr_val) => {
|
||||||
|
if let Some(v) = prev_disr_val.checked_add(1) {
|
||||||
|
v
|
||||||
|
} else {
|
||||||
|
ty::INITIAL_DISCRIMINANT_VALUE
|
||||||
|
}
|
||||||
|
}
|
||||||
None => ty::INITIAL_DISCRIMINANT_VALUE
|
None => ty::INITIAL_DISCRIMINANT_VALUE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -314,6 +314,13 @@ fn search_hashed<K, V, M, F>(table: M,
|
||||||
M: Deref<Target=RawTable<K, V>>,
|
M: Deref<Target=RawTable<K, V>>,
|
||||||
F: FnMut(&K) -> bool,
|
F: FnMut(&K) -> bool,
|
||||||
{
|
{
|
||||||
|
// This is the only function where capacity can be zero. To avoid
|
||||||
|
// undefined behaviour when Bucket::new gets the raw bucket in this
|
||||||
|
// case, immediately return the appropriate search result.
|
||||||
|
if table.capacity() == 0 {
|
||||||
|
return TableRef(table);
|
||||||
|
}
|
||||||
|
|
||||||
let size = table.size();
|
let size = table.size();
|
||||||
let mut probe = Bucket::new(table, hash);
|
let mut probe = Bucket::new(table, hash);
|
||||||
let ib = probe.index();
|
let ib = probe.index();
|
||||||
|
|
|
@ -224,6 +224,9 @@ impl<K, V, M: Deref<Target=RawTable<K, V>>> Bucket<K, V, M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn at_index(table: M, ib_index: usize) -> Bucket<K, V, M> {
|
pub fn at_index(table: M, ib_index: usize) -> Bucket<K, V, M> {
|
||||||
|
// if capacity is 0, then the RawBucket will be populated with bogus pointers.
|
||||||
|
// This is an uncommon case though, so avoid it in release builds.
|
||||||
|
debug_assert!(table.capacity() > 0, "Table should have capacity at this point");
|
||||||
let ib_index = ib_index & (table.capacity() - 1);
|
let ib_index = ib_index & (table.capacity() - 1);
|
||||||
Bucket {
|
Bucket {
|
||||||
raw: unsafe {
|
raw: unsafe {
|
||||||
|
@ -368,10 +371,11 @@ impl<K, V, M: Deref<Target=RawTable<K, V>>> FullBucket<K, V, M> {
|
||||||
/// In the cited blog posts above, this is called the "distance to
|
/// In the cited blog posts above, this is called the "distance to
|
||||||
/// initial bucket", or DIB. Also known as "probe count".
|
/// initial bucket", or DIB. Also known as "probe count".
|
||||||
pub fn distance(&self) -> usize {
|
pub fn distance(&self) -> usize {
|
||||||
|
use core::num::wrapping::WrappingOps;
|
||||||
// Calculates the distance one has to travel when going from
|
// Calculates the distance one has to travel when going from
|
||||||
// `hash mod capacity` onwards to `idx mod capacity`, wrapping around
|
// `hash mod capacity` onwards to `idx mod capacity`, wrapping around
|
||||||
// if the destination is not reached before the end of the table.
|
// if the destination is not reached before the end of the table.
|
||||||
(self.idx - self.hash().inspect() as usize) & (self.table.capacity() - 1)
|
(self.idx.wrapping_sub(self.hash().inspect() as usize)) & (self.table.capacity() - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -30,6 +30,7 @@ pub use core::num::{from_uint, from_u8, from_u16, from_u32, from_u64};
|
||||||
pub use core::num::{from_f32, from_f64};
|
pub use core::num::{from_f32, from_f64};
|
||||||
pub use core::num::{FromStrRadix, from_str_radix};
|
pub use core::num::{FromStrRadix, from_str_radix};
|
||||||
pub use core::num::{FpCategory, ParseIntError, ParseFloatError};
|
pub use core::num::{FpCategory, ParseIntError, ParseFloatError};
|
||||||
|
pub use core::num::wrapping;
|
||||||
|
|
||||||
use option::Option;
|
use option::Option;
|
||||||
|
|
||||||
|
|
|
@ -58,3 +58,5 @@
|
||||||
#[doc(no_inline)] pub use old_io::{Buffer, Writer, Reader, Seek, BufferPrelude};
|
#[doc(no_inline)] pub use old_io::{Buffer, Writer, Reader, Seek, BufferPrelude};
|
||||||
// NB: remove when range syntax lands
|
// NB: remove when range syntax lands
|
||||||
#[doc(no_inline)] pub use iter::range;
|
#[doc(no_inline)] pub use iter::range;
|
||||||
|
|
||||||
|
#[doc(no_inline)] pub use num::wrapping::{Wrapping, WrappingOps};
|
||||||
|
|
|
@ -240,25 +240,24 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
|
||||||
let encoder = cx.expr_ident(trait_span, blkarg);
|
let encoder = cx.expr_ident(trait_span, blkarg);
|
||||||
let emit_variant_arg = cx.ident_of("emit_enum_variant_arg");
|
let emit_variant_arg = cx.ident_of("emit_enum_variant_arg");
|
||||||
let mut stmts = Vec::new();
|
let mut stmts = Vec::new();
|
||||||
let last = fields.len() - 1;
|
if fields.len() > 0 {
|
||||||
for (i, &FieldInfo { ref self_, span, .. }) in fields.iter().enumerate() {
|
let last = fields.len() - 1;
|
||||||
let enc = cx.expr_method_call(span, self_.clone(),
|
for (i, &FieldInfo { ref self_, span, .. }) in fields.iter().enumerate() {
|
||||||
encode, vec!(blkencoder.clone()));
|
let enc = cx.expr_method_call(span, self_.clone(),
|
||||||
let lambda = cx.lambda_expr_1(span, enc, blkarg);
|
encode, vec!(blkencoder.clone()));
|
||||||
let call = cx.expr_method_call(span, blkencoder.clone(),
|
let lambda = cx.lambda_expr_1(span, enc, blkarg);
|
||||||
emit_variant_arg,
|
let call = cx.expr_method_call(span, blkencoder.clone(),
|
||||||
vec!(cx.expr_usize(span, i),
|
emit_variant_arg,
|
||||||
lambda));
|
vec!(cx.expr_usize(span, i),
|
||||||
let call = if i != last {
|
lambda));
|
||||||
cx.expr_try(span, call)
|
let call = if i != last {
|
||||||
} else {
|
cx.expr_try(span, call)
|
||||||
cx.expr(span, ExprRet(Some(call)))
|
} else {
|
||||||
};
|
cx.expr(span, ExprRet(Some(call)))
|
||||||
stmts.push(cx.stmt_expr(call));
|
};
|
||||||
}
|
stmts.push(cx.stmt_expr(call));
|
||||||
|
}
|
||||||
// enums with no fields need to return Ok()
|
} else {
|
||||||
if stmts.len() == 0 {
|
|
||||||
let ret_ok = cx.expr(trait_span,
|
let ret_ok = cx.expr(trait_span,
|
||||||
ExprRet(Some(cx.expr_ok(trait_span,
|
ExprRet(Some(cx.expr_ok(trait_span,
|
||||||
cx.expr_tuple(trait_span, vec![])))));
|
cx.expr_tuple(trait_span, vec![])))));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue