about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libextra/num/bigint.rs767
-rw-r--r--src/libextra/num/rational.rs6
-rw-r--r--src/librustc/middle/trans/debuginfo.rs2
-rw-r--r--src/librustc/util/ppaux.rs2
-rw-r--r--src/libstd/num/f32.rs3
-rw-r--r--src/libstd/num/f64.rs3
-rw-r--r--src/libstd/num/int_macros.rs3
-rw-r--r--src/libstd/num/num.rs953
-rw-r--r--src/libstd/num/strconv.rs26
-rw-r--r--src/libstd/num/uint_macros.rs3
-rw-r--r--src/libstd/prelude.rs2
-rw-r--r--src/libstd/rand/mod.rs4
-rw-r--r--src/libsyntax/ext/build.rs36
-rw-r--r--src/libsyntax/ext/deriving/generic.rs1
-rw-r--r--src/libsyntax/ext/deriving/mod.rs4
-rw-r--r--src/libsyntax/ext/deriving/primitive.rs127
-rw-r--r--src/test/compile-fail/deriving-primitive.rs34
-rw-r--r--src/test/run-pass/deriving-primitive.rs37
-rw-r--r--src/test/run-pass/numeric-method-autoexport.rs4
-rw-r--r--src/test/run-pass/trait-inheritance-num.rs4
-rw-r--r--src/test/run-pass/trait-inheritance-num0.rs2
-rw-r--r--src/test/run-pass/trait-inheritance-num1.rs2
-rw-r--r--src/test/run-pass/trait-inheritance-num3.rs2
-rw-r--r--src/test/run-pass/trait-inheritance-num5.rs2
24 files changed, 1633 insertions, 396 deletions
diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs
index 48fcd972c3c..8604674ea12 100644
--- a/src/libextra/num/bigint.rs
+++ b/src/libextra/num/bigint.rs
@@ -20,12 +20,13 @@ A `BigInt` is a combination of `BigUint` and `Sign`.
 #[allow(non_uppercase_statics)];
 
 use std::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
-use std::int;
 use std::num;
-use std::num::{IntConvertible, Zero, One, ToStrRadix, FromStrRadix, Orderable};
+use std::num::{Zero, One, ToStrRadix, FromStrRadix, Orderable};
+use std::num::{ToPrimitive, FromPrimitive};
 use std::rand::Rng;
 use std::str;
 use std::uint;
