about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libcollections/bit.rs6
-rw-r--r--src/libcore/hash/sip.rs12
-rw-r--r--src/libcore/num/mod.rs3
-rw-r--r--src/libcore/num/wrapping.rs153
-rw-r--r--src/libcore/str/mod.rs9
-rw-r--r--src/librand/distributions/range.rs3
-rw-r--r--src/librand/isaac.rs74
-rw-r--r--src/librustc/metadata/decoder.rs2
-rw-r--r--src/librustc/metadata/encoder.rs2
-rw-r--r--src/librustc/middle/astencode.rs4
-rw-r--r--src/librustc/middle/ty.rs21
-rw-r--r--src/librustc/util/nodemap.rs2
-rw-r--r--src/librustc_back/sha2.rs28
-rw-r--r--src/librustc_typeck/check/mod.rs9
-rw-r--r--src/libstd/collections/hash/map.rs7
-rw-r--r--src/libstd/collections/hash/table.rs6
-rw-r--r--src/libstd/num/mod.rs1
-rw-r--r--src/libstd/prelude/v1.rs2
-rw-r--r--src/libsyntax/ext/deriving/encodable.rs37
19 files changed, 286 insertions, 95 deletions
diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs
index a92eccce142..05bf5f8e42c 100644
--- a/src/libcollections/bit.rs
+++ b/src/libcollections/bit.rs
@@ -818,11 +818,11 @@ 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.
             }
@@ -830,7 +830,7 @@ impl BitVec {
 
         // 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;
         }
 
diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs
index 39bcbacdff1..df0008c500b 100644
--- a/src/libcore/hash/sip.rs
+++ b/src/libcore/hash/sip.rs
@@ -14,7 +14,7 @@
 
 use prelude::*;
 use default::Default;
-
+use num::wrapping::WrappingOps;
 use super::Hasher;
 
 /// An implementation of SipHash 2-4.
@@ -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);
     })
 }
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index d77a1eb4203..3ed059520b1 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -30,6 +30,9 @@ use option::Option::{self, Some, None};
 use result::Result::{self, Ok, Err};
 use str::{FromStr, StrExt};
 
+#[unstable(feature = "core", reason = "may be removed or relocated")]
+pub mod wrapping;
+
 /// A built-in signed or unsigned integer.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Int
diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs
new file mode 100644
index 00000000000..30478a8f09f
--- /dev/null
+++ b/src/libcore/num/wrapping.rs
@@ -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)
+    }
+}
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index b354116993c..a7a06906409 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -830,6 +830,7 @@ impl TwoWaySearcher {
     #[inline]
     #[allow(dead_code)]
     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 right = 0; // Corresponds to j in the paper
         let mut offset = 1; // Corresponds to k in the paper
@@ -839,17 +840,17 @@ impl TwoWaySearcher {
             let a;
             let b;
             if reversed {
-                a = arr[left + offset];
+                a = arr[left.wrapping_add(offset)];
                 b = arr[right + offset];
             } else {
                 a = arr[right + offset];
-                b = arr[left + offset];
+                b = arr[left.wrapping_add(offset)];
             }
             if a < b {
                 // Suffix is smaller, period is entire prefix so far.
                 right += offset;
                 offset = 1;
-                period = right - left;
+                period = right.wrapping_sub(left);
             } else if a == b {
                 // Advance through repetition of the current period.
                 if offset == period {
@@ -866,7 +867,7 @@ impl TwoWaySearcher {
                 period = 1;
             }
         }
-        (left + 1, period)
+        (left.wrapping_add(1), period)
     }
 }
 
diff --git a/src/librand/distributions/range.rs b/src/librand/distributions/range.rs
index 6eb1d68a081..04c67b16a7c 100644
--- a/src/librand/distributions/range.rs
+++ b/src/librand/distributions/range.rs
@@ -14,6 +14,7 @@
 
 use core::prelude::{PartialOrd};
 use core::num::Int;
+use core::num::wrapping::WrappingOps;
 
 use Rng;
 use distributions::{Sample, IndependentSample};
@@ -97,7 +98,7 @@ macro_rules! integer_impl {
             // bijection.
 
             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();
 
                 // this is the largest number that fits into $unsigned
diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs
index 701749ff344..63eb8417655 100644
--- a/src/librand/isaac.rs
+++ b/src/librand/isaac.rs
@@ -304,7 +304,7 @@ impl Isaac64Rng {
     fn init(&mut self, use_rsl: bool) {
         macro_rules! init {
             ($var:ident) => (
-                let mut $var = 0x9e3779b97f4a7c13;
+                let mut $var = Wrapping(0x9e3779b97f4a7c13);
             )
         }
         init!(a); init!(b); init!(c); init!(d);
@@ -312,14 +312,14 @@ impl Isaac64Rng {
 
         macro_rules! mix {
             () => {{
-                a-=e; f^=h>>9;  h+=a;
-                b-=f; g^=a<<9;  a+=b;
-                c-=g; h^=b>>23; b+=c;
-                d-=h; a^=c<<15; c+=d;
-                e-=a; b^=d>>14; d+=e;
-                f-=b; c^=e<<20; e+=f;
-                g-=c; d^=f>>17; f+=g;
-                h-=d; e^=g<<14; g+=h;
+                a=a-e; f=f^h>>9;  h=h+a;
+                b=b-f; g=g^a<<9;  a=a+b;
+                c=c-g; h=h^b>>23; b=b+c;
+                d=d-h; a=a^c<<15; c=c+d;
+                e=e-a; b=b^d>>14; d=d+e;
+                f=f-b; c=c^e<<20; e=e+f;
+                g=g-c; d=d^f>>17; f=f+g;
+                h=h-d; e=e^g<<14; g=g+h;
             }}
         }
 
@@ -331,15 +331,15 @@ impl Isaac64Rng {
             macro_rules! memloop {
                 ($arr:expr) => {{
                     for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
-                        a+=$arr[i  ]; b+=$arr[i+1];
-                        c+=$arr[i+2]; d+=$arr[i+3];
-                        e+=$arr[i+4]; f+=$arr[i+5];
-                        g+=$arr[i+6]; h+=$arr[i+7];
+                        a=a+Wrapping($arr[i  ]); b=b+Wrapping($arr[i+1]);
+                        c=c+Wrapping($arr[i+2]); d=d+Wrapping($arr[i+3]);
+                        e=e+Wrapping($arr[i+4]); f=f+Wrapping($arr[i+5]);
+                        g=g+Wrapping($arr[i+6]); h=h+Wrapping($arr[i+7]);
                         mix!();
-                        self.mem[i  ]=a; self.mem[i+1]=b;
-                        self.mem[i+2]=c; self.mem[i+3]=d;
-                        self.mem[i+4]=e; self.mem[i+5]=f;
-                        self.mem[i+6]=g; self.mem[i+7]=h;
+                        self.mem[i  ]=a.0; self.mem[i+1]=b.0;
+                        self.mem[i+2]=c.0; self.mem[i+3]=d.0;
+                        self.mem[i+4]=e.0; self.mem[i+5]=f.0;
+                        self.mem[i+6]=g.0; self.mem[i+7]=h.0;
                     }
                 }}
             }
@@ -349,10 +349,10 @@ impl Isaac64Rng {
         } else {
             for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
                 mix!();
-                self.mem[i  ]=a; self.mem[i+1]=b;
-                self.mem[i+2]=c; self.mem[i+3]=d;
-                self.mem[i+4]=e; self.mem[i+5]=f;
-                self.mem[i+6]=g; self.mem[i+7]=h;
+                self.mem[i  ]=a.0; self.mem[i+1]=b.0;
+                self.mem[i+2]=c.0; self.mem[i+3]=d.0;
+                self.mem[i+4]=e.0; self.mem[i+5]=f.0;
+                self.mem[i+6]=g.0; self.mem[i+7]=h.0;
             }
         }
 
@@ -363,8 +363,8 @@ impl Isaac64Rng {
     fn isaac64(&mut self) {
         self.c += 1;
         // abbreviations
-        let mut a = self.a;
-        let mut b = self.b + self.c;
+        let mut a = Wrapping(self.a);
+        let mut b = Wrapping(self.b) + Wrapping(self.c);
         const MIDPOINT: uint =  RAND_SIZE_64 / 2;
         const MP_VEC: [(uint, uint); 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
         macro_rules! ind {
@@ -383,13 +383,13 @@ impl Isaac64Rng {
                         let mix = if $j == 0 {!mix} else {mix};
 
                         unsafe {
-                            let x = *self.mem.get_unchecked(base + mr_offset);
-                            a = mix + *self.mem.get_unchecked(base + m2_offset);
-                            let y = ind!(x) + a + b;
-                            *self.mem.get_unchecked_mut(base + mr_offset) = y;
+                            let x = Wrapping(*self.mem.get_unchecked(base + mr_offset));
+                            a = mix + Wrapping(*self.mem.get_unchecked(base + m2_offset));
+                            let y = Wrapping(ind!(x.0)) + a + b;
+                            *self.mem.get_unchecked_mut(base + mr_offset) = y.0;
 
-                            b = ind!(y >> RAND_SIZE_64_LEN) + x;
-                            *self.rsl.get_unchecked_mut(base + mr_offset) = b;
+                            b = Wrapping(ind!(y.0 >> RAND_SIZE_64_LEN)) + x;
+                            *self.rsl.get_unchecked_mut(base + mr_offset) = b.0;
                         }
                     }}
                 }
@@ -401,13 +401,13 @@ impl Isaac64Rng {
                         let mix = if $j == 0 {!mix} else {mix};
 
                         unsafe {
-                            let x = *self.mem.get_unchecked(base + mr_offset);
-                            a = mix + *self.mem.get_unchecked(base + m2_offset);
-                            let y = ind!(x) + a + b;
-                            *self.mem.get_unchecked_mut(base + mr_offset) = y;
+                            let x = Wrapping(*self.mem.get_unchecked(base + mr_offset));
+                            a = mix + Wrapping(*self.mem.get_unchecked(base + m2_offset));
+                            let y = Wrapping(ind!(x.0)) + a + b;
+                            *self.mem.get_unchecked_mut(base + mr_offset) = y.0;
 
-                            b = ind!(y >> RAND_SIZE_64_LEN) + x;
-                            *self.rsl.get_unchecked_mut(base + mr_offset) = b;
+                            b = Wrapping(ind!(y.0 >> RAND_SIZE_64_LEN)) + x;
+                            *self.rsl.get_unchecked_mut(base + mr_offset) = b.0;
                         }
                     }}
                 }
@@ -419,8 +419,8 @@ impl Isaac64Rng {
             }
         }
 
-        self.a = a;
-        self.b = b;
+        self.a = a.0;
+        self.b = b.0;
         self.cnt = RAND_SIZE_64;
     }
 }
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 251c5e6eac7..e32fcaec047 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -783,7 +783,7 @@ pub fn get_enum_variants<'tcx>(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::Nod
             _         => { /* empty */ }
         }
         let old_disr_val = disr_val;
