Skip to content

Commit

Permalink
Auto merge of #22532 - pnkfelix:arith-overflow, r=pnkfelix,eddyb
Browse files Browse the repository at this point in the history
Rebase and follow-through on work done by @cmr and @Aatch.

Implements most of rust-lang/rfcs#560. Errors encountered from the checks during building were fixed.

The checks for division, remainder and bit-shifting have not been implemented yet.

See also PR #20795

cc @Aatch ; cc @nikomatsakis
  • Loading branch information
bors committed Mar 3, 2015
2 parents 38e97b9 + 243c516 commit 14f0942
Show file tree
Hide file tree
Showing 57 changed files with 1,189 additions and 375 deletions.
6 changes: 3 additions & 3 deletions src/libcollections/bit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -818,19 +818,19 @@ impl BitVec {
let full_value = if value { !0 } else { 0 };

// 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 {
let mask = mask_for_bits(self.nbits);
if value {
self.storage[old_last_word] |= !mask;
self.storage[num_cur_blocks - 1] |= !mask;
} else {
// Extra bits are already zero by invariant.
}
}

// Fill in words after the old tail word
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;
}

Expand Down
4 changes: 2 additions & 2 deletions src/libcollections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use core::fmt::Debug;
use core::hash::{Hash, Hasher};
use core::iter::{Map, FromIterator, IntoIterator};
use core::ops::{Index, IndexMut};
use core::{iter, fmt, mem};
use core::{iter, fmt, mem, usize};
use Bound::{self, Included, Excluded, Unbounded};

