about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-04-13 13:51:58 -0700
committerbors <bors@rust-lang.org>2013-04-13 13:51:58 -0700
commit9f337a58ce23a7be54c40885f8fbf5ed93fd8f84 (patch)
treefd1e7689224269109c368f544faee864a5f212d8
parente2d5cebe32c0b1fae7f612a16a9e7b62ed740660 (diff)
parent0615fddd80116d63fba7040bdd89ad59117037dd (diff)
downloadrust-9f337a58ce23a7be54c40885f8fbf5ed93fd8f84.tar.gz
rust-9f337a58ce23a7be54c40885f8fbf5ed93fd8f84.zip
auto merge of #5869 : bjz/rust/master, r=graydon
This restores the trait that was lost in 216e85fadf465c25fe7bc4a9f06f8162ec12b552. `Num` will eventually be broken up into a more fine-grained trait hierarchy in the future once a design can be agreed upon.

To contribute to the discussion about the future of Rust's numeric traits, please see issue #4819 and the [wiki page](https://github.com/mozilla/rust/wiki/Bikeshed-Numeric-Traits).

I have also switched to [implementing NumCast using macros](https://github.com/bjz/rust/commit/353ce872e287edf3764ca416d2a8cd8e1f54329b). This removes a significant number of lines of code.
-rw-r--r--src/libcore/core.rc2
-rw-r--r--src/libcore/num/f32.rs82
-rw-r--r--src/libcore/num/f64.rs82
-rw-r--r--src/libcore/num/float.rs82
-rw-r--r--src/libcore/num/int-template.rs12
-rw-r--r--src/libcore/num/int-template/i16.rs71
-rw-r--r--src/libcore/num/int-template/i32.rs71
-rw-r--r--src/libcore/num/int-template/i64.rs71
-rw-r--r--src/libcore/num/int-template/i8.rs71
-rw-r--r--src/libcore/num/int-template/int.rs71
-rw-r--r--src/libcore/num/num.rs163
-rw-r--r--src/libcore/num/uint-template.rs12
-rw-r--r--src/libcore/num/uint-template/u16.rs71
-rw-r--r--src/libcore/num/uint-template/u32.rs71
-rw-r--r--src/libcore/num/uint-template/u64.rs71
-rw-r--r--src/libcore/num/uint-template/u8.rs71
-rw-r--r--src/libcore/num/uint-template/uint.rs71
-rw-r--r--src/libcore/prelude.rs2
-rw-r--r--src/test/run-pass/trait-inheritance-num.rs2
-rw-r--r--src/test/run-pass/trait-inheritance-num1.rs2
-rw-r--r--src/test/run-pass/trait-inheritance-num2.rs2
-rw-r--r--src/test/run-pass/trait-inheritance-num3.rs2
-rw-r--r--src/test/run-pass/trait-inheritance-num5.rs2
23 files changed, 166 insertions, 991 deletions
diff --git a/src/libcore/core.rc b/src/libcore/core.rc
index 3368f6df870..41db07ca34c 100644
--- a/src/libcore/core.rc
+++ b/src/libcore/core.rc
@@ -99,7 +99,7 @@ pub use vec::{OwnedVector, OwnedCopyableVector};
 pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
 pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
 
-pub use num::NumCast;
+pub use num::{Num, NumCast};
 pub use ptr::Ptr;
 pub use to_str::ToStr;
 pub use clone::Clone;
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index fa82001151e..5e672ea0dfa 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -12,7 +12,6 @@
 
 use cmath;
 use libc::{c_float, c_int};
-use num::NumCast;
 use num::strconv;
 use num;
 use option::Option;
@@ -287,30 +286,6 @@ impl num::One for f32 {
     fn one() -> f32 { 1.0 }
 }
 
-impl NumCast for f32 {
-    /**
-     * Cast `n` to an `f32`
-     */
-    #[inline(always)]
-    fn from<N:NumCast>(n: N) -> f32 { n.to_f32() }
-
-    #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
-    #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
-    #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
-    #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
-    #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
-
-    #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
-    #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
-    #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
-    #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
-    #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
-
-    #[inline(always)] fn to_f32(&self)   -> f32   { *self          }
-    #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
-    #[inline(always)] fn to_float(&self) -> float { *self as float }
-}
-
 #[cfg(notest)]
 impl ops::Add<f32,f32> for f32 {
     fn add(&self, other: &f32) -> f32 { *self + *other }
@@ -580,63 +555,6 @@ impl num::FromStrRadix for f32 {
     }
 }
 
-#[test]
-pub fn test_num() {
-    let ten: f32 = num::cast(10);
-    let two: f32 = num::cast(2);
-
-    assert!((ten.add(&two)    == num::cast(12)));
-    assert!((ten.sub(&two)    == num::cast(8)));
-    assert!((ten.mul(&two)    == num::cast(20)));
-    assert!((ten.div(&two)    == num::cast(5)));
-    assert!((ten.modulo(&two) == num::cast(0)));
-}
-
-#[test]
-fn test_numcast() {
-    assert!((20u     == 20f32.to_uint()));
-    assert!((20u8    == 20f32.to_u8()));
-    assert!((20u16   == 20f32.to_u16()));
-    assert!((20u32   == 20f32.to_u32()));
-    assert!((20u64   == 20f32.to_u64()));
-    assert!((20i     == 20f32.to_int()));
-    assert!((20i8    == 20f32.to_i8()));
-    assert!((20i16   == 20f32.to_i16()));
-    assert!((20i32   == 20f32.to_i32()));
-    assert!((20i64   == 20f32.to_i64()));
-    assert!((20f     == 20f32.to_float()));
-    assert!((20f32   == 20f32.to_f32()));
-    assert!((20f64   == 20f32.to_f64()));
-
-    assert!((20f32 == NumCast::from(20u)));
-    assert!((20f32 == NumCast::from(20u8)));
-    assert!((20f32 == NumCast::from(20u16)));
-    assert!((20f32 == NumCast::from(20u32)));
-    assert!((20f32 == NumCast::from(20u64)));
-    assert!((20f32 == NumCast::from(20i)));
-    assert!((20f32 == NumCast::from(20i8)));
-    assert!((20f32 == NumCast::from(20i16)));
-    assert!((20f32 == NumCast::from(20i32)));
-    assert!((20f32 == NumCast::from(20i64)));
-    assert!((20f32 == NumCast::from(20f)));
-    assert!((20f32 == NumCast::from(20f32)));
-    assert!((20f32 == NumCast::from(20f64)));
-
-    assert!((20f32 == num::cast(20u)));
-    assert!((20f32 == num::cast(20u8)));
-    assert!((20f32 == num::cast(20u16)));
-    assert!((20f32 == num::cast(20u32)));
-    assert!((20f32 == num::cast(20u64)));
-    assert!((20f32 == num::cast(20i)));
-    assert!((20f32 == num::cast(20i8)));
-    assert!((20f32 == num::cast(20i16)));
-    assert!((20f32 == num::cast(20i32)));
-    assert!((20f32 == num::cast(20i64)));
-    assert!((20f32 == num::cast(20f)));
-    assert!((20f32 == num::cast(20f32)));
-    assert!((20f32 == num::cast(20f64)));
-}
-
 //
 // Local Variables:
 // mode: rust
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 67dfabacd0b..4c96da73d21 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -12,7 +12,6 @@
 
 use cmath;
 use libc::{c_double, c_int};
-use num::NumCast;
 use num::strconv;
 use num;
 use option::Option;
@@ -299,30 +298,6 @@ impl cmp::Ord for f64 {
     fn gt(&self, other: &f64) -> bool { (*self) > (*other) }
 }
 
-impl NumCast for f64 {
-    /**
-     * Cast `n` to an `f64`
-     */
-    #[inline(always)]
-    fn from<N:NumCast>(n: N) -> f64 { n.to_f64() }
-
-    #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
-    #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
-    #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
-    #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
-    #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
-
-    #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
-    #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
-    #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
-    #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
-    #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
-
-    #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
-    #[inline(always)] fn to_f64(&self)   -> f64   { *self          }
-    #[inline(always)] fn to_float(&self) -> float { *self as float }
-}
-
 impl num::Zero for f64 {
     #[inline(always)]
     fn zero() -> f64 { 0.0 }
@@ -602,63 +577,6 @@ impl num::FromStrRadix for f64 {
     }
 }
 
-#[test]
-pub fn test_num() {
-    let ten: f64 = num::cast(10);
-    let two: f64 = num::cast(2);
-
-    assert!((ten.add(&two)    == num::cast(12)));
-    assert!((ten.sub(&two)    == num::cast(8)));
-    assert!((ten.mul(&two)    == num::cast(20)));
-    assert!((ten.div(&two)    == num::cast(5)));
-    assert!((ten.modulo(&two) == num::cast(0)));
-}
-
-#[test]
-fn test_numcast() {
-    assert!((20u   == 20f64.to_uint()));
-    assert!((20u8  == 20f64.to_u8()));
-    assert!((20u16 == 20f64.to_u16()));
-    assert!((20u32 == 20f64.to_u32()));
-    assert!((20u64 == 20f64.to_u64()));
-    assert!((20i   == 20f64.to_int()));
-    assert!((20i8  == 20f64.to_i8()));
-    assert!((20i16 == 20f64.to_i16()));
-    assert!((20i32 == 20f64.to_i32()));
-    assert!((20i64 == 20f64.to_i64()));
-    assert!((20f   == 20f64.to_float()));
-    assert!((20f32 == 20f64.to_f32()));
-    assert!((20f64 == 20f64.to_f64()));
-
-    assert!((20f64 == NumCast::from(20u)));
-    assert!((20f64 == NumCast::from(20u8)));
-    assert!((20f64 == NumCast::from(20u16)));
-    assert!((20f64 == NumCast::from(20u32)));
-    assert!((20f64 == NumCast::from(20u64)));
-    assert!((20f64 == NumCast::from(20i)));
-    assert!((20f64 == NumCast::from(20i8)));
-    assert!((20f64 == NumCast::from(20i16)));
-    assert!((20f64 == NumCast::from(20i32)));
-    assert!((20f64 == NumCast::from(20i64)));
-    assert!((20f64 == NumCast::from(20f)));
-    assert!((20f64 == NumCast::from(20f32)));
-    assert!((20f64 == NumCast::from(20f64)));
-
-    assert!((20f64 == num::cast(20u)));
-    assert!((20f64 == num::cast(20u8)));
-    assert!((20f64 == num::cast(20u16)));
-    assert!((20f64 == num::cast(20u32)));
-    assert!((20f64 == num::cast(20u64)));
-    assert!((20f64 == num::cast(20i)));
-    assert!((20f64 == num::cast(20i8)));
-    assert!((20f64 == num::cast(20i16)));
-    assert!((20f64 == num::cast(20i32)));
-    assert!((20f64 == num::cast(20i64)));
-    assert!((20f64 == num::cast(20f)));
-    assert!((20f64 == num::cast(20f32)));
-    assert!((20f64 == num::cast(20f64)));
-}
-
 //
 // Local Variables:
 // mode: rust
diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs
index 25082929703..1ab0e24f62d 100644
--- a/src/libcore/num/float.rs
+++ b/src/libcore/num/float.rs
@@ -21,7 +21,6 @@
 // PORT this must match in width according to architecture
 
 use f64;
-use num::NumCast;
 use num::strconv;
 use num;
 use option::Option;
@@ -417,30 +416,6 @@ impl num::One for float {
     fn one() -> float { 1.0 }
 }
 
-impl NumCast for float {
-    /**
-     * Cast `n` to a `float`
-     */
-    #[inline(always)]
-    fn from<N:NumCast>(n: N) -> float { n.to_float() }
-
-    #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
-    #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
-    #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
-    #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
-    #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
-
-    #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
-    #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
-    #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
-    #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
-    #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
-
-    #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
-    #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
-    #[inline(always)] fn to_float(&self) -> float { *self          }
-}
-
 impl num::Round for float {
     #[inline(always)]
     fn round(&self, mode: num::RoundMode) -> float {
@@ -688,63 +663,6 @@ pub fn test_round() {
     assert!(round(-3.5) == -4.0);
 }
 
-#[test]
-pub fn test_num() {
-    let ten: float = num::cast(10);
-    let two: float = num::cast(2);
-
-    assert!((ten.add(&two)    == num::cast(12)));
-    assert!((ten.sub(&two)    == num::cast(8)));
-    assert!((ten.mul(&two)    == num::cast(20)));
-    assert!((ten.div(&two)    == num::cast(5)));
-    assert!((ten.modulo(&two) == num::cast(0)));
-}
-
-#[test]
-fn test_numcast() {
-    assert!((20u   == 20f.to_uint()));
-    assert!((20u8  == 20f.to_u8()));
-    assert!((20u16 == 20f.to_u16()));
-    assert!((20u32 == 20f.to_u32()));
-    assert!((20u64 == 20f.to_u64()));
-    assert!((20i   == 20f.to_int()));
-    assert!((20i8  == 20f.to_i8()));
-    assert!((20i16 == 20f.to_i16()));
-    assert!((20i32 == 20f.to_i32()));
-    assert!((20i64 == 20f.to_i64()));
-    assert!((20f   == 20f.to_float()));
-    assert!((20f32 == 20f.to_f32()));
-    assert!((20f64 == 20f.to_f64()));
-
-    assert!((20f == NumCast::from(20u)));
-    assert!((20f == NumCast::from(20u8)));
-    assert!((20f == NumCast::from(20u16)));
-    assert!((20f == NumCast::from(20u32)));
-    assert!((20f == NumCast::from(20u64)));
-    assert!((20f == NumCast::from(20i)));
-    assert!((20f == NumCast::from(20i8)));
-    assert!((20f == NumCast::from(20i16)));
-    assert!((20f == NumCast::from(20i32)));
-    assert!((20f == NumCast::from(20i64)));
-    assert!((20f == NumCast::from(20f)));
-    assert!((20f == NumCast::from(20f32)));
-    assert!((20f == NumCast::from(20f64)));
-
-    assert!((20f == num::cast(20u)));
-    assert!((20f == num::cast(20u8)));
-    assert!((20f == num::cast(20u16)));
-    assert!((20f == num::cast(20u32)));
-    assert!((20f == num::cast(20u64)));
-    assert!((20f == num::cast(20i)));
-    assert!((20f == num::cast(20i8)));
-    assert!((20f == num::cast(20i16)));
-    assert!((20f == num::cast(20i32)));
-    assert!((20f == num::cast(20i64)));
-    assert!((20f == num::cast(20f)));
-    assert!((20f == num::cast(20f32)));
-    assert!((20f == num::cast(20f64)));
-}
-
 
 //
 // Local Variables:
diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs
index 4af903908f1..6fbe44737d1 100644
--- a/src/libcore/num/int-template.rs
+++ b/src/libcore/num/int-template.rs
@@ -398,18 +398,6 @@ fn test_int_from_str_overflow() {
 }
 
 #[test]
-pub fn test_num() {
-    let ten: T = num::cast(10);
-    let two: T = num::cast(2);
-
-    assert!((ten.add(&two)    == num::cast(12)));
-    assert!((ten.sub(&two)    == num::cast(8)));
-    assert!((ten.mul(&two)    == num::cast(20)));
-    assert!((ten.div(&two)    == num::cast(5)));
-    assert!((ten.modulo(&two) == num::cast(0)));
-}
-
-#[test]
 pub fn test_ranges() {
     let mut l = ~[];
 
diff --git a/src/libcore/num/int-template/i16.rs b/src/libcore/num/int-template/i16.rs
index 76be224af15..34dcd508397 100644
--- a/src/libcore/num/int-template/i16.rs
+++ b/src/libcore/num/int-template/i16.rs
@@ -10,78 +10,7 @@
 
 //! Operations and constants for `i16`
 
-use num::NumCast;
-
 mod inst {
     pub type T = i16;
     pub static bits: uint = ::u16::bits;
 }
-
-impl NumCast for i16 {
-    /**
-     * Cast `n` to a `i16`
-     */
-    #[inline(always)]
-    fn from<N:NumCast>(n: N) -> i16 { n.to_i16() }
-
-    #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
-    #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
-    #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
-    #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
-    #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
-
-    #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
-    #[inline(always)] fn to_i16(&self)   -> i16   { *self          }
-    #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
-    #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
-    #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
-
-    #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
-    #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
-    #[inline(always)] fn to_float(&self) -> float { *self as float }
-}
-
-#[test]
-fn test_numcast() {
-    assert!((20u   == 20i16.to_uint()));
-    assert!((20u8  == 20i16.to_u8()));
-    assert!((20u16 == 20i16.to_u16()));
-    assert!((20u32 == 20i16.to_u32()));
-    assert!((20u64 == 20i16.to_u64()));
-    assert!((20i   == 20i16.to_int()));
-    assert!((20i8  == 20i16.to_i8()));
-    assert!((20i16 == 20i16.to_i16()));
-    assert!((20i32 == 20i16.to_i32()));
-    assert!((20i64 == 20i16.to_i64()));
-    assert!((20f   == 20i16.to_float()));
-    assert!((20f32 == 20i16.to_f32()));
-    assert!((20f64 == 20i16.to_f64()));
-
-    assert!((20i16 == NumCast::from(20u)));
-    assert!((20i16 == NumCast::from(20u8)));
-    assert!((20i16 == NumCast::from(20u16)));
-    assert!((20i16 == NumCast::from(20u32)));
-    assert!((20i16 == NumCast::from(20u64)));
-    assert!((20i16 == NumCast::from(20i)));
-    assert!((20i16 == NumCast::from(20i8)));
-    assert!((20i16 == NumCast::from(20i16)));
-    assert!((20i16 == NumCast::from(20i32)));
-    assert!((20i16 == NumCast::from(20i64)));
-    assert!((20i16 == NumCast::from(20f)));
-    assert!((20i16 == NumCast::from(20f32)));
-    assert!((20i16 == NumCast::from(20f64)));
-
-    assert!((20i16 == num::cast(20u)));
-    assert!((20i16 == num::cast(20u8)));
-    assert!((20i16 == num::cast(20u16)));
-    assert!((20i16 == num::cast(20u32)));
-    assert!((20i16 == num::cast(20u64)));
-    assert!((20i16 == num::cast(20i)));
-    assert!((20i16 == num::cast(20i8)));
-    assert!((20i16 == num::cast(20i16)));
-    assert!((20i16 == num::cast(20i32)));
-    assert!((20i16 == num::cast(20i64)));
-    assert!((20i16 == num::cast(20f)));
-    assert!((20i16 == num::cast(20f32)));
-    assert!((20i16 == num::cast(20f64)));
-}
diff --git a/src/libcore/num/int-template/i32.rs b/src/libcore/num/int-template/i32.rs
index 596d29aa291..91eea0e8d47 100644
--- a/src/libcore/num/int-template/i32.rs
+++ b/src/libcore/num/int-template/i32.rs
@@ -10,78 +10,7 @@
 
 //! Operations and constants for `i32`
 
-use num::NumCast;
-
 mod inst {
     pub type T = i32;
     pub static bits: uint = ::u32::bits;
 }
-
-impl NumCast for i32 {
-    /**
-     * Cast `n` to a `i32`
-     */
-    #[inline(always)]
-    fn from<N:NumCast>(n: N) -> i32 { n.to_i32() }
-
-    #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
-    #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
-    #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
-    #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
-    #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
-
-    #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
-    #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
-    #[inline(always)] fn to_i32(&self)   -> i32   { *self          }
-    #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
-    #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
-
-    #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
-    #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
-    #[inline(always)] fn to_float(&self) -> float { *self as float }
-}
-
-#[test]
-fn test_numcast() {
-    assert!((20u   == 20i32.to_uint()));
-    assert!((20u8  == 20i32.to_u8()));
-    assert!((20u16 == 20i32.to_u16()));
-    assert!((20u32 == 20i32.to_u32()));
-    assert!((20u64 == 20i32.to_u64()));
-    assert!((20i   == 20i32.to_int()));
-    assert!((20i8  == 20i32.to_i8()));
-    assert!((20i16 == 20i32.to_i16()));
-    assert!((20i32 == 20i32.to_i32()));
-    assert!((20i64 == 20i32.to_i64()));
-    assert!((20f   == 20i32.to_float()));
-    assert!((20f32 == 20i32.to_f32()));
-    assert!((20f64 == 20i32.to_f64()));
-
-    assert!((20i32 == NumCast::from(20u)));
-    assert!((20i32 == NumCast::from(20u8)));
-    assert!((20i32 == NumCast::from(20u16)));
-    assert!((20i32 == NumCast::from(20u32)));
-    assert!((20i32 == NumCast::from(20u64)));
-    assert!((20i32 == NumCast::from(20i)));
-    assert!((20i32 == NumCast::from(20i8)));
-    assert!((20i32 == NumCast::from(20i16)));
-    assert!((20i32 == NumCast::from(20i32)));
-    assert!((20i32 == NumCast::from(20i64)));
-    assert!((20i32 == NumCast::from(20f)));
-    assert!((20i32 == NumCast::from(20f32)));
-    assert!((20i32 == NumCast::from(20f64)));
-
-    assert!((20i32 == num::cast(20u)));
-    assert!((20i32 == num::cast(20u8)));
-    assert!((20i32 == num::cast(20u16)));
-    assert!((20i32 == num::cast(20u32)));
-    assert!((20i32 == num::cast(20u64)));
-    assert!((20i32 == num::cast(20i)));
-    assert!((20i32 == num::cast(20i8)));
-    assert!((20i32 == num::cast(20i16)));
-    assert!((20i32 == num::cast(20i32)));
-    assert!((20i32 == num::cast(20i64)));
-    assert!((20i32 == num::cast(20f)));
-    assert!((20i32 == num::cast(20f32)));
-    assert!((20i32 == num::cast(20f64)));
-}
diff --git a/src/libcore/num/int-template/i64.rs b/src/libcore/num/int-template/i64.rs
index d02c46d9393..3834a1e2a03 100644
--- a/src/libcore/num/int-template/i64.rs
+++ b/src/libcore/num/int-template/i64.rs
@@ -10,78 +10,7 @@
 
 //! Operations and constants for `i64`
 
-use num::NumCast;
-
 mod inst {
     pub type T = i64;
     pub static bits: uint = ::u64::bits;
 }
-
-impl NumCast for i64 {
-    /**
-     * Cast `n` to a `i64`
-     */
-    #[inline(always)]
-    fn from<N:NumCast>(n: N) -> i64 { n.to_i64() }
-
-    #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
-    #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
-    #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
-    #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
-    #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
-
-    #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
-    #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
-    #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
-    #[inline(always)] fn to_i64(&self)   -> i64   { *self          }
-    #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
-
-    #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
-    #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
-    #[inline(always)] fn to_float(&self) -> float { *self as float }
-}
-
-#[test]
-fn test_numcast() {
-    assert!((20u   == 20i64.to_uint()));
-    assert!((20u8  == 20i64.to_u8()));
-    assert!((20u16 == 20i64.to_u16()));
-    assert!((20u32 == 20i64.to_u32()));
-    assert!((20u64 == 20i64.to_u64()));
-    assert!((20i   == 20i64.to_int()));
-    assert!((20i8  == 20i64.to_i8()));
-    assert!((20i16 == 20i64.to_i16()));
-    assert!((20i32 == 20i64.to_i32()));
-    assert!((20i64 == 20i64.to_i64()));
-    assert!((20f   == 20i64.to_float()));
-    assert!((20f32 == 20i64.to_f32()));
-    assert!((20f64 == 20i64.to_f64()));
-
-    assert!((20i64 == NumCast::from(20u)));
-    assert!((20i64 == NumCast::from(20u8)));
-    assert!((20i64 == NumCast::from(20u16)));
-    assert!((20i64 == NumCast::from(20u32)));
-    assert!((20i64 == NumCast::from(20u64)));
-    assert!((20i64 == NumCast::from(20i)));
-    assert!((20i64 == NumCast::from(20i8)));
-    assert!((20i64 == NumCast::from(20i16)));
-    assert!((20i64 == NumCast::from(20i32)));
-    assert!((20i64 == NumCast::from(20i64)));
-    assert!((20i64 == NumCast::from(20f)));
-    assert!((20i64 == NumCast::from(20f32)));
-    assert!((20i64 == NumCast::from(20f64)));
-
-    assert!((20i64 == num::cast(20u)));
-    assert!((20i64 == num::cast(20u8)));
-    assert!((20i64 == num::cast(20u16)));
-    assert!((20i64 == num::cast(20u32)));
-    assert!((20i64 == num::cast(20u64)));
-    assert!((20i64 == num::cast(20i)));
-    assert!((20i64 == num::cast(20i8)));
-    assert!((20i64 == num::cast(20i16)));
-    assert!((20i64 == num::cast(20i32)));
-    assert!((20i64 == num::cast(20i64)));
-    assert!((20i64 == num::cast(20f)));
-    assert!((20i64 == num::cast(20f32)));
-    assert!((20i64 == num::cast(20f64)));
-}
diff --git a/src/libcore/num/int-template/i8.rs b/src/libcore/num/int-template/i8.rs
index c0dd6e01d4b..9486ed748d7 100644
--- a/src/libcore/num/int-template/i8.rs
+++ b/src/libcore/num/int-template/i8.rs
@@ -10,78 +10,7 @@
 
 //! Operations and constants for `i8`
 
-use num::NumCast;
-
 mod inst {
     pub type T = i8;
     pub static bits: uint = ::u8::bits;
 }
-
-impl NumCast for i8 {
-    /**
-     * Cast `n` to a `i8`
-     */
-    #[inline(always)]
-    fn from<N:NumCast>(n: N) -> i8 { n.to_i8() }
-
-    #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
-    #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
-    #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
-    #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
-    #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
-
-    #[inline(always)] fn to_i8(&self)    -> i8    { *self          }
-    #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
-    #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
-    #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
-    #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
-
-    #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
-    #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
-    #[inline(always)] fn to_float(&self) -> float { *self as float }
-}
-
-#[test]
-fn test_numcast() {
-    assert!((20u   == 20i8.to_uint()));
-    assert!((20u8  == 20i8.to_u8()));
-    assert!((20u16 == 20i8.to_u16()));
-    assert!((20u32 == 20i8.to_u32()));
-    assert!((20u64 == 20i8.to_u64()));
-    assert!((20i   == 20i8.to_int()));
-    assert!((20i8  == 20i8.to_i8()));
-    assert!((20i16 == 20i8.to_i16()));
-    assert!((20i32 == 20i8.to_i32()));
-    assert!((20i64 == 20i8.to_i64()));
-    assert!((20f   == 20i8.to_float()));
-    assert!((20f32 == 20i8.to_f32()));
-    assert!((20f64 == 20i8.to_f64()));
-
-    assert!((20i8 == NumCast::from(20u)));
-    assert!((20i8 == NumCast::from(20u8)));
-    assert!((20i8 == NumCast::from(20u16)));
-    assert!((20i8 == NumCast::from(20u32)));
-    assert!((20i8 == NumCast::from(20u64)));
-    assert!((20i8 == NumCast::from(20i)));
-    assert!((20i8 == NumCast::from(20i8)));
-    assert!((20i8 == NumCast::from(20i16)));
-    assert!((20i8 == NumCast::from(20i32)));
-    assert!((20i8 == NumCast::from(20i64)));
-    assert!((20i8 == NumCast::from(20f)));
-    assert!((20i8 == NumCast::from(20f32)));
-    assert!((20i8 == NumCast::from(20f64)));
-
-    assert!((20i8 == num::cast(20u)));
-    assert!((20i8 == num::cast(20u8)));
-    assert!((20i8 == num::cast(20u16)));
-    assert!((20i8 == num::cast(20u32)));
-    assert!((20i8 == num::cast(20u64)));
-    assert!((20i8 == num::cast(20i)));
-    assert!((20i8 == num::cast(20i8)));
-    assert!((20i8 == num::cast(20i16)));
-    assert!((20i8 == num::cast(20i32)));
-    assert!((20i8 == num::cast(20i64)));
-    assert!((20i8 == num::cast(20f)));
-    assert!((20i8 == num::cast(20f32)));
-    assert!((20i8 == num::cast(20f64)));
-}
diff --git a/src/libcore/num/int-template/int.rs b/src/libcore/num/int-template/int.rs
index ea8aec12224..6649b364015 100644
--- a/src/libcore/num/int-template/int.rs
+++ b/src/libcore/num/int-template/int.rs
@@ -10,8 +10,6 @@
 
 //! Operations and constants for `int`
 
-use num::NumCast;
-
 pub use self::inst::pow;
 
 mod inst {
@@ -57,72 +55,3 @@ mod inst {
         assert!((::int::min_value + ::int::max_value + 1 == 0));
     }
 }
-
-impl NumCast for int {
-    /**
-     * Cast `n` to a `int`
-     */
-    #[inline(always)]
-    fn from<N:NumCast>(n: N) -> int { n.to_int() }
-
-    #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
-    #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
-    #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
-    #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
-    #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
-
-    #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
-    #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
-    #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
-    #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
-    #[inline(always)] fn to_int(&self)   -> int   { *self          }
-
-    #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
-    #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
-    #[inline(always)] fn to_float(&self) -> float { *self as float }
-}
-
-#[test]
-fn test_numcast() {
-    assert!((20u   == 20i.to_uint()));
-    assert!((20u8  == 20i.to_u8()));
-    assert!((20u16 == 20i.to_u16()));
-    assert!((20u32 == 20i.to_u32()));
-    assert!((20u64 == 20i.to_u64()));
-    assert!((20i   == 20i.to_int()));
-    assert!((20i8  == 20i.to_i8()));
-    assert!((20i16 == 20i.to_i16()));
-    assert!((20i32 == 20i.to_i32()));
-    assert!((20i64 == 20i.to_i64()));
-    assert!((20f   == 20i.to_float()));
-    assert!((20f32 == 20i.to_f32()));
-    assert!((20f64 == 20i.to_f64()));
-
-    assert!((20i == NumCast::from(20u)));
-    assert!((20i == NumCast::from(20u8)));
-    assert!((20i == NumCast::from(20u16)));
-    assert!((20i == NumCast::from(20u32)));
-    assert!((20i == NumCast::from(20u64)));
-    assert!((20i == NumCast::from(20i)));
-    assert!((20i == NumCast::from(20i8)));
-    assert!((20i == NumCast::from(20i16)));
-    assert!((20i == NumCast::from(20i32)));
-    assert!((20i == NumCast::from(20i64)));
-    assert!((20i == NumCast::from(20f)));
-    assert!((20i == NumCast::from(20f32)));
-    assert!((20i == NumCast::from(20f64)));
-
-    assert!((20i == num::cast(20u)));
-    assert!((20i == num::cast(20u8)));
-    assert!((20i == num::cast(20u16)));
-    assert!((20i == num::cast(20u32)));
-    assert!((20i == num::cast(20u64)));
-    assert!((20i == num::cast(20i)));
-    assert!((20i == num::cast(20i8)));
-    assert!((20i == num::cast(20i16)));
-    assert!((20i == num::cast(20i32)));
-    assert!((20i == num::cast(20i64)));
-    assert!((20i == num::cast(20f)));
-    assert!((20i == num::cast(20f32)));
-    assert!((20i == num::cast(20f64)));
-}
diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs
index daa36f9dc32..19a1e276d37 100644
--- a/src/libcore/num/num.rs
+++ b/src/libcore/num/num.rs
@@ -9,13 +9,35 @@
 // except according to those terms.
 
 //! An interface for numeric types
-use cmp::Ord;
-use ops::{Div, Mul, Neg};
+use cmp::{Eq, Ord};
+use ops::{Neg, Add, Sub, Mul, Div, Modulo};
 use option::Option;
 use kinds::Copy;
 
 pub mod strconv;
 
+pub trait Num: Eq + Zero + One
+             + Neg<Self>
+             + Add<Self,Self>
+             + Sub<Self,Self>
+             + Mul<Self,Self>
+             + Div<Self,Self>
+             + Modulo<Self,Self> {}
+
+impl Num for u8 {}
+impl Num for u16 {}
+impl Num for u32 {}
+impl Num for u64 {}
+impl Num for uint {}
+impl Num for i8 {}
+impl Num for i16 {}
+impl Num for i32 {}
+impl Num for i64 {}
+impl Num for int {}
+impl Num for f32 {}
+impl Num for f64 {}
+impl Num for float {}
+
 pub trait IntConvertible {
     fn to_int(&self) -> int;
     fn from_int(n: int) -> Self;
@@ -49,7 +71,7 @@ pub enum RoundMode {
 }
 
 /**
- * Cast a number the the enclosing type
+ * Cast from one machine scalar to another
  *
  * # Example
  *
@@ -64,7 +86,7 @@ pub fn cast<T:NumCast,U:NumCast>(n: T) -> U {
 }
 
 /**
- * An interface for generic numeric type casts
+ * An interface for casting between machine scalars
  */
 pub trait NumCast {
     fn from<T:NumCast>(n: T) -> Self;
@@ -86,6 +108,49 @@ pub trait NumCast {
     fn to_float(&self) -> float;
 }
 
+macro_rules! impl_num_cast(
+    ($T:ty, $conv:ident) => (
+        impl NumCast for $T {
+            #[inline(always)]
+            fn from<N:NumCast>(n: N) -> $T {
+                // `$conv` could be generated using `concat_idents!`, but that
+                // macro seems to be broken at the moment
+                n.$conv()
+            }
+
+            #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
+            #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
+            #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
+            #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
+            #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
+
+            #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
+            #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
+            #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
+            #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
+            #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
+
+            #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
+            #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
+            #[inline(always)] fn to_float(&self) -> float { *self as float }
+        }
+    )
+)
+
+impl_num_cast!(u8,    to_u8)
+impl_num_cast!(u16,   to_u16)
+impl_num_cast!(u32,   to_u32)
+impl_num_cast!(u64,   to_u64)
+impl_num_cast!(uint,  to_uint)
+impl_num_cast!(i8,    to_i8)
+impl_num_cast!(i16,   to_i16)
+impl_num_cast!(i32,   to_i32)
+impl_num_cast!(i64,   to_i64)
+impl_num_cast!(int,   to_int)
+impl_num_cast!(f32,   to_f32)
+impl_num_cast!(f64,   to_f64)
+impl_num_cast!(float, to_float)
+
 pub trait ToStrRadix {
     pub fn to_str_radix(&self, radix: uint) -> ~str;
 }
@@ -129,3 +194,93 @@ pub fn pow_with_uint<T:NumCast+One+Zero+Copy+Div<T,T>+Mul<T,T>>(
     total
 }
 
+#[cfg(test)]
+fn test_num<T:Num + NumCast>(ten: T, two: T) {
+    assert!(ten.add(&two)    == cast(12));
+    assert!(ten.sub(&two)    == cast(8));
+    assert!(ten.mul(&two)    == cast(20));
+    assert!(ten.div(&two)    == cast(5));
+    assert!(ten.modulo(&two) == cast(0));
+
+    assert!(ten.add(&two)    == ten + two);
+    assert!(ten.sub(&two)    == ten - two);
+    assert!(ten.mul(&two)    == ten * two);
+    assert!(ten.div(&two)    == ten / two);
+    assert!(ten.modulo(&two) == ten % two);
+}
+
+#[test] fn test_u8_num()    { test_num(10u8,  2u8)  }
+#[test] fn test_u16_num()   { test_num(10u16, 2u16) }
+#[test] fn test_u32_num()   { test_num(10u32, 2u32) }
+#[test] fn test_u64_num()   { test_num(10u64, 2u64) }
+#[test] fn test_uint_num()  { test_num(10u,   2u)   }
+#[test] fn test_i8_num()    { test_num(10i8,  2i8)  }
+#[test] fn test_i16_num()   { test_num(10i16, 2i16) }
+#[test] fn test_i32_num()   { test_num(10i32, 2i32) }
+#[test] fn test_i64_num()   { test_num(10i64, 2i64) }
+#[test] fn test_int_num()   { test_num(10i,   2i)   }
+#[test] fn test_f32_num()   { test_num(10f32, 2f32) }
+#[test] fn test_f64_num()   { test_num(10f64, 2f64) }
+#[test] fn test_float_num() { test_num(10f,   2f)   }
+
+macro_rules! test_cast_20(
+    ($_20:expr) => ({
+        let _20 = $_20;
+
+        assert!(20u   == _20.to_uint());
+        assert!(20u8  == _20.to_u8());
+        assert!(20u16 == _20.to_u16());
+        assert!(20u32 == _20.to_u32());
+        assert!(20u64 == _20.to_u64());
+        assert!(20i   == _20.to_int());
+        assert!(20i8  == _20.to_i8());
+        assert!(20i16 == _20.to_i16());
+        assert!(20i32 == _20.to_i32());
+        assert!(20i64 == _20.to_i64());
+        assert!(20f   == _20.to_float());
+        assert!(20f32 == _20.to_f32());
+        assert!(20f64 == _20.to_f64());
+
+        assert!(_20 == NumCast::from(20u));
+        assert!(_20 == NumCast::from(20u8));
+        assert!(_20 == NumCast::from(20u16));
+        assert!(_20 == NumCast::from(20u32));
+        assert!(_20 == NumCast::from(20u64));
+        assert!(_20 == NumCast::from(20i));
+        assert!(_20 == NumCast::from(20i8));
+        assert!(_20 == NumCast::from(20i16));
+        assert!(_20 == NumCast::from(20i32));
+        assert!(_20 == NumCast::from(20i64));
+        assert!(_20 == NumCast::from(20f));
+        assert!(_20 == NumCast::from(20f32));
+        assert!(_20 == NumCast::from(20f64));
+
+        assert!(_20 == cast(20u));
+        assert!(_20 == cast(20u8));
+        assert!(_20 == cast(20u16));
+        assert!(_20 == cast(20u32));
+        assert!(_20 == cast(20u64));
+        assert!(_20 == cast(20i));
+        assert!(_20 == cast(20i8));
+        assert!(_20 == cast(20i16));
+        assert!(_20 == cast(20i32));
+        assert!(_20 == cast(20i64));
+        assert!(_20 == cast(20f));
+        assert!(_20 == cast(20f32));
+        assert!(_20 == cast(20f64));
+    })
+)
+
+#[test] fn test_u8_cast()    { test_cast_20!(20u8)  }
+#[test] fn test_u16_cast()   { test_cast_20!(20u16) }
+#[test] fn test_u32_cast()   { test_cast_20!(20u32) }
+#[test] fn test_u64_cast()   { test_cast_20!(20u64) }
+#[test] fn test_uint_cast()  { test_cast_20!(20u)   }
+#[test] fn test_i8_cast()    { test_cast_20!(20i8)  }
+#[test] fn test_i16_cast()   { test_cast_20!(20i16) }
+#[test] fn test_i32_cast()   { test_cast_20!(20i32) }
+#[test] fn test_i64_cast()   { test_cast_20!(20i64) }
+#[test] fn test_int_cast()   { test_cast_20!(20i)   }
+#[test] fn test_f32_cast()   { test_cast_20!(20f32) }
+#[test] fn test_f64_cast()   { test_cast_20!(20f64) }
+#[test] fn test_float_cast() { test_cast_20!(20f)   }
diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs
index 412921b8c28..1cbdabafdab 100644
--- a/src/libcore/num/uint-template.rs
+++ b/src/libcore/num/uint-template.rs
@@ -412,18 +412,6 @@ pub fn test_ranges() {
 }
 
 #[test]
-pub fn test_num() {
-    let ten: T = num::cast(10);
-    let two: T = num::cast(2);
-
-    assert!((ten.add(&two)    == num::cast(12)));
-    assert!((ten.sub(&two)    == num::cast(8)));
-    assert!((ten.mul(&two)    == num::cast(20)));
-    assert!((ten.div(&two)    == num::cast(5)));
-    assert!((ten.modulo(&two) == num::cast(0)));
-}
-
-#[test]
 #[should_fail]
 #[ignore(cfg(windows))]
 fn test_range_step_zero_step_up() {
diff --git a/src/libcore/num/uint-template/u16.rs b/src/libcore/num/uint-template/u16.rs
index 7445a43e486..63144162fc5 100644
--- a/src/libcore/num/uint-template/u16.rs
+++ b/src/libcore/num/uint-template/u16.rs
@@ -10,80 +10,9 @@
 
 //! Operations and constants for `u16`
 
-use num::NumCast;
-
 mod inst {
     pub type T = u16;
     #[allow(non_camel_case_types)]
     pub type T_SIGNED = i16;
     pub static bits: uint = 16;
 }
-
-impl NumCast for u16 {
-    /**
-     * Cast `n` to a `u16`
-     */
-    #[inline(always)]
-    fn from<N:NumCast>(n: N) -> u16 { n.to_u16() }
-
-    #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
-    #[inline(always)] fn to_u16(&self)   -> u16   { *self          }
-    #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
-    #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
-    #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
-
-    #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
-    #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
-    #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
-    #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
-    #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
-
-    #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
-    #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
-    #[inline(always)] fn to_float(&self) -> float { *self as float }
-}
-
-#[test]
-fn test_numcast() {
-    assert!((20u   == 20u16.to_uint()));
-    assert!((20u8  == 20u16.to_u8()));
-    assert!((20u16 == 20u16.to_u16()));
-    assert!((20u32 == 20u16.to_u32()));
-    assert!((20u64 == 20u16.to_u64()));
-    assert!((20i   == 20u16.to_int()));
-    assert!((20i8  == 20u16.to_i8()));
-    assert!((20i16 == 20u16.to_i16()));
-    assert!((20i32 == 20u16.to_i32()));
-    assert!((20i64 == 20u16.to_i64()));
-    assert!((20f   == 20u16.to_float()));
-    assert!((20f32 == 20u16.to_f32()));
-    assert!((20f64 == 20u16.to_f64()));
-
-    assert!((20u16 == NumCast::from(20u)));
-    assert!((20u16 == NumCast::from(20u8)));
-    assert!((20u16 == NumCast::from(20u16)));
-    assert!((20u16 == NumCast::from(20u32)));
-    assert!((20u16 == NumCast::from(20u64)));
-    assert!((20u16 == NumCast::from(20i)));
-    assert!((20u16 == NumCast::from(20i8)));
-    assert!((20u16 == NumCast::from(20i16)));
-    assert!((20u16 == NumCast::from(20i32)));
-    assert!((20u16 == NumCast::from(20i64)));
-    assert!((20u16 == NumCast::from(20f)));
-    assert!((20u16 == NumCast::from(20f32)));
-    assert!((20u16 == NumCast::from(20f64)));
-
-    assert!((20u16 == num::cast(20u)));
-    assert!((20u16 == num::cast(20u8)));
-    assert!((20u16 == num::cast(20u16)));
-    assert!((20u16 == num::cast(20u32)));
-    assert!((20u16 == num::cast(20u64)));
-    assert!((20u16 == num::cast(20i)));
-    assert!((20u16 == num::cast(20i8)));
-    assert!((20u16 == num::cast(20i16)));
-    assert!((20u16 == num::cast(20i32)));
-    assert!((20u16 == num::cast(20i64)));
-    assert!((20u16 == num::cast(20f)));
-    assert!((20u16 == num::cast(20f32)));
-    assert!((20u16 == num::cast(20f64)));
-}
diff --git a/src/libcore/num/uint-template/u32.rs b/src/libcore/num/uint-template/u32.rs
index cfc112be8a6..4d9958fe38a 100644
--- a/src/libcore/num/uint-template/u32.rs
+++ b/src/libcore/num/uint-template/u32.rs
@@ -10,80 +10,9 @@
 
 //! Operations and constants for `u32`
 
-use num::NumCast;
-
 mod inst {
     pub type T = u32;
     #[allow(non_camel_case_types)]
     pub type T_SIGNED = i32;
     pub static bits: uint = 32;
 }
-
-impl NumCast for u32 {
-    /**
-     * Cast `n` to a `u32`
-     */
-    #[inline(always)]
-    fn from<N:NumCast>(n: N) -> u32 { n.to_u32() }
-
-    #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
-    #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
-    #[inline(always)] fn to_u32(&self)   -> u32   { *self          }
-    #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
-    #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
-
-    #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
-    #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
-    #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
-    #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
-    #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
-
-    #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
-    #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
-    #[inline(always)] fn to_float(&self) -> float { *self as float }
-}
-
-#[test]
-fn test_numcast() {
-    assert!((20u   == 20u64.to_uint()));
-    assert!((20u8  == 20u64.to_u8()));
-    assert!((20u16 == 20u64.to_u16()));
-    assert!((20u32 == 20u64.to_u32()));
-    assert!((20u64 == 20u64.to_u64()));
-    assert!((20i   == 20u64.to_int()));
-    assert!((20i8  == 20u64.to_i8()));
-    assert!((20i16 == 20u64.to_i16()));
-    assert!((20i32 == 20u64.to_i32()));
-    assert!((20i64 == 20u64.to_i64()));
-    assert!((20f   == 20u64.to_float()));
-    assert!((20f32 == 20u64.to_f32()));
-    assert!((20f64 == 20u64.to_f64()));
-
-    assert!((20u64 == NumCast::from(20u)));
-    assert!((20u64 == NumCast::from(20u8)));
-    assert!((20u64 == NumCast::from(20u16)));
-    assert!((20u64 == NumCast::from(20u32)));
-    assert!((20u64 == NumCast::from(20u64)));
-    assert!((20u64 == NumCast::from(20i)));
-    assert!((20u64 == NumCast::from(20i8)));
-    assert!((20u64 == NumCast::from(20i16)));
-    assert!((20u64 == NumCast::from(20i32)));
-    assert!((20u64 == NumCast::from(20i64)));
-    assert!((20u64 == NumCast::from(20f)));
-    assert!((20u64 == NumCast::from(20f32)));
-    assert!((20u64 == NumCast::from(20f64)));
-
-    assert!((20u64 == num::cast(20u)));
-    assert!((20u64 == num::cast(20u8)));
-    assert!((20u64 == num::cast(20u16)));
-    assert!((20u64 == num::cast(20u32)));
-    assert!((20u64 == num::cast(20u64)));
-    assert!((20u64 == num::cast(20i)));
-    assert!((20u64 == num::cast(20i8)));
-    assert!((20u64 == num::cast(20i16)));
-    assert!((20u64 == num::cast(20i32)));
-    assert!((20u64 == num::cast(20i64)));
-    assert!((20u64 == num::cast(20f)));
-    assert!((20u64 == num::cast(20f32)));
-    assert!((20u64 == num::cast(20f64)));
-}
diff --git a/src/libcore/num/uint-template/u64.rs b/src/libcore/num/uint-template/u64.rs
index 4e2f6640d69..af198dd6942 100644
--- a/src/libcore/num/uint-template/u64.rs
+++ b/src/libcore/num/uint-template/u64.rs
@@ -10,80 +10,9 @@
 
 //! Operations and constants for `u64`
 
-use num::NumCast;
-
 mod inst {
     pub type T = u64;
     #[allow(non_camel_case_types)]
     pub type T_SIGNED = i64;
     pub static bits: uint = 64;
 }
-
-impl NumCast for u64 {
-    /**
-     * Cast `n` to a `u64`
-     */
-    #[inline(always)]
-    fn from<N:NumCast>(n: N) -> u64 { n.to_u64() }
-
-    #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
-    #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
-    #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
-    #[inline(always)] fn to_u64(&self)   -> u64   { *self          }
-    #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
-
-    #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
-    #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
-    #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
-    #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
-    #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
-
-    #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
-    #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
-    #[inline(always)] fn to_float(&self) -> float { *self as float }
-}
-
-#[test]
-fn test_numcast() {
-    assert!((20u   == 20u64.to_uint()));
-    assert!((20u8  == 20u64.to_u8()));
-    assert!((20u16 == 20u64.to_u16()));
-    assert!((20u32 == 20u64.to_u32()));
-    assert!((20u64 == 20u64.to_u64()));
-    assert!((20i   == 20u64.to_int()));
-    assert!((20i8  == 20u64.to_i8()));
-    assert!((20i16 == 20u64.to_i16()));
-    assert!((20i32 == 20u64.to_i32()));
-    assert!((20i64 == 20u64.to_i64()));
-    assert!((20f   == 20u64.to_float()));
-    assert!((20f32 == 20u64.to_f32()));
-    assert!((20f64 == 20u64.to_f64()));
-
-    assert!((20u64 == NumCast::from(20u)));
-    assert!((20u64 == NumCast::from(20u8)));
-    assert!((20u64 == NumCast::from(20u16)));
-    assert!((20u64 == NumCast::from(20u32)));
-    assert!((20u64 == NumCast::from(20u64)));
-    assert!((20u64 == NumCast::from(20i)));
-    assert!((20u64 == NumCast::from(20i8)));
-    assert!((20u64 == NumCast::from(20i16)));
-    assert!((20u64 == NumCast::from(20i32)));
-    assert!((20u64 == NumCast::from(20i64)));
-    assert!((20u64 == NumCast::from(20f)));
-    assert!((20u64 == NumCast::from(20f32)));
-    assert!((20u64 == NumCast::from(20f64)));
-
-    assert!((20u64 == num::cast(20u)));
-    assert!((20u64 == num::cast(20u8)));
-    assert!((20u64 == num::cast(20u16)));
-    assert!((20u64 == num::cast(20u32)));
-    assert!((20u64 == num::cast(20u64)));
-    assert!((20u64 == num::cast(20i)));
-    assert!((20u64 == num::cast(20i8)));
-    assert!((20u64 == num::cast(20i16)));
-    assert!((20u64 == num::cast(20i32)));
-    assert!((20u64 == num::cast(20i64)));
-    assert!((20u64 == num::cast(20f)));
-    assert!((20u64 == num::cast(20f32)));
-    assert!((20u64 == num::cast(20f64)));
-}
diff --git a/src/libcore/num/uint-template/u8.rs b/src/libcore/num/uint-template/u8.rs
index 52bc56b955c..ce23bebacda 100644
--- a/src/libcore/num/uint-template/u8.rs
+++ b/src/libcore/num/uint-template/u8.rs
@@ -12,8 +12,6 @@
 
 pub use self::inst::is_ascii;
 
-use num::NumCast;
-
 mod inst {
     pub type T = u8;
     #[allow(non_camel_case_types)]
@@ -25,72 +23,3 @@ mod inst {
 
     pub fn is_ascii(x: T) -> bool { return 0 as T == x & 128 as T; }
 }
-
-impl NumCast for u8 {
-    /**
-     * Cast `n` to a `u8`
-     */
-    #[inline(always)]
-    fn from<N:NumCast>(n: N) -> u8 { n.to_u8() }
-
-    #[inline(always)] fn to_u8(&self)    -> u8    { *self          }
-    #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
-    #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
-    #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
-    #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
-
-    #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
-    #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
-    #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
-    #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
-    #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
-
-    #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
-    #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
-    #[inline(always)] fn to_float(&self) -> float { *self as float }
-}
-
-#[test]
-fn test_numcast() {
-    assert!((20u     == 20u8.to_uint()));
-    assert!((20u8    == 20u8.to_u8()));
-    assert!((20u16   == 20u8.to_u16()));
-    assert!((20u32   == 20u8.to_u32()));
-    assert!((20u64   == 20u8.to_u64()));
-    assert!((20i     == 20u8.to_int()));
-    assert!((20i8    == 20u8.to_i8()));
-    assert!((20i16   == 20u8.to_i16()));
-    assert!((20i32   == 20u8.to_i32()));
-    assert!((20i64   == 20u8.to_i64()));
-    assert!((20f     == 20u8.to_float()));
-    assert!((20f32   == 20u8.to_f32()));
-    assert!((20f64   == 20u8.to_f64()));
-
-    assert!((20u8 == NumCast::from(20u)));
-    assert!((20u8 == NumCast::from(20u8)));
-    assert!((20u8 == NumCast::from(20u16)));
-    assert!((20u8 == NumCast::from(20u32)));
-    assert!((20u8 == NumCast::from(20u64)));
-    assert!((20u8 == NumCast::from(20i)));
-    assert!((20u8 == NumCast::from(20i8)));
-    assert!((20u8 == NumCast::from(20i16)));
-    assert!((20u8 == NumCast::from(20i32)));
-    assert!((20u8 == NumCast::from(20i64)));
-    assert!((20u8 == NumCast::from(20f)));
-    assert!((20u8 == NumCast::from(20f32)));
-    assert!((20u8 == NumCast::from(20f64)));
-
-    assert!((20u8 == num::cast(20u)));
-    assert!((20u8 == num::cast(20u8)));
-    assert!((20u8 == num::cast(20u16)));
-    assert!((20u8 == num::cast(20u32)));
-    assert!((20u8 == num::cast(20u64)));
-    assert!((20u8 == num::cast(20i)));
-    assert!((20u8 == num::cast(20i8)));
-    assert!((20u8 == num::cast(20i16)));
-    assert!((20u8 == num::cast(20i32)));
-    assert!((20u8 == num::cast(20i64)));
-    assert!((20u8 == num::cast(20f)));
-    assert!((20u8 == num::cast(20f32)));
-    assert!((20u8 == num::cast(20f64)));
-}
diff --git a/src/libcore/num/uint-template/uint.rs b/src/libcore/num/uint-template/uint.rs
index 16e53eb4b6c..efcf68aba31 100644
--- a/src/libcore/num/uint-template/uint.rs
+++ b/src/libcore/num/uint-template/uint.rs
@@ -10,8 +10,6 @@
 
 //! Operations and constants for `uint`
 
-use num::NumCast;
-
 pub use self::inst::{
     div_ceil, div_round, div_floor, iterate,
     next_power_of_two
@@ -209,72 +207,3 @@ pub mod inst {
         assert!((accum == 10));
     }
 }
-
-impl NumCast for uint {
-    /**
-     * Cast `n` to a `uint`
-     */
-    #[inline(always)]
-    fn from<N:NumCast>(n: N) -> uint { n.to_uint() }
-
-    #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
-    #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
-    #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
-    #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
-    #[inline(always)] fn to_uint(&self)  -> uint  { *self          }
-
-    #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
-    #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
-    #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
-    #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
-    #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
-
-    #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
-    #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
-    #[inline(always)] fn to_float(&self) -> float { *self as float }
-}
-
-#[test]
-fn test_numcast() {
-    assert!((20u   == 20u.to_uint()));
-    assert!((20u8  == 20u.to_u8()));
-    assert!((20u16 == 20u.to_u16()));
-    assert!((20u32 == 20u.to_u32()));
-    assert!((20u64 == 20u.to_u64()));
-    assert!((20i   == 20u.to_int()));
-    assert!((20i8  == 20u.to_i8()));
-    assert!((20i16 == 20u.to_i16()));
-    assert!((20i32 == 20u.to_i32()));
-    assert!((20i64 == 20u.to_i64()));
-    assert!((20f   == 20u.to_float()));
-    assert!((20f32 == 20u.to_f32()));
-    assert!((20f64 == 20u.to_f64()));
-
-    assert!((20u == NumCast::from(20u)));
-    assert!((20u == NumCast::from(20u8)));
-    assert!((20u == NumCast::from(20u16)));
-    assert!((20u == NumCast::from(20u32)));
-    assert!((20u == NumCast::from(20u64)));
-    assert!((20u == NumCast::from(20i)));
-    assert!((20u == NumCast::from(20i8)));
-    assert!((20u == NumCast::from(20i16)));
-    assert!((20u == NumCast::from(20i32)));
-    assert!((20u == NumCast::from(20i64)));
-    assert!((20u == NumCast::from(20f)));
-    assert!((20u == NumCast::from(20f32)));
-    assert!((20u == NumCast::from(20f64)));
-
-    assert!((20u == num::cast(20u)));
-    assert!((20u == num::cast(20u8)));
-    assert!((20u == num::cast(20u16)));
-    assert!((20u == num::cast(20u32)));
-    assert!((20u == num::cast(20u64)));
-    assert!((20u == num::cast(20i)));
-    assert!((20u == num::cast(20i8)));
-    assert!((20u == num::cast(20i16)));
-    assert!((20u == num::cast(20i32)));
-    assert!((20u == num::cast(20i64)));
-    assert!((20u == num::cast(20f)));
-    assert!((20u == num::cast(20f32)));
-    assert!((20u == num::cast(20f64)));
-}
diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs
index 9c3bf04b2a8..e148493ca45 100644
--- a/src/libcore/prelude.rs
+++ b/src/libcore/prelude.rs
@@ -34,7 +34,7 @@ pub use hash::Hash;
 pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
 pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter};
 pub use iter::Times;
-pub use num::NumCast;
+pub use num::{Num, NumCast};
 pub use path::GenericPath;
 pub use path::Path;
 pub use path::PosixPath;
diff --git a/src/test/run-pass/trait-inheritance-num.rs b/src/test/run-pass/trait-inheritance-num.rs
index b800ffefeb6..0fb2a6b2e72 100644
--- a/src/test/run-pass/trait-inheritance-num.rs
+++ b/src/test/run-pass/trait-inheritance-num.rs
@@ -16,7 +16,7 @@ use core::cmp::{Eq, Ord};
 use core::num::NumCast::from;
 use std::cmp::FuzzyEq;
 
-pub trait NumExt: NumCast + Eq + Ord {}
+pub trait NumExt: Num + NumCast + Eq + Ord {}
 
 pub trait FloatExt: NumExt + FuzzyEq<Self> {}
 
diff --git a/src/test/run-pass/trait-inheritance-num1.rs b/src/test/run-pass/trait-inheritance-num1.rs
index 07b9772af29..d580b99012f 100644
--- a/src/test/run-pass/trait-inheritance-num1.rs
+++ b/src/test/run-pass/trait-inheritance-num1.rs
@@ -11,7 +11,7 @@
 use core::cmp::Ord;
 use core::num::NumCast::from;
 
-pub trait NumExt: NumCast + Ord { }
+pub trait NumExt: Num + NumCast + Ord { }
 
 fn greater_than_one<T:NumExt>(n: &T) -> bool {
     *n > from(1)
diff --git a/src/test/run-pass/trait-inheritance-num2.rs b/src/test/run-pass/trait-inheritance-num2.rs
index 66d7ee96bb2..b40f647814f 100644
--- a/src/test/run-pass/trait-inheritance-num2.rs
+++ b/src/test/run-pass/trait-inheritance-num2.rs
@@ -38,7 +38,7 @@ impl TypeExt for f64 {}
 impl TypeExt for float {}
 
 
-pub trait NumExt: TypeExt + Eq + Ord + NumCast {}
+pub trait NumExt: TypeExt + Eq + Ord + Num + NumCast {}
 
 impl NumExt for u8 {}
 impl NumExt for u16 {}
diff --git a/src/test/run-pass/trait-inheritance-num3.rs b/src/test/run-pass/trait-inheritance-num3.rs
index 67861709e76..5f1fef80ef2 100644
--- a/src/test/run-pass/trait-inheritance-num3.rs
+++ b/src/test/run-pass/trait-inheritance-num3.rs
@@ -11,7 +11,7 @@
 use core::cmp::{Eq, Ord};
 use core::num::NumCast::from;
 
-pub trait NumExt: Eq + Ord + NumCast {}
+pub trait NumExt: Eq + Ord + Num + NumCast {}
 
 impl NumExt for f32 {}
 
diff --git a/src/test/run-pass/trait-inheritance-num5.rs b/src/test/run-pass/trait-inheritance-num5.rs
index 2efe5b23eb5..02cc9a3d221 100644
--- a/src/test/run-pass/trait-inheritance-num5.rs
+++ b/src/test/run-pass/trait-inheritance-num5.rs
@@ -11,7 +11,7 @@
 use core::cmp::{Eq, Ord};
 use core::num::NumCast::from;
 
-pub trait NumExt: Eq + NumCast {}
+pub trait NumExt: Eq + Num + NumCast {}
 
 impl NumExt for f32 {}
 impl NumExt for int {}