about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-10-05 14:26:44 -0700
committerbors <bors@rust-lang.org>2013-10-05 14:26:44 -0700
commit2733b189ac60cea541fbf80e5839e5027ffc9fbf (patch)
treeb9fcc58a2f736f292eb32de9553843c99f91f32d /src/libstd
parent0c388be8d1988a966ef62c545b996b9da0f71e93 (diff)
parent0e8ad4d8a2f23206c723137d765027a7acd97837 (diff)
downloadrust-2733b189ac60cea541fbf80e5839e5027ffc9fbf.tar.gz
rust-2733b189ac60cea541fbf80e5839e5027ffc9fbf.zip
auto merge of #9250 : erickt/rust/num, r=erickt
This PR solves one of the pain points with c-style enums. Simplifies writing a fn to convert from an int/uint to an enum. It does this through a `#[deriving(FromPrimitive)]` syntax extension.

Before this is committed though, we need to discuss if `ToPrimitive`/`FromPrimitive` has the right design (cc #4819). I've changed all the `.to_int()` and `from_int()` style functions to return `Option<int>` so we can handle partial functions. For this PR though only enums and `extra::num::bigint::*` take advantage of returning None for unrepresentable values. In the long run it'd be better if `i64.to_i8()` returned `None` if the value was too large, but I'll save this for a future PR.

Closes #3868.
Diffstat (limited to 'src/libstd')
-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
8 files changed, 897 insertions, 100 deletions
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();
             }
         }
     }