use borrow::Borrow;
Expand Down Expand Up @@ -1467,7 +1467,7 @@ macro_rules! range_impl {
$Range {
inner: AbsIter {
traversals: traversals,
size: 0, // unused
size: usize::MAX, // unused
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/libcollections/btree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1215,7 +1215,8 @@ impl<K, V> Node<K, V> {
ptr::copy(
self.edges_mut().as_mut_ptr().offset(index as isize),
self.edges().as_ptr().offset(index as isize + 1),
self.len() - index + 1
// index can be == len+1, so do the +1 first to avoid underflow.
(self.len() + 1) - index
);

edge
Expand Down
11 changes: 8 additions & 3 deletions src/libcollections/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ use core::iter::{range_step, MultiplicativeIterator};
use core::marker::Sized;
use core::mem::size_of;
use core::mem;
use core::num::wrapping::WrappingOps;
use core::ops::FnMut;
use core::option::Option::{self, Some, None};
use core::ptr::PtrExt;
Expand Down Expand Up @@ -1209,18 +1210,22 @@ struct SizeDirection {
impl Iterator for ElementSwaps {
type Item = (usize, usize);

#[inline]
// #[inline]
fn next(&mut self) -> Option<(usize, usize)> {
fn new_pos_wrapping(i: usize, s: Direction) -> usize {
i.wrapping_add(match s { Pos => 1, Neg => -1 })
}

fn new_pos(i: usize, s: Direction) -> usize {
i + match s { Pos => 1, Neg => -1 }
match s { Pos => i + 1, Neg => i - 1 }
}

// Find the index of the largest mobile element:
// The direction should point into the vector, and the
// swap should be with a smaller `size` element.
let max = self.sdir.iter().cloned().enumerate()
.filter(|&(i, sd)|
new_pos(i, sd.dir) < self.sdir.len() &&
new_pos_wrapping(i, sd.dir) < self.sdir.len() &&
self.sdir[new_pos(i, sd.dir)].size < sd.size)
.max_by(|&(_, sd)| sd.size);
match max {
Expand Down
67 changes: 41 additions & 26 deletions src/libcollections/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use core::fmt;
use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator};
use core::mem;
use core::num::{Int, UnsignedInt};
use core::num::wrapping::WrappingOps;
use core::ops::{Index, IndexMut};
use core::ptr::{self, Unique};
use core::raw::Slice as RawSlice;
Expand Down Expand Up @@ -120,6 +121,20 @@ impl<T> VecDeque<T> {
#[inline]
fn wrap_index(&self, idx: usize) -> usize { wrap_index(idx, self.cap) }

/// Returns the index in the underlying buffer for a given logical element
/// index + addend.
#[inline]
fn wrap_add(&self, idx: usize, addend: usize) -> usize {
wrap_index(idx.wrapping_add(addend), self.cap)
}

/// Returns the index in the underlying buffer for a given logical element
/// index - subtrahend.
#[inline]
fn wrap_sub(&self, idx: usize, subtrahend: usize) -> usize {
wrap_index(idx.wrapping_sub(subtrahend), self.cap)
}

/// Copies a contiguous block of memory len long from src to dst
#[inline]
unsafe fn copy(&self, dst: usize, src: usize, len: usize) {
Expand Down Expand Up @@ -197,7 +212,7 @@ impl<T> VecDeque<T> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get(&self, i: usize) -> Option<&T> {
if i < self.len() {
let idx = self.wrap_index(self.tail + i);
let idx = self.wrap_add(self.tail, i);
unsafe { Some(&*self.ptr.offset(idx as isize)) }
} else {
None
Expand Down Expand Up @@ -227,7 +242,7 @@ impl<T> VecDeque<T> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self, i: usize) -> Option<&mut T> {
if i < self.len() {
let idx = self.wrap_index(self.tail + i);
let idx = self.wrap_add(self.tail, i);
unsafe { Some(&mut *self.ptr.offset(idx as isize)) }
} else {
None
Expand Down Expand Up @@ -257,8 +272,8 @@ impl<T> VecDeque<T> {
pub fn swap(&mut self, i: usize, j: usize) {
assert!(i < self.len());
assert!(j < self.len());
let ri = self.wrap_index(self.tail + i);
let rj = self.wrap_index(self.tail + j);
let ri = self.wrap_add(self.tail, i);
let rj = self.wrap_add(self.tail, j);
unsafe {
ptr::swap(self.ptr.offset(ri as isize), self.ptr.offset(rj as isize))
}
Expand Down Expand Up @@ -427,7 +442,7 @@ impl<T> VecDeque<T> {
// [. . . o o o o o o o . . . . . . ]
// H T
// [o o . o o o o o ]
let len = self.wrap_index(self.head - target_cap);
let len = self.wrap_sub(self.head, target_cap);
unsafe {
self.copy_nonoverlapping(0, target_cap, len);
}
Expand All @@ -438,7 +453,7 @@ impl<T> VecDeque<T> {
// [o o o o o . . . . . . . . . o o ]
// H T
// [o o o o o . o o ]
debug_assert!(self.wrap_index(self.head - 1) < target_cap);
debug_assert!(self.wrap_sub(self.head, 1) < target_cap);
let len = self.cap - self.tail;
let new_tail = target_cap - len;
unsafe {
Expand Down Expand Up @@ -775,7 +790,7 @@ impl<T> VecDeque<T> {
None
} else {
let tail = self.tail;
self.tail = self.wrap_index(self.tail + 1);
self.tail = self.wrap_add(self.tail, 1);
unsafe { Some(self.buffer_read(tail)) }
}
}
Expand All @@ -799,7 +814,7 @@ impl<T> VecDeque<T> {
debug_assert!(!self.is_full());
}

self.tail = self.wrap_index(self.tail - 1);
self.tail = self.wrap_sub(self.tail, 1);
let tail = self.tail;
unsafe { self.buffer_write(tail, t); }
}
Expand All @@ -824,7 +839,7 @@ impl<T> VecDeque<T> {
}

let head = self.head;
self.head = self.wrap_index(self.head + 1);
self.head = self.wrap_add(self.head, 1);
unsafe { self.buffer_write(head, t) }
}

Expand All @@ -847,7 +862,7 @@ impl<T> VecDeque<T> {
if self.is_empty() {
None
} else {
self.head = self.wrap_index(self.head - 1);
self.head = self.wrap_sub(self.head, 1);
let head = self.head;
unsafe { Some(self.buffer_read(head)) }
}
Expand Down Expand Up @@ -971,7 +986,7 @@ impl<T> VecDeque<T> {
// A - The element that should be after the insertion point
// M - Indicates element was moved

let idx = self.wrap_index(self.tail + i);
let idx = self.wrap_add(self.tail, i);

let distance_to_tail = i;
let distance_to_head = self.len() - i;
Expand All @@ -990,7 +1005,7 @@ impl<T> VecDeque<T> {
// [A o o o o o o o . . . . . I]
//

self.tail = self.wrap_index(self.tail - 1);
self.tail = self.wrap_sub(self.tail, 1);
},
(true, true, _) => unsafe {
// contiguous, insert closer to tail:
Expand All @@ -1012,7 +1027,7 @@ impl<T> VecDeque<T> {
// [o I A o o o o o . . . . . . . o]
// M M

let new_tail = self.wrap_index(self.tail - 1);
let new_tail = self.wrap_sub(self.tail, 1);

self.copy(new_tail, self.tail, 1);
// Already moved the tail, so we only copy `i - 1` elements.
Expand All @@ -1031,7 +1046,7 @@ impl<T> VecDeque<T> {
// M M M

self.copy(idx + 1, idx, self.head - idx);
self.head = self.wrap_index(self.head + 1);
self.head = self.wrap_add(self.head, 1);
},
(false, true, true) => unsafe {
// discontiguous, insert closer to tail, tail section:
Expand Down Expand Up @@ -1123,7 +1138,7 @@ impl<T> VecDeque<T> {
}

// tail might've been changed so we need to recalculate
let new_idx = self.wrap_index(self.tail + i);
let new_idx = self.wrap_add(self.tail, i);
unsafe {
self.buffer_write(new_idx, t);
}
Expand Down Expand Up @@ -1170,7 +1185,7 @@ impl<T> VecDeque<T> {
// R - Indicates element that is being removed
// M - Indicates element was moved

let idx = self.wrap_index(self.tail + i);
let idx = self.wrap_add(self.tail, i);

let elem = unsafe {
Some(self.buffer_read(idx))
Expand Down Expand Up @@ -1219,7 +1234,7 @@ impl<T> VecDeque<T> {
// M M

self.copy(self.tail + 1, self.tail, i);
self.tail = self.wrap_index(self.tail + 1);
self.tail = self.wrap_add(self.tail, 1);
},
(false, false, false) => unsafe {
// discontiguous, remove closer to head, head section:
Expand Down Expand Up @@ -1265,7 +1280,7 @@ impl<T> VecDeque<T> {
self.copy(0, 1, self.head - 1);
}

self.head = self.wrap_index(self.head - 1);
self.head = self.wrap_sub(self.head, 1);
},
(false, true, false) => unsafe {
// discontiguous, remove closer to tail, head section:
Expand All @@ -1286,7 +1301,7 @@ impl<T> VecDeque<T> {
// move elements from tail to end forward, excluding the last one
self.copy(self.tail + 1, self.tail, self.cap - self.tail - 1);

self.tail = self.wrap_index(self.tail + 1);
self.tail = self.wrap_add(self.tail, 1);
}
}

Expand Down Expand Up @@ -1354,7 +1369,7 @@ impl<T> VecDeque<T> {
}

// Cleanup where the ends of the buffers are
self.head = self.wrap_index(self.head - other_len);
self.head = self.wrap_sub(self.head, other_len);
other.head = other.wrap_index(other_len);

other
Expand Down Expand Up @@ -1429,7 +1444,7 @@ fn wrap_index(index: usize, size: usize) -> usize {
#[inline]
fn count(tail: usize, head: usize, size: usize) -> usize {
// size is always a power of 2
(head - tail) & (size - 1)
(head.wrapping_sub(tail)) & (size - 1)
}

/// `VecDeque` iterator.
Expand Down Expand Up @@ -1461,7 +1476,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
return None;
}
let tail = self.tail;
self.tail = wrap_index(self.tail + 1, self.ring.len());
self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len());
unsafe { Some(self.ring.get_unchecked(tail)) }
}

Expand All @@ -1479,7 +1494,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
if self.tail == self.head {
return None;
}
self.head = wrap_index(self.head - 1, self.ring.len());
self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len());
unsafe { Some(self.ring.get_unchecked(self.head)) }
}
}
Expand All @@ -1500,7 +1515,7 @@ impl<'a, T> RandomAccessIterator for Iter<'a, T> {
if j >= self.indexable() {
None
} else {
let idx = wrap_index(self.tail + j, self.ring.len());
let idx = wrap_index(self.tail.wrapping_add(j), self.ring.len());
unsafe { Some(self.ring.get_unchecked(idx)) }
}
}
Expand All @@ -1524,7 +1539,7 @@ impl<'a, T> Iterator for IterMut<'a, T> {
return None;
}
let tail = self.tail;
self.tail = wrap_index(self.tail + 1, self.ring.len());
self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len());

unsafe {
let elem = self.ring.get_unchecked_mut(tail);
Expand All @@ -1546,7 +1561,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
if self.tail == self.head {
return None;
}
self.head = wrap_index(self.head - 1, self.ring.len());
self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len());

unsafe {
let elem = self.ring.get_unchecked_mut(self.head);
Expand Down
12 changes: 6 additions & 6 deletions src/libcore/hash/sip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

use prelude::*;
use default::Default;

use num::wrapping::WrappingOps;
use super::Hasher;

/// An implementation of SipHash 2-4.
Expand Down Expand Up @@ -71,17 +71,17 @@ macro_rules! u8to64_le {

macro_rules! rotl {
($x:expr, $b:expr) =>
(($x << $b) | ($x >> (64 - $b)))
(($x << $b) | ($x >> (64.wrapping_sub($b))))
}

macro_rules! compress {
($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);
$v2 += $v3; $v3 = rotl!($v3, 16); $v3 ^= $v2;
$v0 += $v3; $v3 = rotl!($v3, 21); $v3 ^= $v0;
$v2 += $v1; $v1 = rotl!($v1, 17); $v1 ^= $v2;
$v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2;
$v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0;
$v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2;
$v2 = rotl!($v2, 32);
})
}
Expand Down
11 changes: 11 additions & 0 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,3 +546,14 @@ extern "rust-intrinsic" {
/// Performs checked `u64` multiplication.
pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool);
}

// SNAP 880fb89
#[cfg(not(stage0))]
extern "rust-intrinsic" {
/// Returns (a + b) mod 2^N, where N is the width of N in bits.
pub fn overflowing_add<T>(a: T, b: T) -> T;
/// Returns (a - b) mod 2^N, where N is the width of N in bits.
pub fn overflowing_sub<T>(a: T, b: T) -> T;
/// Returns (a * b) mod 2^N, where N is the width of N in bits.
pub fn overflowing_mul<T>(a: T, b: T) -> T;
}
Loading

0 comments on commit 14f0942

Please sign in to comment.