+use std::{i64, u64};
 use std::vec;
 
 /**
@@ -500,18 +501,152 @@ impl Integer for BigUint {
     fn is_odd(&self) -> bool { !self.is_even() }
 }
 
-impl IntConvertible for BigUint {
+impl ToPrimitive for BigUint {
     #[inline]
-    fn to_int(&self) -> int {
-        self.to_int_opt().expect("BigUint conversion would overflow int")
+    fn to_i64(&self) -> Option<i64> {
+        do self.to_u64().and_then |n| {
+            // If top bit of u64 is set, it's too large to convert to i64.
+            if n >> 63 == 0 {
+                Some(n as i64)
+            } else {
+                None
+            }
+        }
+    }
+
+    #[cfg(target_word_size = "32")]
+    #[inline]
+    fn to_u64(&self) -> Option<u64> {
+        match self.data {
+            [] => {
+                Some(0)
+            }
+            [n0] => {
+                Some(n0 as u64)
+            }
+            [n0, n1] => {
+                Some(BigDigit::to_uint(n1, n0) as u64)
+            }
+            [n0, n1, n2] => {
+                let n_lo = BigDigit::to_uint(n1, n0) as u64;
+                let n_hi = n2 as u64;
+                Some((n_hi << 32) + n_lo)
+            }
+            [n0, n1, n2, n3] => {
+                let n_lo = BigDigit::to_uint(n1, n0) as u64;
+                let n_hi = BigDigit::to_uint(n3, n2) as u64;
+                Some((n_hi << 32) + n_lo)
+            }
+            _ => None
+        }
+    }
+
+    #[cfg(target_word_size = "64")]
+    #[inline]
+    fn to_u64(&self) -> Option<u64> {
+        match self.data {
+            [] => {
+                Some(0)
+            }
+            [n0] => {
+                Some(n0 as u64)
+            }
+            [n0, n1] => {
+                Some(BigDigit::to_uint(n1, n0) as u64)
+            }
+            _ => None
+        }
+    }
+}
+
+impl FromPrimitive for BigUint {
+    #[inline]
+    fn from_i64(n: i64) -> Option<BigUint> {
+        if (n > 0) {
+            FromPrimitive::from_u64(n as u64)
+        } else if (n == 0) {
+            Some(Zero::zero())
+        } else {
+            None
+        }
     }
 
+    #[cfg(target_word_size = "32")]
     #[inline]
-    fn from_int(n: int) -> BigUint {
-        if (n < 0) { Zero::zero() } else { BigUint::from_uint(n as uint) }
+    fn from_u64(n: u64) -> Option<BigUint> {
+        let n_lo = (n & 0x0000_0000_FFFF_FFFF) as uint;
+        let n_hi = (n >> 32) as uint;
+
+        let n = match (BigDigit::from_uint(n_hi), BigDigit::from_uint(n_lo)) {
+            ((0,  0),  (0,  0))  => Zero::zero(),
+            ((0,  0),  (0,  n0)) => BigUint::new(~[n0]),
+            ((0,  0),  (n1, n0)) => BigUint::new(~[n0, n1]),
+            ((0,  n2), (n1, n0)) => BigUint::new(~[n0, n1, n2]),
+            ((n3, n2), (n1, n0)) => BigUint::new(~[n0, n1, n2, n3]),
+        };
+        Some(n)
+    }
+
+    #[cfg(target_word_size = "64")]
+    #[inline]
+    fn from_u64(n: u64) -> Option<BigUint> {
+        let n = match BigDigit::from_uint(n as uint) {
+            (0,  0)  => Zero::zero(),
+            (0,  n0) => BigUint::new(~[n0]),
+            (n1, n0) => BigUint::new(~[n0, n1])
+        };
+        Some(n)
     }
 }
 
+/// A generic trait for converting a value to a `BigUint`.
+pub trait ToBigUint {
+    /// Converts the value of `self` to a `BigUint`.
+    fn to_biguint(&self) -> Option<BigUint>;
+}
+
+impl ToBigUint for BigInt {
+    #[inline]
+    fn to_biguint(&self) -> Option<BigUint> {
+        if self.sign == Plus {
+            Some(self.data.clone())
+        } else if self.sign == Zero {
+            Some(Zero::zero())
+        } else {
+            None
+        }
+    }
+}
+
+impl ToBigUint for BigUint {
+    #[inline]
+    fn to_biguint(&self) -> Option<BigUint> {
+        Some(self.clone())
+    }
+}
+
+macro_rules! impl_to_biguint(
+    ($T:ty, $from_ty:path) => {
+        impl ToBigUint for $T {
+            #[inline]
+            fn to_biguint(&self) -> Option<BigUint> {
+                $from_ty(*self)
+            }
+        }
+    }
+)
+
+impl_to_biguint!(int,  FromPrimitive::from_int)
+impl_to_biguint!(i8,   FromPrimitive::from_i8)
+impl_to_biguint!(i16,  FromPrimitive::from_i16)
+impl_to_biguint!(i32,  FromPrimitive::from_i32)
+impl_to_biguint!(i64,  FromPrimitive::from_i64)
+impl_to_biguint!(uint, FromPrimitive::from_uint)
+impl_to_biguint!(u8,   FromPrimitive::from_u8)
+impl_to_biguint!(u16,  FromPrimitive::from_u16)
+impl_to_biguint!(u32,  FromPrimitive::from_u32)
+impl_to_biguint!(u64,  FromPrimitive::from_u64)
+
 impl ToStrRadix for BigUint {
     fn to_str_radix(&self, radix: uint) -> ~str {
         assert!(1 < radix && radix <= 16);
@@ -522,16 +657,16 @@ impl ToStrRadix for BigUint {
         return fill_concat(convert_base((*self).clone(), base), radix, max_len);
 
         fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] {
-            let divider    = BigUint::from_uint(base);
+            let divider    = FromPrimitive::from_uint(base).unwrap();
             let mut result = ~[];
             let mut m      = n;
             while m > divider {
                 let (d, m0) = m.div_mod_floor(&divider);
-                result.push(m0.to_uint() as BigDigit);
+                result.push(m0.to_uint().unwrap() as BigDigit);
                 m = d;
             }
             if !m.is_zero() {
-                result.push(m.to_uint() as BigDigit);
+                result.push(m.to_uint().unwrap() as BigDigit);
             }
             return result;
         }
@@ -573,25 +708,17 @@ impl BigUint {
 
     /// Creates and initializes a `BigUint`.
     #[inline]
-    pub fn from_uint(n: uint) -> BigUint {
-        match BigDigit::from_uint(n) {
-            (0,  0)  => Zero::zero(),
-            (0,  n0) => BigUint::new(~[n0]),
-            (n1, n0) => BigUint::new(~[n0, n1])
-        }
-    }
-
-    /// Creates and initializes a `BigUint`.
-    #[inline]
     pub fn from_slice(slice: &[BigDigit]) -> BigUint {
         return BigUint::new(slice.to_owned());
     }
 
     /// Creates and initializes a `BigUint`.
-    pub fn parse_bytes(buf: &[u8], radix: uint)
-        -> Option<BigUint> {
+    pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<BigUint> {
         let (base, unit_len) = get_radix_base(radix);
-        let base_num: BigUint = BigUint::from_uint(base);
+        let base_num = match FromPrimitive::from_uint(base) {
+            Some(base_num) => base_num,
+            None => { return None; }
+        };
 
         let mut end             = buf.len();
         let mut n: BigUint      = Zero::zero();
@@ -599,10 +726,19 @@ impl BigUint {
         loop {
             let start = num::max(end, unit_len) - unit_len;
             match uint::parse_bytes(buf.slice(start, end), radix) {
-                // FIXME(#6102): Assignment operator for BigInt causes ICE
-                // Some(d) => n += BigUint::from_uint(d) * power,
-                Some(d) => n = n + BigUint::from_uint(d) * power,
-                None    => return None
+                Some(d) => {
+                    let d: Option<BigUint> = FromPrimitive::from_uint(d);
+                    match d {
+                        Some(d) => {
+                            // FIXME(#6102): Assignment operator for BigInt
+                            // causes ICE:
+                            // n += d * power;
+                            n = n + d * power;
+                        }
+                        None => { return None; }
+                    }
+                }
+                None => { return None; }
             }
             if end <= unit_len {
                 return Some(n);
@@ -614,44 +750,6 @@ impl BigUint {
         }
     }
 
-
-    /// Converts this `BigUint` into a `uint`, failing if the conversion
-    /// would overflow.
-    #[inline]
-    pub fn to_uint(&self) -> uint {
-        self.to_uint_opt().expect("BigUint conversion would overflow uint")
-    }
-
-    /// Converts this `BigUint` into a `uint`, unless it would overflow.
-    #[inline]
-    pub fn to_uint_opt(&self) -> Option<uint> {
-        match self.data.len() {
-            0 => Some(0),
-            1 => Some(self.data[0] as uint),
-            2 => Some(BigDigit::to_uint(self.data[1], self.data[0])),
-            _ => None
-        }
-    }
-
-    /// Converts this `BigUint` into an `int`, unless it would overflow.
-    pub fn to_int_opt(&self) -> Option<int> {
-        self.to_uint_opt().and_then(|n| {
-            // If top bit of uint is set, it's too large to convert to
-            // int.
-            if (n >> (2*BigDigit::bits - 1) != 0) {
-                None
-            } else {
-                Some(n as int)
-            }
-        })
-    }
-
-    /// Converts this `BigUint` into a `BigInt`.
-    #[inline]
-    pub fn to_bigint(&self) -> BigInt {
-        BigInt::from_biguint(Plus, self.clone())
-    }
-
     #[inline]
     fn shl_unit(&self, n_unit: uint) -> BigUint {
         if n_unit == 0 || self.is_zero() { return (*self).clone(); }
@@ -706,30 +804,6 @@ impl BigUint {
     }
 }
 
-#[cfg(target_word_size = "64")]
-#[inline]
-fn get_radix_base(radix: uint) -> (uint, uint) {
-    assert!(1 < radix && radix <= 16);
-    match radix {
-        2  => (4294967296, 32),
-        3  => (3486784401, 20),
-        4  => (4294967296, 16),
-        5  => (1220703125, 13),
-        6  => (2176782336, 12),
-        7  => (1977326743, 11),
-        8  => (1073741824, 10),
-        9  => (3486784401, 10),
-        10 => (1000000000, 9),
-        11 => (2357947691, 9),
-        12 => (429981696,  8),
-        13 => (815730721,  8),
-        14 => (1475789056, 8),
-        15 => (2562890625, 8),
-        16 => (4294967296, 8),
-        _  => fail2!()
-    }
-}
-
 #[cfg(target_word_size = "32")]
 #[inline]
 fn get_radix_base(radix: uint) -> (uint, uint) {
@@ -754,6 +828,30 @@ fn get_radix_base(radix: uint) -> (uint, uint) {
     }
 }
 
+#[cfg(target_word_size = "64")]
+#[inline]
+fn get_radix_base(radix: uint) -> (uint, uint) {
+    assert!(1 < radix && radix <= 16);
+    match radix {
+        2  => (4294967296, 32),
+        3  => (3486784401, 20),
+        4  => (4294967296, 16),
+        5  => (1220703125, 13),
+        6  => (2176782336, 12),
+        7  => (1977326743, 11),
+        8  => (1073741824, 10),
+        9  => (3486784401, 10),
+        10 => (1000000000, 9),
+        11 => (2357947691, 9),
+        12 => (429981696,  8),
+        13 => (815730721,  8),
+        14 => (1475789056, 8),
+        15 => (2562890625, 8),
+        16 => (4294967296, 8),
+        _  => fail2!()
+    }
+}
+
 /// A Sign is a `BigInt`'s composing element.
 #[deriving(Eq, Clone)]
 pub enum Sign { Minus, Zero, Plus }
@@ -1077,26 +1175,111 @@ impl Integer for BigInt {
     fn is_odd(&self) -> bool { self.data.is_odd() }
 }
 
-impl IntConvertible for BigInt {
+impl ToPrimitive for BigInt {
+    #[inline]
+    fn to_i64(&self) -> Option<i64> {
+        match self.sign {
+            Plus  => self.data.to_i64(),
+            Zero  => Some(0),
+            Minus => {
+                do self.data.to_u64().and_then |n| {
+                    let m: u64 = 1 << 63;
+                    if n < m {
+                        Some(-(n as i64))
+                    } else if n == m {
+                        Some(i64::min_value)
+                    } else {
+                        None
+                    }
+                }
+            }
+        }
+    }
+
     #[inline]
-    fn to_int(&self) -> int {
-        self.to_int_opt().expect("BigInt conversion would overflow int")
+    fn to_u64(&self) -> Option<u64> {
+        match self.sign {
+            Plus => self.data.to_u64(),
+            Zero => Some(0),
+            Minus => None
+        }
     }
+}
 
+impl FromPrimitive for BigInt {
     #[inline]
-    fn from_int(n: int) -> BigInt {
+    fn from_i64(n: i64) -> Option<BigInt> {
         if n > 0 {
-           return BigInt::from_biguint(Plus,  BigUint::from_uint(n as uint));
+            do FromPrimitive::from_u64(n as u64).and_then |n| {
+                Some(BigInt::from_biguint(Plus, n))
+            }
+        } else if n < 0 {
+            do FromPrimitive::from_u64(u64::max_value - (n as u64) + 1).and_then |n| {
+                Some(BigInt::from_biguint(Minus, n))
+            }
+        } else {
+            Some(Zero::zero())
         }
-        if n < 0 {
-            return BigInt::from_biguint(
-                Minus, BigUint::from_uint(uint::max_value - (n as uint) + 1)
-            );
+    }
+
+    #[inline]
+    fn from_u64(n: u64) -> Option<BigInt> {
+        if n == 0 {
+            Some(Zero::zero())
+        } else {
+            do FromPrimitive::from_u64(n).and_then |n| {
+                Some(BigInt::from_biguint(Plus, n))
+            }
         }
-        return Zero::zero();
     }
 }
 
+/// A generic trait for converting a value to a `BigInt`.
+pub trait ToBigInt {
+    /// Converts the value of `self` to a `BigInt`.
+    fn to_bigint(&self) -> Option<BigInt>;
+}
+
+impl ToBigInt for BigInt {
+    #[inline]
+    fn to_bigint(&self) -> Option<BigInt> {
+        Some(self.clone())
+    }
+}
+
+impl ToBigInt for BigUint {
+    #[inline]
+    fn to_bigint(&self) -> Option<BigInt> {
+        if self.is_zero() {
+            Some(Zero::zero())
+        } else {
+            Some(BigInt { sign: Plus, data: self.clone() })
+        }
+    }
+}
+
+macro_rules! impl_to_bigint(
+    ($T:ty, $from_ty:path) => {
+        impl ToBigInt for $T {
+            #[inline]
+            fn to_bigint(&self) -> Option<BigInt> {
+                $from_ty(*self)
+            }
+        }
+    }
+)
+
+impl_to_bigint!(int,  FromPrimitive::from_int)
+impl_to_bigint!(i8,   FromPrimitive::from_i8)
+impl_to_bigint!(i16,  FromPrimitive::from_i16)
+impl_to_bigint!(i32,  FromPrimitive::from_i32)
+impl_to_bigint!(i64,  FromPrimitive::from_i64)
+impl_to_bigint!(uint, FromPrimitive::from_uint)
+impl_to_bigint!(u8,   FromPrimitive::from_u8)
+impl_to_bigint!(u16,  FromPrimitive::from_u16)
+impl_to_bigint!(u32,  FromPrimitive::from_u32)
+impl_to_bigint!(u64,  FromPrimitive::from_u64)
+
 impl ToStrRadix for BigInt {
     #[inline]
     fn to_str_radix(&self, radix: uint) -> ~str {
@@ -1196,8 +1379,8 @@ impl<R: Rng> RandBigInt for R {
                         ubound: &BigInt)
                         -> BigInt {
         assert!(*lbound < *ubound);
-        let delta = (*ubound - *lbound).to_biguint();
-        return *lbound + self.gen_biguint_below(&delta).to_bigint();
+        let delta = (*ubound - *lbound).to_biguint().unwrap();
+        return *lbound + self.gen_biguint_below(&delta).to_bigint().unwrap();
     }
 }
 
@@ -1219,13 +1402,6 @@ impl BigInt {
 
     /// Creates and initializes a `BigInt`.
     #[inline]
-    pub fn from_uint(n: uint) -> BigInt {
-        if n == 0 { return Zero::zero(); }
-        return BigInt::from_biguint(Plus, BigUint::from_uint(n));
-    }
-
-    /// Creates and initializes a `BigInt`.
-    #[inline]
     pub fn from_slice(sign: Sign, slice: &[BigDigit]) -> BigInt {
         BigInt::from_biguint(sign, BigUint::from_slice(slice))
     }
@@ -1244,51 +1420,9 @@ impl BigInt {
             .map_move(|bu| BigInt::from_biguint(sign, bu));
     }
 
-    /// Converts this `BigInt` into a `uint`, failing if the conversion
-    /// would overflow.
-    #[inline]
-    pub fn to_uint(&self) -> uint {
-        self.to_uint_opt().expect("BigInt conversion would overflow uint")
-    }
-
-    /// Converts this `BigInt` into a `uint`, unless it would overflow.
-    #[inline]
-    pub fn to_uint_opt(&self) -> Option<uint> {
-        match self.sign {
-            Plus => self.data.to_uint_opt(),
-            Zero => Some(0),
-            Minus => None
-        }
-    }
-
-    /// Converts this `BigInt` into an `int`, unless it would overflow.
-    pub fn to_int_opt(&self) -> Option<int> {
-        match self.sign {
-            Plus  => self.data.to_int_opt(),
-            Zero  => Some(0),
-            Minus => self.data.to_uint_opt().and_then(|n| {
-                let m: uint = 1 << (2*BigDigit::bits-1);
-                if (n > m) {
-                    None
-                } else if (n == m) {
-                    Some(int::min_value)
-                } else {
-                    Some(-(n as int))
-                }
-            })
-        }
-    }
-
-    /// Converts this `BigInt` into a `BigUint`, failing if BigInt is
-    /// negative.
-    #[inline]
-    pub fn to_biguint(&self) -> BigUint {
-        self.to_biguint_opt().expect("negative BigInt cannot convert to BigUint")
-    }
-
     /// Converts this `BigInt` into a `BigUint`, if it's not negative.
     #[inline]
-    pub fn to_biguint_opt(&self) -> Option<BigUint> {
+    pub fn to_biguint(&self) -> Option<BigUint> {
         match self.sign {
             Plus => Some(self.data.clone()),
             Zero => Some(Zero::zero()),
@@ -1299,15 +1433,15 @@ impl BigInt {
 
 #[cfg(test)]
 mod biguint_tests {
-
     use super::*;
 
     use std::cmp::{Less, Equal, Greater};
-    use std::int;
-    use std::num::{IntConvertible, Zero, One, FromStrRadix};
+    use std::i64;
+    use std::num::{Zero, One, FromStrRadix};
+    use std::num::{ToPrimitive, FromPrimitive};
     use std::rand::{task_rng};
     use std::str;
-    use std::uint;
+    use std::u64;
     use std::vec;
 
     #[test]
@@ -1479,49 +1613,117 @@ mod biguint_tests {
               "88887777666655554444333322221111");
     }
 
+    #[cfg(target_word_size = "32")]
+    #[test]
+    fn test_convert_i64() {
+        fn check(b1: BigUint, i: i64) {
+            let b2: BigUint = FromPrimitive::from_i64(i).unwrap();
+            assert!(b1 == b2);
+            assert!(b1.to_i64().unwrap() == i);
+        }
+
+        check(Zero::zero(), 0);
+        check(One::one(), 1);
+        check(i64::max_value.to_biguint().unwrap(), i64::max_value);
+
+        check(BigUint::new(~[                   ]), 0);
+        check(BigUint::new(~[ 1                 ]), (1 << (0*BigDigit::bits)));
+        check(BigUint::new(~[-1                 ]), (1 << (1*BigDigit::bits)) - 1);
+        check(BigUint::new(~[ 0,  1             ]), (1 << (1*BigDigit::bits)));
+        check(BigUint::new(~[-1, -1             ]), (1 << (2*BigDigit::bits)) - 1);
+        check(BigUint::new(~[ 0,  0,  1         ]), (1 << (2*BigDigit::bits)));
+        check(BigUint::new(~[-1, -1, -1         ]), (1 << (3*BigDigit::bits)) - 1);
+        check(BigUint::new(~[ 0,  0,  0,  1     ]), (1 << (3*BigDigit::bits)));
+        check(BigUint::new(~[-1, -1, -1, -1 >> 1]), i64::max_value);
+
+        assert_eq!(i64::min_value.to_biguint(), None);
+        assert_eq!(BigUint::new(~[-1, -1, -1, -1    ]).to_i64(), None);
+        assert_eq!(BigUint::new(~[ 0,  0,  0,  0,  1]).to_i64(), None);
+        assert_eq!(BigUint::new(~[-1, -1, -1, -1, -1]).to_i64(), None);
+    }
+
+    #[cfg(target_word_size = "64")]
     #[test]
-    fn test_convert_int() {
-        fn check(v: ~[BigDigit], i: int) {
-            let b = BigUint::new(v);
-            assert!(b == IntConvertible::from_int(i));
-            assert!(b.to_int() == i);
+    fn test_convert_i64() {
+        fn check(b1: BigUint, i: i64) {
+            let b2: BigUint = FromPrimitive::from_i64(i).unwrap();
+            assert!(b1 == b2);
+            assert!(b1.to_i64().unwrap() == i);
         }
 
-        check(~[], 0);
-        check(~[1], 1);
-        check(~[-1], (uint::max_value >> BigDigit::bits) as int);
-        check(~[ 0,  1], ((uint::max_value >> BigDigit::bits) + 1) as int);
-        check(~[-1, -1 >> 1], int::max_value);
+        check(Zero::zero(), 0);
+        check(One::one(), 1);
+        check(i64::max_value.to_biguint().unwrap(), i64::max_value);
 
-        assert_eq!(BigUint::new(~[0, -1]).to_int_opt(), None);
-        assert_eq!(BigUint::new(~[0, 0, 1]).to_int_opt(), None);
-        assert_eq!(BigUint::new(~[0, 0, -1]).to_int_opt(), None);
+        check(BigUint::new(~[           ]), 0);
+        check(BigUint::new(~[ 1         ]), (1 << (0*BigDigit::bits)));
+        check(BigUint::new(~[-1         ]), (1 << (1*BigDigit::bits)) - 1);
+        check(BigUint::new(~[ 0,  1     ]), (1 << (1*BigDigit::bits)));
+        check(BigUint::new(~[-1, -1 >> 1]), i64::max_value);
+
+        assert_eq!(i64::min_value.to_biguint(), None);
+        assert_eq!(BigUint::new(~[-1, -1    ]).to_i64(), None);
+        assert_eq!(BigUint::new(~[ 0,  0,  1]).to_i64(), None);
+        assert_eq!(BigUint::new(~[-1, -1, -1]).to_i64(), None);
     }
 
+    #[cfg(target_word_size = "32")]
     #[test]
-    fn test_convert_uint() {
-        fn check(v: ~[BigDigit], u: uint) {
-            let b = BigUint::new(v);
-            assert!(b == BigUint::from_uint(u));
-            assert!(b.to_uint() == u);
+    fn test_convert_u64() {
+        fn check(b1: BigUint, u: u64) {
+            let b2: BigUint = FromPrimitive::from_u64(u).unwrap();
+            assert!(b1 == b2);
+            assert!(b1.to_u64().unwrap() == u);
         }
 
-        check(~[], 0);
-        check(~[ 1], 1);
-        check(~[-1], uint::max_value >> BigDigit::bits);
-        check(~[ 0,  1], (uint::max_value >> BigDigit::bits) + 1);
-        check(~[ 0, -1], uint::max_value << BigDigit::bits);
-        check(~[-1, -1], uint::max_value);
+        check(Zero::zero(), 0);
+        check(One::one(), 1);
+        check(u64::min_value.to_biguint().unwrap(), u64::min_value);
+        check(u64::max_value.to_biguint().unwrap(), u64::max_value);
+
+        check(BigUint::new(~[              ]), 0);
+        check(BigUint::new(~[ 1            ]), (1 << (0*BigDigit::bits)));
+        check(BigUint::new(~[-1            ]), (1 << (1*BigDigit::bits)) - 1);
+        check(BigUint::new(~[ 0,  1        ]), (1 << (1*BigDigit::bits)));
+        check(BigUint::new(~[-1, -1        ]), (1 << (2*BigDigit::bits)) - 1);
+        check(BigUint::new(~[ 0,  0,  1    ]), (1 << (2*BigDigit::bits)));
+        check(BigUint::new(~[-1, -1, -1    ]), (1 << (3*BigDigit::bits)) - 1);
+        check(BigUint::new(~[ 0,  0,  0,  1]), (1 << (3*BigDigit::bits)));
+        check(BigUint::new(~[-1, -1, -1, -1]), u64::max_value);
 
-        assert_eq!(BigUint::new(~[0, 0, 1]).to_uint_opt(), None);
-        assert_eq!(BigUint::new(~[0, 0, -1]).to_uint_opt(), None);
+        assert_eq!(BigUint::new(~[ 0,  0,  0,  0,  1]).to_u64(), None);
+        assert_eq!(BigUint::new(~[-1, -1, -1, -1, -1]).to_u64(), None);
+    }
+
+    #[cfg(target_word_size = "64")]
+    #[test]
+    fn test_convert_u64() {
+        fn check(b1: BigUint, u: u64) {
+            let b2: BigUint = FromPrimitive::from_u64(u).unwrap();
+            assert!(b1 == b2);
+            assert!(b1.to_u64().unwrap() == u);
+        }
+
+        check(Zero::zero(), 0);
+        check(One::one(), 1);
+        check(u64::min_value.to_biguint().unwrap(), u64::min_value);
+        check(u64::max_value.to_biguint().unwrap(), u64::max_value);
+
+        check(BigUint::new(~[      ]), 0);
+        check(BigUint::new(~[ 1    ]), (1 << (0*BigDigit::bits)));
+        check(BigUint::new(~[-1    ]), (1 << (1*BigDigit::bits)) - 1);
+        check(BigUint::new(~[ 0,  1]), (1 << (1*BigDigit::bits)));
+        check(BigUint::new(~[-1, -1]), u64::max_value);
+
+        assert_eq!(BigUint::new(~[ 0,  0,  1]).to_u64(), None);
+        assert_eq!(BigUint::new(~[-1, -1, -1]).to_u64(), None);
     }
 
     #[test]
     fn test_convert_to_bigint() {
         fn check(n: BigUint, ans: BigInt) {
-            assert_eq!(n.to_bigint(), ans);
-            assert_eq!(n.to_bigint().to_biguint(), n);
+            assert_eq!(n.to_bigint().unwrap(), ans);
+            assert_eq!(n.to_bigint().unwrap().to_biguint().unwrap(), n);
         }
         check(Zero::zero(), Zero::zero());
         check(BigUint::new(~[1,2,3]),
@@ -1660,9 +1862,9 @@ mod biguint_tests {
     #[test]
     fn test_gcd() {
         fn check(a: uint, b: uint, c: uint) {
-            let big_a = BigUint::from_uint(a);
-            let big_b = BigUint::from_uint(b);
-            let big_c = BigUint::from_uint(c);
+            let big_a: BigUint = FromPrimitive::from_uint(a).unwrap();
+            let big_b: BigUint = FromPrimitive::from_uint(b).unwrap();
+            let big_c: BigUint = FromPrimitive::from_uint(c).unwrap();
 
             assert_eq!(big_a.gcd(&big_b), big_c);
         }
@@ -1677,9 +1879,9 @@ mod biguint_tests {
     #[test]
     fn test_lcm() {
         fn check(a: uint, b: uint, c: uint) {
-            let big_a = BigUint::from_uint(a);
-            let big_b = BigUint::from_uint(b);
-            let big_c = BigUint::from_uint(c);
+            let big_a: BigUint = FromPrimitive::from_uint(a).unwrap();
+            let big_b: BigUint = FromPrimitive::from_uint(b).unwrap();
+            let big_c: BigUint = FromPrimitive::from_uint(c).unwrap();
 
             assert_eq!(big_a.lcm(&big_b), big_c);
         }
@@ -1694,20 +1896,18 @@ mod biguint_tests {
 
     #[test]
     fn test_is_even() {
-        let one: Option<BigUint> = FromStr::from_str("1");
-        let two: Option<BigUint> = FromStr::from_str("2");
-        let thousand: Option<BigUint> = FromStr::from_str("1000");
-        let big: Option<BigUint> =
-            FromStr::from_str("1000000000000000000000");
-        let bigger: Option<BigUint> =
-            FromStr::from_str("1000000000000000000001");
-        assert!(one.unwrap().is_odd());
-        assert!(two.unwrap().is_even());
-        assert!(thousand.unwrap().is_even());
-        assert!(big.unwrap().is_even());
-        assert!(bigger.unwrap().is_odd());
-        assert!((BigUint::from_uint(1) << 64).is_even());
-        assert!(((BigUint::from_uint(1) << 64) + BigUint::from_uint(1)).is_odd());
+        let one: BigUint = FromStr::from_str("1").unwrap();
+        let two: BigUint = FromStr::from_str("2").unwrap();
+        let thousand: BigUint = FromStr::from_str("1000").unwrap();
+        let big: BigUint = FromStr::from_str("1000000000000000000000").unwrap();
+        let bigger: BigUint = FromStr::from_str("1000000000000000000001").unwrap();
+        assert!(one.is_odd());
+        assert!(two.is_even());
+        assert!(thousand.is_even());
+        assert!(big.is_even());
+        assert!(bigger.is_odd());
+        assert!((one << 64).is_even());
+        assert!(((one << 64) + one).is_odd());
     }
 
     fn to_str_pairs() -> ~[ (BigUint, ~[(uint, ~str)]) ] {
@@ -1805,8 +2005,8 @@ mod biguint_tests {
             let mut f: BigUint = One::one();
             for i in range(2, n + 1) {
                 // FIXME(#6102): Assignment operator for BigInt causes ICE
-                // f *= BigUint::from_uint(i);
-                f = f * BigUint::from_uint(i);
+                // f *= FromPrimitive::from_uint(i);
+                f = f * FromPrimitive::from_uint(i).unwrap();
             }
             return f;
         }
@@ -1828,9 +2028,12 @@ mod biguint_tests {
     #[test]
     fn test_bits() {
         assert_eq!(BigUint::new(~[0,0,0,0]).bits(), 0);
-        assert_eq!(BigUint::from_uint(0).bits(), 0);
-        assert_eq!(BigUint::from_uint(1).bits(), 1);
-        assert_eq!(BigUint::from_uint(3).bits(), 2);
+        let n: BigUint = FromPrimitive::from_uint(0).unwrap();
+        assert_eq!(n.bits(), 0);
+        let n: BigUint = FromPrimitive::from_uint(1).unwrap();
+        assert_eq!(n.bits(), 1);
+        let n: BigUint = FromPrimitive::from_uint(3).unwrap();
+        assert_eq!(n.bits(), 2);
         let n: BigUint = FromStrRadix::from_str_radix("4000000000", 16).unwrap();
         assert_eq!(n.bits(), 39);
         let one: BigUint = One::one();
@@ -1849,13 +2052,13 @@ mod biguint_tests {
         let mut rng = task_rng();
 
         do 10.times {
-            assert_eq!(rng.gen_bigint_range(&BigInt::from_uint(236),
-                                            &BigInt::from_uint(237)),
-                       BigInt::from_uint(236));
+            assert_eq!(rng.gen_bigint_range(&FromPrimitive::from_uint(236).unwrap(),
+                                            &FromPrimitive::from_uint(237).unwrap()),
+                       FromPrimitive::from_uint(236).unwrap());
         }
 
-        let l = BigUint::from_uint(403469000 + 2352);
-        let u = BigUint::from_uint(403469000 + 3513);
+        let l = FromPrimitive::from_uint(403469000 + 2352).unwrap();
+        let u = FromPrimitive::from_uint(403469000 + 3513).unwrap();
         do 1000.times {
             let n: BigUint = rng.gen_biguint_below(&u);
             assert!(n < u);
@@ -1869,16 +2072,16 @@ mod biguint_tests {
     #[test]
     #[should_fail]
     fn test_zero_rand_range() {
-        task_rng().gen_biguint_range(&BigUint::from_uint(54),
-                                     &BigUint::from_uint(54));
+        task_rng().gen_biguint_range(&FromPrimitive::from_uint(54).unwrap(),
+                                     &FromPrimitive::from_uint(54).unwrap());
     }
 
     #[test]
     #[should_fail]
     fn test_negative_rand_range() {
         let mut rng = task_rng();
-        let l = BigUint::from_uint(2352);
-        let u = BigUint::from_uint(3513);
+        let l = FromPrimitive::from_uint(2352).unwrap();
+        let u = FromPrimitive::from_uint(3513).unwrap();
         // Switching u and l should fail:
         let _n: BigUint = rng.gen_biguint_range(&u, &l);
     }
@@ -1889,16 +2092,17 @@ mod bigint_tests {
     use super::*;
 
     use std::cmp::{Less, Equal, Greater};
-    use std::int;
-    use std::num::{IntConvertible, Zero, One, FromStrRadix};
+    use std::i64;
+    use std::num::{Zero, One, FromStrRadix};
+    use std::num::{ToPrimitive, FromPrimitive};
     use std::rand::{task_rng};
-    use std::uint;
+    use std::u64;
 
     #[test]
     fn test_from_biguint() {
         fn check(inp_s: Sign, inp_n: uint, ans_s: Sign, ans_n: uint) {
-            let inp = BigInt::from_biguint(inp_s, BigUint::from_uint(inp_n));
-            let ans = BigInt { sign: ans_s, data: BigUint::from_uint(ans_n)};
+            let inp = BigInt::from_biguint(inp_s, FromPrimitive::from_uint(inp_n).unwrap());
+            let ans = BigInt { sign: ans_s, data: FromPrimitive::from_uint(ans_n).unwrap()};
             assert_eq!(inp, ans);
         }
         check(Plus, 1, Plus, 1);
@@ -1951,62 +2155,62 @@ mod bigint_tests {
     }
 
     #[test]
-    fn test_convert_int() {
-        fn check(b: BigInt, i: int) {
-            assert!(b == IntConvertible::from_int(i));
-            assert!(b.to_int() == i);
+    fn test_convert_i64() {
+        fn check(b1: BigInt, i: i64) {
+            let b2: BigInt = FromPrimitive::from_i64(i).unwrap();
+            assert!(b1 == b2);
+            assert!(b1.to_i64().unwrap() == i);
         }
 
         check(Zero::zero(), 0);
         check(One::one(), 1);
-        check(BigInt::from_biguint(
-            Plus, BigUint::from_uint(int::max_value as uint)
-        ), int::max_value);
-
-        assert_eq!(BigInt::from_biguint(
-            Plus, BigUint::from_uint(int::max_value as uint + 1)
-        ).to_int_opt(), None);
-        assert_eq!(BigInt::from_biguint(
-            Plus, BigUint::new(~[1, 2, 3])
-        ).to_int_opt(), None);
-
-        check(BigInt::from_biguint(
-            Minus, BigUint::new(~[0, 1<<(BigDigit::bits-1)])
-        ), int::min_value);
-        assert_eq!(BigInt::from_biguint(
-            Minus, BigUint::new(~[1, 1<<(BigDigit::bits-1)])
-        ).to_int_opt(), None);
-        assert_eq!(BigInt::from_biguint(
-            Minus, BigUint::new(~[1, 2, 3])).to_int_opt(), None);
+        check(i64::min_value.to_bigint().unwrap(), i64::min_value);
+        check(i64::max_value.to_bigint().unwrap(), i64::max_value);
+
+        assert_eq!(
+            (i64::max_value as u64 + 1).to_bigint().unwrap().to_i64(),
+            None);
+
+        assert_eq!(
+            BigInt::from_biguint(Plus,  BigUint::new(~[1, 2, 3, 4, 5])).to_i64(),
+            None);
+
+        assert_eq!(
+            BigInt::from_biguint(Minus, BigUint::new(~[1, 0, 0, 1<<(BigDigit::bits-1)])).to_i64(),
+            None);
+
+        assert_eq!(
+            BigInt::from_biguint(Minus, BigUint::new(~[1, 2, 3, 4, 5])).to_i64(),
+            None);
     }
 
     #[test]
-    fn test_convert_uint() {
-        fn check(b: BigInt, u: uint) {
-            assert!(b == BigInt::from_uint(u));
-            assert!(b.to_uint() == u);
+    fn test_convert_u64() {
+        fn check(b1: BigInt, u: u64) {
+            let b2: BigInt = FromPrimitive::from_u64(u).unwrap();
+            assert!(b1 == b2);
+            assert!(b1.to_u64().unwrap() == u);
         }
 
         check(Zero::zero(), 0);
         check(One::one(), 1);
+        check(u64::min_value.to_bigint().unwrap(), u64::min_value);
+        check(u64::max_value.to_bigint().unwrap(), u64::max_value);
 
-        check(
-            BigInt::from_biguint(Plus, BigUint::from_uint(uint::max_value)),
-            uint::max_value);
-        assert_eq!(BigInt::from_biguint(
-            Plus, BigUint::new(~[1, 2, 3])).to_uint_opt(), None);
+        assert_eq!(
+            BigInt::from_biguint(Plus, BigUint::new(~[1, 2, 3, 4, 5])).to_u64(),
+            None);
 
-        assert_eq!(BigInt::from_biguint(
-            Minus, BigUint::from_uint(uint::max_value)).to_uint_opt(), None);
-        assert_eq!(BigInt::from_biguint(
-            Minus, BigUint::new(~[1, 2, 3])).to_uint_opt(), None);
+        let max_value: BigUint = FromPrimitive::from_u64(u64::max_value).unwrap();
+        assert_eq!(BigInt::from_biguint(Minus, max_value).to_u64(), None);
+        assert_eq!(BigInt::from_biguint(Minus, BigUint::new(~[1, 2, 3, 4, 5])).to_u64(), None);
     }
 
     #[test]
     fn test_convert_to_biguint() {
         fn check(n: BigInt, ans_1: BigUint) {
-            assert_eq!(n.to_biguint(), ans_1);
-            assert_eq!(n.to_biguint().to_bigint(), n);
+            assert_eq!(n.to_biguint().unwrap(), ans_1);
+            assert_eq!(n.to_biguint().unwrap().to_bigint().unwrap(), n);
         }
         let zero: BigInt = Zero::zero();
         let unsigned_zero: BigUint = Zero::zero();
@@ -2017,7 +2221,7 @@ mod bigint_tests {
         check(zero, unsigned_zero);
         check(positive, BigUint::new(~[1,2,3]));
 
-        assert_eq!(negative.to_biguint_opt(), None);
+        assert_eq!(negative.to_biguint(), None);
     }
 
     static sum_triples: &'static [(&'static [BigDigit],
@@ -2233,9 +2437,9 @@ mod bigint_tests {
     #[test]
     fn test_gcd() {
         fn check(a: int, b: int, c: int) {
-            let big_a: BigInt = IntConvertible::from_int(a);
-            let big_b: BigInt = IntConvertible::from_int(b);
-            let big_c: BigInt = IntConvertible::from_int(c);
+            let big_a: BigInt = FromPrimitive::from_int(a).unwrap();
+            let big_b: BigInt = FromPrimitive::from_int(b).unwrap();
+            let big_c: BigInt = FromPrimitive::from_int(c).unwrap();
 
             assert_eq!(big_a.gcd(&big_b), big_c);
         }
@@ -2253,9 +2457,9 @@ mod bigint_tests {
     #[test]
     fn test_lcm() {
         fn check(a: int, b: int, c: int) {
-            let big_a: BigInt = IntConvertible::from_int(a);
-            let big_b: BigInt = IntConvertible::from_int(b);
-            let big_c: BigInt = IntConvertible::from_int(c);
+            let big_a: BigInt = FromPrimitive::from_int(a).unwrap();
+            let big_b: BigInt = FromPrimitive::from_int(b).unwrap();
+            let big_c: BigInt = FromPrimitive::from_int(c).unwrap();
 
             assert_eq!(big_a.lcm(&big_b), big_c);
         }
@@ -2282,13 +2486,14 @@ mod bigint_tests {
         let zero: BigInt = Zero::zero();
         assert_eq!(one.abs_sub(&zero), one);
         let one: BigInt = One::one();
-        assert_eq!(one.abs_sub(&-one), IntConvertible::from_int(2));
+        let two: BigInt = FromPrimitive::from_int(2).unwrap();
+        assert_eq!(one.abs_sub(&-one), two);
     }
 
     #[test]
     fn test_to_str_radix() {
         fn check(n: int, ans: &str) {
-            let n: BigInt = IntConvertible::from_int(n);
+            let n: BigInt = FromPrimitive::from_int(n).unwrap();
             assert!(ans == n.to_str_radix(10));
         }
         check(10, "10");
@@ -2303,7 +2508,7 @@ mod bigint_tests {
     fn test_from_str_radix() {
         fn check(s: &str, ans: Option<int>) {
             let ans = ans.map_move(|n| {
-                let x: BigInt = IntConvertible::from_int(n);
+                let x: BigInt = FromPrimitive::from_int(n).unwrap();
                 x
             });
             assert_eq!(FromStrRadix::from_str_radix(s, 10), ans);
@@ -2339,9 +2544,9 @@ mod bigint_tests {
         let mut rng = task_rng();
 
         do 10.times {
-            assert_eq!(rng.gen_bigint_range(&BigInt::from_uint(236),
-                                            &BigInt::from_uint(237)),
-                       BigInt::from_uint(236));
+            assert_eq!(rng.gen_bigint_range(&FromPrimitive::from_uint(236).unwrap(),
+                                            &FromPrimitive::from_uint(237).unwrap()),
+                       FromPrimitive::from_uint(236).unwrap());
         }
 
         fn check(l: BigInt, u: BigInt) {
@@ -2352,8 +2557,8 @@ mod bigint_tests {
                 assert!(n < u);
             }
         }
-        let l = BigInt::from_uint(403469000 + 2352);
-        let u = BigInt::from_uint(403469000 + 3513);
+        let l: BigInt = FromPrimitive::from_uint(403469000 + 2352).unwrap();
+        let u: BigInt = FromPrimitive::from_uint(403469000 + 3513).unwrap();
         check( l.clone(),  u.clone());
         check(-l.clone(),  u.clone());
         check(-u.clone(), -l.clone());
@@ -2362,16 +2567,16 @@ mod bigint_tests {
     #[test]
     #[should_fail]
     fn test_zero_rand_range() {
-        task_rng().gen_bigint_range(&IntConvertible::from_int(54),
-                                    &IntConvertible::from_int(54));
+        task_rng().gen_bigint_range(&FromPrimitive::from_int(54).unwrap(),
+                                    &FromPrimitive::from_int(54).unwrap());
     }
 
     #[test]
     #[should_fail]
     fn test_negative_rand_range() {
         let mut rng = task_rng();
-        let l = BigInt::from_uint(2352);
-        let u = BigInt::from_uint(3513);
+        let l = FromPrimitive::from_uint(2352).unwrap();
+        let u = FromPrimitive::from_uint(3513).unwrap();
         // Switching u and l should fail:
         let _n: BigInt = rng.gen_bigint_range(&u, &l);
     }
@@ -2381,13 +2586,13 @@ mod bigint_tests {
 mod bench {
     use super::*;
     use std::{iter, util};
-    use std::num::{Zero, One};
+    use std::num::{FromPrimitive, Zero, One};
     use extra::test::BenchHarness;
 
     fn factorial(n: uint) -> BigUint {
         let mut f: BigUint = One::one();
         for i in iter::range_inclusive(1, n) {
-            f = f * BigUint::from_uint(i);
+            f = f * FromPrimitive::from_uint(i).unwrap();
         }
         f
     }
diff --git a/src/libextra/num/rational.rs b/src/libextra/num/rational.rs
index e7142f6f9ff..a8dfdfbfd00 100644
--- a/src/libextra/num/rational.rs
+++ b/src/libextra/num/rational.rs
@@ -306,7 +306,7 @@ impl<T: FromStrRadix + Clone + Integer + Ord>
 mod test {
 
     use super::*;
-    use std::num::{Zero,One,FromStrRadix,IntConvertible};
+    use std::num::{Zero,One,FromStrRadix,FromPrimitive};
     use std::from_str::FromStr;
 
     pub static _0 : Rational = Ratio { numer: 0, denom: 1};
@@ -318,8 +318,8 @@ mod test {
 
     pub fn to_big(n: Rational) -> BigRational {
         Ratio::new(
-            IntConvertible::from_int(n.numer),
-            IntConvertible::from_int(n.denom)
+            FromPrimitive::from_int(n.numer).unwrap(),
+            FromPrimitive::from_int(n.denom).unwrap()
         )
     }
 
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index ded61f975db..52695100b3e 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -107,7 +107,7 @@ use std::hashmap::HashMap;
 use std::libc::{c_uint, c_ulonglong, c_longlong};
 use std::ptr;
 use std::vec;
-use syntax::codemap::Span;
+use syntax::codemap::{Span, Pos};
 use syntax::{ast, codemap, ast_util, ast_map, opt_vec, visit};
 use syntax::parse::token;
 use syntax::parse::token::special_idents;
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 21517e42169..d5219ed0867 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -26,7 +26,7 @@ use middle::ty;
 use middle::typeck;
 use syntax::abi::AbiSet;
 use syntax::ast_map;
-use syntax::codemap::Span;
+use syntax::codemap::{Span, Pos};
 use syntax::parse::token;
 use syntax::print::pprust;
 use syntax::{ast, ast_util};
diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs
index 41a3d193379..2b4a636e1ad 100644
--- a/src/libstd/num/f32.rs
+++ b/src/libstd/num/f32.rs
@@ -590,6 +590,9 @@ impl Primitive for f32 {
 
     #[inline]
     fn bytes(_: Option<f32>) -> uint { Primitive::bits(Some(0f32)) / 8 }
+
+    #[inline]
+    fn is_signed(_: Option<f32>) -> bool { true }
 }
 
 impl Float for f32 {
diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs
index 772596d15fb..d4442e5b34f 100644
--- a/src/libstd/num/f64.rs
+++ b/src/libstd/num/f64.rs
@@ -638,6 +638,9 @@ impl Primitive for f64 {
 
     #[inline]
     fn bytes(_: Option<f64>) -> uint { Primitive::bits(Some(0f64)) / 8 }
+
+    #[inline]
+    fn is_signed(_: Option<f64>) -> bool { true }
 }
 
 impl Float for f64 {
diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs
index 1070e8e592f..7fae567809b 100644
--- a/src/libstd/num/int_macros.rs
+++ b/src/libstd/num/int_macros.rs
@@ -380,6 +380,9 @@ impl Primitive for $T {
 
     #[inline]
     fn bytes(_: Option<$T>) -> uint { bits / 8 }
+
+    #[inline]
+    fn is_signed(_: Option<$T>) -> bool { true }
 }
 
 // String conversion functions and impl str -> num
diff --git a/src/libstd/num/num.rs b/src/libstd/num/num.rs
index 95b1057dfd0..fde1928f4a3 100644
--- a/src/libstd/num/num.rs
+++ b/src/libstd/num/num.rs
@@ -32,11 +32,6 @@ pub trait Num: Eq + Zero + One
              + Div<Self,Self>
              + Rem<Self,Self> {}
 
-pub trait IntConvertible {
-    fn to_int(&self) -> int;
-    fn from_int(n: int) -> Self;
-}
-
 pub trait Orderable: Ord {
     // These should be methods on `Ord`, with overridable default implementations. We don't want
     // to encumber all implementors of Ord by requiring them to implement these functions, but at
@@ -291,6 +286,7 @@ pub trait Primitive: Clone
     // FIXME (#8888): Removing `unused_self` requires #8888 to be fixed.
     fn bits(unused_self: Option<Self>) -> uint;
     fn bytes(unused_self: Option<Self>) -> uint;
+    fn is_signed(unused_self: Option<Self>) -> bool;
 }
 
 /// A collection of traits relevant to primitive signed and unsigned integers
@@ -353,6 +349,448 @@ pub trait Float: Real
 #[inline(always)] pub fn ln_1p<T: Float>(value: T) -> T { value.ln_1p() }
 #[inline(always)] pub fn mul_add<T: Float>(a: T, b: T, c: T) -> T { a.mul_add(b, c) }
 
+/// A generic trait for converting a value to a number.
+pub trait ToPrimitive {
+    /// Converts the value of `self` to an `int`.
+    #[inline]
+    fn to_int(&self) -> Option<int> {
+        self.to_i64().and_then(|x| x.to_int())
+    }
+
+    /// Converts the value of `self` to an `i8`.
+    #[inline]
+    fn to_i8(&self) -> Option<i8> {
+        self.to_i64().and_then(|x| x.to_i8())
+    }
+
+    /// Converts the value of `self` to an `i16`.
+    #[inline]
+    fn to_i16(&self) -> Option<i16> {
+        self.to_i64().and_then(|x| x.to_i16())
+    }
+
+    /// Converts the value of `self` to an `i32`.
+    #[inline]
+    fn to_i32(&self) -> Option<i32> {
+        self.to_i64().and_then(|x| x.to_i32())
+    }
+
+    /// Converts the value of `self` to an `i64`.
+    fn to_i64(&self) -> Option<i64>;
+
+    /// Converts the value of `self` to an `uint`.
+    #[inline]
+    fn to_uint(&self) -> Option<uint> {
+        self.to_u64().and_then(|x| x.to_uint())
+    }
+
+    /// Converts the value of `self` to an `u8`.
+    #[inline]
+    fn to_u8(&self) -> Option<u8> {
+        self.to_u64().and_then(|x| x.to_u8())
+    }
+
+    /// Converts the value of `self` to an `u16`.
+    #[inline]
+    fn to_u16(&self) -> Option<u16> {
+        self.to_u64().and_then(|x| x.to_u16())
+    }
+
+    /// Converts the value of `self` to an `u32`.
+    #[inline]
+    fn to_u32(&self) -> Option<u32> {
+        self.to_u64().and_then(|x| x.to_u32())
+    }
+
+    /// Converts the value of `self` to an `u64`.
+    #[inline]
+    fn to_u64(&self) -> Option<u64> {
+        self.to_u64().and_then(|x| x.to_u64())
+    }
+
+    /// Converts the value of `self` to an `f32`.
+    #[inline]
+    fn to_f32(&self) -> Option<f32> {
+        self.to_f64().and_then(|x| x.to_f32())
+    }
+
+    /// Converts the value of `self` to an `f64`.
+    #[inline]
+    fn to_f64(&self) -> Option<f64> {
+        self.to_i64().and_then(|x| x.to_f64())
+    }
+}
+
+macro_rules! impl_to_primitive_int_to_int(
+    ($SrcT:ty, $DstT:ty) => (
+        {
+            if Primitive::bits(None::<$SrcT>) <= Primitive::bits(None::<$DstT>) {
+                Some(*self as $DstT)
+            } else {
+                let n = *self as i64;
+                let min_value: $DstT = Bounded::min_value();
+                let max_value: $DstT = Bounded::max_value();
+                if min_value as i64 <= n && n <= max_value as i64 {
+                    Some(*self as $DstT)
+                } else {
+                    None
+                }
+            }
+        }
+    )
+)
+
+macro_rules! impl_to_primitive_int_to_uint(
+    ($SrcT:ty, $DstT:ty) => (
+        {
+            let zero: $SrcT = Zero::zero();
+            let max_value: $DstT = Bounded::max_value();
+            if zero <= *self && *self as u64 <= max_value as u64 {
+                Some(*self as $DstT)
+            } else {
+                None
+            }
+        }
+    )
+)
+
+macro_rules! impl_to_primitive_int(
+    ($T:ty) => (
+        impl ToPrimitive for $T {
+            #[inline]
+            fn to_int(&self) -> Option<int> { impl_to_primitive_int_to_int!($T, int) }
+            #[inline]
+            fn to_i8(&self) -> Option<i8> { impl_to_primitive_int_to_int!($T, i8) }
+            #[inline]
+            fn to_i16(&self) -> Option<i16> { impl_to_primitive_int_to_int!($T, i16) }
+            #[inline]
+            fn to_i32(&self) -> Option<i32> { impl_to_primitive_int_to_int!($T, i32) }
+            #[inline]
+            fn to_i64(&self) -> Option<i64> { impl_to_primitive_int_to_int!($T, i64) }
+
+            #[inline]
+            fn to_uint(&self) -> Option<uint> { impl_to_primitive_int_to_uint!($T, uint) }
+            #[inline]
+            fn to_u8(&self) -> Option<u8> { impl_to_primitive_int_to_uint!($T, u8) }
+            #[inline]
+            fn to_u16(&self) -> Option<u16> { impl_to_primitive_int_to_uint!($T, u16) }
+            #[inline]
+            fn to_u32(&self) -> Option<u32> { impl_to_primitive_int_to_uint!($T, u32) }
+            #[inline]
+            fn to_u64(&self) -> Option<u64> { impl_to_primitive_int_to_uint!($T, u64) }
+
+            #[inline]
+            fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
+            #[inline]
+            fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
+        }
+    )
+)
+
+impl_to_primitive_int!(int)
+impl_to_primitive_int!(i8)
+impl_to_primitive_int!(i16)
+impl_to_primitive_int!(i32)
+impl_to_primitive_int!(i64)
+
+macro_rules! impl_to_primitive_uint_to_int(
+    ($DstT:ty) => (
+        {
+            let max_value: $DstT = Bounded::max_value();
+            if *self as u64 <= max_value as u64 {
+                Some(*self as $DstT)
+            } else {
+                None
+            }
+        }
+    )
+)
+
+macro_rules! impl_to_primitive_uint_to_uint(
+    ($SrcT:ty, $DstT:ty) => (
+        {
+            if Primitive::bits(None::<$SrcT>) <= Primitive::bits(None::<$DstT>) {
+                Some(*self as $DstT)
+            } else {
+                let zero: $SrcT = Zero::zero();
+                let max_value: $DstT = Bounded::max_value();
+                if zero <= *self && *self as u64 <= max_value as u64 {
+                    Some(*self as $DstT)
+                } else {
+                    None
+                }
+            }
+        }
+    )
+)
+
+macro_rules! impl_to_primitive_uint(
+    ($T:ty) => (
+        impl ToPrimitive for $T {
+            #[inline]
+            fn to_int(&self) -> Option<int> { impl_to_primitive_uint_to_int!(int) }
+            #[inline]
+            fn to_i8(&self) -> Option<i8> { impl_to_primitive_uint_to_int!(i8) }
+            #[inline]
+            fn to_i16(&self) -> Option<i16> { impl_to_primitive_uint_to_int!(i16) }
+            #[inline]
+            fn to_i32(&self) -> Option<i32> { impl_to_primitive_uint_to_int!(i32) }
+            #[inline]
+            fn to_i64(&self) -> Option<i64> { impl_to_primitive_uint_to_int!(i64) }
+
+            #[inline]
+            fn to_uint(&self) -> Option<uint> { impl_to_primitive_uint_to_uint!($T, uint) }
+            #[inline]
+            fn to_u8(&self) -> Option<u8> { impl_to_primitive_uint_to_uint!($T, u8) }
+            #[inline]
+            fn to_u16(&self) -> Option<u16> { impl_to_primitive_uint_to_uint!($T, u16) }
+            #[inline]
+            fn to_u32(&self) -> Option<u32> { impl_to_primitive_uint_to_uint!($T, u32) }
+            #[inline]
+            fn to_u64(&self) -> Option<u64> { impl_to_primitive_uint_to_uint!($T, u64) }
+
+            #[inline]
+            fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
+            #[inline]
+            fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
+        }
+    )
+)
+
+impl_to_primitive_uint!(uint)
+impl_to_primitive_uint!(u8)
+impl_to_primitive_uint!(u16)
+impl_to_primitive_uint!(u32)
+impl_to_primitive_uint!(u64)
+
+macro_rules! impl_to_primitive_float_to_float(
+    ($SrcT:ty, $DstT:ty) => (
+        if Primitive::bits(None::<$SrcT>) <= Primitive::bits(None::<$DstT>) {
+            Some(*self as $DstT)
+        } else {
+            let n = *self as f64;
+            let min_value: $SrcT = Bounded::min_value();
+            let max_value: $SrcT = Bounded::max_value();
+            if min_value as f64 <= n && n <= max_value as f64 {
+                Some(*self as $DstT)
+            } else {
+                None
+            }
+        }
+    )
+)
+
+macro_rules! impl_to_primitive_float(
+    ($T:ty) => (
+        impl ToPrimitive for $T {
+            #[inline]
+            fn to_int(&self) -> Option<int> { Some(*self as int) }
+            #[inline]
+            fn to_i8(&self) -> Option<i8> { Some(*self as i8) }
+            #[inline]
+            fn to_i16(&self) -> Option<i16> { Some(*self as i16) }
+            #[inline]
+            fn to_i32(&self) -> Option<i32> { Some(*self as i32) }
+            #[inline]
+            fn to_i64(&self) -> Option<i64> { Some(*self as i64) }
+
+            #[inline]
+            fn to_uint(&self) -> Option<uint> { Some(*self as uint) }
+            #[inline]
+            fn to_u8(&self) -> Option<u8> { Some(*self as u8) }
+            #[inline]
+            fn to_u16(&self) -> Option<u16> { Some(*self as u16) }
+            #[inline]
+            fn to_u32(&self) -> Option<u32> { Some(*self as u32) }
+            #[inline]
+            fn to_u64(&self) -> Option<u64> { Some(*self as u64) }
+
+            #[inline]
+            fn to_f32(&self) -> Option<f32> { impl_to_primitive_float_to_float!($T, f32) }
+            #[inline]
+            fn to_f64(&self) -> Option<f64> { impl_to_primitive_float_to_float!($T, f64) }
+        }
+    )
+)
+
+impl_to_primitive_float!(f32)
+impl_to_primitive_float!(f64)
+
+/// A generic trait for converting a number to a value.
+pub trait FromPrimitive {
+    /// Convert an `int` to return an optional value of this type. If the
+    /// value cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_int(n: int) -> Option<Self> {
+        FromPrimitive::from_i64(n as i64)
+    }
+
+    /// Convert an `i8` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_i8(n: i8) -> Option<Self> {
+        FromPrimitive::from_i64(n as i64)
+    }
+
+    /// Convert an `i16` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_i16(n: i16) -> Option<Self> {
+        FromPrimitive::from_i64(n as i64)
+    }
+
+    /// Convert an `i32` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_i32(n: i32) -> Option<Self> {
+        FromPrimitive::from_i64(n as i64)
+    }
+
+    /// Convert an `i64` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    fn from_i64(n: i64) -> Option<Self>;
+
+    /// Convert an `uint` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_uint(n: uint) -> Option<Self> {
+        FromPrimitive::from_u64(n as u64)
+    }
+
+    /// Convert an `u8` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_u8(n: u8) -> Option<Self> {
+        FromPrimitive::from_u64(n as u64)
+    }
+
+    /// Convert an `u16` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_u16(n: u16) -> Option<Self> {
+        FromPrimitive::from_u64(n as u64)
+    }
+
+    /// Convert an `u32` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_u32(n: u32) -> Option<Self> {
+        FromPrimitive::from_u64(n as u64)
+    }
+
+    /// Convert an `u64` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    fn from_u64(n: u64) -> Option<Self>;
+
+    /// Convert a `f32` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_f32(n: f32) -> Option<Self> {
+        FromPrimitive::from_f64(n as f64)
+    }
+
+    /// Convert a `f64` to return an optional value of this type. If the
+    /// type cannot be represented by this value, the `None` is returned.
+    #[inline]
+    fn from_f64(n: f64) -> Option<Self> {
+        FromPrimitive::from_i64(n as i64)
+    }
+}
+
+/// A utility function that just calls `FromPrimitive::from_int`.
+pub fn from_int<A: FromPrimitive>(n: int) -> Option<A> {
+    FromPrimitive::from_int(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_i8`.
+pub fn from_i8<A: FromPrimitive>(n: i8) -> Option<A> {
+    FromPrimitive::from_i8(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_i16`.
+pub fn from_i16<A: FromPrimitive>(n: i16) -> Option<A> {
+    FromPrimitive::from_i16(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_i32`.
+pub fn from_i32<A: FromPrimitive>(n: i32) -> Option<A> {
+    FromPrimitive::from_i32(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_i64`.
+pub fn from_i64<A: FromPrimitive>(n: i64) -> Option<A> {
+    FromPrimitive::from_i64(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_uint`.
+pub fn from_uint<A: FromPrimitive>(n: uint) -> Option<A> {
+    FromPrimitive::from_uint(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_u8`.
+pub fn from_u8<A: FromPrimitive>(n: u8) -> Option<A> {
+    FromPrimitive::from_u8(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_u16`.
+pub fn from_u16<A: FromPrimitive>(n: u16) -> Option<A> {
+    FromPrimitive::from_u16(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_u32`.
+pub fn from_u32<A: FromPrimitive>(n: u32) -> Option<A> {
+    FromPrimitive::from_u32(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_u64`.
+pub fn from_u64<A: FromPrimitive>(n: u64) -> Option<A> {
+    FromPrimitive::from_u64(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_f32`.
+pub fn from_f32<A: FromPrimitive>(n: f32) -> Option<A> {
+    FromPrimitive::from_f32(n)
+}
+
+/// A utility function that just calls `FromPrimitive::from_f64`.
+pub fn from_f64<A: FromPrimitive>(n: f64) -> Option<A> {
+    FromPrimitive::from_f64(n)
+}
+
+macro_rules! impl_from_primitive(
+    ($T:ty, $to_ty:expr) => (
+        impl FromPrimitive for $T {
+            #[inline] fn from_int(n: int) -> Option<$T> { $to_ty }
+            #[inline] fn from_i8(n: i8) -> Option<$T> { $to_ty }
+            #[inline] fn from_i16(n: i16) -> Option<$T> { $to_ty }
+            #[inline] fn from_i32(n: i32) -> Option<$T> { $to_ty }
+            #[inline] fn from_i64(n: i64) -> Option<$T> { $to_ty }
+
+            #[inline] fn from_uint(n: uint) -> Option<$T> { $to_ty }
+            #[inline] fn from_u8(n: u8) -> Option<$T> { $to_ty }
+            #[inline] fn from_u16(n: u16) -> Option<$T> { $to_ty }
+            #[inline] fn from_u32(n: u32) -> Option<$T> { $to_ty }
+            #[inline] fn from_u64(n: u64) -> Option<$T> { $to_ty }
+
+            #[inline] fn from_f32(n: f32) -> Option<$T> { $to_ty }
+            #[inline] fn from_f64(n: f64) -> Option<$T> { $to_ty }
+        }
+    )
+)
+
+impl_from_primitive!(int, n.to_int())
+impl_from_primitive!(i8, n.to_i8())
+impl_from_primitive!(i16, n.to_i16())
+impl_from_primitive!(i32, n.to_i32())
+impl_from_primitive!(i64, n.to_i64())
+impl_from_primitive!(uint, n.to_uint())
+impl_from_primitive!(u8, n.to_u8())
+impl_from_primitive!(u16, n.to_u16())
+impl_from_primitive!(u32, n.to_u32())
+impl_from_primitive!(u64, n.to_u64())
+impl_from_primitive!(f32, n.to_f32())
+impl_from_primitive!(f64, n.to_f64())
+
 /// Cast from one machine scalar to another
 ///
 /// # Example
@@ -363,54 +801,24 @@ pub trait Float: Real
 /// ```
 ///
 #[inline]
-pub fn cast<T:NumCast,U:NumCast>(n: T) -> U {
+pub fn cast<T: NumCast,U: NumCast>(n: T) -> Option<U> {
     NumCast::from(n)
 }
 
 /// An interface for casting between machine scalars
-pub trait NumCast {
-    fn from<T:NumCast>(n: T) -> Self;
-
-    fn to_u8(&self) -> u8;
-    fn to_u16(&self) -> u16;
-    fn to_u32(&self) -> u32;
-    fn to_u64(&self) -> u64;
-    fn to_uint(&self) -> uint;
-
-    fn to_i8(&self) -> i8;
-    fn to_i16(&self) -> i16;
-    fn to_i32(&self) -> i32;
-    fn to_i64(&self) -> i64;
-    fn to_int(&self) -> int;
-
-    fn to_f32(&self) -> f32;
-    fn to_f64(&self) -> f64;
+pub trait NumCast: ToPrimitive {
+    fn from<T: ToPrimitive>(n: T) -> Option<Self>;
 }
 
 macro_rules! impl_num_cast(
     ($T:ty, $conv:ident) => (
         impl NumCast for $T {
             #[inline]
-            fn from<N:NumCast>(n: N) -> $T {
+            fn from<N: ToPrimitive>(n: N) -> Option<$T> {
                 // `$conv` could be generated using `concat_idents!`, but that
                 // macro seems to be broken at the moment
                 n.$conv()
             }
-
-            #[inline] fn to_u8(&self)    -> u8    { *self as u8    }
-            #[inline] fn to_u16(&self)   -> u16   { *self as u16   }
-            #[inline] fn to_u32(&self)   -> u32   { *self as u32   }
-            #[inline] fn to_u64(&self)   -> u64   { *self as u64   }
-            #[inline] fn to_uint(&self)  -> uint  { *self as uint  }
-
-            #[inline] fn to_i8(&self)    -> i8    { *self as i8    }
-            #[inline] fn to_i16(&self)   -> i16   { *self as i16   }
-            #[inline] fn to_i32(&self)   -> i32   { *self as i32   }
-            #[inline] fn to_i64(&self)   -> i64   { *self as i64   }
-            #[inline] fn to_int(&self)   -> int   { *self as int   }
-
-            #[inline] fn to_f32(&self)   -> f32   { *self as f32   }
-            #[inline] fn to_f64(&self)   -> f64   { *self as f64   }
         }
     )
 )
@@ -461,7 +869,7 @@ pub fn pow_with_uint<T:NumCast+One+Zero+Div<T,T>+Mul<T,T>>(radix: uint, pow: uin
     if radix == 0u { return _0; }
     let mut my_pow     = pow;
     let mut total      = _1;
-    let mut multiplier = cast(radix);
+    let mut multiplier = cast(radix).unwrap();
     while (my_pow > 0u) {
         if my_pow % 2u == 1u {
             total = total * multiplier;
@@ -543,11 +951,11 @@ pub trait CheckedDiv: Div<Self, Self> {
 /// Helper function for testing numeric operations
 #[cfg(test)]
 pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
-    assert_eq!(ten.add(&two),  cast(12));
-    assert_eq!(ten.sub(&two),  cast(8));
-    assert_eq!(ten.mul(&two),  cast(20));
-    assert_eq!(ten.div(&two),  cast(5));
-    assert_eq!(ten.rem(&two),  cast(0));
+    assert_eq!(ten.add(&two),  cast(12).unwrap());
+    assert_eq!(ten.sub(&two),  cast(8).unwrap());
+    assert_eq!(ten.mul(&two),  cast(20).unwrap());
+    assert_eq!(ten.div(&two),  cast(5).unwrap());
+    assert_eq!(ten.rem(&two),  cast(0).unwrap());
 
     assert_eq!(ten.add(&two),  ten + two);
     assert_eq!(ten.sub(&two),  ten - two);
@@ -559,51 +967,60 @@ pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
 #[cfg(test)]
 mod tests {
     use prelude::*;
-    use uint;
     use super::*;
+    use i8;
+    use i16;
+    use i32;
+    use i64;
+    use int;
+    use u8;
+    use u16;
+    use u32;
+    use u64;
+    use uint;
 
     macro_rules! test_cast_20(
         ($_20:expr) => ({
             let _20 = $_20;
 
-            assert_eq!(20u,   _20.to_uint());
-            assert_eq!(20u8,  _20.to_u8());
-            assert_eq!(20u16, _20.to_u16());
-            assert_eq!(20u32, _20.to_u32());
-            assert_eq!(20u64, _20.to_u64());
-            assert_eq!(20i,   _20.to_int());
-            assert_eq!(20i8,  _20.to_i8());
-            assert_eq!(20i16, _20.to_i16());
-            assert_eq!(20i32, _20.to_i32());
-            assert_eq!(20i64, _20.to_i64());
-            assert_eq!(20f32, _20.to_f32());
-            assert_eq!(20f64, _20.to_f64());
-
-            assert_eq!(_20, NumCast::from(20u));
-            assert_eq!(_20, NumCast::from(20u8));
-            assert_eq!(_20, NumCast::from(20u16));
-            assert_eq!(_20, NumCast::from(20u32));
-            assert_eq!(_20, NumCast::from(20u64));
-            assert_eq!(_20, NumCast::from(20i));
-            assert_eq!(_20, NumCast::from(20i8));
-            assert_eq!(_20, NumCast::from(20i16));
-            assert_eq!(_20, NumCast::from(20i32));
-            assert_eq!(_20, NumCast::from(20i64));
-            assert_eq!(_20, NumCast::from(20f32));
-            assert_eq!(_20, NumCast::from(20f64));
-
-            assert_eq!(_20, cast(20u));
-            assert_eq!(_20, cast(20u8));
-            assert_eq!(_20, cast(20u16));
-            assert_eq!(_20, cast(20u32));
-            assert_eq!(_20, cast(20u64));
-            assert_eq!(_20, cast(20i));
-            assert_eq!(_20, cast(20i8));
-            assert_eq!(_20, cast(20i16));
-            assert_eq!(_20, cast(20i32));
-            assert_eq!(_20, cast(20i64));
-            assert_eq!(_20, cast(20f32));
-            assert_eq!(_20, cast(20f64));
+            assert_eq!(20u,   _20.to_uint().unwrap());
+            assert_eq!(20u8,  _20.to_u8().unwrap());
+            assert_eq!(20u16, _20.to_u16().unwrap());
+            assert_eq!(20u32, _20.to_u32().unwrap());
+            assert_eq!(20u64, _20.to_u64().unwrap());
+            assert_eq!(20i,   _20.to_int().unwrap());
+            assert_eq!(20i8,  _20.to_i8().unwrap());
+            assert_eq!(20i16, _20.to_i16().unwrap());
+            assert_eq!(20i32, _20.to_i32().unwrap());
+            assert_eq!(20i64, _20.to_i64().unwrap());
+            assert_eq!(20f32, _20.to_f32().unwrap());
+            assert_eq!(20f64, _20.to_f64().unwrap());
+
+            assert_eq!(_20, NumCast::from(20u).unwrap());
+            assert_eq!(_20, NumCast::from(20u8).unwrap());
+            assert_eq!(_20, NumCast::from(20u16).unwrap());
+            assert_eq!(_20, NumCast::from(20u32).unwrap());
+            assert_eq!(_20, NumCast::from(20u64).unwrap());
+            assert_eq!(_20, NumCast::from(20i).unwrap());
+            assert_eq!(_20, NumCast::from(20i8).unwrap());
+            assert_eq!(_20, NumCast::from(20i16).unwrap());
+            assert_eq!(_20, NumCast::from(20i32).unwrap());
+            assert_eq!(_20, NumCast::from(20i64).unwrap());
+            assert_eq!(_20, NumCast::from(20f32).unwrap());
+            assert_eq!(_20, NumCast::from(20f64).unwrap());
+
+            assert_eq!(_20, cast(20u).unwrap());
+            assert_eq!(_20, cast(20u8).unwrap());
+            assert_eq!(_20, cast(20u16).unwrap());
+            assert_eq!(_20, cast(20u32).unwrap());
+            assert_eq!(_20, cast(20u64).unwrap());
+            assert_eq!(_20, cast(20i).unwrap());
+            assert_eq!(_20, cast(20i8).unwrap());
+            assert_eq!(_20, cast(20i16).unwrap());
+            assert_eq!(_20, cast(20i32).unwrap());
+            assert_eq!(_20, cast(20i64).unwrap());
+            assert_eq!(_20, cast(20f32).unwrap());
+            assert_eq!(_20, cast(20f64).unwrap());
         })
     )
 
@@ -621,6 +1038,374 @@ mod tests {
     #[test] fn test_f64_cast()   { test_cast_20!(20f64) }
 
     #[test]
+    fn test_cast_range_int_min() {
+        assert_eq!(int::min_value.to_int(),  Some(int::min_value as int));
+        assert_eq!(int::min_value.to_i8(),   None);
+        assert_eq!(int::min_value.to_i16(),  None);
+        // int::min_value.to_i32() is word-size specific
+        assert_eq!(int::min_value.to_i64(),  Some(int::min_value as i64));
+        assert_eq!(int::min_value.to_uint(), None);
+        assert_eq!(int::min_value.to_u8(),   None);
+        assert_eq!(int::min_value.to_u16(),  None);
+        assert_eq!(int::min_value.to_u32(),  None);
+        assert_eq!(int::min_value.to_u64(),  None);
+
+        #[cfg(target_word_size = "32")]
+        fn check_word_size() {
+            assert_eq!(int::min_value.to_i32(), Some(int::min_value as i32));
+        }
+
+        #[cfg(target_word_size = "64")]
+        fn check_word_size() {
+            assert_eq!(int::min_value.to_i32(), None);
+        }
+
+        check_word_size();
+    }
+
+    #[test]
+    fn test_cast_range_i8_min() {
+        assert_eq!(i8::min_value.to_int(),  Some(i8::min_value as int));
+        assert_eq!(i8::min_value.to_i8(),   Some(i8::min_value as i8));
+        assert_eq!(i8::min_value.to_i16(),  Some(i8::min_value as i16));
+        assert_eq!(i8::min_value.to_i32(),  Some(i8::min_value as i32));
+        assert_eq!(i8::min_value.to_i64(),  Some(i8::min_value as i64));
+        assert_eq!(i8::min_value.to_uint(), None);
+        assert_eq!(i8::min_value.to_u8(),   None);
+        assert_eq!(i8::min_value.to_u16(),  None);
+        assert_eq!(i8::min_value.to_u32(),  None);
+        assert_eq!(i8::min_value.to_u64(),  None);
+    }
+
+    #[test]
+    fn test_cast_range_i16_min() {
+        assert_eq!(i16::min_value.to_int(),  Some(i16::min_value as int));
+        assert_eq!(i16::min_value.to_i8(),   None);
+        assert_eq!(i16::min_value.to_i16(),  Some(i16::min_value as i16));
+        assert_eq!(i16::min_value.to_i32(),  Some(i16::min_value as i32));
+        assert_eq!(i16::min_value.to_i64(),  Some(i16::min_value as i64));
+        assert_eq!(i16::min_value.to_uint(), None);
+        assert_eq!(i16::min_value.to_u8(),   None);
+        assert_eq!(i16::min_value.to_u16(),  None);
+        assert_eq!(i16::min_value.to_u32(),  None);
+        assert_eq!(i16::min_value.to_u64(),  None);
+    }
+
+    #[test]
+    fn test_cast_range_i32_min() {
+        assert_eq!(i32::min_value.to_int(),  Some(i32::min_value as int));
+        assert_eq!(i32::min_value.to_i8(),   None);
+        assert_eq!(i32::min_value.to_i16(),  None);
+        assert_eq!(i32::min_value.to_i32(),  Some(i32::min_value as i32));
+        assert_eq!(i32::min_value.to_i64(),  Some(i32::min_value as i64));
+        assert_eq!(i32::min_value.to_uint(), None);
+        assert_eq!(i32::min_value.to_u8(),   None);
+        assert_eq!(i32::min_value.to_u16(),  None);
+        assert_eq!(i32::min_value.to_u32(),  None);
+        assert_eq!(i32::min_value.to_u64(),  None);
+    }
+
+    #[test]
+    fn test_cast_range_i64_min() {
+        // i64::min_value.to_int() is word-size specific
+        assert_eq!(i64::min_value.to_i8(),   None);
+        assert_eq!(i64::min_value.to_i16(),  None);
+        assert_eq!(i64::min_value.to_i32(),  None);
+        assert_eq!(i64::min_value.to_i64(),  Some(i64::min_value as i64));
+        assert_eq!(i64::min_value.to_uint(), None);
+        assert_eq!(i64::min_value.to_u8(),   None);
+        assert_eq!(i64::min_value.to_u16(),  None);
+        assert_eq!(i64::min_value.to_u32(),  None);
+        assert_eq!(i64::min_value.to_u64(),  None);
+
+        #[cfg(target_word_size = "32")]
+        fn check_word_size() {
+            assert_eq!(i64::min_value.to_int(), None);
+        }
+
+        #[cfg(target_word_size = "64")]
+        fn check_word_size() {
+            assert_eq!(i64::min_value.to_int(), Some(i64::min_value as int));
+        }
+
+        check_word_size();
+    }
+
+    #[test]
+    fn test_cast_range_int_max() {
+        assert_eq!(int::max_value.to_int(),  Some(int::max_value as int));
+        assert_eq!(int::max_value.to_i8(),   None);
+        assert_eq!(int::max_value.to_i16(),  None);
+        // int::max_value.to_i32() is word-size specific
+        assert_eq!(int::max_value.to_i64(),  Some(int::max_value as i64));
+        assert_eq!(int::max_value.to_u8(),   None);
+        assert_eq!(int::max_value.to_u16(),  None);
+        // int::max_value.to_u32() is word-size specific
+        assert_eq!(int::max_value.to_u64(),  Some(int::max_value as u64));
+
+        #[cfg(target_word_size = "32")]
+        fn check_word_size() {
+            assert_eq!(int::max_value.to_i32(), Some(int::max_value as i32));
+            assert_eq!(int::max_value.to_u32(), Some(int::max_value as u32));
+        }
+
+        #[cfg(target_word_size = "64")]
+        fn check_word_size() {
+            assert_eq!(int::max_value.to_i32(), None);
+            assert_eq!(int::max_value.to_u32(), None);
+        }
+
+        check_word_size();
+    }
+
+    #[test]
+    fn test_cast_range_i8_max() {
+        assert_eq!(i8::max_value.to_int(),  Some(i8::max_value as int));
+        assert_eq!(i8::max_value.to_i8(),   Some(i8::max_value as i8));
+        assert_eq!(i8::max_value.to_i16(),  Some(i8::max_value as i16));
+        assert_eq!(i8::max_value.to_i32(),  Some(i8::max_value as i32));
+        assert_eq!(i8::max_value.to_i64(),  Some(i8::max_value as i64));
+        assert_eq!(i8::max_value.to_uint(), Some(i8::max_value as uint));
+        assert_eq!(i8::max_value.to_u8(),   Some(i8::max_value as u8));
+        assert_eq!(i8::max_value.to_u16(),  Some(i8::max_value as u16));
+        assert_eq!(i8::max_value.to_u32(),  Some(i8::max_value as u32));
+        assert_eq!(i8::max_value.to_u64(),  Some(i8::max_value as u64));
+    }
+
+    #[test]
+    fn test_cast_range_i16_max() {
+        assert_eq!(i16::max_value.to_int(),  Some(i16::max_value as int));
+        assert_eq!(i16::max_value.to_i8(),   None);
+        assert_eq!(i16::max_value.to_i16(),  Some(i16::max_value as i16));
+        assert_eq!(i16::max_value.to_i32(),  Some(i16::max_value as i32));
+        assert_eq!(i16::max_value.to_i64(),  Some(i16::max_value as i64));
+        assert_eq!(i16::max_value.to_uint(), Some(i16::max_value as uint));
+        assert_eq!(i16::max_value.to_u8(),   None);
+        assert_eq!(i16::max_value.to_u16(),  Some(i16::max_value as u16));
+        assert_eq!(i16::max_value.to_u32(),  Some(i16::max_value as u32));
+        assert_eq!(i16::max_value.to_u64(),  Some(i16::max_value as u64));
+    }
+
+    #[test]
+    fn test_cast_range_i32_max() {
+        assert_eq!(i32::max_value.to_int(),  Some(i32::max_value as int));
+        assert_eq!(i32::max_value.to_i8(),   None);
+        assert_eq!(i32::max_value.to_i16(),  None);
+        assert_eq!(i32::max_value.to_i32(),  Some(i32::max_value as i32));
+        assert_eq!(i32::max_value.to_i64(),  Some(i32::max_value as i64));
+        assert_eq!(i32::max_value.to_uint(), Some(i32::max_value as uint));
+        assert_eq!(i32::max_value.to_u8(),   None);
+        assert_eq!(i32::max_value.to_u16(),  None);
+        assert_eq!(i32::max_value.to_u32(),  Some(i32::max_value as u32));
+        assert_eq!(i32::max_value.to_u64(),  Some(i32::max_value as u64));
+    }
+
+    #[test]
+    fn test_cast_range_i64_max() {
+        // i64::max_value.to_int() is word-size specific
+        assert_eq!(i64::max_value.to_i8(),   None);
+        assert_eq!(i64::max_value.to_i16(),  None);
+        assert_eq!(i64::max_value.to_i32(),  None);
+        assert_eq!(i64::max_value.to_i64(),  Some(i64::max_value as i64));
+        // i64::max_value.to_uint() is word-size specific
+        assert_eq!(i64::max_value.to_u8(),   None);
+        assert_eq!(i64::max_value.to_u16(),  None);
+        assert_eq!(i64::max_value.to_u32(),  None);
+        assert_eq!(i64::max_value.to_u64(),  Some(i64::max_value as u64));
+
+        #[cfg(target_word_size = "32")]
+        fn check_word_size() {
+            assert_eq!(i64::max_value.to_int(),  None);
+            assert_eq!(i64::max_value.to_uint(), None);
+        }
+
+        #[cfg(target_word_size = "64")]
+        fn check_word_size() {
+            assert_eq!(i64::max_value.to_int(),  Some(i64::max_value as int));
+            assert_eq!(i64::max_value.to_uint(), Some(i64::max_value as uint));
+        }
+
+        check_word_size();
+    }
+
+    #[test]
+    fn test_cast_range_uint_min() {
+        assert_eq!(uint::min_value.to_int(),  Some(uint::min_value as int));
+        assert_eq!(uint::min_value.to_i8(),   Some(uint::min_value as i8));
+        assert_eq!(uint::min_value.to_i16(),  Some(uint::min_value as i16));
+        assert_eq!(uint::min_value.to_i32(),  Some(uint::min_value as i32));
+        assert_eq!(uint::min_value.to_i64(),  Some(uint::min_value as i64));
+        assert_eq!(uint::min_value.to_uint(), Some(uint::min_value as uint));
+        assert_eq!(uint::min_value.to_u8(),   Some(uint::min_value as u8));
+        assert_eq!(uint::min_value.to_u16(),  Some(uint::min_value as u16));
+        assert_eq!(uint::min_value.to_u32(),  Some(uint::min_value as u32));
+        assert_eq!(uint::min_value.to_u64(),  Some(uint::min_value as u64));
+    }
+
+    #[test]
+    fn test_cast_range_u8_min() {
+        assert_eq!(u8::min_value.to_int(),  Some(u8::min_value as int));
+        assert_eq!(u8::min_value.to_i8(),   Some(u8::min_value as i8));
+        assert_eq!(u8::min_value.to_i16(),  Some(u8::min_value as i16));
+        assert_eq!(u8::min_value.to_i32(),  Some(u8::min_value as i32));
+        assert_eq!(u8::min_value.to_i64(),  Some(u8::min_value as i64));
+        assert_eq!(u8::min_value.to_uint(), Some(u8::min_value as uint));
+        assert_eq!(u8::min_value.to_u8(),   Some(u8::min_value as u8));
+        assert_eq!(u8::min_value.to_u16(),  Some(u8::min_value as u16));
+        assert_eq!(u8::min_value.to_u32(),  Some(u8::min_value as u32));
+        assert_eq!(u8::min_value.to_u64(),  Some(u8::min_value as u64));
+    }
+
+    #[test]
+    fn test_cast_range_u16_min() {
+        assert_eq!(u16::min_value.to_int(),  Some(u16::min_value as int));
+        assert_eq!(u16::min_value.to_i8(),   Some(u16::min_value as i8));
+        assert_eq!(u16::min_value.to_i16(),  Some(u16::min_value as i16));
+        assert_eq!(u16::min_value.to_i32(),  Some(u16::min_value as i32));
+        assert_eq!(u16::min_value.to_i64(),  Some(u16::min_value as i64));
+        assert_eq!(u16::min_value.to_uint(), Some(u16::min_value as uint));
+        assert_eq!(u16::min_value.to_u8(),   Some(u16::min_value as u8));
+        assert_eq!(u16::min_value.to_u16(),  Some(u16::min_value as u16));
+        assert_eq!(u16::min_value.to_u32(),  Some(u16::min_value as u32));
+        assert_eq!(u16::min_value.to_u64(),  Some(u16::min_value as u64));
+    }
+
+    #[test]
+    fn test_cast_range_u32_min() {
+        assert_eq!(u32::min_value.to_int(),  Some(u32::min_value as int));
+        assert_eq!(u32::min_value.to_i8(),   Some(u32::min_value as i8));
+        assert_eq!(u32::min_value.to_i16(),  Some(u32::min_value as i16));
+        assert_eq!(u32::min_value.to_i32(),  Some(u32::min_value as i32));
+        assert_eq!(u32::min_value.to_i64(),  Some(u32::min_value as i64));
+        assert_eq!(u32::min_value.to_uint(), Some(u32::min_value as uint));
+        assert_eq!(u32::min_value.to_u8(),   Some(u32::min_value as u8));
+        assert_eq!(u32::min_value.to_u16(),  Some(u32::min_value as u16));
+        assert_eq!(u32::min_value.to_u32(),  Some(u32::min_value as u32));
+        assert_eq!(u32::min_value.to_u64(),  Some(u32::min_value as u64));
+    }
+
+    #[test]
+    fn test_cast_range_u64_min() {
+        assert_eq!(u64::min_value.to_int(),  Some(u64::min_value as int));
+        assert_eq!(u64::min_value.to_i8(),   Some(u64::min_value as i8));
+        assert_eq!(u64::min_value.to_i16(),  Some(u64::min_value as i16));
+        assert_eq!(u64::min_value.to_i32(),  Some(u64::min_value as i32));
+        assert_eq!(u64::min_value.to_i64(),  Some(u64::min_value as i64));
+        assert_eq!(u64::min_value.to_uint(), Some(u64::min_value as uint));
+        assert_eq!(u64::min_value.to_u8(),   Some(u64::min_value as u8));
+        assert_eq!(u64::min_value.to_u16(),  Some(u64::min_value as u16));
+        assert_eq!(u64::min_value.to_u32(),  Some(u64::min_value as u32));
+        assert_eq!(u64::min_value.to_u64(),  Some(u64::min_value as u64));
+    }
+
+    #[test]
+    fn test_cast_range_uint_max() {
+        assert_eq!(uint::max_value.to_int(),  None);
+        assert_eq!(uint::max_value.to_i8(),   None);
+        assert_eq!(uint::max_value.to_i16(),  None);
+        assert_eq!(uint::max_value.to_i32(),  None);
+        // uint::max_value.to_i64() is word-size specific
+        assert_eq!(uint::max_value.to_u8(),   None);
+        assert_eq!(uint::max_value.to_u16(),  None);
+        // uint::max_value.to_u32() is word-size specific
+        assert_eq!(uint::max_value.to_u64(),  Some(uint::max_value as u64));
+
+        #[cfg(target_word_size = "32")]
+        fn check_word_size() {
+            assert_eq!(uint::max_value.to_u32(), Some(uint::max_value as u32));
+            assert_eq!(uint::max_value.to_i64(), Some(uint::max_value as i64));
+        }
+
+        #[cfg(target_word_size = "64")]
+        fn check_word_size() {
+            assert_eq!(uint::max_value.to_u32(), None);
+            assert_eq!(uint::max_value.to_i64(), None);
+        }
+
+        check_word_size();
+    }
+
+    #[test]
+    fn test_cast_range_u8_max() {
+        assert_eq!(u8::max_value.to_int(),  Some(u8::max_value as int));
+        assert_eq!(u8::max_value.to_i8(),   None);
+        assert_eq!(u8::max_value.to_i16(),  Some(u8::max_value as i16));
+        assert_eq!(u8::max_value.to_i32(),  Some(u8::max_value as i32));
+        assert_eq!(u8::max_value.to_i64(),  Some(u8::max_value as i64));
+        assert_eq!(u8::max_value.to_uint(), Some(u8::max_value as uint));
+        assert_eq!(u8::max_value.to_u8(),   Some(u8::max_value as u8));
+        assert_eq!(u8::max_value.to_u16(),  Some(u8::max_value as u16));
+        assert_eq!(u8::max_value.to_u32(),  Some(u8::max_value as u32));
+        assert_eq!(u8::max_value.to_u64(),  Some(u8::max_value as u64));
+    }
+
+    #[test]
+    fn test_cast_range_u16_max() {
+        assert_eq!(u16::max_value.to_int(),  Some(u16::max_value as int));
+        assert_eq!(u16::max_value.to_i8(),   None);
+        assert_eq!(u16::max_value.to_i16(),  None);
+        assert_eq!(u16::max_value.to_i32(),  Some(u16::max_value as i32));
+        assert_eq!(u16::max_value.to_i64(),  Some(u16::max_value as i64));
+        assert_eq!(u16::max_value.to_uint(), Some(u16::max_value as uint));
+        assert_eq!(u16::max_value.to_u8(),   None);
+        assert_eq!(u16::max_value.to_u16(),  Some(u16::max_value as u16));
+        assert_eq!(u16::max_value.to_u32(),  Some(u16::max_value as u32));
+        assert_eq!(u16::max_value.to_u64(),  Some(u16::max_value as u64));
+    }
+
+    #[test]
+    fn test_cast_range_u32_max() {
+        // u32::max_value.to_int() is word-size specific
+        assert_eq!(u32::max_value.to_i8(),   None);
+        assert_eq!(u32::max_value.to_i16(),  None);
+        assert_eq!(u32::max_value.to_i32(),  None);
+        assert_eq!(u32::max_value.to_i64(),  Some(u32::max_value as i64));
+        assert_eq!(u32::max_value.to_uint(), Some(u32::max_value as uint));
+        assert_eq!(u32::max_value.to_u8(),   None);
+        assert_eq!(u32::max_value.to_u16(),  None);
+        assert_eq!(u32::max_value.to_u32(),  Some(u32::max_value as u32));
+        assert_eq!(u32::max_value.to_u64(),  Some(u32::max_value as u64));
+
+        #[cfg(target_word_size = "32")]
+        fn check_word_size() {
+            assert_eq!(u32::max_value.to_int(),  None);
+        }
+
+        #[cfg(target_word_size = "64")]
+        fn check_word_size() {
+            assert_eq!(u32::max_value.to_int(),  Some(u32::max_value as int));
+        }
+
+        check_word_size();
+    }
+
+    #[test]
+    fn test_cast_range_u64_max() {
+        assert_eq!(u64::max_value.to_int(),  None);
+        assert_eq!(u64::max_value.to_i8(),   None);
+        assert_eq!(u64::max_value.to_i16(),  None);
+        assert_eq!(u64::max_value.to_i32(),  None);
+        assert_eq!(u64::max_value.to_i64(),  None);
+        // u64::max_value.to_uint() is word-size specific
+        assert_eq!(u64::max_value.to_u8(),   None);
+        assert_eq!(u64::max_value.to_u16(),  None);
+        assert_eq!(u64::max_value.to_u32(),  None);
+        assert_eq!(u64::max_value.to_u64(),  Some(u64::max_value as u64));
+
+        #[cfg(target_word_size = "32")]
+        fn check_word_size() {
+            assert_eq!(u64::max_value.to_uint(), None);
+        }
+
+        #[cfg(target_word_size = "64")]
+        fn check_word_size() {
+            assert_eq!(u64::max_value.to_uint(), Some(u64::max_value as uint));
+        }
+
+        check_word_size();
+    }
+
+    #[test]
     fn test_saturating_add_uint() {
         use uint::max_value;
         assert_eq!(3u.saturating_add(5u), 8u);
diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs
index 1863369fdf7..0f253a26ccf 100644
--- a/src/libstd/num/strconv.rs
+++ b/src/libstd/num/strconv.rs
@@ -140,7 +140,7 @@ pub fn int_to_str_bytes_common<T:NumCast+Zero+Eq+Ord+Integer+
     let _0: T = Zero::zero();
 
     let neg = num < _0;
-    let radix_gen: T = cast(radix);
+    let radix_gen: T = cast(radix).unwrap();
 
     let mut deccum = num;
     // This is just for integral types, the largest of which is a u64. The
@@ -163,7 +163,7 @@ pub fn int_to_str_bytes_common<T:NumCast+Zero+Eq+Ord+Integer+
         } else {
             current_digit_signed
         };
-        buf[cur] = match current_digit.to_u8() {
+        buf[cur] = match current_digit.to_u8().unwrap() {
             i @ 0..9 => '0' as u8 + i,
             i        => 'a' as u8 + (i - 10),
         };
@@ -247,7 +247,7 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+
 
     let neg = num < _0 || (negative_zero && _1 / num == Float::neg_infinity());
     let mut buf: ~[u8] = ~[];
-    let radix_gen: T   = cast(radix as int);
+    let radix_gen: T   = cast(radix as int).unwrap();
 
     // First emit the non-fractional part, looping at least once to make
     // sure at least a `0` gets emitted.
@@ -265,7 +265,7 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+
         deccum = deccum / radix_gen;
         deccum = deccum.trunc();
 
-        buf.push(char::from_digit(current_digit.to_int() as uint, radix)
+        buf.push(char::from_digit(current_digit.to_int().unwrap() as uint, radix)
              .unwrap() as u8);
 
         // No more digits to calculate for the non-fractional part -> break
@@ -322,7 +322,7 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+
             let current_digit = deccum.trunc().abs();
 
             buf.push(char::from_digit(
-                current_digit.to_int() as uint, radix).unwrap() as u8);
+                current_digit.to_int().unwrap() as uint, radix).unwrap() as u8);
 
             // Decrease the deccumulator one fractional digit at a time
             deccum = deccum.fract();
@@ -492,7 +492,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
 
     let _0: T = Zero::zero();
     let _1: T = One::one();
-    let radix_gen: T = cast(radix as int);
+    let radix_gen: T = cast(radix as int).unwrap();
 
     let len = buf.len();
 
@@ -543,9 +543,9 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
 
                 // add/subtract current digit depending on sign
                 if accum_positive {
-                    accum = accum + cast(digit as int);
+                    accum = accum + cast(digit as int).unwrap();
                 } else {
-                    accum = accum - cast(digit as int);
+                    accum = accum - cast(digit as int).unwrap();
                 }
 
                 // Detect overflow by comparing to last value, except
@@ -556,11 +556,11 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
 
                     // Detect overflow by reversing the shift-and-add proccess
                     if accum_positive &&
-                        (last_accum != ((accum - cast(digit as int))/radix_gen.clone())) {
+                        (last_accum != ((accum - cast(digit as int).unwrap())/radix_gen.clone())) {
                         return NumStrConv::inf();
                     }
                     if !accum_positive &&
-                        (last_accum != ((accum + cast(digit as int))/radix_gen.clone())) {
+                        (last_accum != ((accum + cast(digit as int).unwrap())/radix_gen.clone())) {
                         return NumStrConv::neg_inf();
                     }
                 }
@@ -596,7 +596,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
                     // Decrease power one order of magnitude
                     power = power / radix_gen;
 
-                    let digit_t: T = cast(digit);
+                    let digit_t: T = cast(digit).unwrap();
 
                     // add/subtract current digit depending on sign
                     if accum_positive {
@@ -654,9 +654,9 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
         match exp {
             Some(exp_pow) => {
                 multiplier = if exp_pow < 0 {
-                    _1 / pow_with_uint::<T>(base, (-exp_pow.to_int()) as uint)
+                    _1 / pow_with_uint::<T>(base, (-exp_pow.to_int().unwrap()) as uint)
                 } else {
-                    pow_with_uint::<T>(base, exp_pow.to_int() as uint)
+                    pow_with_uint::<T>(base, exp_pow.to_int().unwrap() as uint)
                 }
             }
             None => return None // invalid exponent -> invalid number
diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs
index 45280482b87..f52feced67c 100644
--- a/src/libstd/num/uint_macros.rs
+++ b/src/libstd/num/uint_macros.rs
@@ -306,6 +306,9 @@ impl Primitive for $T {
 
     #[inline]
     fn bytes(_: Option<$T>) -> uint { bits / 8 }
+
+    #[inline]
+    fn is_signed(_: Option<$T>) -> bool { false }
 }
 
 impl BitCount for $T {
diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs
index 96ade70f007..273a01c1811 100644
--- a/src/libstd/prelude.rs
+++ b/src/libstd/prelude.rs
@@ -59,7 +59,7 @@ pub use num::{Orderable, Signed, Unsigned, Round};
 pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};
 pub use num::{Integer, Fractional, Real, RealExt};
 pub use num::{Bitwise, BitCount, Bounded};
-pub use num::{Primitive, Int, Float, ToStrRadix};
+pub use num::{Primitive, Int, Float, ToStrRadix, ToPrimitive, FromPrimitive};
 pub use path::GenericPath;
 pub use path::Path;
 pub use path::PosixPath;
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
index 50a8f184092..70bcb0f7170 100644
--- a/src/libstd/rand/mod.rs
+++ b/src/libstd/rand/mod.rs
@@ -317,12 +317,12 @@ pub trait Rng {
     /// ```
     fn gen_integer_range<T: Rand + Int>(&mut self, low: T, high: T) -> T {
         assert!(low < high, "RNG.gen_integer_range called with low >= high");
-        let range = (high - low).to_u64();
+        let range = (high - low).to_u64().unwrap();
         let accept_zone = u64::max_value - u64::max_value % range;
         loop {
             let rand = self.gen::<u64>();
             if rand < accept_zone {
-                return low + NumCast::from(rand % range);
+                return low + NumCast::from(rand % range).unwrap();
             }
         }
     }
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 5111682f6d0..65a6572fa5e 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -113,6 +113,7 @@ pub trait AstBuilder {
                         expr: @ast::Expr, ident: ast::Ident,
                         args: ~[@ast::Expr]) -> @ast::Expr;
     fn expr_block(&self, b: ast::Block) -> @ast::Expr;
+    fn expr_cast(&self, sp: Span, expr: @ast::Expr, ty: ast::Ty) -> @ast::Expr;
 
     fn field_imm(&self, span: Span, name: Ident, e: @ast::Expr) -> ast::Field;
     fn expr_struct(&self, span: Span, path: ast::Path, fields: ~[ast::Field]) -> @ast::Expr;
@@ -132,6 +133,10 @@ pub trait AstBuilder {
     fn expr_str(&self, sp: Span, s: @str) -> @ast::Expr;
     fn expr_str_uniq(&self, sp: Span, s: @str) -> @ast::Expr;
 
+    fn expr_some(&self, sp: Span, expr: @ast::Expr) -> @ast::Expr;
+    fn expr_none(&self, sp: Span) -> @ast::Expr;
+
+    fn expr_fail(&self, span: Span, msg: @str) -> @ast::Expr;
     fn expr_unreachable(&self, span: Span) -> @ast::Expr;
 
     fn pat(&self, span: Span, pat: ast::Pat_) -> @ast::Pat;
@@ -564,7 +569,30 @@ impl AstBuilder for @ExtCtxt {
     }
 
 
-    fn expr_unreachable(&self, span: Span) -> @ast::Expr {
+    fn expr_cast(&self, sp: Span, expr: @ast::Expr, ty: ast::Ty) -> @ast::Expr {
+        self.expr(sp, ast::ExprCast(expr, ty))
+    }
+
+
+    fn expr_some(&self, sp: Span, expr: @ast::Expr) -> @ast::Expr {
+        let some = ~[
+            self.ident_of("std"),
+            self.ident_of("option"),
+            self.ident_of("Some"),
+        ];
+        self.expr_call_global(sp, some, ~[expr])
+    }
+
+    fn expr_none(&self, sp: Span) -> @ast::Expr {
+        let none = self.path_global(sp, ~[
+            self.ident_of("std"),
+            self.ident_of("option"),
+            self.ident_of("None"),
+        ]);
+        self.expr_path(none)
+    }
+
+    fn expr_fail(&self, span: Span, msg: @str) -> @ast::Expr {
         let loc = self.codemap().lookup_char_pos(span.lo);
         self.expr_call_global(
             span,
@@ -575,12 +603,16 @@ impl AstBuilder for @ExtCtxt {
                 self.ident_of("fail_with"),
             ],
             ~[
-                self.expr_str(span, @"internal error: entered unreachable code"),
+                self.expr_str(span, msg),
                 self.expr_str(span, loc.file.name),
                 self.expr_uint(span, loc.line),
             ])
     }
 
+    fn expr_unreachable(&self, span: Span) -> @ast::Expr {
+        self.expr_fail(span, @"internal error: entered unreachable code")
+    }
+
 
     fn pat(&self, span: Span, pat: ast::Pat_) -> @ast::Pat {
         @ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span: span }
diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs
index f5e45eec7e0..b3fd4f920d8 100644
--- a/src/libsyntax/ext/deriving/generic.rs
+++ b/src/libsyntax/ext/deriving/generic.rs
@@ -1151,6 +1151,7 @@ pub fn cs_or(enum_nonmatch_f: EnumNonMatchFunc,
              enum_nonmatch_f,
              cx, span, substructure)
 }
+
 /// cs_binop with binop == and
 #[inline]
 pub fn cs_and(enum_nonmatch_f: EnumNonMatchFunc,
diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs
index a428c6704f9..3e65f7bdefb 100644
--- a/src/libsyntax/ext/deriving/mod.rs
+++ b/src/libsyntax/ext/deriving/mod.rs
@@ -32,6 +32,7 @@ pub mod rand;
 pub mod to_str;
 pub mod zero;
 pub mod default;
+pub mod primitive;
 
 #[path="cmp/eq.rs"]
 pub mod eq;
@@ -97,9 +98,12 @@ pub fn expand_meta_deriving(cx: @ExtCtxt,
                             "Rand" => expand!(rand::expand_deriving_rand),
 
                             "ToStr" => expand!(to_str::expand_deriving_to_str),
+
                             "Zero" => expand!(zero::expand_deriving_zero),
                             "Default" => expand!(default::expand_deriving_default),
 
+                            "FromPrimitive" => expand!(primitive::expand_deriving_from_primitive),
+
                             ref tname => {
                                 cx.span_err(titem.span, format!("unknown \
                                     `deriving` trait: `{}`", *tname));
diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs
new file mode 100644
index 00000000000..38c30def1d1
--- /dev/null
+++ b/src/libsyntax/ext/deriving/primitive.rs
@@ -0,0 +1,127 @@
+// Copyright 2012-2013 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.
+
+use ast::{MetaItem, item, Expr};
+use ast;
+use codemap::Span;
+use ext::base::ExtCtxt;
+use ext::build::AstBuilder;
+use ext::deriving::generic::*;
+
+pub fn expand_deriving_from_primitive(cx: @ExtCtxt,
+                                      span: Span,
+                                      mitem: @MetaItem,
+                                      in_items: ~[@item]) -> ~[@item] {
+    let trait_def = TraitDef {
+        path: Path::new(~["std", "num", "FromPrimitive"]),
+        additional_bounds: ~[],
+        generics: LifetimeBounds::empty(),
+        methods: ~[
+            MethodDef {
+                name: "from_i64",
+                generics: LifetimeBounds::empty(),
+                explicit_self: None,
+                args: ~[
+                    Literal(Path::new(~["i64"])),
+                ],
+                ret_ty: Literal(Path::new_(~["std", "option", "Option"],
+                                           None,
+                                           ~[~Self],
+                                           true)),
+                const_nonmatching: false,
+                combine_substructure: |c, s, sub| cs_from("i64", c, s, sub),
+            },
+            MethodDef {
+                name: "from_u64",
+                generics: LifetimeBounds::empty(),
+                explicit_self: None,
+                args: ~[
+                    Literal(Path::new(~["u64"])),
+                ],
+                ret_ty: Literal(Path::new_(~["std", "option", "Option"],
+                                           None,
+                                           ~[~Self],
+                                           true)),
+                const_nonmatching: false,
+                combine_substructure: |c, s, sub| cs_from("u64", c, s, sub),
+            },
+        ]
+    };
+
+    trait_def.expand(cx, span, mitem, in_items)
+}
+
+fn cs_from(name: &str, cx: @ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
+    let n = match substr.nonself_args {
+        [n] => n,
+        _ => cx.span_bug(span, "Incorrect number of arguments in `deriving(FromPrimitive)`")
+    };
+
+    match *substr.fields {
+        StaticStruct(*) => {
+            cx.span_err(span, "`FromPrimitive` cannot be derived for structs");
+            return cx.expr_fail(span, @"");
+        }
+        StaticEnum(enum_def, _) => {
+            if enum_def.variants.is_empty() {
+                cx.span_err(span, "`FromPrimitive` cannot be derived for enums with no variants");
+                return cx.expr_fail(span, @"");
+            }
+
+            let mut arms = ~[];
+
+            for variant in enum_def.variants.iter() {
+                match variant.node.kind {
+                    ast::tuple_variant_kind(ref args) => {
+                        if !args.is_empty() {
+                            cx.span_err(span, "`FromPrimitive` cannot be derived for \
+                                               enum variants with arguments");
+                            return cx.expr_fail(span, @"");
+                        }
+
+                        // expr for `$n == $variant as $name`
+                        let variant = cx.expr_ident(span, variant.node.name);
+                        let ty = cx.ty_ident(span, cx.ident_of(name));
+                        let cast = cx.expr_cast(span, variant, ty);
+                        let guard = cx.expr_binary(span, ast::BiEq, n, cast);
+
+                        // expr for `Some($variant)`
+                        let body = cx.expr_some(span, variant);
+
+                        // arm for `_ if $guard => $body`
+                        let arm = ast::Arm {
+                            pats: ~[cx.pat_wild(span)],
+                            guard: Some(guard),
+                            body: cx.block_expr(body),
+                        };
+
+                        arms.push(arm);
+                    }
+                    ast::struct_variant_kind(_) => {
+                        cx.span_err(span, "`FromPrimitive` cannot be derived for enums \
+                                           with struct variants");
+                        return cx.expr_fail(span, @"");
+                    }
+                }
+            }
+
+            // arm for `_ => None`
+            let arm = ast::Arm {
+                pats: ~[cx.pat_wild(span)],
+                guard: None,
+                body: cx.block_expr(cx.expr_none(span)),
+            };
+            arms.push(arm);
+
+            cx.expr_match(span, n, arms)
+        }
+        _ => cx.bug("expected StaticEnum in deriving(FromPrimitive)")
+    }
+}
diff --git a/src/test/compile-fail/deriving-primitive.rs b/src/test/compile-fail/deriving-primitive.rs
new file mode 100644
index 00000000000..1af0193ca47
--- /dev/null
+++ b/src/test/compile-fail/deriving-primitive.rs
@@ -0,0 +1,34 @@
+// Copyright 2013 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.
+
+use std::num::FromPrimitive;
+use std::int;
+
+#[deriving(FromPrimitive)]
+struct A { x: int }
+//~^^ ERROR `FromPrimitive` cannot be derived for structs
+//~^^^ ERROR `FromPrimitive` cannot be derived for structs
+
+#[deriving(FromPrimitive)]
+struct B(int);
+//~^^ ERROR `FromPrimitive` cannot be derived for structs
+//~^^^ ERROR `FromPrimitive` cannot be derived for structs
+
+#[deriving(FromPrimitive)]
+enum C { Foo(int), Bar(uint) }
+//~^^ ERROR `FromPrimitive` cannot be derived for enum variants with arguments
+//~^^^ ERROR `FromPrimitive` cannot be derived for enum variants with arguments
+
+#[deriving(FromPrimitive)]
+enum D { Baz { x: int } }
+//~^^ ERROR `FromPrimitive` cannot be derived for enums with struct variants
+//~^^^ ERROR `FromPrimitive` cannot be derived for enums with struct variants
+
+pub fn main() {}
diff --git a/src/test/run-pass/deriving-primitive.rs b/src/test/run-pass/deriving-primitive.rs
new file mode 100644
index 00000000000..f82d77b28ea
--- /dev/null
+++ b/src/test/run-pass/deriving-primitive.rs
@@ -0,0 +1,37 @@
+// Copyright 2013 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.
+
+use std::num::FromPrimitive;
+use std::int;
+
+#[deriving(Eq, FromPrimitive)]
+enum A {
+    Foo = int::max_value,
+    Bar = 1,
+    Baz = 3,
+    Qux,
+}
+
+pub fn main() {
+    let x: Option<A> = FromPrimitive::from_int(int::max_value);
+    assert_eq!(x, Some(Foo));
+
+    let x: Option<A> = FromPrimitive::from_int(1);
+    assert_eq!(x, Some(Bar));
+
+    let x: Option<A> = FromPrimitive::from_int(3);
+    assert_eq!(x, Some(Baz));
+
+    let x: Option<A> = FromPrimitive::from_int(4);
+    assert_eq!(x, Some(Qux));
+
+    let x: Option<A> = FromPrimitive::from_int(5);
+    assert_eq!(x, None);
+}
diff --git a/src/test/run-pass/numeric-method-autoexport.rs b/src/test/run-pass/numeric-method-autoexport.rs
index f2df3fc66ea..1422f93e612 100644
--- a/src/test/run-pass/numeric-method-autoexport.rs
+++ b/src/test/run-pass/numeric-method-autoexport.rs
@@ -36,6 +36,6 @@ pub fn main() {
 
 // floats
     // num
-    assert_eq!(10f32.to_int(), 10);
-    assert_eq!(10f64.to_int(), 10);
+    assert_eq!(10f32.to_int().unwrap(), 10);
+    assert_eq!(10f64.to_int().unwrap(), 10);
 }
diff --git a/src/test/run-pass/trait-inheritance-num.rs b/src/test/run-pass/trait-inheritance-num.rs
index 87de3a2be14..8d3c258558e 100644
--- a/src/test/run-pass/trait-inheritance-num.rs
+++ b/src/test/run-pass/trait-inheritance-num.rs
@@ -19,7 +19,7 @@ pub trait NumExt: Num + NumCast + Eq + Ord {}
 
 pub trait FloatExt: NumExt + ApproxEq<Self> {}
 
-fn greater_than_one<T:NumExt>(n: &T) -> bool { *n > NumCast::from(1) }
-fn greater_than_one_float<T:FloatExt>(n: &T) -> bool { *n > NumCast::from(1) }
+fn greater_than_one<T:NumExt>(n: &T) -> bool { *n > NumCast::from(1).unwrap() }
+fn greater_than_one_float<T:FloatExt>(n: &T) -> bool { *n > NumCast::from(1).unwrap() }
 
 pub fn main() {}
diff --git a/src/test/run-pass/trait-inheritance-num0.rs b/src/test/run-pass/trait-inheritance-num0.rs
index ae285f3bc95..46efac84907 100644
--- a/src/test/run-pass/trait-inheritance-num0.rs
+++ b/src/test/run-pass/trait-inheritance-num0.rs
@@ -22,7 +22,7 @@ trait Num {
 pub trait NumExt: Num + NumCast { }
 
 fn greater_than_one<T:NumExt>(n: &T) -> bool {
-    n.gt(&NumCast::from(1))
+    n.gt(&NumCast::from(1).unwrap())
 }
 
 pub fn main() {}
diff --git a/src/test/run-pass/trait-inheritance-num1.rs b/src/test/run-pass/trait-inheritance-num1.rs
index d22a8154a5b..28abae175cd 100644
--- a/src/test/run-pass/trait-inheritance-num1.rs
+++ b/src/test/run-pass/trait-inheritance-num1.rs
@@ -14,7 +14,7 @@ use std::num::NumCast;
 pub trait NumExt: Num + NumCast + Ord { }
 
 fn greater_than_one<T:NumExt>(n: &T) -> bool {
-    *n > NumCast::from(1)
+    *n > NumCast::from(1).unwrap()
 }
 
 pub fn main() {}
diff --git a/src/test/run-pass/trait-inheritance-num3.rs b/src/test/run-pass/trait-inheritance-num3.rs
index b7150e873a5..7909f015912 100644
--- a/src/test/run-pass/trait-inheritance-num3.rs
+++ b/src/test/run-pass/trait-inheritance-num3.rs
@@ -16,7 +16,7 @@ pub trait NumExt: Eq + Ord + Num + NumCast {}
 impl NumExt for f32 {}
 
 fn num_eq_one<T:NumExt>(n: T) {
-    println!("{}", n == NumCast::from(1))
+    println!("{}", n == NumCast::from(1).unwrap())
 }
 
 pub fn main() {
diff --git a/src/test/run-pass/trait-inheritance-num5.rs b/src/test/run-pass/trait-inheritance-num5.rs
index aee954df461..0310dde2a6d 100644
--- a/src/test/run-pass/trait-inheritance-num5.rs
+++ b/src/test/run-pass/trait-inheritance-num5.rs
@@ -17,7 +17,7 @@ impl NumExt for f32 {}
 impl NumExt for int {}
 
 fn num_eq_one<T:NumExt>() -> T {
-    NumCast::from(1)
+    NumCast::from(1).unwrap()
 }
 
 pub fn main() {