-        disr_val += 1;
+        disr_val = disr_val.wrapping_add(1);
         Rc::new(ty::VariantInfo {
             args: arg_tys,
             arg_names: arg_names,
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 131a299cc50..8152a2bf16d 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -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));
         rbml_w.end_tag();
-        disr_val += 1;
+        disr_val = disr_val.wrapping_add(1);
         i += 1;
     }
 }
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 599dde4b701..33c0fb8b031 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -204,7 +204,9 @@ impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> {
     pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId {
         // from_id_range should be non-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
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index aaba840825e..b6d1fc5a369 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -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)
                            -> Rc<Vec<Rc<VariantInfo<'tcx>>>> {
+    use std::num::Int; // For checked_add
     memoized(&cx.enum_var_cache, id, |id: ast::DefId| {
         if ast::LOCAL_CRATE != id.krate {
             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;
                             Rc::new(enum_definition.variants.iter().map(|variant| {
 
-                                let mut discriminant = match last_discriminant {
-                                    Some(val) => val + 1,
-                                    None => INITIAL_DISCRIMINANT_VALUE
-                                };
-
+                                let mut discriminant = INITIAL_DISCRIMINANT_VALUE;
                                 if let Some(ref e) = variant.node.disr_expr {
                                     // Preserve all values, and prefer signed.
                                     let ty = Some(cx.types.i64);
@@ -5373,7 +5370,19 @@ pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
                                                       "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);
                                 Rc::new(VariantInfo::from_ast_variant(cx, &**variant,
diff --git a/src/librustc/util/nodemap.rs b/src/librustc/util/nodemap.rs
index b15da7dab3e..0f69aa941a3 100644
--- a/src/librustc/util/nodemap.rs
+++ b/src/librustc/util/nodemap.rs
@@ -57,7 +57,7 @@ impl Hasher for FnvHasher {
         let FnvHasher(mut hash) = *self;
         for byte in bytes {
             hash = hash ^ (*byte as u64);
-            hash = hash * 0x100000001b3;
+            hash = hash.wrapping_mul(0x100000001b3);
         }
         *self = FnvHasher(hash);
     }
diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs
index 6654a46f7c3..8acb6851f11 100644
--- a/src/librustc_back/sha2.rs
+++ b/src/librustc_back/sha2.rs
@@ -347,17 +347,19 @@ impl Engine256State {
         // 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.
         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 {
             ($A:ident, $B:ident, $C:ident, $D:ident,
              $E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => (
                 {
-                    $H += sum1($E) + ch($E, $F, $G) + $K[$t] + w[$t];
-                    $D += $H;
-                    $H += sum0($A) + maj($A, $B, $C);
+                    $H = $H.wrapping_add(sum1($E)).wrapping_add(ch($E, $F, $G))
+                        .wrapping_add($K[$t]).wrapping_add(w[$t]);
+                    $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);
         }
 
-        self.h0 += a;
-        self.h1 += b;
-        self.h2 += c;
-        self.h3 += d;
-        self.h4 += e;
-        self.h5 += f;
-        self.h6 += g;
-        self.h7 += h;
+        self.h0 = self.h0.wrapping_add(a);
+        self.h1 = self.h1.wrapping_add(b);
+        self.h2 = self.h2.wrapping_add(c);
+        self.h3 = self.h3.wrapping_add(d);
+        self.h4 = self.h4.wrapping_add(e);
+        self.h5 = self.h5.wrapping_add(f);
+        self.h6 = self.h6.wrapping_add(g);
+        self.h7 = self.h7.wrapping_add(h);
     }
 }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 273aadc383c..10771935e22 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4554,6 +4554,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                           id: ast::NodeId,
                           hint: attr::ReprAttr)
                           -> Vec<Rc<ty::VariantInfo<'tcx>>> {
+        use std::num::Int;
 
         let rty = ty::node_id_to_type(ccx.tcx, id);
         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
             // initialization expression is valid, otherwise use the last value plus one.
             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
             };
 
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index faddbba5059..8eb29a8327a 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -314,6 +314,13 @@ fn search_hashed<K, V, M, F>(table: M,
     M: Deref<Target=RawTable<K, V>>,
     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 mut probe = Bucket::new(table, hash);
     let ib = probe.index();
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 4c03d8915eb..908b5267b69 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -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> {
+        // 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);
         Bucket {
             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
     /// initial bucket", or DIB. Also known as "probe count".
     pub fn distance(&self) -> usize {
+        use core::num::wrapping::WrappingOps;
         // Calculates the distance one has to travel when going from
         // `hash mod capacity` onwards to `idx mod capacity`, wrapping around
         // 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]
diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs
index d776079efae..d4428282b14 100644
--- a/src/libstd/num/mod.rs
+++ b/src/libstd/num/mod.rs
@@ -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::{FromStrRadix, from_str_radix};
 pub use core::num::{FpCategory, ParseIntError, ParseFloatError};
+pub use core::num::wrapping;
 
 use option::Option;
 
diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs
index dad0ff0a15e..60e1354482c 100644
--- a/src/libstd/prelude/v1.rs
+++ b/src/libstd/prelude/v1.rs
@@ -58,3 +58,5 @@
 #[doc(no_inline)] pub use old_io::{Buffer, Writer, Reader, Seek, BufferPrelude};
 // NB: remove when range syntax lands
 #[doc(no_inline)] pub use iter::range;
+
+#[doc(no_inline)] pub use num::wrapping::{Wrapping, WrappingOps};
diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs
index 8038074cee1..94b7d1b4d8c 100644
--- a/src/libsyntax/ext/deriving/encodable.rs
+++ b/src/libsyntax/ext/deriving/encodable.rs
@@ -240,25 +240,24 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
             let encoder = cx.expr_ident(trait_span, blkarg);
             let emit_variant_arg = cx.ident_of("emit_enum_variant_arg");
             let mut stmts = Vec::new();
-            let last = fields.len() - 1;
-            for (i, &FieldInfo { ref self_, span, .. }) in fields.iter().enumerate() {
-                let enc = cx.expr_method_call(span, self_.clone(),
-                                              encode, vec!(blkencoder.clone()));
-                let lambda = cx.lambda_expr_1(span, enc, blkarg);
-                let call = cx.expr_method_call(span, blkencoder.clone(),
-                                               emit_variant_arg,
-                                               vec!(cx.expr_usize(span, i),
-                                                 lambda));
-                let call = if i != last {
-                    cx.expr_try(span, call)
-                } else {
-                    cx.expr(span, ExprRet(Some(call)))
-                };
-                stmts.push(cx.stmt_expr(call));
-            }
-
-            // enums with no fields need to return Ok()
-            if stmts.len() == 0 {
+            if fields.len() > 0 {
+                let last = fields.len() - 1;
+                for (i, &FieldInfo { ref self_, span, .. }) in fields.iter().enumerate() {
+                    let enc = cx.expr_method_call(span, self_.clone(),
+                                                  encode, vec!(blkencoder.clone()));
+                    let lambda = cx.lambda_expr_1(span, enc, blkarg);
+                    let call = cx.expr_method_call(span, blkencoder.clone(),
+                                                   emit_variant_arg,
+                                                   vec!(cx.expr_usize(span, i),
+                                                        lambda));
+                    let call = if i != last {
+                        cx.expr_try(span, call)
+                    } else {
+                        cx.expr(span, ExprRet(Some(call)))
+                    };
+                    stmts.push(cx.stmt_expr(call));
+                }
+            } else {
                 let ret_ok = cx.expr(trait_span,
                                      ExprRet(Some(cx.expr_ok(trait_span,
                                                              cx.expr_tuple(trait_span, vec![])))));