about summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure12
-rw-r--r--mk/main.mk11
-rw-r--r--src/compiletest/compiletest.rs2
-rw-r--r--src/doc/footer.inc2
-rw-r--r--src/doc/intro.md4
-rw-r--r--src/liballoc/arc.rs21
-rw-r--r--src/liballoc/boxed.rs8
-rw-r--r--src/liballoc/heap.rs43
-rw-r--r--src/liballoc/lib.rs3
-rw-r--r--src/liballoc/rc.rs35
-rw-r--r--src/libarena/lib.rs1
-rw-r--r--src/libcollections/bit.rs4
-rw-r--r--src/libcollections/btree/map.rs14
-rw-r--r--src/libcollections/btree/set.rs4
-rw-r--r--src/libcollections/dlist.rs10
-rw-r--r--src/libcollections/lib.rs3
-rw-r--r--src/libcollections/ring_buf.rs8
-rw-r--r--src/libcollections/string.rs9
-rw-r--r--src/libcollections/vec.rs8
-rw-r--r--src/libcollections/vec_map.rs12
-rw-r--r--src/libcore/hash/mod.rs473
-rw-r--r--src/libcore/hash/sip.rs460
-rw-r--r--src/libcore/intrinsics.rs13
-rw-r--r--src/libcore/iter.rs4
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/num/int.rs7
-rw-r--r--src/libcore/num/mod.rs8
-rw-r--r--src/libcoretest/hash/mod.rs103
-rw-r--r--src/libcoretest/intrinsics.rs31
-rw-r--r--src/libflate/lib.rs1
-rw-r--r--src/libfmt_macros/lib.rs1
-rw-r--r--src/libgetopts/lib.rs1
-rw-r--r--src/libgraphviz/lib.rs1
-rw-r--r--src/liblibc/lib.rs1
-rw-r--r--src/liblog/lib.rs1
-rw-r--r--src/librand/lib.rs1
-rw-r--r--src/librbml/lib.rs1
-rw-r--r--src/libregex/lib.rs1
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/lint/builtin.rs77
-rw-r--r--src/librustc/lint/context.rs46
-rw-r--r--src/librustc/lint/mod.rs5
-rw-r--r--src/librustc/metadata/csearch.rs13
-rw-r--r--src/librustc/metadata/decoder.rs5
-rw-r--r--src/librustc/metadata/encoder.rs9
-rw-r--r--src/librustc/metadata/filesearch.rs4
-rw-r--r--src/librustc/middle/stability.rs16
-rw-r--r--src/librustc/middle/traits/project.rs10
-rw-r--r--src/librustc/middle/ty.rs30
-rw-r--r--src/librustc/session/config.rs27
-rw-r--r--src/librustc/util/common.rs22
-rw-r--r--src/librustc/util/nodemap.rs46
-rw-r--r--src/librustc/util/ppaux.rs11
-rw-r--r--src/librustc_back/lib.rs1
-rw-r--r--src/librustc_back/svh.rs16
-rw-r--r--src/librustc_back/target/aarch64_unknown_linux_gnu.rs2
-rw-r--r--src/librustc_back/target/arm_apple_ios.rs2
-rw-r--r--src/librustc_back/target/arm_linux_androideabi.rs2
-rw-r--r--src/librustc_back/target/arm_unknown_linux_gnueabi.rs2
-rw-r--r--src/librustc_back/target/arm_unknown_linux_gnueabihf.rs2
-rw-r--r--src/librustc_back/target/i386_apple_ios.rs2
-rw-r--r--src/librustc_back/target/i686_apple_darwin.rs2
-rw-r--r--src/librustc_back/target/i686_pc_windows_gnu.rs2
-rw-r--r--src/librustc_back/target/i686_unknown_dragonfly.rs2
-rw-r--r--src/librustc_back/target/i686_unknown_linux_gnu.rs2
-rw-r--r--src/librustc_back/target/mips_unknown_linux_gnu.rs2
-rw-r--r--src/librustc_back/target/mipsel_unknown_linux_gnu.rs2
-rw-r--r--src/librustc_back/target/mod.rs6
-rw-r--r--src/librustc_back/target/x86_64_apple_darwin.rs2
-rw-r--r--src/librustc_back/target/x86_64_pc_windows_gnu.rs2
-rw-r--r--src/librustc_back/target/x86_64_unknown_dragonfly.rs2
-rw-r--r--src/librustc_back/target/x86_64_unknown_freebsd.rs2
-rw-r--r--src/librustc_back/target/x86_64_unknown_linux_gnu.rs2
-rw-r--r--src/librustc_borrowck/lib.rs1
-rw-r--r--src/librustc_driver/lib.rs22
-rw-r--r--src/librustc_llvm/lib.rs1
-rw-r--r--src/librustc_resolve/lib.rs8
-rw-r--r--src/librustc_trans/lib.rs1
-rw-r--r--src/librustc_trans/trans/base.rs4
-rw-r--r--src/librustc_trans/trans/context.rs2
-rw-r--r--src/librustc_trans/trans/intrinsic.rs2
-rw-r--r--src/librustc_trans/trans/machine.rs6
-rw-r--r--src/librustc_trans/trans/monomorphize.rs6
-rw-r--r--src/librustc_trans/trans/type_.rs2
-rw-r--r--src/librustc_typeck/check/wf.rs58
-rw-r--r--src/librustc_typeck/lib.rs1
-rw-r--r--src/librustdoc/core.rs4
-rw-r--r--src/librustdoc/html/static/main.css2
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/librustdoc/test.rs3
-rw-r--r--src/libserialize/collection_impls.rs60
-rw-r--r--src/libserialize/json.rs6
-rw-r--r--src/libserialize/lib.rs4
-rw-r--r--src/libstd/bitflags.rs6
-rw-r--r--src/libstd/collections/hash/map.rs206
-rw-r--r--src/libstd/collections/hash/mod.rs3
-rw-r--r--src/libstd/collections/hash/set.rs217
-rw-r--r--src/libstd/collections/hash/state.rs51
-rw-r--r--src/libstd/collections/hash/table.rs11
-rw-r--r--src/libstd/collections/mod.rs7
-rw-r--r--src/libstd/hash.rs105
-rw-r--r--src/libstd/io/process.rs8
-rw-r--r--src/libstd/lib.rs4
-rw-r--r--src/libstd/num/mod.rs42
-rw-r--r--src/libstd/path/posix.rs2
-rw-r--r--src/libstd/path/windows.rs2
-rw-r--r--src/libstd/rand/mod.rs4
-rw-r--r--src/libstd/sys/common/backtrace.rs7
-rw-r--r--src/libstd/sys/unix/c.rs4
-rw-r--r--src/libstd/sys/unix/process.rs9
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs6
-rw-r--r--src/libstd/sys/windows/process.rs9
-rw-r--r--src/libsyntax/codemap.rs7
-rw-r--r--src/libsyntax/ext/deriving/hash.rs3
-rw-r--r--src/libsyntax/lib.rs1
-rw-r--r--src/libsyntax/ptr.rs13
-rw-r--r--src/libsyntax/std_inject.rs21
-rw-r--r--src/libsyntax/util/interner.rs9
-rw-r--r--src/libterm/lib.rs1
-rw-r--r--src/libtest/lib.rs1
-rw-r--r--src/libtest/stats.rs4
-rw-r--r--src/libunicode/lib.rs1
-rw-r--r--src/test/bench/core-set.rs3
-rw-r--r--src/test/compile-fail/associated-types-multiple-types-one-trait.rs56
-rw-r--r--src/test/compile-fail/extern-with-type-bounds.rs33
-rw-r--r--src/test/compile-fail/feature-gate-feature-gate.rs14
-rw-r--r--src/test/compile-fail/feature-gated-feature-in-macro-arg.rs8
-rw-r--r--src/test/compile-fail/huge-enum.rs4
-rw-r--r--src/test/compile-fail/issue-17913.rs4
-rw-r--r--src/test/compile-fail/where-clauses-not-parameter.rs18
-rw-r--r--src/test/pretty/issue-4264.pp1
-rw-r--r--src/test/run-pass/deriving-hash.rs12
-rw-r--r--src/test/run-pass/deriving-meta-multiple.rs4
-rw-r--r--src/test/run-pass/deriving-meta.rs4
-rw-r--r--src/test/run-pass/drop-trait-enum.rs4
-rw-r--r--src/test/run-pass/extern-stress.rs2
-rw-r--r--src/test/run-pass/extern-yield.rs2
-rw-r--r--src/test/run-pass/huge-largest-array.rs4
-rw-r--r--src/test/run-pass/issue-9396.rs2
-rw-r--r--src/test/run-pass/simd-size-align.rs70
-rw-r--r--src/test/run-pass/tcp-accept-stress.rs16
-rw-r--r--src/test/run-pass/threads.rs2
-rw-r--r--src/test/run-pass/typeid-intrinsic.rs5
-rw-r--r--src/test/run-pass/unique-send-2.rs10
-rw-r--r--src/test/run-pass/unwind-resource.rs2
-rw-r--r--src/test/run-pass/vec-fixed-length.rs2
146 files changed, 1762 insertions, 1180 deletions
diff --git a/configure b/configure
index ea9320c901b..61c737e0fd3 100755
--- a/configure
+++ b/configure
@@ -599,6 +599,18 @@ then
 fi
 putvar CFG_RELEASE_CHANNEL
 
+# A magic value that allows the compiler to use unstable features
+# during the bootstrap even when doing so would normally be an error
+# because of feature staging or because the build turns on
+# warnings-as-errors and unstable features default to warnings.  The
+# build has to match this key in an env var. Meant to be a mild
+# deterrent from users just turning on unstable features on the stable
+# channel.
+# Basing CFG_BOOTSTRAP_KEY on CFG_BOOTSTRAP_KEY lets it get picked up
+# during a Makefile reconfig.
+CFG_BOOTSTRAP_KEY="${CFG_BOOTSTRAP_KEY-`date +%N`}"
+putvar CFG_BOOTSTRAP_KEY
+
 step_msg "looking for build programs"
 
 probe_need CFG_PERL        perl
diff --git a/mk/main.mk b/mk/main.mk
index a97e68af59b..e892286f7fd 100644
--- a/mk/main.mk
+++ b/mk/main.mk
@@ -25,11 +25,13 @@ ifeq ($(CFG_RELEASE_CHANNEL),stable)
 CFG_RELEASE=$(CFG_RELEASE_NUM)
 # This is the string used in dist artifact file names, e.g. "0.12.0", "nightly"
 CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)
+CFG_DISABLE_UNSTABLE_FEATURES=1
 endif
 ifeq ($(CFG_RELEASE_CHANNEL),beta)
 # The beta channel is temporarily called 'alpha'
 CFG_RELEASE=$(CFG_RELEASE_NUM)-alpha$(CFG_BETA_CYCLE)
 CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-alpha$(CFG_BETA_CYCLE)
+CFG_DISABLE_UNSTABLE_FEATURES=1
 endif
 ifeq ($(CFG_RELEASE_CHANNEL),nightly)
 CFG_RELEASE=$(CFG_RELEASE_NUM)-nightly
@@ -319,11 +321,20 @@ export CFG_VERSION_WIN
 export CFG_RELEASE
 export CFG_PACKAGE_NAME
 export CFG_BUILD
+export CFG_RELEASE_CHANNEL
 export CFG_LLVM_ROOT
 export CFG_PREFIX
 export CFG_LIBDIR
 export CFG_LIBDIR_RELATIVE
 export CFG_DISABLE_INJECT_STD_VERSION
+ifdef CFG_DISABLE_UNSTABLE_FEATURES
+CFG_INFO := $(info cfg: disabling unstable features (CFG_DISABLE_UNSTABLE_FEATURES))
+# Turn on feature-staging
+export CFG_DISABLE_UNSTABLE_FEATURES
+endif
+# Subvert unstable feature lints to do the self-build
+export CFG_BOOTSTRAP_KEY
+export RUSTC_BOOTSTRAP_KEY:=$(CFG_BOOTSTRAP_KEY)
 
 ######################################################################
 # Per-stage targets and runner
diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs
index e2420b0a220..ac8cf543a42 100644
--- a/src/compiletest/compiletest.rs
+++ b/src/compiletest/compiletest.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![crate_type = "bin"]
-#![feature(slicing_syntax, unboxed_closures)]
+#![feature(slicing_syntax)]
 
 #![deny(warnings)]
 
diff --git a/src/doc/footer.inc b/src/doc/footer.inc
index 4e7d60586f2..f32f2fd443f 100644
--- a/src/doc/footer.inc
+++ b/src/doc/footer.inc
@@ -1,5 +1,5 @@
 <footer><p>
-Copyright &copy; 2011-2014 The Rust Project Developers. Licensed under the
+Copyright &copy; 2011-2015 The Rust Project Developers. Licensed under the
 <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>
 or the <a href="http://opensource.org/licenses/MIT">MIT license</a>, at your option.
 </p><p>
diff --git a/src/doc/intro.md b/src/doc/intro.md
index fbc96a577a4..ffe33f41bc7 100644
--- a/src/doc/intro.md
+++ b/src/doc/intro.md
@@ -542,7 +542,7 @@ use std::thread::Thread;
 fn main() {
     let vec = vec![1i, 2, 3];
 
-    for i in range(1u, 3) {
+    for i in range(0u, 3) {
         Thread::spawn(move || {
             println!("{}", vec[i]);
         }).detach();
@@ -558,7 +558,7 @@ a vector:
 ```{rust}
 let vec = vec![1i, 2, 3];
 
-for i in range(1u, vec.len()) {
+for i in range(0u, vec.len()) {
      println!("{}", vec[i]);
 }
 ```
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index 5d47602b5e1..636d80e7451 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -67,21 +67,20 @@
 //! }
 //! ```
 
+use core::prelude::*;
+
 use core::atomic;
 use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst};
 use core::borrow::BorrowFrom;
-use core::clone::Clone;
 use core::fmt::{self, Show};
-use core::cmp::{Eq, Ord, PartialEq, PartialOrd, Ordering};
+use core::cmp::{Ordering};
 use core::default::Default;
-use core::marker::{Sync, Send};
-use core::mem::{min_align_of, size_of, drop};
+use core::mem::{min_align_of, size_of};
 use core::mem;
 use core::nonzero::NonZero;
-use core::ops::{Drop, Deref};
-use core::option::Option;
-use core::option::Option::{Some, None};
-use core::ptr::{self, PtrExt};
+use core::ops::Deref;
+use core::ptr;
+use core::hash::{Hash, Hasher};
 use heap::deallocate;
 
 /// An atomically reference counted wrapper for shared state.
@@ -591,6 +590,12 @@ impl<T: Default + Sync + Send> Default for Arc<T> {
     fn default() -> Arc<T> { Arc::new(Default::default()) }
 }
 
+impl<H: Hasher, T: Hash<H>> Hash<H> for Arc<T> {
+    fn hash(&self, state: &mut H) {
+        (**self).hash(state)
+    }
+}
+
 #[cfg(test)]
 #[allow(experimental)]
 mod tests {
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index d46f18abf97..adca8b9cc4c 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -106,12 +106,20 @@ impl<T: ?Sized + Ord> Ord for Box<T> {
 #[stable]}
 impl<T: ?Sized + Eq> Eq for Box<T> {}
 
+#[cfg(stage0)]
 impl<S: hash::Writer, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
     #[inline]
     fn hash(&self, state: &mut S) {
         (**self).hash(state);
     }
 }
+#[cfg(not(stage0))]
+impl<S: hash::Hasher, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        (**self).hash(state);
+    }
+}
 
 /// Extension methods for an owning `Any` trait object.
 #[unstable = "post-DST and coherence changes, this will not be a trait but \
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index c57435cdc8c..439bb6c55dc 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -115,16 +115,20 @@ unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) {
 // The minimum alignment guaranteed by the architecture. This value is used to
 // add fast paths for low alignment values. In practice, the alignment is a
 // constant at the call site and the branch will be optimized out.
-#[cfg(any(target_arch = "arm",
-          target_arch = "mips",
-          target_arch = "mipsel"))]
+#[cfg(all(not(feature = "external_funcs"),
+          not(feature = "external_crate"),
+          any(target_arch = "arm",
+              target_arch = "mips",
+              target_arch = "mipsel")))]
 const MIN_ALIGN: uint = 8;
-#[cfg(any(target_arch = "x86",
-          target_arch = "x86_64",
-          target_arch = "aarch64"))]
+#[cfg(all(not(feature = "external_funcs"),
+          not(feature = "external_crate"),
+          any(target_arch = "x86",
+              target_arch = "x86_64",
+              target_arch = "aarch64"))]
 const MIN_ALIGN: uint = 16;
 
-#[cfg(external_funcs)]
+#[cfg(feature = "external_funcs")]
 mod imp {
     extern {
         fn rust_allocate(size: uint, align: uint) -> *mut u8;
@@ -142,14 +146,13 @@ mod imp {
     }
 
     #[inline]
-    pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: uint, size: uint,
-                                     align: uint) -> uint {
-        rust_reallocate_inplace(ptr, old_size, size, align)
+    pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
+        rust_deallocate(ptr, old_size, align)
     }
 
     #[inline]
-    pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) {
-        rust_deallocate(ptr, old_size, align)
+    pub unsafe fn reallocate(ptr: *mut u8, old_size: uint, size: uint, align: uint) -> *mut u8 {
+        rust_reallocate(ptr, old_size, size, align)
     }
 
     #[inline]
@@ -169,14 +172,16 @@ mod imp {
     }
 }
 
-#[cfg(external_crate)]
+#[cfg(feature = "external_crate")]
 mod imp {
     extern crate external;
     pub use self::external::{allocate, deallocate, reallocate_inplace, reallocate};
     pub use self::external::{usable_size, stats_print};
 }
 
-#[cfg(all(not(external_funcs), not(external_crate), jemalloc))]
+#[cfg(all(not(feature = "external_funcs"),
+          not(feature = "external_crate"),
+          jemalloc))]
 mod imp {
     use core::option::Option;
     use core::option::Option::None;
@@ -253,7 +258,10 @@ mod imp {
     }
 }
 
-#[cfg(all(not(external_funcs), not(external_crate), not(jemalloc), unix))]
+#[cfg(all(not(feature = "external_funcs"),
+          not(feature = "external_crate"),
+          not(jemalloc),
+          unix))]
 mod imp {
     use core::cmp;
     use core::ptr;
@@ -314,7 +322,10 @@ mod imp {
     pub fn stats_print() {}
 }
 
-#[cfg(all(not(external_funcs), not(external_crate), not(jemalloc), windows))]
+#[cfg(all(not(feature = "external_funcs"),
+          not(feature = "external_crate"),
+          not(jemalloc),
+          windows))]
 mod imp {
     use libc::{c_void, size_t};
     use libc;
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index ba6e89cdd76..dc6037c3c0c 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -58,6 +58,7 @@
 
 #![crate_name = "alloc"]
 #![experimental]
+#![staged_api]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
@@ -69,6 +70,8 @@
 
 #[macro_use]
 extern crate core;
+
+#[cfg(all(not(feature = "external_funcs"), not(feature = "external_crate")))]
 extern crate libc;
 
 // Allow testing this library
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 67b25427710..83eff71e2b8 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -10,23 +10,26 @@
 
 //! Thread-local reference-counted boxes (the `Rc<T>` type).
 //!
-//! The `Rc<T>` type provides shared ownership of an immutable value. Destruction is deterministic,
-//! and will occur as soon as the last owner is gone. It is marked as non-sendable because it
-//! avoids the overhead of atomic reference counting.
+//! The `Rc<T>` type provides shared ownership of an immutable value.
+//! Destruction is deterministic, and will occur as soon as the last owner is
+//! gone. It is marked as non-sendable because it avoids the overhead of atomic
+//! reference counting.
 //!
-//! The `downgrade` method can be used to create a non-owning `Weak<T>` pointer to the box. A
-//! `Weak<T>` pointer can be upgraded to an `Rc<T>` pointer, but will return `None` if the value
-//! has already been dropped.
+//! The `downgrade` method can be used to create a non-owning `Weak<T>` pointer
+//! to the box. A `Weak<T>` pointer can be upgraded to an `Rc<T>` pointer, but
+//! will return `None` if the value has already been dropped.
 //!
-//! For example, a tree with parent pointers can be represented by putting the nodes behind strong
-//! `Rc<T>` pointers, and then storing the parent pointers as `Weak<T>` pointers.
+//! For example, a tree with parent pointers can be represented by putting the
+//! nodes behind strong `Rc<T>` pointers, and then storing the parent pointers
+//! as `Weak<T>` pointers.
 //!
 //! # Examples
 //!
-//! Consider a scenario where a set of `Gadget`s are owned by a given `Owner`.  We want to have our
-//! `Gadget`s point to their `Owner`. We can't do this with unique ownership, because more than one
-//! gadget may belong to the same `Owner`. `Rc<T>` allows us to share an `Owner` between multiple
-//! `Gadget`s, and have the `Owner` remain allocated as long as any `Gadget` points at it.
+//! Consider a scenario where a set of `Gadget`s are owned by a given `Owner`.
+//! We want to have our `Gadget`s point to their `Owner`. We can't do this with
+//! unique ownership, because more than one gadget may belong to the same
+//! `Owner`. `Rc<T>` allows us to share an `Owner` between multiple `Gadget`s,
+//! and have the `Owner` remain allocated as long as any `Gadget` points at it.
 //!
 //! ```rust
 //! use std::rc::Rc;
@@ -597,12 +600,20 @@ impl<T: Ord> Ord for Rc<T> {
 }
 
 // FIXME (#18248) Make `T` `Sized?`
+#[cfg(stage0)]
 impl<S: hash::Writer, T: Hash<S>> Hash<S> for Rc<T> {
     #[inline]
     fn hash(&self, state: &mut S) {
         (**self).hash(state);
     }
 }
+#[cfg(not(stage0))]
+impl<S: hash::Hasher, T: Hash<S>> Hash<S> for Rc<T> {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        (**self).hash(state);
+    }
+}
 
 #[experimental = "Show is experimental."]
 impl<T: fmt::Show> fmt::Show for Rc<T> {
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 423c16bfee8..79e43b9cc64 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -21,6 +21,7 @@
 
 #![crate_name = "arena"]
 #![experimental]
+#![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs
index 2154d06377a..f7277d4dfd8 100644
--- a/src/libcollections/bit.rs
+++ b/src/libcollections/bit.rs
@@ -982,7 +982,7 @@ impl fmt::Show for Bitv {
 }
 
 #[stable]
-impl<S: hash::Writer> hash::Hash<S> for Bitv {
+impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Bitv {
     fn hash(&self, state: &mut S) {
         self.nbits.hash(state);
         for elem in self.blocks() {
@@ -1742,7 +1742,7 @@ impl fmt::Show for BitvSet {
     }
 }
 
-impl<S: hash::Writer> hash::Hash<S> for BitvSet {
+impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for BitvSet {
     fn hash(&self, state: &mut S) {
         for pos in self.iter() {
             pos.hash(state);
diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs
index 4e44779810b..3e1533dd35f 100644
--- a/src/libcollections/btree/map.rs
+++ b/src/libcollections/btree/map.rs
@@ -23,7 +23,9 @@ use core::borrow::BorrowFrom;
 use core::cmp::Ordering;
 use core::default::Default;
 use core::fmt::Show;
-use core::hash::{Writer, Hash};
+use core::hash::{Hash, Hasher};
+#[cfg(stage0)]
+use core::hash::Writer;
 use core::iter::{Map, FromIterator};
 use core::ops::{Index, IndexMut};
 use core::{iter, fmt, mem};
@@ -820,6 +822,7 @@ impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
 }
 
 #[stable]
+#[cfg(stage0)]
 impl<S: Writer, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
     fn hash(&self, state: &mut S) {
         for elt in self.iter() {
@@ -827,6 +830,15 @@ impl<S: Writer, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
         }
     }
 }
+#[stable]
+#[cfg(not(stage0))]
+impl<S: Hasher, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
+    fn hash(&self, state: &mut S) {
+        for elt in self.iter() {
+            elt.hash(state);
+        }
+    }
+}
 
 #[stable]
 impl<K: Ord, V> Default for BTreeMap<K, V> {
diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs
index 25df4a3cc2a..812cff6fab7 100644
--- a/src/libcollections/btree/set.rs
+++ b/src/libcollections/btree/set.rs
@@ -678,7 +678,7 @@ mod test {
     use prelude::*;
 
     use super::BTreeSet;
-    use std::hash;
+    use std::hash::{self, SipHasher};
 
     #[test]
     fn test_clone_eq() {
@@ -703,7 +703,7 @@ mod test {
       y.insert(2);
       y.insert(1);
 
-      assert!(hash::hash(&x) == hash::hash(&y));
+      assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y));
     }
 
     struct Counter<'a, 'b> {
diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs
index 63ea9f7cb43..0b426f6016c 100644
--- a/src/libcollections/dlist.rs
+++ b/src/libcollections/dlist.rs
@@ -27,7 +27,7 @@ use alloc::boxed::Box;
 use core::cmp::Ordering;
 use core::default::Default;
 use core::fmt;
-use core::hash::{Writer, Hash};
+use core::hash::{Writer, Hasher, Hash};
 use core::iter::{self, FromIterator};
 use core::mem;
 use core::ptr;
@@ -675,7 +675,7 @@ impl<A: fmt::Show> fmt::Show for DList<A> {
 }
 
 #[stable]
-impl<S: Writer, A: Hash<S>> Hash<S> for DList<A> {
+impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for DList<A> {
     fn hash(&self, state: &mut S) {
         self.len().hash(state);
         for elt in self.iter() {
@@ -688,7 +688,7 @@ impl<S: Writer, A: Hash<S>> Hash<S> for DList<A> {
 mod tests {
     use prelude::*;
     use std::rand;
-    use std::hash;
+    use std::hash::{self, SipHasher};
     use std::thread::Thread;
     use test::Bencher;
     use test;
@@ -951,7 +951,7 @@ mod tests {
       let mut x = DList::new();
       let mut y = DList::new();
 
-      assert!(hash::hash(&x) == hash::hash(&y));
+      assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y));
 
       x.push_back(1i);
       x.push_back(2);
@@ -961,7 +961,7 @@ mod tests {
       y.push_front(2);
       y.push_front(1);
 
-      assert!(hash::hash(&x) == hash::hash(&y));
+      assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y));
     }
 
     #[test]
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index e7f48c291c9..a3adc09b581 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -15,6 +15,7 @@
 
 #![crate_name = "collections"]
 #![experimental]
+#![staged_api]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
@@ -23,8 +24,8 @@
 
 #![allow(unknown_features)]
 #![feature(unsafe_destructor, slicing_syntax)]
-#![feature(old_impl_check)]
 #![feature(unboxed_closures)]
+#![feature(old_impl_check)]
 #![no_std]
 
 #[macro_use]
diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs
index 42c17136a08..a35482aa5d3 100644
--- a/src/libcollections/ring_buf.rs
+++ b/src/libcollections/ring_buf.rs
@@ -27,7 +27,7 @@ use core::ops::{Index, IndexMut};
 use core::ptr;
 use core::raw::Slice as RawSlice;
 
-use std::hash::{Writer, Hash};
+use std::hash::{Writer, Hash, Hasher};
 use std::cmp;
 
 use alloc::heap;
@@ -1562,7 +1562,7 @@ impl<A: Ord> Ord for RingBuf<A> {
 }
 
 #[stable]
-impl<S: Writer, A: Hash<S>> Hash<S> for RingBuf<A> {
+impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for RingBuf<A> {
     fn hash(&self, state: &mut S) {
         self.len().hash(state);
         for elt in self.iter() {
@@ -1631,7 +1631,7 @@ mod tests {
     use prelude::*;
     use core::iter;
     use std::fmt::Show;
-    use std::hash;
+    use std::hash::{self, SipHasher};
     use test::Bencher;
     use test;
 
@@ -2283,7 +2283,7 @@ mod tests {
       y.push_back(2);
       y.push_back(3);
 
-      assert!(hash::hash(&x) == hash::hash(&y));
+      assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y));
     }
 
     #[test]
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index 507703c3a90..2d8fd159159 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -820,12 +820,21 @@ impl fmt::Show for String {
 }
 
 #[experimental = "waiting on Hash stabilization"]
+#[cfg(stage0)]
 impl<H: hash::Writer> hash::Hash<H> for String {
     #[inline]
     fn hash(&self, hasher: &mut H) {
         (**self).hash(hasher)
     }
 }
+#[experimental = "waiting on Hash stabilization"]
+#[cfg(not(stage0))]
+impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for String {
+    #[inline]
+    fn hash(&self, hasher: &mut H) {
+        (**self).hash(hasher)
+    }
+}
 
 #[unstable = "recent addition, needs more experience"]
 impl<'a> Add<&'a str> for String {
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 312d739e3a4..c2de5d24025 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -1183,12 +1183,20 @@ impl<T:Clone> Clone for Vec<T> {
     }
 }
 
+#[cfg(stage0)]
 impl<S: hash::Writer, T: Hash<S>> Hash<S> for Vec<T> {
     #[inline]
     fn hash(&self, state: &mut S) {
         self.as_slice().hash(state);
     }
 }
+#[cfg(not(stage0))]
+impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for Vec<T> {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        self.as_slice().hash(state);
+    }
+}
 
 #[experimental = "waiting on Index stability"]
 impl<T> Index<uint> for Vec<T> {
diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs
index 4399a6fec22..d4ce266d3e2 100644
--- a/src/libcollections/vec_map.rs
+++ b/src/libcollections/vec_map.rs
@@ -18,7 +18,7 @@ use core::prelude::*;
 use core::cmp::Ordering;
 use core::default::Default;
 use core::fmt;
-use core::hash::{Hash, Writer};
+use core::hash::{Hash, Writer, Hasher};
 use core::iter::{Enumerate, FilterMap, Map, FromIterator};
 use core::iter;
 use core::mem::replace;
@@ -85,7 +85,7 @@ impl<V:Clone> Clone for VecMap<V> {
     }
 }
 
-impl<S: Writer, V: Hash<S>> Hash<S> for VecMap<V> {
+impl<S: Writer + Hasher, V: Hash<S>> Hash<S> for VecMap<V> {
     fn hash(&self, state: &mut S) {
         // In order to not traverse the `VecMap` twice, count the elements
         // during iteration.
@@ -712,7 +712,7 @@ impl<V> DoubleEndedIterator for IntoIter<V> {
 #[cfg(test)]
 mod test_map {
     use prelude::*;
-    use core::hash::hash;
+    use core::hash::{hash, SipHasher};
 
     use super::VecMap;
 
@@ -1004,7 +1004,7 @@ mod test_map {
         let mut x = VecMap::new();
         let mut y = VecMap::new();
 
-        assert!(hash(&x) == hash(&y));
+        assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y));
         x.insert(1, 'a');
         x.insert(2, 'b');
         x.insert(3, 'c');
@@ -1013,12 +1013,12 @@ mod test_map {
         y.insert(2, 'b');
         y.insert(1, 'a');
 
-        assert!(hash(&x) == hash(&y));
+        assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y));
 
         x.insert(1000, 'd');
         x.remove(&1000);
 
-        assert!(hash(&x) == hash(&y));
+        assert!(hash::<_, SipHasher>(&x) == hash::<_, SipHasher>(&y));
     }
 
     #[test]
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index d8b9cf9594d..a82ea009e13 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -16,8 +16,7 @@
 //! # Examples
 //!
 //! ```rust
-//! use std::hash;
-//! use std::hash::Hash;
+//! use std::hash::{hash, Hash, SipHasher};
 //!
 //! #[derive(Hash)]
 //! struct Person {
@@ -29,16 +28,14 @@
 //! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
 //! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
 //!
-//! assert!(hash::hash(&person1) != hash::hash(&person2));
+//! assert!(hash::<_, SipHasher>(&person1) != hash::<_, SipHasher>(&person2));
 //! ```
 //!
 //! If you need more control over how a value is hashed, you need to implement
 //! the trait `Hash`:
 //!
 //! ```rust
-//! use std::hash;
-//! use std::hash::Hash;
-//! use std::hash::sip::SipState;
+//! use std::hash::{hash, Hash, Hasher, Writer, SipHasher};
 //!
 //! struct Person {
 //!     id: uint,
@@ -46,8 +43,8 @@
 //!     phone: u64,
 //! }
 //!
-//! impl Hash for Person {
-//!     fn hash(&self, state: &mut SipState) {
+//! impl<H: Hasher + Writer> Hash<H> for Person {
+//!     fn hash(&self, state: &mut H) {
 //!         self.id.hash(state);
 //!         self.phone.hash(state);
 //!     }
@@ -56,186 +53,382 @@
 //! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
 //! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
 //!
-//! assert!(hash::hash(&person1) == hash::hash(&person2));
+//! assert_eq!(hash::<_, SipHasher>(&person1), hash::<_, SipHasher>(&person2));
 //! ```
 
-#![allow(unused_must_use)]
+#![unstable = "module was recently redesigned"]
 
-use prelude::*;
+use default::Default;
 
-use borrow::{Cow, ToOwned};
-use intrinsics::TypeId;
-use mem;
-use num::Int;
+pub use self::sip::SipHasher;
 
-/// Reexport the `sip::hash` function as our default hasher.
-pub use self::sip::hash as hash;
+mod sip;
 
-pub mod sip;
+/// A hashable type.
+///
+/// The `H` type parameter is an abstract hash state that is used by the `Hash`
+/// to compute the hash. Specific implementations of this trait may specialize
+/// for particular instances of `H` in order to be able to optimize the hashing
+/// behavior.
+#[cfg(stage0)]
+pub trait Hash<H> {
+    /// Feeds this value into the state given, updating the hasher as necessary.
+    fn hash(&self, state: &mut H);
+}
 
-/// A hashable type. The `S` type parameter is an abstract hash state that is
-/// used by the `Hash` to compute the hash. It defaults to
-/// `std::hash::sip::SipState`.
-pub trait Hash<S = sip::SipState> {
-    /// Computes the hash of a value.
-    fn hash(&self, state: &mut S);
+/// A hashable type.
+///
+/// The `H` type parameter is an abstract hash state that is used by the `Hash`
+/// to compute the hash. Specific implementations of this trait may specialize
+/// for particular instances of `H` in order to be able to optimize the hashing
+/// behavior.
+#[cfg(not(stage0))]
+pub trait Hash<H: Hasher> {
+    /// Feeds this value into the state given, updating the hasher as necessary.
+    fn hash(&self, state: &mut H);
 }
 
-/// A trait that computes a hash for a value. The main users of this trait are
-/// containers like `HashMap`, which need a generic way hash multiple types.
-pub trait Hasher<S> {
-    /// Compute the hash of a value.
-    fn hash<T: ?Sized + Hash<S>>(&self, value: &T) -> u64;
+/// A trait which represents the ability to hash an arbitrary stream of bytes.
+pub trait Hasher {
+    /// Result type of one run of hashing generated by this hasher.
+    type Output;
+
+    /// Resets this hasher back to its initial state (as if it were just
+    /// created).
+    fn reset(&mut self);
+
+    /// Completes a round of hashing, producing the output hash generated.
+    fn finish(&self) -> Self::Output;
 }
 
+/// A common bound on the `Hasher` parameter to `Hash` implementations in order
+/// to generically hash an aggregate.
+#[experimental = "this trait will likely be replaced by io::Writer"]
 #[allow(missing_docs)]
 pub trait Writer {
     fn write(&mut self, bytes: &[u8]);
 }
 
+/// Hash a value with the default SipHasher algorithm (two initial keys of 0).
+///
+/// The specified value will be hashed with this hasher and then the resulting
+/// hash will be returned.
+pub fn hash<T: Hash<H>, H: Hasher + Default>(value: &T) -> H::Output {
+    let mut h: H = Default::default();
+    value.hash(&mut h);
+    h.finish()
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
-macro_rules! impl_hash {
-    ($ty:ident, $uty:ident) => {
-        impl<S: Writer> Hash<S> for $ty {
-            #[inline]
-            fn hash(&self, state: &mut S) {
-                let a: [u8; ::$ty::BYTES] = unsafe {
-                    mem::transmute((*self as $uty).to_le() as $ty)
-                };
-                state.write(a.as_slice())
+#[cfg(stage0)]
+mod impls {
+    use prelude::*;
+
+    use borrow::{Cow, ToOwned};
+    use intrinsics::TypeId;
+    use mem;
+    use super::{Hash, Writer};
+    use num::Int;
+
+    macro_rules! impl_hash {
+        ($ty:ident, $uty:ident) => {
+            impl<S: Writer> Hash<S> for $ty {
+                #[inline]
+                fn hash(&self, state: &mut S) {
+                    let a: [u8; ::$ty::BYTES] = unsafe {
+                        mem::transmute((*self as $uty).to_le() as $ty)
+                    };
+                    state.write(a.as_slice())
+                }
             }
         }
     }
-}
 
-impl_hash! { u8, u8 }
-impl_hash! { u16, u16 }
-impl_hash! { u32, u32 }
-impl_hash! { u64, u64 }
-impl_hash! { uint, uint }
-impl_hash! { i8, u8 }
-impl_hash! { i16, u16 }
-impl_hash! { i32, u32 }
-impl_hash! { i64, u64 }
-impl_hash! { int, uint }
-
-impl<S: Writer> Hash<S> for bool {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        (*self as u8).hash(state);
+    impl_hash! { u8, u8 }
+    impl_hash! { u16, u16 }
+    impl_hash! { u32, u32 }
+    impl_hash! { u64, u64 }
+    impl_hash! { uint, uint }
+    impl_hash! { i8, u8 }
+    impl_hash! { i16, u16 }
+    impl_hash! { i32, u32 }
+    impl_hash! { i64, u64 }
+    impl_hash! { int, uint }
+
+    impl<S: Writer> Hash<S> for bool {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            (*self as u8).hash(state);
+        }
     }
-}
 
-impl<S: Writer> Hash<S> for char {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        (*self as u32).hash(state);
+    impl<S: Writer> Hash<S> for char {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            (*self as u32).hash(state);
+        }
     }
-}
 
-impl<S: Writer> Hash<S> for str {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        state.write(self.as_bytes());
-        0xffu8.hash(state)
+    impl<S: Writer> Hash<S> for str {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            state.write(self.as_bytes());
+            0xffu8.hash(state)
+        }
     }
-}
 
-macro_rules! impl_hash_tuple {
-    () => (
-        impl<S: Writer> Hash<S> for () {
-            #[inline]
-            fn hash(&self, state: &mut S) {
-                state.write(&[]);
+    macro_rules! impl_hash_tuple {
+        () => (
+            impl<S> Hash<S> for () {
+                #[inline]
+                fn hash(&self, _state: &mut S) {}
             }
-        }
-    );
-
-    ( $($name:ident)+) => (
-        impl<S: Writer, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
-            #[inline]
-            #[allow(non_snake_case)]
-            fn hash(&self, state: &mut S) {
-                match *self {
-                    ($(ref $name,)*) => {
-                        $(
-                            $name.hash(state);
-                        )*
+        );
+
+        ( $($name:ident)+) => (
+            impl<S, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
+                #[inline]
+                #[allow(non_snake_case)]
+                fn hash(&self, state: &mut S) {
+                    match *self {
+                        ($(ref $name,)*) => {
+                            $(
+                                $name.hash(state);
+                            )*
+                        }
                     }
                 }
             }
+        );
+    }
+
+    impl_hash_tuple! {}
+    impl_hash_tuple! { A }
+    impl_hash_tuple! { A B }
+    impl_hash_tuple! { A B C }
+    impl_hash_tuple! { A B C D }
+    impl_hash_tuple! { A B C D E }
+    impl_hash_tuple! { A B C D E F }
+    impl_hash_tuple! { A B C D E F G }
+    impl_hash_tuple! { A B C D E F G H }
+    impl_hash_tuple! { A B C D E F G H I }
+    impl_hash_tuple! { A B C D E F G H I J }
+    impl_hash_tuple! { A B C D E F G H I J K }
+    impl_hash_tuple! { A B C D E F G H I J K L }
+
+    impl<S: Writer, T: Hash<S>> Hash<S> for [T] {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            self.len().hash(state);
+            for elt in self.iter() {
+                elt.hash(state);
+            }
         }
-    );
-}
+    }
+
 
-impl_hash_tuple! {}
-impl_hash_tuple! { A }
-impl_hash_tuple! { A B }
-impl_hash_tuple! { A B C }
-impl_hash_tuple! { A B C D }
-impl_hash_tuple! { A B C D E }
-impl_hash_tuple! { A B C D E F }
-impl_hash_tuple! { A B C D E F G }
-impl_hash_tuple! { A B C D E F G H }
-impl_hash_tuple! { A B C D E F G H I }
-impl_hash_tuple! { A B C D E F G H I J }
-impl_hash_tuple! { A B C D E F G H I J K }
-impl_hash_tuple! { A B C D E F G H I J K L }
-
-impl<S: Writer, T: Hash<S>> Hash<S> for [T] {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.len().hash(state);
-        for elt in self.iter() {
-            elt.hash(state);
+    impl<'a, S, T: ?Sized + Hash<S>> Hash<S> for &'a T {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            (**self).hash(state);
         }
     }
-}
 
+    impl<'a, S, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            (**self).hash(state);
+        }
+    }
 
-impl<'a, S: Writer, T: ?Sized + Hash<S>> Hash<S> for &'a T {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        (**self).hash(state);
+    impl<S: Writer, T> Hash<S> for *const T {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            // NB: raw-pointer Hash does _not_ dereference
+            // to the target; it just gives you the pointer-bytes.
+            (*self as uint).hash(state);
+        }
     }
-}
 
-impl<'a, S: Writer, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        (**self).hash(state);
+    impl<S: Writer, T> Hash<S> for *mut T {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            // NB: raw-pointer Hash does _not_ dereference
+            // to the target; it just gives you the pointer-bytes.
+            (*self as uint).hash(state);
+        }
     }
-}
 
-impl<S: Writer, T> Hash<S> for *const T {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        // NB: raw-pointer Hash does _not_ dereference
-        // to the target; it just gives you the pointer-bytes.
-        (*self as uint).hash(state);
+    impl<S: Writer> Hash<S> for TypeId {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            self.hash().hash(state)
+        }
     }
-}
 
-impl<S: Writer, T> Hash<S> for *mut T {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        // NB: raw-pointer Hash does _not_ dereference
-        // to the target; it just gives you the pointer-bytes.
-        (*self as uint).hash(state);
+    impl<'a, T, B: ?Sized, S> Hash<S> for Cow<'a, T, B>
+        where B: Hash<S> + ToOwned<T>
+    {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            Hash::hash(&**self, state)
+        }
     }
 }
 
-impl<S: Writer> Hash<S> for TypeId {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.hash().hash(state)
+#[cfg(not(stage0))]
+mod impls {
+    use prelude::*;
+
+    use borrow::{Cow, ToOwned};
+    use intrinsics::TypeId;
+    use mem;
+    use super::{Hash, Writer, Hasher};
+    use num::Int;
+
+    macro_rules! impl_hash {
+        ($ty:ident, $uty:ident) => {
+            impl<S: Writer + Hasher> Hash<S> for $ty {
+                #[inline]
+                fn hash(&self, state: &mut S) {
+                    let a: [u8; ::$ty::BYTES] = unsafe {
+                        mem::transmute((*self as $uty).to_le() as $ty)
+                    };
+                    state.write(a.as_slice())
+                }
+            }
+        }
+    }
+
+    impl_hash! { u8, u8 }
+    impl_hash! { u16, u16 }
+    impl_hash! { u32, u32 }
+    impl_hash! { u64, u64 }
+    impl_hash! { uint, uint }
+    impl_hash! { i8, u8 }
+    impl_hash! { i16, u16 }
+    impl_hash! { i32, u32 }
+    impl_hash! { i64, u64 }
+    impl_hash! { int, uint }
+
+    impl<S: Writer + Hasher> Hash<S> for bool {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            (*self as u8).hash(state);
+        }
+    }
+
+    impl<S: Writer + Hasher> Hash<S> for char {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            (*self as u32).hash(state);
+        }
+    }
+
+    impl<S: Writer + Hasher> Hash<S> for str {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            state.write(self.as_bytes());
+            0xffu8.hash(state)
+        }
+    }
+
+    macro_rules! impl_hash_tuple {
+        () => (
+            impl<S: Hasher> Hash<S> for () {
+                #[inline]
+                fn hash(&self, _state: &mut S) {}
+            }
+        );
+
+        ( $($name:ident)+) => (
+            impl<S: Hasher, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
+                #[inline]
+                #[allow(non_snake_case)]
+                fn hash(&self, state: &mut S) {
+                    match *self {
+                        ($(ref $name,)*) => {
+                            $(
+                                $name.hash(state);
+                            )*
+                        }
+                    }
+                }
+            }
+        );
+    }
+
+    impl_hash_tuple! {}
+    impl_hash_tuple! { A }
+    impl_hash_tuple! { A B }
+    impl_hash_tuple! { A B C }
+    impl_hash_tuple! { A B C D }
+    impl_hash_tuple! { A B C D E }
+    impl_hash_tuple! { A B C D E F }
+    impl_hash_tuple! { A B C D E F G }
+    impl_hash_tuple! { A B C D E F G H }
+    impl_hash_tuple! { A B C D E F G H I }
+    impl_hash_tuple! { A B C D E F G H I J }
+    impl_hash_tuple! { A B C D E F G H I J K }
+    impl_hash_tuple! { A B C D E F G H I J K L }
+
+    impl<S: Writer + Hasher, T: Hash<S>> Hash<S> for [T] {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            self.len().hash(state);
+            for elt in self.iter() {
+                elt.hash(state);
+            }
+        }
+    }
+
+
+    impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a T {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            (**self).hash(state);
+        }
+    }
+
+    impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            (**self).hash(state);
+        }
     }
-}
 
-impl<'a, T, B: ?Sized, S> Hash<S> for Cow<'a, T, B> where B: Hash<S> + ToOwned<T> {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        Hash::hash(&**self, state)
+    impl<S: Writer + Hasher, T> Hash<S> for *const T {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            // NB: raw-pointer Hash does _not_ dereference
+            // to the target; it just gives you the pointer-bytes.
+            (*self as uint).hash(state);
+        }
+    }
+
+    impl<S: Writer + Hasher, T> Hash<S> for *mut T {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            // NB: raw-pointer Hash does _not_ dereference
+            // to the target; it just gives you the pointer-bytes.
+            (*self as uint).hash(state);
+        }
+    }
+
+    impl<S: Writer + Hasher> Hash<S> for TypeId {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            self.hash().hash(state)
+        }
+    }
+
+    impl<'a, T, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, T, B>
+        where B: Hash<S> + ToOwned<T>
+    {
+        #[inline]
+        fn hash(&self, state: &mut S) {
+            Hash::hash(&**self, state)
+        }
     }
 }
diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs
index c4d45e9c2c8..c20fb8457d2 100644
--- a/src/libcore/hash/sip.rs
+++ b/src/libcore/hash/sip.rs
@@ -11,27 +11,27 @@
 // ignore-lexer-test FIXME #15883
 
 //! An implementation of SipHash 2-4.
-//!
-//! See: http://131002.net/siphash/
-//!
-//! Consider this as a main "general-purpose" hash for all hashtables: it
-//! runs at good speed (competitive with spooky and city) and permits
-//! strong _keyed_ hashing. Key your hashtables from a strong RNG,
-//! such as `rand::Rng`.
-//!
-//! Although the SipHash algorithm is considered to be cryptographically
-//! strong, this implementation has not been reviewed for such purposes.
-//! As such, all cryptographic uses of this implementation are strongly
-//! discouraged.
 
 use prelude::*;
 use default::Default;
 
-use super::{Hash, Hasher, Writer};
-
-/// `SipState` computes a SipHash 2-4 hash over a stream of bytes.
-#[derive(Copy)]
-pub struct SipState {
+use super::{Hasher, Writer};
+
+/// An implementation of SipHash 2-4.
+///
+/// See: http://131002.net/siphash/
+///
+/// Consider this as a main "general-purpose" hash for all hashtables: it
+/// runs at good speed (competitive with spooky and city) and permits
+/// strong _keyed_ hashing. Key your hashtables from a strong RNG,
+/// such as `rand::Rng`.
+///
+/// Although the SipHash algorithm is considered to be cryptographically
+/// strong, this implementation has not been reviewed for such purposes.
+/// As such, all cryptographic uses of this implementation are strongly
+/// discouraged.
+#[allow(missing_copy_implementations)]
+pub struct SipHasher {
     k0: u64,
     k1: u64,
     length: uint, // how many bytes we've processed
@@ -86,17 +86,17 @@ macro_rules! compress {
     })
 }
 
-impl SipState {
-    /// Creates a `SipState` that is keyed off the provided keys.
+impl SipHasher {
+    /// Creates a new `SipHasher` with the two initial keys set to 0.
     #[inline]
-    pub fn new() -> SipState {
-        SipState::new_with_keys(0, 0)
+    pub fn new() -> SipHasher {
+        SipHasher::new_with_keys(0, 0)
     }
 
-    /// Creates a `SipState` that is keyed off the provided keys.
+    /// Creates a `SipHasher` that is keyed off the provided keys.
     #[inline]
-    pub fn new_with_keys(key0: u64, key1: u64) -> SipState {
-        let mut state = SipState {
+    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
+        let mut state = SipHasher {
             k0: key0,
             k1: key1,
             length: 0,
@@ -111,43 +111,12 @@ impl SipState {
         state
     }
 
-    /// Resets the state to its initial state.
-    #[inline]
-    pub fn reset(&mut self) {
-        self.length = 0;
-        self.v0 = self.k0 ^ 0x736f6d6570736575;
-        self.v1 = self.k1 ^ 0x646f72616e646f6d;
-        self.v2 = self.k0 ^ 0x6c7967656e657261;
-        self.v3 = self.k1 ^ 0x7465646279746573;
-        self.ntail = 0;
-    }
-
     /// Returns the computed hash.
-    #[inline]
-    pub fn result(&self) -> u64 {
-        let mut v0 = self.v0;
-        let mut v1 = self.v1;
-        let mut v2 = self.v2;
-        let mut v3 = self.v3;
-
-        let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;
-
-        v3 ^= b;
-        compress!(v0, v1, v2, v3);
-        compress!(v0, v1, v2, v3);
-        v0 ^= b;
-
-        v2 ^= 0xff;
-        compress!(v0, v1, v2, v3);
-        compress!(v0, v1, v2, v3);
-        compress!(v0, v1, v2, v3);
-        compress!(v0, v1, v2, v3);
-
-        v0 ^ v1 ^ v2 ^ v3
-    }
+    #[deprecated = "renamed to finish"]
+    pub fn result(&self) -> u64 { self.finish() }
 }
 
-impl Writer for SipState {
+impl Writer for SipHasher {
     #[inline]
     fn write(&mut self, msg: &[u8]) {
         let length = msg.len();
@@ -195,355 +164,60 @@ impl Writer for SipState {
     }
 }
 
-#[stable]
-impl Clone for SipState {
-    #[inline]
-    fn clone(&self) -> SipState {
-        *self
-    }
-}
+impl Hasher for SipHasher {
+    type Output = u64;
 
-#[stable]
-impl Default for SipState {
-    #[inline]
-    #[stable]
-    fn default() -> SipState {
-        SipState::new()
+    fn reset(&mut self) {
+        self.length = 0;
+        self.v0 = self.k0 ^ 0x736f6d6570736575;
+        self.v1 = self.k1 ^ 0x646f72616e646f6d;
+        self.v2 = self.k0 ^ 0x6c7967656e657261;
+        self.v3 = self.k1 ^ 0x7465646279746573;
+        self.ntail = 0;
     }
-}
 
-/// `SipHasher` computes the SipHash algorithm from a stream of bytes.
-#[derive(Clone)]
-#[allow(missing_copy_implementations)]
-pub struct SipHasher {
-    k0: u64,
-    k1: u64,
-}
+    fn finish(&self) -> u64 {
+        let mut v0 = self.v0;
+        let mut v1 = self.v1;
+        let mut v2 = self.v2;
+        let mut v3 = self.v3;
 
-impl SipHasher {
-    /// Creates a `Sip`.
-    #[inline]
-    pub fn new() -> SipHasher {
-        SipHasher::new_with_keys(0, 0)
-    }
+        let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;
 
-    /// Creates a `Sip` that is keyed off the provided keys.
-    #[inline]
-    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
-        SipHasher {
-            k0: key0,
-            k1: key1,
-        }
+        v3 ^= b;
+        compress!(v0, v1, v2, v3);
+        compress!(v0, v1, v2, v3);
+        v0 ^= b;
+
+        v2 ^= 0xff;
+        compress!(v0, v1, v2, v3);
+        compress!(v0, v1, v2, v3);
+        compress!(v0, v1, v2, v3);
+        compress!(v0, v1, v2, v3);
+
+        v0 ^ v1 ^ v2 ^ v3
     }
 }
 
-impl Hasher<SipState> for SipHasher {
+impl Clone for SipHasher {
     #[inline]
-    fn hash<T: ?Sized + Hash<SipState>>(&self, value: &T) -> u64 {
-        let mut state = SipState::new_with_keys(self.k0, self.k1);
-        value.hash(&mut state);
-        state.result()
+    fn clone(&self) -> SipHasher {
+        SipHasher {
+            k0: self.k0,
+            k1: self.k1,
+            length: self.length,
+            v0: self.v0,
+            v1: self.v1,
+            v2: self.v2,
+            v3: self.v3,
+            tail: self.tail,
+            ntail: self.ntail,
+        }
     }
 }
 
 impl Default for SipHasher {
-    #[inline]
     fn default() -> SipHasher {
         SipHasher::new()
     }
 }
-
-/// Hashes a value using the SipHash algorithm.
-#[inline]
-pub fn hash<T: ?Sized + Hash<SipState>>(value: &T) -> u64 {
-    let mut state = SipState::new();
-    value.hash(&mut state);
-    state.result()
-}
-
-/// Hashes a value with the SipHash algorithm with the provided keys.
-#[inline]
-pub fn hash_with_keys<T: ?Sized + Hash<SipState>>(k0: u64, k1: u64, value: &T) -> u64 {
-    let mut state = SipState::new_with_keys(k0, k1);
-    value.hash(&mut state);
-    state.result()
-}
-
-#[cfg(test)]
-mod tests {
-    use test::Bencher;
-    use prelude::*;
-    use std::fmt;
-
-    use super::super::{Hash, Writer};
-    use super::{SipState, hash, hash_with_keys};
-
-    // Hash just the bytes of the slice, without length prefix
-    struct Bytes<'a>(&'a [u8]);
-
-    impl<'a, S: Writer> Hash<S> for Bytes<'a> {
-        #[allow(unused_must_use)]
-        fn hash(&self, state: &mut S) {
-            let Bytes(v) = *self;
-            state.write(v);
-        }
-    }
-
-    #[test]
-    #[allow(unused_must_use)]
-    fn test_siphash() {
-        let vecs : [[u8; 8]; 64] = [
-            [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ],
-            [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ],
-            [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ],
-            [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ],
-            [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ],
-            [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ],
-            [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ],
-            [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ],
-            [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ],
-            [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ],
-            [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ],
-            [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ],
-            [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ],
-            [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ],
-            [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ],
-            [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ],
-            [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ],
-            [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ],
-            [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ],
-            [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ],
-            [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ],
-            [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ],
-            [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ],
-            [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ],
-            [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ],
-            [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ],
-            [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ],
-            [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ],
-            [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ],
-            [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ],
-            [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ],
-            [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ],
-            [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ],
-            [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ],
-            [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ],
-            [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ],
-            [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ],
-            [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ],
-            [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ],
-            [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ],
-            [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ],
-            [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ],
-            [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ],
-            [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ],
-            [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ],
-            [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ],
-            [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ],
-            [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ],
-            [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ],
-            [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ],
-            [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ],
-            [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ],
-            [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ],
-            [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ],
-            [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ],
-            [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ],
-            [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ],
-            [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ],
-            [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ],
-            [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ],
-            [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ],
-            [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ],
-            [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ],
-            [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ]
-        ];
-
-        let k0 = 0x_07_06_05_04_03_02_01_00_u64;
-        let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64;
-        let mut buf = Vec::new();
-        let mut t = 0;
-        let mut state_inc = SipState::new_with_keys(k0, k1);
-        let mut state_full = SipState::new_with_keys(k0, k1);
-
-        fn to_hex_str(r: &[u8; 8]) -> String {
-            let mut s = String::new();
-            for b in r.iter() {
-                s.push_str(format!("{}", fmt::radix(*b, 16)).as_slice());
-            }
-            s
-        }
-
-        fn result_bytes(h: u64) -> Vec<u8> {
-            vec![(h >> 0) as u8,
-              (h >> 8) as u8,
-              (h >> 16) as u8,
-              (h >> 24) as u8,
-              (h >> 32) as u8,
-              (h >> 40) as u8,
-              (h >> 48) as u8,
-              (h >> 56) as u8,
-            ]
-        }
-
-        fn result_str(h: u64) -> String {
-            let r = result_bytes(h);
-            let mut s = String::new();
-            for b in r.iter() {
-                s.push_str(format!("{}", fmt::radix(*b, 16)).as_slice());
-            }
-            s
-        }
-
-        while t < 64 {
-            debug!("siphash test {}: {}", t, buf);
-            let vec = u8to64_le!(vecs[t], 0);
-            let out = hash_with_keys(k0, k1, &Bytes(buf.as_slice()));
-            debug!("got {}, expected {}", out, vec);
-            assert_eq!(vec, out);
-
-            state_full.reset();
-            state_full.write(buf.as_slice());
-            let f = result_str(state_full.result());
-            let i = result_str(state_inc.result());
-            let v = to_hex_str(&vecs[t]);
-            debug!("{}: ({}) => inc={} full={}", t, v, i, f);
-
-            assert_eq!(f, i);
-            assert_eq!(f, v);
-
-            buf.push(t as u8);
-            state_inc.write(&[t as u8]);
-
-            t += 1;
-        }
-    }
-
-    #[test] #[cfg(target_arch = "aarch64")]
-    fn test_hash_uint() {
-        let val = 0xdeadbeef_deadbeef_u64;
-        assert_eq!(hash(&(val as u64)), hash(&(val as uint)));
-        assert!(hash(&(val as u32)) != hash(&(val as uint)));
-    }
-    #[test] #[cfg(target_arch = "arm")]
-    fn test_hash_uint() {
-        let val = 0xdeadbeef_deadbeef_u64;
-        assert!(hash(&(val as u64)) != hash(&(val as uint)));
-        assert_eq!(hash(&(val as u32)), hash(&(val as uint)));
-    }
-    #[test] #[cfg(target_arch = "x86_64")]
-    fn test_hash_uint() {
-        let val = 0xdeadbeef_deadbeef_u64;
-        assert_eq!(hash(&(val as u64)), hash(&(val as uint)));
-        assert!(hash(&(val as u32)) != hash(&(val as uint)));
-    }
-    #[test] #[cfg(target_arch = "x86")]
-    fn test_hash_uint() {
-        let val = 0xdeadbeef_deadbeef_u64;
-        assert!(hash(&(val as u64)) != hash(&(val as uint)));
-        assert_eq!(hash(&(val as u32)), hash(&(val as uint)));
-    }
-
-    #[test]
-    fn test_hash_idempotent() {
-        let val64 = 0xdeadbeef_deadbeef_u64;
-        assert_eq!(hash(&val64), hash(&val64));
-        let val32 = 0xdeadbeef_u32;
-        assert_eq!(hash(&val32), hash(&val32));
-    }
-
-    #[test]
-    fn test_hash_no_bytes_dropped_64() {
-        let val = 0xdeadbeef_deadbeef_u64;
-
-        assert!(hash(&val) != hash(&zero_byte(val, 0)));
-        assert!(hash(&val) != hash(&zero_byte(val, 1)));
-        assert!(hash(&val) != hash(&zero_byte(val, 2)));
-        assert!(hash(&val) != hash(&zero_byte(val, 3)));
-        assert!(hash(&val) != hash(&zero_byte(val, 4)));
-        assert!(hash(&val) != hash(&zero_byte(val, 5)));
-        assert!(hash(&val) != hash(&zero_byte(val, 6)));
-        assert!(hash(&val) != hash(&zero_byte(val, 7)));
-
-        fn zero_byte(val: u64, byte: uint) -> u64 {
-            assert!(byte < 8);
-            val & !(0xff << (byte * 8))
-        }
-    }
-
-    #[test]
-    fn test_hash_no_bytes_dropped_32() {
-        let val = 0xdeadbeef_u32;
-
-        assert!(hash(&val) != hash(&zero_byte(val, 0)));
-        assert!(hash(&val) != hash(&zero_byte(val, 1)));
-        assert!(hash(&val) != hash(&zero_byte(val, 2)));
-        assert!(hash(&val) != hash(&zero_byte(val, 3)));
-
-        fn zero_byte(val: u32, byte: uint) -> u32 {
-            assert!(byte < 4);
-            val & !(0xff << (byte * 8))
-        }
-    }
-
-    #[test]
-    fn test_hash_no_concat_alias() {
-        let s = ("aa", "bb");
-        let t = ("aabb", "");
-        let u = ("a", "abb");
-
-        assert!(s != t && t != u);
-        assert!(hash(&s) != hash(&t) && hash(&s) != hash(&u));
-
-        let v: (&[u8], &[u8], &[u8]) = (&[1u8], &[0u8, 0], &[0u8]);
-        let w: (&[u8], &[u8], &[u8]) = (&[1u8, 0, 0, 0], &[], &[]);
-
-        assert!(v != w);
-        assert!(hash(&v) != hash(&w));
-    }
-
-    #[bench]
-    fn bench_str_under_8_bytes(b: &mut Bencher) {
-        let s = "foo";
-        b.iter(|| {
-            assert_eq!(hash(&s), 16262950014981195938);
-        })
-    }
-
-    #[bench]
-    fn bench_str_of_8_bytes(b: &mut Bencher) {
-        let s = "foobar78";
-        b.iter(|| {
-            assert_eq!(hash(&s), 4898293253460910787);
-        })
-    }
-
-    #[bench]
-    fn bench_str_over_8_bytes(b: &mut Bencher) {
-        let s = "foobarbaz0";
-        b.iter(|| {
-            assert_eq!(hash(&s), 10581415515220175264);
-        })
-    }
-
-    #[bench]
-    fn bench_long_str(b: &mut Bencher) {
-        let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \
-incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \
-exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \
-irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \
-pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \
-officia deserunt mollit anim id est laborum.";
-        b.iter(|| {
-            assert_eq!(hash(&s), 17717065544121360093);
-        })
-    }
-
-    #[bench]
-    fn bench_u64(b: &mut Bencher) {
-        let u = 16262950014981195938u64;
-        b.iter(|| {
-            assert_eq!(hash(&u), 5254097107239593357);
-        })
-    }
-}
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 822416a387e..bb2bfa95372 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -42,6 +42,8 @@
 #![experimental]
 #![allow(missing_docs)]
 
+use marker::Sized;
+
 pub type GlueFn = extern "Rust" fn(*const i8);
 
 #[lang="ty_desc"]
@@ -200,6 +202,10 @@ extern "rust-intrinsic" {
     /// Gets an identifier which is globally unique to the specified type. This
     /// function will return the same value for a type regardless of whichever
     /// crate it is invoked in.
+    #[cfg(not(stage0))]
+    pub fn type_id<T: ?Sized + 'static>() -> TypeId;
+
+    #[cfg(stage0)]
     pub fn type_id<T: 'static>() -> TypeId;
 
     /// Create a value initialized to zero.
@@ -551,8 +557,15 @@ pub struct TypeId {
 
 impl TypeId {
     /// Returns the `TypeId` of the type this generic function has been instantiated with
+    #[cfg(not(stage0))]
+    pub fn of<T: ?Sized + 'static>() -> TypeId {
+        unsafe { type_id::<T>() }
+    }
+
+    #[cfg(stage0)]
     pub fn of<T: 'static>() -> TypeId {
         unsafe { type_id::<T>() }
     }
+
     pub fn hash(&self) -> u64 { self.t }
 }
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index d30cfc405a1..f0f4a191e4f 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -2749,9 +2749,9 @@ macro_rules! step_impl_no_between {
 }
 
 step_impl!(uint u8 u16 u32 int i8 i16 i32);
-#[cfg(target_word_size = "64")]
+#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
 step_impl!(u64 i64);
-#[cfg(target_word_size = "32")]
+#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
 step_impl_no_between!(u64 i64);
 
 
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 890417b133f..21c25a12730 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -49,6 +49,7 @@
 
 #![crate_name = "core"]
 #![experimental]
+#![staged_api]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
diff --git a/src/libcore/num/int.rs b/src/libcore/num/int.rs
index fe68b78b2b6..065763a0d8e 100644
--- a/src/libcore/num/int.rs
+++ b/src/libcore/num/int.rs
@@ -16,5 +16,8 @@
 
 #![deprecated = "replaced by isize"]
 
-#[cfg(target_word_size = "32")] int_module! { int, 32 }
-#[cfg(target_word_size = "64")] int_module! { int, 64 }
+#[cfg(stage0)] #[cfg(target_word_size = "32")] int_module! { int, 32 }
+#[cfg(stage0)] #[cfg(target_word_size = "64")] int_module! { int, 64 }
+
+#[cfg(not(stage0))] #[cfg(target_pointer_width = "32")] int_module! { int, 32 }
+#[cfg(not(stage0))] #[cfg(target_pointer_width = "64")] int_module! { int, 64 }
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 490d8111f46..47da5de5391 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -496,7 +496,7 @@ uint_impl! { u64 = u64, 64,
     intrinsics::u64_sub_with_overflow,
     intrinsics::u64_mul_with_overflow }
 
-#[cfg(target_word_size = "32")]
+#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
 uint_impl! { uint = u32, 32,
     intrinsics::ctpop32,
     intrinsics::ctlz32,
@@ -506,7 +506,7 @@ uint_impl! { uint = u32, 32,
     intrinsics::u32_sub_with_overflow,
     intrinsics::u32_mul_with_overflow }
 
-#[cfg(target_word_size = "64")]
+#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
 uint_impl! { uint = u64, 64,
     intrinsics::ctpop64,
     intrinsics::ctlz64,
@@ -601,13 +601,13 @@ int_impl! { i64 = i64, u64, 64,
     intrinsics::i64_sub_with_overflow,
     intrinsics::i64_mul_with_overflow }
 
-#[cfg(target_word_size = "32")]
+#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
 int_impl! { int = i32, u32, 32,
     intrinsics::i32_add_with_overflow,
     intrinsics::i32_sub_with_overflow,
     intrinsics::i32_mul_with_overflow }
 
-#[cfg(target_word_size = "64")]
+#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
 int_impl! { int = i64, u64, 64,
     intrinsics::i64_add_with_overflow,
     intrinsics::i64_sub_with_overflow,
diff --git a/src/libcoretest/hash/mod.rs b/src/libcoretest/hash/mod.rs
index 63bf9ec3314..63935894bf5 100644
--- a/src/libcoretest/hash/mod.rs
+++ b/src/libcoretest/hash/mod.rs
@@ -7,27 +7,22 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-use core::marker::Sized;
-use std::mem;
-
-use core::slice::SliceExt;
-use core::hash::{Hash, Hasher, Writer};
 
-struct MyWriterHasher;
+use std::mem;
+use std::hash::{Hash, Hasher, Writer};
+use std::default::Default;
 
-impl Hasher<MyWriter> for MyWriterHasher {
-    fn hash<T: ?Sized + Hash<MyWriter>>(&self, value: &T) -> u64 {
-        let mut state = MyWriter { hash: 0 };
-        value.hash(&mut state);
-        state.hash
-    }
+struct MyHasher {
+    hash: u64,
 }
 
-struct MyWriter {
-    hash: u64,
+impl Default for MyHasher {
+    fn default() -> MyHasher {
+        MyHasher { hash: 0 }
+    }
 }
 
-impl Writer for MyWriter {
+impl Writer for MyHasher {
     // Most things we'll just add up the bytes.
     fn write(&mut self, buf: &[u8]) {
         for byte in buf.iter() {
@@ -36,66 +31,88 @@ impl Writer for MyWriter {
     }
 }
 
+impl Hasher for MyHasher {
+    type Output = u64;
+    fn reset(&mut self) { self.hash = 0; }
+    fn finish(&self) -> u64 { self.hash }
+}
+
+
 #[test]
 fn test_writer_hasher() {
-    let hasher = MyWriterHasher;
+    fn hash<T: Hash<MyHasher>>(t: &T) -> u64 {
+        ::std::hash::hash::<_, MyHasher>(t)
+    }
 
-    assert_eq!(hasher.hash(&()), 0);
+    assert_eq!(hash(&()), 0);
 
-    assert_eq!(hasher.hash(&5u8), 5);
-    assert_eq!(hasher.hash(&5u16), 5);
-    assert_eq!(hasher.hash(&5u32), 5);
-    assert_eq!(hasher.hash(&5u64), 5);
-    assert_eq!(hasher.hash(&5u), 5);
+    assert_eq!(hash(&5u8), 5);
+    assert_eq!(hash(&5u16), 5);
+    assert_eq!(hash(&5u32), 5);
+    assert_eq!(hash(&5u64), 5);
+    assert_eq!(hash(&5u), 5);
 
-    assert_eq!(hasher.hash(&5i8), 5);
-    assert_eq!(hasher.hash(&5i16), 5);
-    assert_eq!(hasher.hash(&5i32), 5);
-    assert_eq!(hasher.hash(&5i64), 5);
-    assert_eq!(hasher.hash(&5i), 5);
+    assert_eq!(hash(&5i8), 5);
+    assert_eq!(hash(&5i16), 5);
+    assert_eq!(hash(&5i32), 5);
+    assert_eq!(hash(&5i64), 5);
+    assert_eq!(hash(&5i), 5);
 
-    assert_eq!(hasher.hash(&false), 0);
-    assert_eq!(hasher.hash(&true), 1);
+    assert_eq!(hash(&false), 0);
+    assert_eq!(hash(&true), 1);
 
-    assert_eq!(hasher.hash(&'a'), 97);
+    assert_eq!(hash(&'a'), 97);
 
     let s: &str = "a";
-    assert_eq!(hasher.hash(& s), 97 + 0xFF);
+    assert_eq!(hash(& s), 97 + 0xFF);
     // FIXME (#18283) Enable test
     //let s: Box<str> = box "a";
     //assert_eq!(hasher.hash(& s), 97 + 0xFF);
     let cs: &[u8] = &[1u8, 2u8, 3u8];
-    assert_eq!(hasher.hash(& cs), 9);
+    assert_eq!(hash(& cs), 9);
     let cs: Box<[u8]> = box [1u8, 2u8, 3u8];
-    assert_eq!(hasher.hash(& cs), 9);
+    assert_eq!(hash(& cs), 9);
 
     // FIXME (#18248) Add tests for hashing Rc<str> and Rc<[T]>
 
     unsafe {
         let ptr: *const int = mem::transmute(5i);
-        assert_eq!(hasher.hash(&ptr), 5);
+        assert_eq!(hash(&ptr), 5);
     }
 
     unsafe {
         let ptr: *mut int = mem::transmute(5i);
-        assert_eq!(hasher.hash(&ptr), 5);
+        assert_eq!(hash(&ptr), 5);
     }
 }
 
-struct Custom {
-    hash: u64
+struct Custom { hash: u64 }
+struct CustomHasher { output: u64 }
+
+impl Hasher for CustomHasher {
+    type Output = u64;
+    fn reset(&mut self) { self.output = 0; }
+    fn finish(&self) -> u64 { self.output }
+}
+
+impl Default for CustomHasher {
+    fn default() -> CustomHasher {
+        CustomHasher { output: 0 }
+    }
 }
 
-impl Hash<u64> for Custom {
-    fn hash(&self, state: &mut u64) {
-        *state = self.hash;
+impl Hash<CustomHasher> for Custom {
+    fn hash(&self, state: &mut CustomHasher) {
+        state.output = self.hash;
     }
 }
 
 #[test]
 fn test_custom_state() {
+    fn hash<T: Hash<CustomHasher>>(t: &T) -> u64 {
+        ::std::hash::hash::<_, CustomHasher>(t)
+    }
+
     let custom = Custom { hash: 5 };
-    let mut state = 0;
-    custom.hash(&mut state);
-    assert_eq!(state, 5);
+    assert_eq!(hash(&Custom { hash: 5 }), 5);
 }
diff --git a/src/libcoretest/intrinsics.rs b/src/libcoretest/intrinsics.rs
new file mode 100644
index 00000000000..bcf8a6a433b
--- /dev/null
+++ b/src/libcoretest/intrinsics.rs
@@ -0,0 +1,31 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::intrinsics::TypeId;
+
+#[test]
+fn test_typeid_sized_types() {
+    struct X; struct Y(uint);
+
+    assert_eq!(TypeId::of::<X>(), TypeId::of::<X>());
+    assert_eq!(TypeId::of::<Y>(), TypeId::of::<Y>());
+    assert!(TypeId::of::<X>() != TypeId::of::<Y>());
+}
+
+#[test]
+fn test_typeid_unsized_types() {
+    trait Z {}
+    struct X(str); struct Y(Z + 'static);
+
+    assert_eq!(TypeId::of::<X>(), TypeId::of::<X>());
+    assert_eq!(TypeId::of::<Y>(), TypeId::of::<Y>());
+    assert!(TypeId::of::<X>() != TypeId::of::<Y>());
+}
+
diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs
index f38440d86c6..1896bdd182a 100644
--- a/src/libflate/lib.rs
+++ b/src/libflate/lib.rs
@@ -16,6 +16,7 @@
 
 #![crate_name = "flate"]
 #![experimental]
+#![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs
index 47cc072a636..a703bfbb8fe 100644
--- a/src/libfmt_macros/lib.rs
+++ b/src/libfmt_macros/lib.rs
@@ -16,6 +16,7 @@
 
 #![crate_name = "fmt_macros"]
 #![experimental]
+#![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs
index f50e24c6354..0dd6a430a88 100644
--- a/src/libgetopts/lib.rs
+++ b/src/libgetopts/lib.rs
@@ -79,6 +79,7 @@
 
 #![crate_name = "getopts"]
 #![experimental = "use the crates.io `getopts` library instead"]
+#![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs
index 83bad70e7b1..21a8ba03454 100644
--- a/src/libgraphviz/lib.rs
+++ b/src/libgraphviz/lib.rs
@@ -266,6 +266,7 @@
 
 #![crate_name = "graphviz"]
 #![experimental]
+#![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs
index dff27f800c7..c39fd074387 100644
--- a/src/liblibc/lib.rs
+++ b/src/liblibc/lib.rs
@@ -11,6 +11,7 @@
 #![crate_name = "libc"]
 #![crate_type = "rlib"]
 #![cfg_attr(not(feature = "cargo-build"), experimental)]
+#![cfg_attr(not(feature = "cargo-build"), staged_api)]
 #![no_std]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs
index 08b01e956e1..6bfbbb99fc7 100644
--- a/src/liblog/lib.rs
+++ b/src/liblog/lib.rs
@@ -157,6 +157,7 @@
 
 #![crate_name = "log"]
 #![experimental = "use the crates.io `log` library instead"]
+#![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/librand/lib.rs b/src/librand/lib.rs
index 9d33f65cd59..ec34b904a68 100644
--- a/src/librand/lib.rs
+++ b/src/librand/lib.rs
@@ -25,6 +25,7 @@
 
 #![no_std]
 #![experimental]
+#![staged_api]
 
 #[macro_use]
 extern crate core;
diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs
index a66d1dd08c1..66f4f2321fd 100644
--- a/src/librbml/lib.rs
+++ b/src/librbml/lib.rs
@@ -17,6 +17,7 @@
 
 #![crate_name = "rbml"]
 #![experimental]
+#![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/libregex/lib.rs b/src/libregex/lib.rs
index c039abc9aff..bd376528a0e 100644
--- a/src/libregex/lib.rs
+++ b/src/libregex/lib.rs
@@ -17,6 +17,7 @@
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![experimental = "use the crates.io `regex` library instead"]
+#![staged_api]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/",
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index a3a041c2497..5525874a614 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -16,6 +16,7 @@
 
 #![crate_name = "rustc"]
 #![experimental]
+#![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 1af8e2f29eb..9d7e833e711 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -34,7 +34,7 @@ use middle::{def, pat_util, stability};
 use middle::const_eval::{eval_const_expr_partial, const_int, const_uint};
 use util::ppaux::{ty_to_string};
 use util::nodemap::{FnvHashMap, NodeSet};
-use lint::{Context, LintPass, LintArray};
+use lint::{Context, LintPass, LintArray, Lint};
 
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::num::SignedInt;
@@ -1643,6 +1643,13 @@ declare_lint! {
     "detects use of #[unstable] items (incl. items with no stability attribute)"
 }
 
+declare_lint!(STAGED_EXPERIMENTAL, Warn,
+              "detects use of #[experimental] items in staged builds");
+
+declare_lint!(STAGED_UNSTABLE, Warn,
+              "detects use of #[unstable] items (incl. items with no stability attribute) \
+               in staged builds");
+
 /// Checks for use of items with `#[deprecated]`, `#[experimental]` and
 /// `#[unstable]` attributes, or no stability attribute.
 #[derive(Copy)]
@@ -1650,12 +1657,13 @@ pub struct Stability;
 
 impl Stability {
     fn lint(&self, cx: &Context, id: ast::DefId, span: Span) {
-        let stability = stability::lookup(cx.tcx, id);
+
+        let ref stability = stability::lookup(cx.tcx, id);
         let cross_crate = !ast_util::is_local(id);
 
         // stability attributes are promises made across crates; only
         // check DEPRECATED for crate-local usage.
-        let (lint, label) = match stability {
+        let (lint, label) = match *stability {
             // no stability attributes == Unstable
             None if cross_crate => (UNSTABLE, "unmarked"),
             Some(attr::Stability { level: attr::Unstable, .. }) if cross_crate =>
@@ -1667,24 +1675,53 @@ impl Stability {
             _ => return
         };
 
-        let msg = match stability {
-            Some(attr::Stability { text: Some(ref s), .. }) => {
-                format!("use of {} item: {}", label, *s)
+        output(cx, span, stability, lint, label);
+        if cross_crate && stability::is_staged_api(cx.tcx, id) {
+            if lint.name == UNSTABLE.name {
+                output(cx, span, stability, STAGED_UNSTABLE, label);
+            } else if lint.name == EXPERIMENTAL.name {
+                output(cx, span, stability, STAGED_EXPERIMENTAL, label);
             }
-            _ => format!("use of {} item", label)
-        };
+        }
 
-        cx.span_lint(lint, span, msg.index(&FullRange));
+        fn output(cx: &Context, span: Span, stability: &Option<attr::Stability>,
+                  lint: &'static Lint, label: &'static str) {
+            let msg = match *stability {
+                Some(attr::Stability { text: Some(ref s), .. }) => {
+                    format!("use of {} item: {}", label, *s)
+                }
+                _ => format!("use of {} item", label)
+            };
+
+            cx.span_lint(lint, span, msg.index(&FullRange));
+        }
     }
 
+
     fn is_internal(&self, cx: &Context, span: Span) -> bool {
         cx.tcx.sess.codemap().span_is_internal(span)
     }
+
 }
 
 impl LintPass for Stability {
     fn get_lints(&self) -> LintArray {
-        lint_array!(DEPRECATED, EXPERIMENTAL, UNSTABLE)
+        lint_array!(DEPRECATED, EXPERIMENTAL, UNSTABLE, STAGED_EXPERIMENTAL, STAGED_UNSTABLE)
+    }
+
+    fn check_crate(&mut self, _: &Context, c: &ast::Crate) {
+        // Just mark the #[staged_api] attribute used, though nothing else is done
+        // with it during this pass over the source.
+        for attr in c.attrs.iter() {
+            if attr.name().get() == "staged_api" {
+                match attr.node.value.node {
+                    ast::MetaWord(_) => {
+                        attr::mark_used(attr);
+                    }
+                    _ => (/*pass*/)
+                }
+            }
+        }
     }
 
     fn check_view_item(&mut self, cx: &Context, item: &ast::ViewItem) {
@@ -1746,6 +1783,7 @@ impl LintPass for Stability {
             }
             _ => return
         };
+
         self.lint(cx, id, span);
     }
 
@@ -1878,3 +1916,22 @@ impl LintPass for HardwiredLints {
         )
     }
 }
+
+/// Forbids using the `#[feature(...)]` attribute
+#[deriving(Copy)]
+pub struct UnstableFeatures;
+
+declare_lint!(UNSTABLE_FEATURES, Allow,
+              "enabling unstable features");
+
+impl LintPass for UnstableFeatures {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNSTABLE_FEATURES)
+    }
+    fn check_attribute(&mut self, ctx: &Context, attr: &ast::Attribute) {
+        use syntax::attr;
+        if attr::contains_name(&[attr.node.value.clone()], "feature") {
+            ctx.span_lint(UNSTABLE_FEATURES, attr.span, "unstable feature");
+        }
+    }
+}
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 51998bdbcf2..7d58b04a7f4 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -28,8 +28,9 @@ use self::TargetLint::*;
 use middle::privacy::ExportedItems;
 use middle::ty::{self, Ty};
 use session::{early_error, Session};
+use session::config::UnstableFeatures;
 use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass, LintPassObject};
-use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid};
+use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid, ReleaseChannel};
 use lint::builtin;
 use util::nodemap::FnvHashMap;
 
@@ -210,6 +211,7 @@ impl LintStore {
                      UnusedAllocation,
                      Stability,
                      MissingCopyImplementations,
+                     UnstableFeatures,
         );
 
         add_builtin_with_new!(sess,
@@ -298,6 +300,29 @@ impl LintStore {
             }
         }
     }
+
+    fn maybe_stage_features(&mut self, sess: &Session) {
+        let lvl = match sess.opts.unstable_features {
+            UnstableFeatures::Default => return,
+            UnstableFeatures::Disallow => Warn,
+            UnstableFeatures::Cheat => Allow
+        };
+        match self.by_name.get("unstable_features") {
+            Some(&Id(lint_id)) => self.set_level(lint_id, (lvl, ReleaseChannel)),
+            Some(&Renamed(_, lint_id)) => self.set_level(lint_id, (lvl, ReleaseChannel)),
+            None => unreachable!()
+        }
+        match self.by_name.get("staged_unstable") {
+            Some(&Id(lint_id)) => self.set_level(lint_id, (lvl, ReleaseChannel)),
+            Some(&Renamed(_, lint_id)) => self.set_level(lint_id, (lvl, ReleaseChannel)),
+            None => unreachable!()
+        }
+        match self.by_name.get("staged_experimental") {
+            Some(&Id(lint_id)) => self.set_level(lint_id, (lvl, ReleaseChannel)),
+            Some(&Renamed(_, lint_id)) => self.set_level(lint_id, (lvl, ReleaseChannel)),
+            None => unreachable!()
+        }
+    }
 }
 
 /// Context for lint checking.
@@ -380,6 +405,7 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
     if level == Allow { return }
 
     let name = lint.name_lower();
+    let mut def = None;
     let mut note = None;
     let msg = match source {
         Default => {
@@ -394,7 +420,13 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
                     }, name.replace("_", "-"))
         },
         Node(src) => {
-            note = Some(src);
+            def = Some(src);
+            msg.to_string()
+        }
+        ReleaseChannel => {
+            let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)");
+            note = Some(format!("this feature may not be used in the {} release channel",
+                                release_channel));
             msg.to_string()
         }
     };
@@ -410,7 +442,11 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
         _ => sess.bug("impossible level in raw_emit_lint"),
     }
 
-    for span in note.into_iter() {
+    for note in note.into_iter() {
+        sess.note(note.index(&FullRange));
+    }
+
+    for span in def.into_iter() {
         sess.span_note(span, "lint level defined here");
     }
 }
@@ -767,6 +803,10 @@ impl LintPass for GatherNodeLevels {
 /// Consumes the `lint_store` field of the `Session`.
 pub fn check_crate(tcx: &ty::ctxt,
                    exported_items: &ExportedItems) {
+
+    // If this is a feature-staged build of rustc then flip several lints to 'forbid'
+    tcx.sess.lint_store.borrow_mut().maybe_stage_features(&tcx.sess);
+
     let krate = tcx.map.krate();
     let mut cx = Context::new(tcx, krate, exported_items);
 
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index e9778fa05ff..8a266a2530b 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -186,7 +186,7 @@ impl PartialEq for LintId {
 
 impl Eq for LintId { }
 
-impl<S: hash::Writer> hash::Hash<S> for LintId {
+impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for LintId {
     fn hash(&self, state: &mut S) {
         let ptr = self.lint as *const Lint;
         ptr.hash(state);
@@ -248,6 +248,9 @@ pub enum LintSource {
 
     /// Lint level was set by a command-line flag.
     CommandLine,
+
+    /// Lint level was set by the release channel.
+    ReleaseChannel
 }
 
 pub type LevelSource = (Level, LintSource);
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index 72ce61b133a..39c7f80703d 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -27,6 +27,7 @@ use std::rc::Rc;
 use syntax::ast;
 use syntax::ast_map;
 use syntax::attr;
+use syntax::attr::AttrMetaMethods;
 use syntax::diagnostic::expect;
 use syntax::parse::token;
 
@@ -375,6 +376,18 @@ pub fn get_stability(cstore: &cstore::CStore,
     decoder::get_stability(&*cdata, def.node)
 }
 
+pub fn is_staged_api(cstore: &cstore::CStore, def: ast::DefId) -> bool {
+    let cdata = cstore.get_crate_data(def.krate);
+    let attrs = decoder::get_crate_attributes(cdata.data());
+    for attr in attrs.iter() {
+        if attr.name().get() == "staged_api" {
+            match attr.node.value.node { ast::MetaWord(_) => return true, _ => (/*pass*/) }
+        }
+    }
+
+    return false;
+}
+
 pub fn get_repr_attrs(cstore: &cstore::CStore, def: ast::DefId)
                       -> Vec<attr::ReprAttr> {
     let cdata = cstore.get_crate_data(def.krate);
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 9e71c867efa..750f8a29856 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -33,8 +33,7 @@ use middle::ty::{self, Ty};
 use middle::astencode::vtable_decoder_helpers;
 
 use std::collections::HashMap;
-use std::hash::Hash;
-use std::hash;
+use std::hash::{self, Hash, SipHasher};
 use std::io::extensions::u64_from_be_bytes;
 use std::io;
 use std::num::FromPrimitive;
@@ -94,7 +93,7 @@ pub fn maybe_find_item<'a>(item_id: ast::NodeId,
     }
     lookup_hash(items,
                 |a| eq_item(a, item_id),
-                hash::hash(&(item_id as i64)))
+                hash::hash::<i64, SipHasher>(&(item_id as i64)))
 }
 
 fn find_item<'a>(item_id: ast::NodeId, items: rbml::Doc<'a>) -> rbml::Doc<'a> {
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 83038df338b..3d54d286258 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -29,8 +29,7 @@ use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
 
 use serialize::Encodable;
 use std::cell::RefCell;
-use std::hash::Hash;
-use std::hash;
+use std::hash::{Hash, Hasher, SipHasher};
 use syntax::abi;
 use syntax::ast::{self, DefId, NodeId};
 use syntax::ast_map::{PathElem, PathElems};
@@ -1598,11 +1597,13 @@ fn encode_info_for_items(ecx: &EncodeContext,
 
 fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
     F: FnMut(&mut SeekableMemWriter, &T),
-    T: Hash,
+    T: Hash<SipHasher>,
 {
     let mut buckets: Vec<Vec<entry<T>>> = range(0, 256u16).map(|_| Vec::new()).collect();
     for elt in index.into_iter() {
-        let h = hash::hash(&elt.val) as uint;
+        let mut s = SipHasher::new();
+        elt.val.hash(&mut s);
+        let h = s.finish() as uint;
         (&mut buckets[h % 256]).push(elt);
     }
 
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index 29625d0a6af..e8160487e16 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -272,12 +272,12 @@ fn find_libdir(sysroot: &Path) -> String {
         }
     }
 
-    #[cfg(target_word_size = "64")]
+    #[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
     fn primary_libdir_name() -> String {
         "lib64".to_string()
     }
 
-    #[cfg(target_word_size = "32")]
+    #[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
     fn primary_libdir_name() -> String {
         "lib32".to_string()
     }
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 359ad8d3941..e712f510d9d 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -189,3 +189,19 @@ pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
         }
     })
 }
+
+pub fn is_staged_api(tcx: &ty::ctxt, id: DefId) -> bool {
+    match ty::trait_item_of_item(tcx, id) {
+        Some(ty::MethodTraitItemId(trait_method_id))
+            if trait_method_id != id => {
+                is_staged_api(tcx, trait_method_id)
+            }
+        _ if is_local(id) => {
+            // Unused case
+            unreachable!()
+        }
+        _ => {
+            csearch::is_staged_api(&tcx.sess.cstore, id)
+        }
+    }
+}
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs
index 3e16e2965a6..e9eb3f4f4b0 100644
--- a/src/librustc/middle/traits/project.rs
+++ b/src/librustc/middle/traits/project.rs
@@ -452,7 +452,9 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
     for predicate in elaborate_predicates(selcx.tcx(), env_predicates) {
         match predicate {
             ty::Predicate::Projection(ref data) => {
-                let is_match = infcx.probe(|_| {
+                let same_name = data.item_name() == obligation.predicate.item_name;
+
+                let is_match = same_name && infcx.probe(|_| {
                     let origin = infer::Misc(obligation.cause.span);
                     let obligation_poly_trait_ref =
                         obligation_trait_ref.to_poly_trait_ref();
@@ -465,6 +467,9 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
                 });
 
                 if is_match {
+                    debug!("assemble_candidates_from_predicates: candidate {}",
+                           data.repr(selcx.tcx()));
+
                     candidate_set.vec.push(
                         ProjectionTyCandidate::ParamEnv(data.clone()));
                 }
@@ -527,6 +532,9 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
 
     match vtable {
         super::VtableImpl(data) => {
+            debug!("assemble_candidates_from_impls: impl candidate {}",
+                   data.repr(selcx.tcx()));
+
             candidate_set.vec.push(
                 ProjectionTyCandidate::Impl(data));
         }
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 9b9a58178cc..14349c8e440 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -72,7 +72,7 @@ use std::borrow::BorrowFrom;
 use std::cell::{Cell, RefCell};
 use std::cmp::{self, Ordering};
 use std::fmt::{self, Show};
-use std::hash::{Hash, sip, Writer};
+use std::hash::{Hash, Writer, SipHasher, Hasher};
 use std::mem;
 use std::ops;
 use std::rc::Rc;
@@ -946,11 +946,18 @@ impl<'tcx> PartialEq for TyS<'tcx> {
 }
 impl<'tcx> Eq for TyS<'tcx> {}
 
+#[cfg(stage0)]
 impl<'tcx, S: Writer> Hash<S> for TyS<'tcx> {
     fn hash(&self, s: &mut S) {
         (self as *const _).hash(s)
     }
 }
+#[cfg(not(stage0))]
+impl<'tcx, S: Writer + Hasher> Hash<S> for TyS<'tcx> {
+    fn hash(&self, s: &mut S) {
+        (self as *const _).hash(s)
+    }
+}
 
 pub type Ty<'tcx> = &'tcx TyS<'tcx>;
 
@@ -968,7 +975,7 @@ impl<'tcx> PartialEq for InternedTy<'tcx> {
 
 impl<'tcx> Eq for InternedTy<'tcx> {}
 
-impl<'tcx, S: Writer> Hash<S> for InternedTy<'tcx> {
+impl<'tcx, S: Writer + Hasher> Hash<S> for InternedTy<'tcx> {
     fn hash(&self, s: &mut S) {
         self.ty.sty.hash(s)
     }
@@ -1892,6 +1899,10 @@ pub struct ProjectionPredicate<'tcx> {
 pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>;
 
 impl<'tcx> PolyProjectionPredicate<'tcx> {
+    pub fn item_name(&self) -> ast::Name {
+        self.0.projection_ty.item_name // safe to skip the binder to access a name
+    }
+
     pub fn sort_key(&self) -> (ast::DefId, ast::Name) {
         self.0.projection_ty.sort_key()
     }
@@ -6164,15 +6175,16 @@ pub fn trait_item_of_item(tcx: &ctxt, def_id: ast::DefId)
 /// Creates a hash of the type `Ty` which will be the same no matter what crate
 /// context it's calculated within. This is used by the `type_id` intrinsic.
 pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -> u64 {
-    let mut state = sip::SipState::new();
+    let mut state = SipHasher::new();
     helper(tcx, ty, svh, &mut state);
-    return state.result();
+    return state.finish();
 
-    fn helper<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh, state: &mut sip::SipState) {
+    fn helper<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh,
+                    state: &mut SipHasher) {
         macro_rules! byte { ($b:expr) => { ($b as u8).hash(state) } }
         macro_rules! hash { ($e:expr) => { $e.hash(state) }  }
 
-        let region = |&: state: &mut sip::SipState, r: Region| {
+        let region = |&: state: &mut SipHasher, r: Region| {
             match r {
                 ReStatic => {}
                 ReLateBound(db, BrAnon(i)) => {
@@ -6189,7 +6201,7 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
                 }
             }
         };
-        let did = |&: state: &mut sip::SipState, did: DefId| {
+        let did = |&: state: &mut SipHasher, did: DefId| {
             let h = if ast_util::is_local(did) {
                 svh.clone()
             } else {
@@ -6198,10 +6210,10 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
             h.as_str().hash(state);
             did.node.hash(state);
         };
-        let mt = |&: state: &mut sip::SipState, mt: mt| {
+        let mt = |&: state: &mut SipHasher, mt: mt| {
             mt.mutbl.hash(state);
         };
-        let fn_sig = |&: state: &mut sip::SipState, sig: &Binder<FnSig<'tcx>>| {
+        let fn_sig = |&: state: &mut SipHasher, sig: &Binder<FnSig<'tcx>>| {
             let sig = anonymize_late_bound_regions(tcx, sig).0;
             for a in sig.inputs.iter() { helper(tcx, *a, svh, state); }
             if let ty::FnConverging(output) = sig.output {
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 4968066f7b6..b239b0dac47 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -111,7 +111,24 @@ pub struct Options {
     /// An optional name to use as the crate for std during std injection,
     /// written `extern crate std = "name"`. Default to "std". Used by
     /// out-of-tree drivers.
-    pub alt_std_name: Option<String>
+    pub alt_std_name: Option<String>,
+    /// Indicates how the compiler should treat unstable features
+    pub unstable_features: UnstableFeatures
+}
+
+#[deriving(Clone, Copy)]
+pub enum UnstableFeatures {
+    /// Hard errors for unstable features are active, as on
+    /// beta/stable channels.
+    Disallow,
+    /// Use the default lint levels
+    Default,
+    /// Errors are bypassed for bootstrapping. This is required any time
+    /// during the build that feature-related lints are set to warn or above
+    /// because the build turns on warnings-as-errors and uses lots of unstable
+    /// features. As a result, this this is always required for building Rust
+    /// itself.
+    Cheat
 }
 
 #[derive(Clone, PartialEq, Eq)]
@@ -217,6 +234,7 @@ pub fn basic_options() -> Options {
         crate_name: None,
         alt_std_name: None,
         libs: Vec::new(),
+        unstable_features: UnstableFeatures::Disallow
     }
 }
 
@@ -594,7 +612,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
 
     let end = sess.target.target.target_endian.index(&FullRange);
     let arch = sess.target.target.arch.index(&FullRange);
-    let wordsz = sess.target.target.target_word_size.index(&FullRange);
+    let wordsz = sess.target.target.target_pointer_width.index(&FullRange);
     let os = sess.target.target.target_os.index(&FullRange);
 
     let fam = match sess.target.target.options.is_like_windows {
@@ -609,7 +627,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
          mk(InternedString::new("target_family"), fam),
          mk(InternedString::new("target_arch"), intern(arch)),
          mk(InternedString::new("target_endian"), intern(end)),
-         mk(InternedString::new("target_word_size"),
+         mk(InternedString::new("target_pointer_width"),
             intern(wordsz))
     );
 }
@@ -643,7 +661,7 @@ pub fn build_target_config(opts: &Options, sp: &SpanHandler) -> Config {
     }
     };
 
-    let (int_type, uint_type) = match target.target_word_size.index(&FullRange) {
+    let (int_type, uint_type) = match target.target_pointer_width.index(&FullRange) {
         "32" => (ast::TyI32, ast::TyU32),
         "64" => (ast::TyI64, ast::TyU64),
         w    => sp.handler().fatal((format!("target specification was invalid: unrecognized \
@@ -1149,6 +1167,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         crate_name: crate_name,
         alt_std_name: None,
         libs: libs,
+        unstable_features: UnstableFeatures::Disallow
     }
 }
 
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 26f98e28a8d..c505e9e3112 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -16,6 +16,7 @@ use std::fmt::Show;
 use std::hash::{Hash, Hasher};
 use std::iter::repeat;
 use std::time::Duration;
+use std::collections::hash_state::HashState;
 
 use syntax::ast;
 use syntax::visit;
@@ -140,11 +141,11 @@ pub fn block_query<P>(b: &ast::Block, p: P) -> bool where P: FnMut(&ast::Expr) -
 /// Efficiency note: This is implemented in an inefficient way because it is typically invoked on
 /// very small graphs. If the graphs become larger, a more efficient graph representation and
 /// algorithm would probably be advised.
-pub fn can_reach<S,H:Hasher<S>,T:Eq+Clone+Hash<S>>(
-    edges_map: &HashMap<T,Vec<T>,H>,
-    source: T,
-    destination: T)
-    -> bool
+pub fn can_reach<T, S>(edges_map: &HashMap<T, Vec<T>, S>, source: T,
+                       destination: T) -> bool
+    where S: HashState,
+          <S as HashState>::Hasher: Hasher<Output=u64>,
+          T: Hash< <S as HashState>::Hasher> + Eq + Clone,
 {
     if source == destination {
         return true;
@@ -202,11 +203,12 @@ pub fn can_reach<S,H:Hasher<S>,T:Eq+Clone+Hash<S>>(
 /// }
 /// ```
 #[inline(always)]
-pub fn memoized<T, U, S, H, F>(cache: &RefCell<HashMap<T, U, H>>, arg: T, f: F) -> U where
-    T: Clone + Hash<S> + Eq,
-    U: Clone,
-    H: Hasher<S>,
-    F: FnOnce(T) -> U,
+pub fn memoized<T, U, S, F>(cache: &RefCell<HashMap<T, U, S>>, arg: T, f: F) -> U
+    where T: Clone + Hash<<S as HashState>::Hasher> + Eq,
+          U: Clone,
+          S: HashState,
+          <S as HashState>::Hasher: Hasher<Output=u64>,
+          F: FnOnce(T) -> U,
 {
     let key = arg.clone();
     let result = cache.borrow().get(&key).map(|result| result.clone());
diff --git a/src/librustc/util/nodemap.rs b/src/librustc/util/nodemap.rs
index ee224d1ec80..044534ae852 100644
--- a/src/librustc/util/nodemap.rs
+++ b/src/librustc/util/nodemap.rs
@@ -12,12 +12,14 @@
 
 #![allow(non_snake_case)]
 
+use std::collections::hash_state::{DefaultState};
 use std::collections::{HashMap, HashSet};
-use std::hash::{Hasher, Hash, Writer};
+use std::default::Default;
+use std::hash::{Hasher, Writer};
 use syntax::ast;
 
-pub type FnvHashMap<K, V> = HashMap<K, V, FnvHasher>;
-pub type FnvHashSet<V> = HashSet<V, FnvHasher>;
+pub type FnvHashMap<K, V> = HashMap<K, V, DefaultState<FnvHasher>>;
+pub type FnvHashSet<V> = HashSet<V, DefaultState<FnvHasher>>;
 
 pub type NodeMap<T> = FnvHashMap<ast::NodeId, T>;
 pub type DefIdMap<T> = FnvHashMap<ast::DefId, T>;
@@ -28,16 +30,16 @@ pub type DefIdSet = FnvHashSet<ast::DefId>;
 // Hacks to get good names
 pub mod FnvHashMap {
     use std::hash::Hash;
-    use std::collections::HashMap;
-    pub fn new<K: Hash<super::FnvState> + Eq, V>() -> super::FnvHashMap<K, V> {
-        HashMap::with_hasher(super::FnvHasher)
+    use std::default::Default;
+    pub fn new<K: Hash<super::FnvHasher> + Eq, V>() -> super::FnvHashMap<K, V> {
+        Default::default()
     }
 }
 pub mod FnvHashSet {
     use std::hash::Hash;
-    use std::collections::HashSet;
-    pub fn new<V: Hash<super::FnvState> + Eq>() -> super::FnvHashSet<V> {
-        HashSet::with_hasher(super::FnvHasher)
+    use std::default::Default;
+    pub fn new<V: Hash<super::FnvHasher> + Eq>() -> super::FnvHashSet<V> {
+        Default::default()
     }
 }
 pub mod NodeMap {
@@ -68,28 +70,26 @@ pub mod DefIdSet {
 ///
 /// This uses FNV hashing, as described here:
 /// http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
-#[derive(Clone, Copy, Default)]
-pub struct FnvHasher;
-
 #[allow(missing_copy_implementations)]
-pub struct FnvState(u64);
+pub struct FnvHasher(u64);
 
-impl Hasher<FnvState> for FnvHasher {
-    fn hash<T: ?Sized + Hash<FnvState>>(&self, t: &T) -> u64 {
-        let mut state = FnvState(0xcbf29ce484222325);
-        t.hash(&mut state);
-        let FnvState(ret) = state;
-        return ret;
-    }
+impl Default for FnvHasher {
+    fn default() -> FnvHasher { FnvHasher(0xcbf29ce484222325) }
+}
+
+impl Hasher for FnvHasher {
+    type Output = u64;
+    fn reset(&mut self) { *self = Default::default(); }
+    fn finish(&self) -> u64 { self.0 }
 }
 
-impl Writer for FnvState {
+impl Writer for FnvHasher {
     fn write(&mut self, bytes: &[u8]) {
-        let FnvState(mut hash) = *self;
+        let FnvHasher(mut hash) = *self;
         for byte in bytes.iter() {
             hash = hash ^ (*byte as u64);
             hash = hash * 0x100000001b3;
         }
-        *self = FnvState(hash);
+        *self = FnvHasher(hash);
     }
 }
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 2d433369366..edd1bc873be 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -26,6 +26,7 @@ use middle::ty;
 use middle::ty_fold::TypeFoldable;
 
 use std::collections::HashMap;
+use std::collections::hash_state::HashState;
 use std::hash::{Hash, Hasher};
 use std::rc::Rc;
 use syntax::abi;
@@ -1350,11 +1351,11 @@ impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for ty::Binder<T> {
     }
 }
 
-#[old_impl_check]
-impl<'tcx, S, H, K, V> Repr<'tcx> for HashMap<K,V,H>
-    where K : Hash<S> + Eq + Repr<'tcx>,
-          V : Repr<'tcx>,
-          H : Hasher<S>
+impl<'tcx, S, K, V> Repr<'tcx> for HashMap<K, V, S>
+    where K: Hash<<S as HashState>::Hasher> + Eq + Repr<'tcx>,
+          V: Repr<'tcx>,
+          S: HashState,
+          <S as HashState>::Hasher: Hasher<Output=u64>,
 {
     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
         format!("HashMap({})",
diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs
index ca39477fbdc..5d863def32e 100644
--- a/src/librustc_back/lib.rs
+++ b/src/librustc_back/lib.rs
@@ -23,6 +23,7 @@
 
 #![crate_name = "rustc_back"]
 #![experimental]
+#![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs
index 4812a2948d1..236855b7065 100644
--- a/src/librustc_back/svh.rs
+++ b/src/librustc_back/svh.rs
@@ -47,8 +47,7 @@
 //! Original issue: https://github.com/rust-lang/rust/issues/10207
 
 use std::fmt;
-use std::hash::Hash;
-use std::hash::sip::SipState;
+use std::hash::{Hash, SipHasher, Hasher};
 use std::iter::range_step;
 use syntax::ast;
 use syntax::visit;
@@ -78,7 +77,7 @@ impl Svh {
 
         // FIXME: this should use SHA1, not SipHash. SipHash is not built to
         //        avoid collisions.
-        let mut state = SipState::new();
+        let mut state = SipHasher::new();
 
         for data in metadata.iter() {
             data.hash(&mut state);
@@ -102,7 +101,7 @@ impl Svh {
             attr.node.value.hash(&mut state);
         }
 
-        let hash = state.result();
+        let hash = state.finish();
         return Svh {
             hash: range_step(0u, 64u, 4u).map(|i| hex(hash >> i)).collect()
         };
@@ -147,14 +146,13 @@ mod svh_visitor {
     use syntax::visit;
     use syntax::visit::{Visitor, FnKind};
 
-    use std::hash::Hash;
-    use std::hash::sip::SipState;
+    use std::hash::{Hash, SipHasher};
 
     pub struct StrictVersionHashVisitor<'a> {
-        pub st: &'a mut SipState,
+        pub st: &'a mut SipHasher,
     }
 
-    pub fn make<'a>(st: &'a mut SipState) -> StrictVersionHashVisitor<'a> {
+    pub fn make<'a>(st: &'a mut SipHasher) -> StrictVersionHashVisitor<'a> {
         StrictVersionHashVisitor { st: st }
     }
 
@@ -398,7 +396,7 @@ mod svh_visitor {
         }
 
         // All of the remaining methods just record (in the hash
-        // SipState) that the visitor saw that particular variant
+        // SipHasher) that the visitor saw that particular variant
         // (with its payload), and continue walking as the default
         // visitor would.
         //
diff --git a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs
index 296552a6abd..a3ef6372f06 100644
--- a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs
@@ -18,7 +18,7 @@ pub fn target() -> Target {
                       n32:64-S128".to_string(),
         llvm_target: "aarch64-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "64".to_string(),
+        target_pointer_width: "64".to_string(),
         arch: "aarch64".to_string(),
         target_os: "linux".to_string(),
         options: base,
diff --git a/src/librustc_back/target/arm_apple_ios.rs b/src/librustc_back/target/arm_apple_ios.rs
index 8bb64eae625..e0afef6e390 100644
--- a/src/librustc_back/target/arm_apple_ios.rs
+++ b/src/librustc_back/target/arm_apple_ios.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
                       -a:0:64-n32".to_string(),
         llvm_target: "arm-apple-ios".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "32".to_string(),
+        target_pointer_width: "32".to_string(),
         arch: "arm".to_string(),
         target_os: "ios".to_string(),
         options: TargetOptions {
diff --git a/src/librustc_back/target/arm_linux_androideabi.rs b/src/librustc_back/target/arm_linux_androideabi.rs
index ecfb1667f60..6fc77a715a5 100644
--- a/src/librustc_back/target/arm_linux_androideabi.rs
+++ b/src/librustc_back/target/arm_linux_androideabi.rs
@@ -27,7 +27,7 @@ pub fn target() -> Target {
                       -a:0:64-n32".to_string(),
         llvm_target: "arm-linux-androideabi".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "32".to_string(),
+        target_pointer_width: "32".to_string(),
         arch: "arm".to_string(),
         target_os: "android".to_string(),
         options: base,
diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs
index 985af35e145..32eccaf54b0 100644
--- a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs
+++ b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs
@@ -20,7 +20,7 @@ pub fn target() -> Target {
                       -a:0:64-n32".to_string(),
         llvm_target: "arm-unknown-linux-gnueabi".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "32".to_string(),
+        target_pointer_width: "32".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
 
diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
index 3cf0c312820..eff3601250f 100644
--- a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
+++ b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
@@ -20,7 +20,7 @@ pub fn target() -> Target {
                       -a:0:64-n32".to_string(),
         llvm_target: "arm-unknown-linux-gnueabihf".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "32".to_string(),
+        target_pointer_width: "32".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
 
diff --git a/src/librustc_back/target/i386_apple_ios.rs b/src/librustc_back/target/i386_apple_ios.rs
index 45669bc9585..a1fcc9ac53f 100644
--- a/src/librustc_back/target/i386_apple_ios.rs
+++ b/src/librustc_back/target/i386_apple_ios.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
                       -n8:16:32".to_string(),
         llvm_target: "i386-apple-ios".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "32".to_string(),
+        target_pointer_width: "32".to_string(),
         arch: "x86".to_string(),
         target_os: "ios".to_string(),
 
diff --git a/src/librustc_back/target/i686_apple_darwin.rs b/src/librustc_back/target/i686_apple_darwin.rs
index feef5b98dcb..1b079323bf9 100644
--- a/src/librustc_back/target/i686_apple_darwin.rs
+++ b/src/librustc_back/target/i686_apple_darwin.rs
@@ -22,7 +22,7 @@ pub fn target() -> Target {
                       -n8:16:32".to_string(),
         llvm_target: "i686-apple-darwin".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "32".to_string(),
+        target_pointer_width: "32".to_string(),
         arch: "x86".to_string(),
         target_os: "macos".to_string(),
         options: base,
diff --git a/src/librustc_back/target/i686_pc_windows_gnu.rs b/src/librustc_back/target/i686_pc_windows_gnu.rs
index 4d75590e664..c2ab68ee052 100644
--- a/src/librustc_back/target/i686_pc_windows_gnu.rs
+++ b/src/librustc_back/target/i686_pc_windows_gnu.rs
@@ -26,7 +26,7 @@ pub fn target() -> Target {
         data_layout: "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32".to_string(),
         llvm_target: "i686-pc-windows-gnu".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "32".to_string(),
+        target_pointer_width: "32".to_string(),
         arch: "x86".to_string(),
         target_os: "windows".to_string(),
         options: options,
diff --git a/src/librustc_back/target/i686_unknown_dragonfly.rs b/src/librustc_back/target/i686_unknown_dragonfly.rs
index a12657ff4dc..7910eba7ea1 100644
--- a/src/librustc_back/target/i686_unknown_dragonfly.rs
+++ b/src/librustc_back/target/i686_unknown_dragonfly.rs
@@ -18,7 +18,7 @@ pub fn target() -> Target {
         data_layout: "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string(),
         llvm_target: "i686-unknown-dragonfly".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "32".to_string(),
+        target_pointer_width: "32".to_string(),
         arch: "x86".to_string(),
         target_os: "dragonfly".to_string(),
         options: base,
diff --git a/src/librustc_back/target/i686_unknown_linux_gnu.rs b/src/librustc_back/target/i686_unknown_linux_gnu.rs
index 1a4560d5cd5..c93a564fef5 100644
--- a/src/librustc_back/target/i686_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/i686_unknown_linux_gnu.rs
@@ -18,7 +18,7 @@ pub fn target() -> Target {
         data_layout: "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string(),
         llvm_target: "i686-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "32".to_string(),
+        target_pointer_width: "32".to_string(),
         arch: "x86".to_string(),
         target_os: "linux".to_string(),
         options: base,
diff --git a/src/librustc_back/target/mips_unknown_linux_gnu.rs b/src/librustc_back/target/mips_unknown_linux_gnu.rs
index c8c5ddcbd0d..8acc248e234 100644
--- a/src/librustc_back/target/mips_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/mips_unknown_linux_gnu.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
                       -a:0:64-n32".to_string(),
         llvm_target: "mips-unknown-linux-gnu".to_string(),
         target_endian: "big".to_string(),
-        target_word_size: "32".to_string(),
+        target_pointer_width: "32".to_string(),
         arch: "mips".to_string(),
         target_os: "linux".to_string(),
         options: super::linux_base::opts()
diff --git a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs
index 3571f7b26c0..604c62eb69f 100644
--- a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
                       -a:0:64-n32".to_string(),
         llvm_target: "mipsel-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "32".to_string(),
+        target_pointer_width: "32".to_string(),
         arch: "mips".to_string(),
         target_os: "linux".to_string(),
 
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 23c8fc7de51..87897c28857 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -85,8 +85,8 @@ pub struct Target {
     pub llvm_target: String,
     /// String to use as the `target_endian` `cfg` variable.
     pub target_endian: String,
-    /// String to use as the `target_word_size` `cfg` variable.
-    pub target_word_size: String,
+    /// String to use as the `target_pointer_width` `cfg` variable.
+    pub target_pointer_width: String,
     /// OS name to use for conditional compilation.
     pub target_os: String,
     /// Architecture to use for ABI considerations. Valid options: "x86", "x86_64", "arm",
@@ -233,7 +233,7 @@ impl Target {
             data_layout: get_req_field("data-layout"),
             llvm_target: get_req_field("llvm-target"),
             target_endian: get_req_field("target-endian"),
-            target_word_size: get_req_field("target-word-size"),
+            target_pointer_width: get_req_field("target-word-size"),
             arch: get_req_field("arch"),
             target_os: get_req_field("os"),
             options: Default::default(),
diff --git a/src/librustc_back/target/x86_64_apple_darwin.rs b/src/librustc_back/target/x86_64_apple_darwin.rs
index 07e6cdfed2c..0ebd3bd3215 100644
--- a/src/librustc_back/target/x86_64_apple_darwin.rs
+++ b/src/librustc_back/target/x86_64_apple_darwin.rs
@@ -21,7 +21,7 @@ pub fn target() -> Target {
                       s0:64:64-f80:128:128-n8:16:32:64".to_string(),
         llvm_target: "x86_64-apple-darwin".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "64".to_string(),
+        target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "macos".to_string(),
         options: base,
diff --git a/src/librustc_back/target/x86_64_pc_windows_gnu.rs b/src/librustc_back/target/x86_64_pc_windows_gnu.rs
index 6ca74eb7fc0..9e1294a8962 100644
--- a/src/librustc_back/target/x86_64_pc_windows_gnu.rs
+++ b/src/librustc_back/target/x86_64_pc_windows_gnu.rs
@@ -23,7 +23,7 @@ pub fn target() -> Target {
                       s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
         llvm_target: "x86_64-pc-windows-gnu".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "64".to_string(),
+        target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "windows".to_string(),
         options: base,
diff --git a/src/librustc_back/target/x86_64_unknown_dragonfly.rs b/src/librustc_back/target/x86_64_unknown_dragonfly.rs
index bff3eaf6bc8..6635306b0e1 100644
--- a/src/librustc_back/target/x86_64_unknown_dragonfly.rs
+++ b/src/librustc_back/target/x86_64_unknown_dragonfly.rs
@@ -20,7 +20,7 @@ pub fn target() -> Target {
                      s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
         llvm_target: "x86_64-unknown-dragonfly".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "64".to_string(),
+        target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "dragonfly".to_string(),
         options: base,
diff --git a/src/librustc_back/target/x86_64_unknown_freebsd.rs b/src/librustc_back/target/x86_64_unknown_freebsd.rs
index 8d5603a3878..2aba2b8defb 100644
--- a/src/librustc_back/target/x86_64_unknown_freebsd.rs
+++ b/src/librustc_back/target/x86_64_unknown_freebsd.rs
@@ -20,7 +20,7 @@ pub fn target() -> Target {
                      s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
         llvm_target: "x86_64-unknown-freebsd".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "64".to_string(),
+        target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "freebsd".to_string(),
         options: base,
diff --git a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
index e0a67cd6250..d7a6df3a8b0 100644
--- a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
@@ -20,7 +20,7 @@ pub fn target() -> Target {
                       s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
         llvm_target: "x86_64-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
-        target_word_size: "64".to_string(),
+        target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "linux".to_string(),
         options: base,
diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs
index 26bcd5f4c10..452eaaaa52d 100644
--- a/src/librustc_borrowck/lib.rs
+++ b/src/librustc_borrowck/lib.rs
@@ -10,6 +10,7 @@
 
 #![crate_name = "rustc_borrowck"]
 #![experimental]
+#![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 5af114abeea..1c2d956e279 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -16,6 +16,7 @@
 
 #![crate_name = "rustc_driver"]
 #![experimental]
+#![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -46,7 +47,7 @@ pub use syntax::diagnostic;
 
 use rustc_trans::back::link;
 use rustc::session::{config, Session, build_session};
-use rustc::session::config::{Input, PrintRequest};
+use rustc::session::config::{Input, PrintRequest, UnstableFeatures};
 use rustc::lint::Lint;
 use rustc::lint;
 use rustc::metadata;
@@ -132,7 +133,11 @@ fn run_compiler(args: &[String]) {
         _ => early_error("multiple input filenames provided")
     };
 
+    let mut sopts = sopts;
+    sopts.unstable_features = get_unstable_features_setting();
+
     let mut sess = build_session(sopts, input_file_path, descriptions);
+
     let cfg = config::build_configuration(&sess);
     if print_crate_info(&sess, Some(&input), &odir, &ofile) {
         return
@@ -181,6 +186,21 @@ fn run_compiler(args: &[String]) {
     driver::compile_input(sess, cfg, &input, &odir, &ofile, None);
 }
 
+pub fn get_unstable_features_setting() -> UnstableFeatures {
+    // Whether this is a feature-staged build, i.e. on the beta or stable channel
+    let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
+    // The secret key needed to get through the rustc build itself by
+    // subverting the unstable features lints
+    let bootstrap_secret_key = option_env!("CFG_BOOTSTRAP_KEY");
+    // The matching key to the above, only known by the build system
+    let bootstrap_provided_key = os::getenv("RUSTC_BOOTSTRAP_KEY");
+    match (disable_unstable_features, bootstrap_secret_key, bootstrap_provided_key) {
+        (_, Some(ref s), Some(ref p)) if s == p => UnstableFeatures::Cheat,
+        (true, _, _) => UnstableFeatures::Disallow,
+        (false, _, _) => UnstableFeatures::Default
+    }
+}
+
 /// Returns a version string such as "0.12.0-dev".
 pub fn release_str() -> Option<&'static str> {
     option_env!("CFG_RELEASE")
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 0bed754aa3c..961d3a6cfa1 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -15,6 +15,7 @@
 
 #![crate_name = "rustc_llvm"]
 #![experimental]
+#![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 93ad69e03b1..f21297c60d6 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -10,6 +10,7 @@
 
 #![crate_name = "rustc_resolve"]
 #![experimental]
+#![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -2943,8 +2944,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                     HasTypeParameters(
                                         generics, FnSpace, foreign_item.id,
                                         ItemRibKind),
-                                    |this| visit::walk_foreign_item(this,
-                                                                    &**foreign_item));
+                                    |this| {
+                                        this.resolve_type_parameters(&generics.ty_params);
+                                        this.resolve_where_clause(&generics.where_clause);
+                                        visit::walk_foreign_item(this, &**foreign_item)
+                                    });
                             }
                             ForeignItemStatic(..) => {
                                 visit::walk_foreign_item(this,
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index b6f90a4c2f5..3497ff2221c 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -16,6 +16,7 @@
 
 #![crate_name = "rustc_trans"]
 #![experimental]
+#![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 057d0f378e6..39632f2b084 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -1128,7 +1128,7 @@ pub fn call_lifetime_end(cx: Block, ptr: ValueRef) {
 pub fn call_memcpy(cx: Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) {
     let _icx = push_ctxt("call_memcpy");
     let ccx = cx.ccx();
-    let key = match ccx.sess().target.target.target_word_size.index(&FullRange) {
+    let key = match ccx.sess().target.target.target_pointer_width.index(&FullRange) {
         "32" => "llvm.memcpy.p0i8.p0i8.i32",
         "64" => "llvm.memcpy.p0i8.p0i8.i64",
         tws => panic!("Unsupported target word size for memcpy: {}", tws),
@@ -1175,7 +1175,7 @@ fn memzero<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>) {
 
     let llty = type_of::type_of(ccx, ty);
 
-    let intrinsic_key = match ccx.sess().target.target.target_word_size.index(&FullRange) {
+    let intrinsic_key = match ccx.sess().target.target.target_pointer_width.index(&FullRange) {
         "32" => "llvm.memset.p0i8.i32",
         "64" => "llvm.memset.p0i8.i64",
         tws => panic!("Unsupported target word size for memset: {}", tws),
diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs
index 35fb34eafb4..d450ce24de7 100644
--- a/src/librustc_trans/trans/context.rs
+++ b/src/librustc_trans/trans/context.rs
@@ -721,7 +721,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
     /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
     /// address space on 64-bit ARMv8 and x86_64.
     pub fn obj_size_bound(&self) -> u64 {
-        match self.sess().target.target.target_word_size.index(&FullRange) {
+        match self.sess().target.target.target_pointer_width.index(&FullRange) {
             "32" => 1 << 31,
             "64" => 1 << 47,
             _ => unreachable!() // error handled by config::build_target_config
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index ed75445b993..b22c7f763f0 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -313,7 +313,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         (_, "size_of") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
             let lltp_ty = type_of::type_of(ccx, tp_ty);
-            C_uint(ccx, machine::llsize_of_real(ccx, lltp_ty))
+            C_uint(ccx, machine::llsize_of_alloc(ccx, lltp_ty))
         }
         (_, "min_align_of") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
diff --git a/src/librustc_trans/trans/machine.rs b/src/librustc_trans/trans/machine.rs
index 41738f1e58f..95d67cd54c1 100644
--- a/src/librustc_trans/trans/machine.rs
+++ b/src/librustc_trans/trans/machine.rs
@@ -43,8 +43,10 @@ pub fn llsize_of_alloc(cx: &CrateContext, ty: Type) -> llsize {
 
 // Returns, as near as we can figure, the "real" size of a type. As in, the
 // bits in this number of bytes actually carry data related to the datum
-// with the type. Not junk, padding, accidentally-damaged words, or
-// whatever. Rounds up to the nearest byte though, so if you have a 1-bit
+// with the type. Not junk, accidentally-damaged words, or whatever.
+// Note that padding of the type will be included for structs, but not for the
+// other types (i.e. SIMD types).
+// Rounds up to the nearest byte though, so if you have a 1-bit
 // value, we return 1 here, not 0. Most of rustc works in bytes. Be warned
 // that LLVM *does* distinguish between e.g. a 1-bit value and an 8-bit value
 // at the codegen level! In general you should prefer `llbitsize_of_real`
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index e2594765f4f..cc98ee9592b 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -32,7 +32,7 @@ use syntax::ast_map;
 use syntax::ast_util::{local_def, PostExpansionMethod};
 use syntax::attr;
 use syntax::codemap::DUMMY_SP;
-use std::hash::{sip, Hash};
+use std::hash::{Hasher, Hash, SipHasher};
 
 pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                 fn_id: ast::DefId,
@@ -125,11 +125,11 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     let hash;
     let s = {
-        let mut state = sip::SipState::new();
+        let mut state = SipHasher::new();
         hash_id.hash(&mut state);
         mono_ty.hash(&mut state);
 
-        hash = format!("h{}", state.result());
+        hash = format!("h{}", state.finish());
         ccx.tcx().map.with_path(fn_id.node, |path| {
             exported_name(path, hash.index(&FullRange))
         })
diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs
index 66e27ed1188..2e236154d48 100644
--- a/src/librustc_trans/trans/type_.rs
+++ b/src/librustc_trans/trans/type_.rs
@@ -103,7 +103,7 @@ impl Type {
     }
 
     pub fn int(ccx: &CrateContext) -> Type {
-        match ccx.tcx().sess.target.target.target_word_size.index(&FullRange) {
+        match ccx.tcx().sess.target.target.target_pointer_width.index(&FullRange) {
             "32" => Type::i32(ccx),
             "64" => Type::i64(ccx),
             tws => panic!("Unsupported target word size for int: {}", tws),
diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs
index 898a5f9fe0c..8b65895dad7 100644
--- a/src/librustc_typeck/check/wf.rs
+++ b/src/librustc_typeck/check/wf.rs
@@ -77,6 +77,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                     enum_variants(fcx, enum_def)
                 });
             }
+            ast::ItemTrait(..) => {
+                let trait_def =
+                    ty::lookup_trait_def(ccx.tcx, local_def(item.id));
+                reject_non_type_param_bounds(
+                    ccx.tcx,
+                    item.span,
+                    &trait_def.generics);
+            }
             _ => {}
         }
     }
@@ -237,21 +245,32 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
 fn reject_non_type_param_bounds<'tcx>(tcx: &ty::ctxt<'tcx>,
                                       span: Span,
                                       generics: &ty::Generics<'tcx>) {
+
     for predicate in generics.predicates.iter() {
         match predicate {
             &ty::Predicate::Trait(ty::Binder(ref tr)) => {
-                let self_ty = tr.self_ty();
-                if !self_ty.walk().any(|t| is_ty_param(t)) {
-                    tcx.sess.span_err(
-                        span,
-                        format!("cannot bound type `{}`, where clause \
-                                 bounds may only be attached to types involving \
-                                 type parameters",
-                                 self_ty.repr(tcx)).as_slice())
-                }
+                let found_param = tr.input_types().iter()
+                                    .flat_map(|ty| ty.walk())
+                                    .any(is_ty_param);
+                if !found_param { report_bound_error(tcx, span, tr.self_ty() )}
+            }
+            &ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(ty, _))) => {
+                let found_param = ty.walk().any(|t| is_ty_param(t));
+                if !found_param { report_bound_error(tcx, span, ty) }
             }
             _ => {}
-        }
+        };
+    }
+
+    fn report_bound_error<'t>(tcx: &ty::ctxt<'t>,
+                          span: Span,
+                          bounded_ty: ty::Ty<'t>) {
+        tcx.sess.span_err(
+            span,
+            format!("cannot bound type `{}`, where clause \
+                bounds may only be attached to types involving \
+                type parameters",
+                bounded_ty.repr(tcx)).as_slice())
     }
 
     fn is_ty_param(ty: ty::Ty) -> bool {
@@ -267,6 +286,24 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         self.check_item_well_formed(i);
         visit::walk_item(self, i);
     }
+
+    fn visit_trait_item(&mut self, t: &'v ast::TraitItem) {
+        match t {
+            &ast::TraitItem::ProvidedMethod(_) |
+            &ast::TraitItem::TypeTraitItem(_) => {},
+            &ast::TraitItem::RequiredMethod(ref method) => {
+                match ty::impl_or_trait_item(self.ccx.tcx, local_def(method.id)) {
+                    ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
+                        reject_non_type_param_bounds(
+                            self.ccx.tcx,
+                            method.span,
+                            &ty_method.generics)
+                    }
+                    _ => {}
+                }
+            }
+        }
+    }
 }
 
 pub struct BoundsChecker<'cx,'tcx:'cx> {
@@ -455,7 +492,6 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     let arg_tys =
                         ty::assert_no_late_bound_regions(
                             fcx.tcx(), &ty::ty_fn_args(ctor_ty));
-
                     AdtVariant {
                         fields: args.iter().enumerate().map(|(index, arg)| {
                             let arg_ty = arg_tys[index];
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index ae8731dfa47..85221c2e913 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -65,6 +65,7 @@ This API is completely unstable and subject to change.
 
 #![crate_name = "rustc_typeck"]
 #![experimental]
+#![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 46c212a9f2d..4885bd373eb 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -11,6 +11,7 @@ pub use self::MaybeTyped::*;
 
 use rustc_driver::driver;
 use rustc::session::{self, config};
+use rustc::session::config::UnstableFeatures;
 use rustc::session::search_paths::SearchPaths;
 use rustc::middle::{privacy, ty};
 use rustc::lint;
@@ -95,10 +96,11 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
         externs: externs,
         target_triple: triple.unwrap_or(config::host_triple().to_string()),
         cfg: config::parse_cfgspecs(cfgs),
+        // Ensure that rustdoc works even if rustc is feature-staged
+        unstable_features: UnstableFeatures::Default,
         ..config::basic_options().clone()
     };
 
-
     let codemap = codemap::CodeMap::new();
     let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None);
     let span_diagnostic_handler =
diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css
index a5a48254141..5951ac2bae7 100644
--- a/src/librustdoc/html/static/main.css
+++ b/src/librustdoc/html/static/main.css
@@ -157,7 +157,6 @@ nav.sub {
     left: 0;
     top: 0;
     min-height: 100%;
-    z-index: -1;
 }
 
 .content, nav { max-width: 960px; }
@@ -221,6 +220,7 @@ nav.sub {
 .content pre.line-numbers {
     float: left;
     border: none;
+    position: relative;
 
     -webkit-user-select: none;
     -moz-user-select: none;
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index ee65ef06623..daa930fddcb 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -10,6 +10,7 @@
 
 #![crate_name = "rustdoc"]
 #![experimental]
+#![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index bbe35eb0e9c..8e0f4b2d443 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -22,6 +22,7 @@ use std::collections::{HashSet, HashMap};
 use testing;
 use rustc::session::{self, config};
 use rustc::session::search_paths::{SearchPaths, PathKind};
+use rustc_driver::get_unstable_features_setting;
 use rustc_driver::driver;
 use syntax::ast;
 use syntax::codemap::{CodeMap, dummy_spanned};
@@ -52,6 +53,7 @@ pub fn run(input: &str,
         search_paths: libs.clone(),
         crate_types: vec!(config::CrateTypeDylib),
         externs: externs.clone(),
+        unstable_features: get_unstable_features_setting(),
         ..config::basic_options().clone()
     };
 
@@ -128,6 +130,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
             .. config::basic_codegen_options()
         },
         test: as_test_harness,
+        unstable_features: get_unstable_features_setting(),
         ..config::basic_options().clone()
     };
 
diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs
index d89a4754d2e..42498328ff6 100644
--- a/src/libserialize/collection_impls.rs
+++ b/src/libserialize/collection_impls.rs
@@ -13,6 +13,7 @@
 use std::uint;
 use std::default::Default;
 use std::hash::{Hash, Hasher};
+use std::collections::hash_state::HashState;
 
 use {Decodable, Encodable, Decoder, Encoder};
 use std::collections::{DList, RingBuf, BTreeMap, BTreeSet, HashMap, HashSet, VecMap};
@@ -156,13 +157,12 @@ impl<
     }
 }
 
-#[old_impl_check]
-impl<
-    K: Encodable + Hash<X> + Eq,
-    V: Encodable,
-    X,
-    H: Hasher<X>
-> Encodable for HashMap<K, V, H> {
+impl<K, V, S> Encodable for HashMap<K, V, S>
+    where K: Encodable + Hash< <S as HashState>::Hasher> + Eq,
+          V: Encodable,
+          S: HashState,
+          <S as HashState>::Hasher: Hasher<Output=u64>
+{
     fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
         e.emit_map(self.len(), |e| {
             let mut i = 0;
@@ -176,17 +176,16 @@ impl<
     }
 }
 
-#[old_impl_check]
-impl<
-    K: Decodable + Hash<S> + Eq,
-    V: Decodable,
-    S,
-    H: Hasher<S> + Default
-> Decodable for HashMap<K, V, H> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V, H>, D::Error> {
+impl<K, V, S> Decodable for HashMap<K, V, S>
+    where K: Decodable + Hash< <S as HashState>::Hasher> + Eq,
+          V: Decodable,
+          S: HashState + Default,
+          <S as HashState>::Hasher: Hasher<Output=u64>
+{
+    fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V, S>, D::Error> {
         d.read_map(|d, len| {
-            let hasher = Default::default();
-            let mut map = HashMap::with_capacity_and_hasher(len, hasher);
+            let state = Default::default();
+            let mut map = HashMap::with_capacity_and_hash_state(len, state);
             for i in range(0u, len) {
                 let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                 let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
@@ -197,12 +196,11 @@ impl<
     }
 }
 
-#[old_impl_check]
-impl<
-    T: Encodable + Hash<X> + Eq,
-    X,
-    H: Hasher<X>
-> Encodable for HashSet<T, H> {
+impl<T, S> Encodable for HashSet<T, S>
+    where T: Encodable + Hash< <S as HashState>::Hasher> + Eq,
+          S: HashState,
+          <S as HashState>::Hasher: Hasher<Output=u64>
+{
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             let mut i = 0;
@@ -215,15 +213,15 @@ impl<
     }
 }
 
-#[old_impl_check]
-impl<
-    T: Decodable + Hash<S> + Eq,
-    S,
-    H: Hasher<S> + Default
-> Decodable for HashSet<T, H> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T, H>, D::Error> {
+impl<T, S> Decodable for HashSet<T, S>
+    where T: Decodable + Hash< <S as HashState>::Hasher> + Eq,
+          S: HashState + Default,
+          <S as HashState>::Hasher: Hasher<Output=u64>
+{
+    fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T, S>, D::Error> {
         d.read_seq(|d, len| {
-            let mut set = HashSet::with_capacity_and_hasher(len, Default::default());
+            let state = Default::default();
+            let mut set = HashSet::with_capacity_and_hash_state(len, state);
             for i in range(0u, len) {
                 set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
             }
diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs
index fd0b5c55903..4b631d7ef9e 100644
--- a/src/libserialize/json.rs
+++ b/src/libserialize/json.rs
@@ -3473,7 +3473,7 @@ mod tests {
         }
     }
     #[test]
-    #[cfg_attr(target_word_size = "32", ignore)] // FIXME(#14064)
+    #[cfg_attr(target_pointer_width = "32", ignore)] // FIXME(#14064)
     fn test_streaming_parser() {
         assert_stream_equal(
             r#"{ "foo":"bar", "array" : [0, 1, 2, 3, 4, 5], "idents":[null,true,false]}"#,
@@ -3512,7 +3512,7 @@ mod tests {
     }
 
     #[test]
-    #[cfg_attr(target_word_size = "32", ignore)] // FIXME(#14064)
+    #[cfg_attr(target_pointer_width = "32", ignore)] // FIXME(#14064)
     fn test_read_object_streaming() {
         assert_eq!(last_event("{ "),      Error(SyntaxError(EOFWhileParsingObject, 1, 3)));
         assert_eq!(last_event("{1"),      Error(SyntaxError(KeyMustBeAString,      1, 2)));
@@ -3596,7 +3596,7 @@ mod tests {
         );
     }
     #[test]
-    #[cfg_attr(target_word_size = "32", ignore)] // FIXME(#14064)
+    #[cfg_attr(target_pointer_width = "32", ignore)] // FIXME(#14064)
     fn test_read_array_streaming() {
         assert_stream_equal(
             "[]",
diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs
index f0a51fcea18..d51f070632f 100644
--- a/src/libserialize/lib.rs
+++ b/src/libserialize/lib.rs
@@ -16,6 +16,7 @@ Core encoding and decoding interfaces.
 
 #![crate_name = "serialize"]
 #![unstable = "deprecated in favor of rustc-serialize on crates.io"]
+#![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -23,8 +24,9 @@ Core encoding and decoding interfaces.
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![allow(unknown_features)]
-#![feature(slicing_syntax)]
+#![cfg_attr(stage0, allow(unused_attributes))]
 #![feature(old_impl_check)]
+#![feature(slicing_syntax)]
 
 // test harness access
 #[cfg(test)] extern crate test;
diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs
index 5764962b51b..8dc41368e7f 100644
--- a/src/libstd/bitflags.rs
+++ b/src/libstd/bitflags.rs
@@ -273,7 +273,7 @@ macro_rules! bitflags {
 #[cfg(test)]
 #[allow(non_upper_case_globals)]
 mod tests {
-    use hash;
+    use hash::{self, SipHasher};
     use option::Option::{Some, None};
 
     bitflags! {
@@ -467,9 +467,9 @@ mod tests {
     fn test_hash() {
       let mut x = Flags::empty();
       let mut y = Flags::empty();
-      assert!(hash::hash(&x) == hash::hash(&y));
+      assert!(hash::hash::<Flags, SipHasher>(&x) == hash::hash::<Flags, SipHasher>(&y));
       x = Flags::all();
       y = FlagABC;
-      assert!(hash::hash(&x) == hash::hash(&y));
+      assert!(hash::hash::<Flags, SipHasher>(&x) == hash::hash::<Flags, SipHasher>(&y));
     }
 }
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index c3381d5cd64..c3bdfbb12d8 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -19,16 +19,15 @@ use clone::Clone;
 use cmp::{max, Eq, PartialEq};
 use default::Default;
 use fmt::{self, Show};
-use hash::{Hash, Hasher, RandomSipHasher};
+use hash::{self, Hash, SipHasher};
 use iter::{self, Iterator, IteratorExt, FromIterator, Extend, Map};
 use marker::Sized;
 use mem::{self, replace};
 use num::{Int, UnsignedInt};
 use ops::{Deref, FnMut, Index, IndexMut};
-use option::Option;
-use option::Option::{Some, None};
-use result::Result;
-use result::Result::{Ok, Err};
+use option::Option::{self, Some, None};
+use rand::{self, Rng};
+use result::Result::{self, Ok, Err};
 
 use super::table::{
     self,
@@ -44,6 +43,7 @@ use super::table::BucketState::{
     Empty,
     Full,
 };
+use super::state::HashState;
 
 const INITIAL_LOG2_CAP: uint = 5;
 pub const INITIAL_CAPACITY: uint = 1 << INITIAL_LOG2_CAP; // 2^5
@@ -297,9 +297,9 @@ fn test_resize_policy() {
 /// ```
 #[derive(Clone)]
 #[stable]
-pub struct HashMap<K, V, H = RandomSipHasher> {
+pub struct HashMap<K, V, S = RandomState> {
     // All hashes are keyed on these values, to prevent hash collision attacks.
-    hasher: H,
+    hash_state: S,
 
     table: RawTable<K, V>,
 
@@ -439,17 +439,20 @@ impl<K, V, M> SearchResult<K, V, M> {
     }
 }
 
-#[old_impl_check]
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
-    fn make_hash<X: ?Sized + Hash<S>>(&self, x: &X) -> SafeHash {
-        table::make_hash(&self.hasher, x)
+impl<K, V, S, H> HashMap<K, V, S>
+    where K: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
+    fn make_hash<X: ?Sized>(&self, x: &X) -> SafeHash where X: Hash<H> {
+        table::make_hash(&self.hash_state, x)
     }
 
     /// Search for a key, yielding the index if it's found in the hashtable.
     /// If you already have the hash for the key lying around, use
     /// search_hashed.
     fn search<'a, Q: ?Sized>(&'a self, q: &Q) -> Option<FullBucketImm<'a, K, V>>
-        where Q: BorrowFrom<K> + Eq + Hash<S>
+        where Q: BorrowFrom<K> + Eq + Hash<H>
     {
         let hash = self.make_hash(q);
         search_hashed(&self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k)))
@@ -457,7 +460,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     }
 
     fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> Option<FullBucketMut<'a, K, V>>
-        where Q: BorrowFrom<K> + Eq + Hash<S>
+        where Q: BorrowFrom<K> + Eq + Hash<H>
     {
         let hash = self.make_hash(q);
         search_hashed(&mut self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k)))
@@ -486,7 +489,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     }
 }
 
-impl<K: Hash + Eq, V> HashMap<K, V, RandomSipHasher> {
+impl<K: Hash<Hasher> + Eq, V> HashMap<K, V, RandomState> {
     /// Create an empty HashMap.
     ///
     /// # Example
@@ -497,9 +500,8 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomSipHasher> {
     /// ```
     #[inline]
     #[stable]
-    pub fn new() -> HashMap<K, V, RandomSipHasher> {
-        let hasher = RandomSipHasher::new();
-        HashMap::with_hasher(hasher)
+    pub fn new() -> HashMap<K, V, RandomState> {
+        Default::default()
     }
 
     /// Creates an empty hash map with the given initial capacity.
@@ -512,14 +514,16 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomSipHasher> {
     /// ```
     #[inline]
     #[stable]
-    pub fn with_capacity(capacity: uint) -> HashMap<K, V, RandomSipHasher> {
-        let hasher = RandomSipHasher::new();
-        HashMap::with_capacity_and_hasher(capacity, hasher)
+    pub fn with_capacity(capacity: uint) -> HashMap<K, V, RandomState> {
+        HashMap::with_capacity_and_hash_state(capacity, Default::default())
     }
 }
 
-#[old_impl_check]
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
+impl<K, V, S, H> HashMap<K, V, S>
+    where K: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
     /// Creates an empty hashmap which will use the given hasher to hash keys.
     ///
     /// The creates map has the default initial capacity.
@@ -528,17 +532,17 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     ///
     /// ```
     /// use std::collections::HashMap;
-    /// use std::hash::sip::SipHasher;
+    /// use std::collections::hash_map::RandomState;
     ///
-    /// let h = SipHasher::new();
-    /// let mut map = HashMap::with_hasher(h);
+    /// let s = RandomState::new();
+    /// let mut map = HashMap::with_hash_state(s);
     /// map.insert(1i, 2u);
     /// ```
     #[inline]
     #[unstable = "hasher stuff is unclear"]
-    pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
+    pub fn with_hash_state(hash_state: S) -> HashMap<K, V, S> {
         HashMap {
-            hasher:        hasher,
+            hash_state:    hash_state,
             resize_policy: DefaultResizePolicy::new(),
             table:         RawTable::new(0),
         }
@@ -556,21 +560,22 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     ///
     /// ```
     /// use std::collections::HashMap;
-    /// use std::hash::sip::SipHasher;
+    /// use std::collections::hash_map::RandomState;
     ///
-    /// let h = SipHasher::new();
-    /// let mut map = HashMap::with_capacity_and_hasher(10, h);
+    /// let s = RandomState::new();
+    /// let mut map = HashMap::with_capacity_and_hash_state(10, s);
     /// map.insert(1i, 2u);
     /// ```
     #[inline]
     #[unstable = "hasher stuff is unclear"]
-    pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashMap<K, V, H> {
+    pub fn with_capacity_and_hash_state(capacity: uint, hash_state: S)
+                                        -> HashMap<K, V, S> {
         let resize_policy = DefaultResizePolicy::new();
         let min_cap = max(INITIAL_CAPACITY, resize_policy.min_capacity(capacity));
         let internal_cap = min_cap.checked_next_power_of_two().expect("capacity overflow");
         assert!(internal_cap >= capacity, "capacity overflow");
         HashMap {
-            hasher:        hasher,
+            hash_state:    hash_state,
             resize_policy: resize_policy,
             table:         RawTable::new(internal_cap),
         }
@@ -1031,7 +1036,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// ```
     #[stable]
     pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
-        where Q: Hash<S> + Eq + BorrowFrom<K>
+        where Q: Hash<H> + Eq + BorrowFrom<K>
     {
         self.search(k).map(|bucket| bucket.into_refs().1)
     }
@@ -1054,7 +1059,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// ```
     #[stable]
     pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
-        where Q: Hash<S> + Eq + BorrowFrom<K>
+        where Q: Hash<H> + Eq + BorrowFrom<K>
     {
         self.search(k).is_some()
     }
@@ -1080,7 +1085,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// ```
     #[stable]
     pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
-        where Q: Hash<S> + Eq + BorrowFrom<K>
+        where Q: Hash<H> + Eq + BorrowFrom<K>
     {
         self.search_mut(k).map(|bucket| bucket.into_mut_refs().1)
     }
@@ -1132,7 +1137,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// ```
     #[stable]
     pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
-        where Q: Hash<S> + Eq + BorrowFrom<K>
+        where Q: Hash<H> + Eq + BorrowFrom<K>
     {
         if self.table.size() == 0 {
             return None
@@ -1189,10 +1194,12 @@ fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHas
     }
 }
 
-#[stable]
-#[old_impl_check]
-impl<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V, H> {
-    fn eq(&self, other: &HashMap<K, V, H>) -> bool {
+impl<K, V, S, H> PartialEq for HashMap<K, V, S>
+    where K: Eq + Hash<H>, V: PartialEq,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
+    fn eq(&self, other: &HashMap<K, V, S>) -> bool {
         if self.len() != other.len() { return false; }
 
         self.iter().all(|(key, value)|
@@ -1202,12 +1209,18 @@ impl<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V,
 }
 
 #[stable]
-#[old_impl_check]
-impl<K: Eq + Hash<S>, V: Eq, S, H: Hasher<S>> Eq for HashMap<K, V, H> {}
+impl<K, V, S, H> Eq for HashMap<K, V, S>
+    where K: Eq + Hash<H>, V: Eq,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{}
 
 #[stable]
-#[old_impl_check]
-impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H> {
+impl<K, V, S, H> Show for HashMap<K, V, S>
+    where K: Eq + Hash<H> + Show, V: Show,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "HashMap {{"));
 
@@ -1221,18 +1234,22 @@ impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H>
 }
 
 #[stable]
-#[old_impl_check]
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> {
-    #[stable]
-    fn default() -> HashMap<K, V, H> {
-        HashMap::with_hasher(Default::default())
+impl<K, V, S, H> Default for HashMap<K, V, S>
+    where K: Eq + Hash<H>,
+          S: HashState<Hasher=H> + Default,
+          H: hash::Hasher<Output=u64>
+{
+    fn default() -> HashMap<K, V, S> {
+        HashMap::with_hash_state(Default::default())
     }
 }
 
 #[stable]
-#[old_impl_check]
-impl<K: Hash<S> + Eq, Q: ?Sized, V, S, H: Hasher<S>> Index<Q> for HashMap<K, V, H>
-    where Q: BorrowFrom<K> + Hash<S> + Eq
+impl<K, Q: ?Sized, V, S, H> Index<Q> for HashMap<K, V, S>
+    where K: Eq + Hash<H>,
+          Q: Eq + Hash<H> + BorrowFrom<K>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
 {
     type Output = V;
 
@@ -1243,9 +1260,11 @@ impl<K: Hash<S> + Eq, Q: ?Sized, V, S, H: Hasher<S>> Index<Q> for HashMap<K, V,
 }
 
 #[stable]
-#[old_impl_check]
-impl<K: Hash<S> + Eq, Q: ?Sized, V, S, H: Hasher<S>> IndexMut<Q> for HashMap<K, V, H>
-    where Q: BorrowFrom<K> + Hash<S> + Eq
+impl<K, V, S, H, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
+    where K: Eq + Hash<H>,
+          Q: Eq + Hash<H> + BorrowFrom<K>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
 {
     type Output = V;
 
@@ -1473,19 +1492,26 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
 }
 
 #[stable]
-#[old_impl_check]
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for HashMap<K, V, H> {
-    fn from_iter<T: Iterator<Item=(K, V)>>(iter: T) -> HashMap<K, V, H> {
+impl<K, V, S, H> FromIterator<(K, V)> for HashMap<K, V, S>
+    where K: Eq + Hash<H>,
+          S: HashState<Hasher=H> + Default,
+          H: hash::Hasher<Output=u64>
+{
+    fn from_iter<T: Iterator<Item=(K, V)>>(iter: T) -> HashMap<K, V, S> {
         let lower = iter.size_hint().0;
-        let mut map = HashMap::with_capacity_and_hasher(lower, Default::default());
+        let mut map = HashMap::with_capacity_and_hash_state(lower,
+                                                            Default::default());
         map.extend(iter);
         map
     }
 }
 
 #[stable]
-#[old_impl_check]
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Extend<(K, V)> for HashMap<K, V, H> {
+impl<K, V, S, H> Extend<(K, V)> for HashMap<K, V, S>
+    where K: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
     fn extend<T: Iterator<Item=(K, V)>>(&mut self, mut iter: T) {
         for (k, v) in iter {
             self.insert(k, v);
@@ -1493,6 +1519,64 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Extend<(K, V)> for HashMap<K, V, H> {
     }
 }
 
+
+/// `RandomState` is the default state for `HashMap` types.
+///
+/// A particular instance `RandomState` will create the same instances of
+/// `Hasher`, but the hashers created by two different `RandomState`
+/// instances are unlikely to produce the same result for the same values.
+#[derive(Clone)]
+#[allow(missing_copy_implementations)]
+#[unstable = "hashing an hash maps may be altered"]
+pub struct RandomState {
+    k0: u64,
+    k1: u64,
+}
+
+#[unstable = "hashing an hash maps may be altered"]
+impl RandomState {
+    /// Construct a new `RandomState` that is initialized with random keys.
+    #[inline]
+    pub fn new() -> RandomState {
+        let mut r = rand::thread_rng();
+        RandomState { k0: r.gen(), k1: r.gen() }
+    }
+}
+
+#[unstable = "hashing an hash maps may be altered"]
+impl HashState for RandomState {
+    type Hasher = Hasher;
+    fn hasher(&self) -> Hasher {
+        Hasher { inner: SipHasher::new_with_keys(self.k0, self.k1) }
+    }
+}
+
+#[unstable = "hashing an hash maps may be altered"]
+impl Default for RandomState {
+    #[inline]
+    fn default() -> RandomState {
+        RandomState::new()
+    }
+}
+
+/// A hasher implementation which is generated from `RandomState` instances.
+///
+/// This is the default hasher used in a `HashMap` to hash keys. Types do not
+/// typically declare an ability to explicitly hash into this particular type,
+/// but rather in a `H: hash::Writer` type parameter.
+#[allow(missing_copy_implementations)]
+pub struct Hasher { inner: SipHasher }
+
+impl hash::Writer for Hasher {
+    fn write(&mut self, data: &[u8]) { self.inner.write(data) }
+}
+
+impl hash::Hasher for Hasher {
+    type Output = u64;
+    fn reset(&mut self) { self.inner.reset() }
+    fn finish(&self) -> u64 { self.inner.finish() }
+}
+
 #[cfg(test)]
 mod test_map {
     use prelude::v1::*;
diff --git a/src/libstd/collections/hash/mod.rs b/src/libstd/collections/hash/mod.rs
index ee3fc1e6ac3..47e300af269 100644
--- a/src/libstd/collections/hash/mod.rs
+++ b/src/libstd/collections/hash/mod.rs
@@ -11,6 +11,7 @@
 //! Unordered containers, implemented as hash-tables
 
 mod bench;
+mod table;
 pub mod map;
 pub mod set;
-mod table;
+pub mod state;
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index f66e5384942..4003d3addf1 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -17,12 +17,13 @@ use core::marker::Sized;
 use default::Default;
 use fmt::Show;
 use fmt;
-use hash::{Hash, Hasher, RandomSipHasher};
+use hash::{self, Hash};
 use iter::{Iterator, IteratorExt, FromIterator, Map, Chain, Extend};
 use ops::{BitOr, BitAnd, BitXor, Sub};
 use option::Option::{Some, None, self};
 
-use super::map::{self, HashMap, Keys, INITIAL_CAPACITY};
+use super::map::{self, HashMap, Keys, INITIAL_CAPACITY, RandomState, Hasher};
+use super::state::HashState;
 
 // Future Optimization (FIXME!)
 // =============================
@@ -90,11 +91,11 @@ use super::map::{self, HashMap, Keys, INITIAL_CAPACITY};
 /// ```
 #[derive(Clone)]
 #[stable]
-pub struct HashSet<T, H = RandomSipHasher> {
-    map: HashMap<T, (), H>
+pub struct HashSet<T, S = RandomState> {
+    map: HashMap<T, (), S>
 }
 
-impl<T: Hash + Eq> HashSet<T, RandomSipHasher> {
+impl<T: Hash<Hasher> + Eq> HashSet<T, RandomState> {
     /// Create an empty HashSet.
     ///
     /// # Example
@@ -105,7 +106,7 @@ impl<T: Hash + Eq> HashSet<T, RandomSipHasher> {
     /// ```
     #[inline]
     #[stable]
-    pub fn new() -> HashSet<T, RandomSipHasher> {
+    pub fn new() -> HashSet<T, RandomState> {
         HashSet::with_capacity(INITIAL_CAPACITY)
     }
 
@@ -120,13 +121,16 @@ impl<T: Hash + Eq> HashSet<T, RandomSipHasher> {
     /// ```
     #[inline]
     #[stable]
-    pub fn with_capacity(capacity: uint) -> HashSet<T, RandomSipHasher> {
+    pub fn with_capacity(capacity: uint) -> HashSet<T, RandomState> {
         HashSet { map: HashMap::with_capacity(capacity) }
     }
 }
 
-#[old_impl_check]
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
+impl<T, S, H> HashSet<T, S>
+    where T: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
     /// Creates a new empty hash set which will use the given hasher to hash
     /// keys.
     ///
@@ -136,16 +140,16 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     ///
     /// ```
     /// use std::collections::HashSet;
-    /// use std::hash::sip::SipHasher;
+    /// use std::collections::hash_map::RandomState;
     ///
-    /// let h = SipHasher::new();
-    /// let mut set = HashSet::with_hasher(h);
+    /// let s = RandomState::new();
+    /// let mut set = HashSet::with_hash_state(s);
     /// set.insert(2u);
     /// ```
     #[inline]
     #[unstable = "hasher stuff is unclear"]
-    pub fn with_hasher(hasher: H) -> HashSet<T, H> {
-        HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
+    pub fn with_hash_state(hash_state: S) -> HashSet<T, S> {
+        HashSet::with_capacity_and_hash_state(INITIAL_CAPACITY, hash_state)
     }
 
     /// Create an empty HashSet with space for at least `capacity`
@@ -160,16 +164,19 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     ///
     /// ```
     /// use std::collections::HashSet;
-    /// use std::hash::sip::SipHasher;
+    /// use std::collections::hash_map::RandomState;
     ///
-    /// let h = SipHasher::new();
-    /// let mut set = HashSet::with_capacity_and_hasher(10u, h);
+    /// let s = RandomState::new();
+    /// let mut set = HashSet::with_capacity_and_hash_state(10u, s);
     /// set.insert(1i);
     /// ```
     #[inline]
     #[unstable = "hasher stuff is unclear"]
-    pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet<T, H> {
-        HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
+    pub fn with_capacity_and_hash_state(capacity: uint, hash_state: S)
+                                        -> HashSet<T, S> {
+        HashSet {
+            map: HashMap::with_capacity_and_hash_state(capacity, hash_state),
+        }
     }
 
     /// Returns the number of elements the set can hold without reallocating.
@@ -300,7 +307,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(diff, [4i].iter().map(|&x| x).collect());
     /// ```
     #[stable]
-    pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> Difference<'a, T, H> {
+    pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S> {
         Difference {
             iter: self.iter(),
             other: other,
@@ -328,8 +335,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(diff1, [1i, 4].iter().map(|&x| x).collect());
     /// ```
     #[stable]
-    pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
-        -> SymmetricDifference<'a, T, H> {
+    pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, S>)
+        -> SymmetricDifference<'a, T, S> {
         SymmetricDifference { iter: self.difference(other).chain(other.difference(self)) }
     }
 
@@ -351,7 +358,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(diff, [2i, 3].iter().map(|&x| x).collect());
     /// ```
     #[stable]
-    pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>) -> Intersection<'a, T, H> {
+    pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> {
         Intersection {
             iter: self.iter(),
             other: other,
@@ -376,7 +383,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect());
     /// ```
     #[stable]
-    pub fn union<'a>(&'a self, other: &'a HashSet<T, H>) -> Union<'a, T, H> {
+    pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> {
         Union { iter: self.iter().chain(other.difference(self)) }
     }
 
@@ -452,7 +459,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// ```
     #[stable]
     pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
-        where Q: BorrowFrom<T> + Hash<S> + Eq
+        where Q: BorrowFrom<T> + Hash<H> + Eq
     {
         self.map.contains_key(value)
     }
@@ -475,7 +482,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(a.is_disjoint(&b), false);
     /// ```
     #[stable]
-    pub fn is_disjoint(&self, other: &HashSet<T, H>) -> bool {
+    pub fn is_disjoint(&self, other: &HashSet<T, S>) -> bool {
         self.iter().all(|v| !other.contains(v))
     }
 
@@ -496,7 +503,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(set.is_subset(&sup), false);
     /// ```
     #[stable]
-    pub fn is_subset(&self, other: &HashSet<T, H>) -> bool {
+    pub fn is_subset(&self, other: &HashSet<T, S>) -> bool {
         self.iter().all(|v| other.contains(v))
     }
 
@@ -521,7 +528,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// ```
     #[inline]
     #[stable]
-    pub fn is_superset(&self, other: &HashSet<T, H>) -> bool {
+    pub fn is_superset(&self, other: &HashSet<T, S>) -> bool {
         other.is_subset(self)
     }
 
@@ -562,16 +569,19 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// ```
     #[stable]
     pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
-        where Q: BorrowFrom<T> + Hash<S> + Eq
+        where Q: BorrowFrom<T> + Hash<H> + Eq
     {
         self.map.remove(value).is_some()
     }
 }
 
 #[stable]
-#[old_impl_check]
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
-    fn eq(&self, other: &HashSet<T, H>) -> bool {
+impl<T, S, H> PartialEq for HashSet<T, S>
+    where T: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
+    fn eq(&self, other: &HashSet<T, S>) -> bool {
         if self.len() != other.len() { return false; }
 
         self.iter().all(|key| other.contains(key))
@@ -579,12 +589,18 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
 }
 
 #[stable]
-#[old_impl_check]
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> Eq for HashSet<T, H> {}
+impl<T, S, H> Eq for HashSet<T, S>
+    where T: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{}
 
 #[stable]
-#[old_impl_check]
-impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
+impl<T, S, H> fmt::Show for HashSet<T, S>
+    where T: Eq + Hash<H> + fmt::Show,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "HashSet {{"));
 
@@ -598,19 +614,25 @@ impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
 }
 
 #[stable]
-#[old_impl_check]
-impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> {
-    fn from_iter<I: Iterator<Item=T>>(iter: I) -> HashSet<T, H> {
+impl<T, S, H> FromIterator<T> for HashSet<T, S>
+    where T: Eq + Hash<H>,
+          S: HashState<Hasher=H> + Default,
+          H: hash::Hasher<Output=u64>
+{
+    fn from_iter<I: Iterator<Item=T>>(iter: I) -> HashSet<T, S> {
         let lower = iter.size_hint().0;
-        let mut set = HashSet::with_capacity_and_hasher(lower, Default::default());
+        let mut set = HashSet::with_capacity_and_hash_state(lower, Default::default());
         set.extend(iter);
         set
     }
 }
 
 #[stable]
-#[old_impl_check]
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> Extend<T> for HashSet<T, H> {
+impl<T, S, H> Extend<T> for HashSet<T, S>
+    where T: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
+{
     fn extend<I: Iterator<Item=T>>(&mut self, mut iter: I) {
         for k in iter {
             self.insert(k);
@@ -619,21 +641,26 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> Extend<T> for HashSet<T, H> {
 }
 
 #[stable]
-#[old_impl_check]
-impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
+impl<T, S, H> Default for HashSet<T, S>
+    where T: Eq + Hash<H>,
+          S: HashState<Hasher=H> + Default,
+          H: hash::Hasher<Output=u64>
+{
     #[stable]
-    fn default() -> HashSet<T, H> {
-        HashSet::with_hasher(Default::default())
+    fn default() -> HashSet<T, S> {
+        HashSet::with_hash_state(Default::default())
     }
 }
 
 #[stable]
-#[old_impl_check]
-impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
-BitOr<&'b HashSet<T, H>> for &'a HashSet<T, H> {
-    type Output = HashSet<T, H>;
+impl<'a, 'b, T, S, H> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
+    where T: Eq + Hash<H> + Clone,
+          S: HashState<Hasher=H> + Default,
+          H: hash::Hasher<Output=u64>
+{
+    type Output = HashSet<T, S>;
 
-    /// Returns the union of `self` and `rhs` as a new `HashSet<T, H>`.
+    /// Returns the union of `self` and `rhs` as a new `HashSet<T, S>`.
     ///
     /// # Examples
     ///
@@ -653,18 +680,20 @@ BitOr<&'b HashSet<T, H>> for &'a HashSet<T, H> {
     /// }
     /// assert_eq!(i, expected.len());
     /// ```
-    fn bitor(self, rhs: &HashSet<T, H>) -> HashSet<T, H> {
+    fn bitor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
         self.union(rhs).cloned().collect()
     }
 }
 
 #[stable]
-#[old_impl_check]
-impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
-BitAnd<&'b HashSet<T, H>> for &'a HashSet<T, H> {
-    type Output = HashSet<T, H>;
+impl<'a, 'b, T, S, H> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
+    where T: Eq + Hash<H> + Clone,
+          S: HashState<Hasher=H> + Default,
+          H: hash::Hasher<Output=u64>
+{
+    type Output = HashSet<T, S>;
 
-    /// Returns the intersection of `self` and `rhs` as a new `HashSet<T, H>`.
+    /// Returns the intersection of `self` and `rhs` as a new `HashSet<T, S>`.
     ///
     /// # Examples
     ///
@@ -684,18 +713,20 @@ BitAnd<&'b HashSet<T, H>> for &'a HashSet<T, H> {
     /// }
     /// assert_eq!(i, expected.len());
     /// ```
-    fn bitand(self, rhs: &HashSet<T, H>) -> HashSet<T, H> {
+    fn bitand(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
         self.intersection(rhs).cloned().collect()
     }
 }
 
 #[stable]
-#[old_impl_check]
-impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
-BitXor<&'b HashSet<T, H>> for &'a HashSet<T, H> {
-    type Output = HashSet<T, H>;
+impl<'a, 'b, T, S, H> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
+    where T: Eq + Hash<H> + Clone,
+          S: HashState<Hasher=H> + Default,
+          H: hash::Hasher<Output=u64>
+{
+    type Output = HashSet<T, S>;
 
-    /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet<T, H>`.
+    /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet<T, S>`.
     ///
     /// # Examples
     ///
@@ -715,18 +746,20 @@ BitXor<&'b HashSet<T, H>> for &'a HashSet<T, H> {
     /// }
     /// assert_eq!(i, expected.len());
     /// ```
-    fn bitxor(self, rhs: &HashSet<T, H>) -> HashSet<T, H> {
+    fn bitxor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
         self.symmetric_difference(rhs).cloned().collect()
     }
 }
 
 #[stable]
-#[old_impl_check]
-impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
-Sub<&'b HashSet<T, H>> for &'a HashSet<T, H> {
-    type Output = HashSet<T, H>;
+impl<'a, 'b, T, S, H> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
+    where T: Eq + Hash<H> + Clone,
+          S: HashState<Hasher=H> + Default,
+          H: hash::Hasher<Output=u64>
+{
+    type Output = HashSet<T, S>;
 
-    /// Returns the difference of `self` and `rhs` as a new `HashSet<T, H>`.
+    /// Returns the difference of `self` and `rhs` as a new `HashSet<T, S>`.
     ///
     /// # Examples
     ///
@@ -746,7 +779,7 @@ Sub<&'b HashSet<T, H>> for &'a HashSet<T, H> {
     /// }
     /// assert_eq!(i, expected.len());
     /// ```
-    fn sub(self, rhs: &HashSet<T, H>) -> HashSet<T, H> {
+    fn sub(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
         self.difference(rhs).cloned().collect()
     }
 }
@@ -771,32 +804,32 @@ pub struct Drain<'a, K: 'a> {
 
 /// Intersection iterator
 #[stable]
-pub struct Intersection<'a, T: 'a, H: 'a> {
+pub struct Intersection<'a, T: 'a, S: 'a> {
     // iterator of the first set
     iter: Iter<'a, T>,
     // the second set
-    other: &'a HashSet<T, H>,
+    other: &'a HashSet<T, S>,
 }
 
 /// Difference iterator
 #[stable]
-pub struct Difference<'a, T: 'a, H: 'a> {
+pub struct Difference<'a, T: 'a, S: 'a> {
     // iterator of the first set
     iter: Iter<'a, T>,
     // the second set
-    other: &'a HashSet<T, H>,
+    other: &'a HashSet<T, S>,
 }
 
 /// Symmetric difference iterator.
 #[stable]
-pub struct SymmetricDifference<'a, T: 'a, H: 'a> {
-    iter: Chain<Difference<'a, T, H>, Difference<'a, T, H>>
+pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
+    iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>
 }
 
 /// Set union iterator.
 #[stable]
-pub struct Union<'a, T: 'a, H: 'a> {
-    iter: Chain<Iter<'a, T>, Difference<'a, T, H>>
+pub struct Union<'a, T: 'a, S: 'a> {
+    iter: Chain<Iter<'a, T>, Difference<'a, T, S>>
 }
 
 #[stable]
@@ -824,9 +857,10 @@ impl<'a, K: 'a> Iterator for Drain<'a, K> {
 }
 
 #[stable]
-#[old_impl_check]
-impl<'a, T, S, H> Iterator for Intersection<'a, T, H>
-    where T: Eq + Hash<S>, H: Hasher<S>
+impl<'a, T, S, H> Iterator for Intersection<'a, T, S>
+    where T: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
 {
     type Item = &'a T;
 
@@ -848,9 +882,10 @@ impl<'a, T, S, H> Iterator for Intersection<'a, T, H>
 }
 
 #[stable]
-#[old_impl_check]
-impl<'a, T, S, H> Iterator for Difference<'a, T, H>
-    where T: Eq + Hash<S>, H: Hasher<S>
+impl<'a, T, S, H> Iterator for Difference<'a, T, S>
+    where T: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
 {
     type Item = &'a T;
 
@@ -872,9 +907,10 @@ impl<'a, T, S, H> Iterator for Difference<'a, T, H>
 }
 
 #[stable]
-#[old_impl_check]
-impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, H>
-    where T: Eq + Hash<S>, H: Hasher<S>
+impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, S>
+    where T: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
 {
     type Item = &'a T;
 
@@ -883,9 +919,10 @@ impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, H>
 }
 
 #[stable]
-#[old_impl_check]
-impl<'a, T, S, H> Iterator for Union<'a, T, H>
-    where T: Eq + Hash<S>, H: Hasher<S>
+impl<'a, T, S, H> Iterator for Union<'a, T, S>
+    where T: Eq + Hash<H>,
+          S: HashState<Hasher=H>,
+          H: hash::Hasher<Output=u64>
 {
     type Item = &'a T;
 
diff --git a/src/libstd/collections/hash/state.rs b/src/libstd/collections/hash/state.rs
new file mode 100644
index 00000000000..ffbc958f179
--- /dev/null
+++ b/src/libstd/collections/hash/state.rs
@@ -0,0 +1,51 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use clone::Clone;
+use default::Default;
+use hash;
+
+/// A trait representing stateful hashes which can be used to hash keys in a
+/// `HashMap`.
+///
+/// A HashState is used as a factory for instances of `Hasher` which a `HashMap`
+/// can then use to hash keys independently. A `HashMap` by default uses a state
+/// which will create instances of a `SipHasher`, but a custom state factory can
+/// be provided to the `with_hash_state` function.
+///
+/// If a hashing algorithm has no initial state, then the `Hasher` type for that
+/// algorithm can implement the `Default` trait and create hash maps with the
+/// `DefaultState` structure. This state is 0-sized and will simply delegate
+/// to `Default` when asked to create a hasher.
+pub trait HashState {
+    type Hasher: hash::Hasher;
+
+    /// Creates a new hasher based on the given state of this object.
+    fn hasher(&self) -> Self::Hasher;
+}
+
+/// A structure which is a factory for instances of `Hasher` which implement the
+/// default trait.
+///
+/// This struct has is 0-sized and does not need construction.
+pub struct DefaultState<H>;
+
+impl<H: Default + hash::Hasher> HashState for DefaultState<H> {
+    type Hasher = H;
+    fn hasher(&self) -> H { Default::default() }
+}
+
+impl<H> Clone for DefaultState<H> {
+    fn clone(&self) -> DefaultState<H> { DefaultState }
+}
+
+impl<H> Default for DefaultState<H> {
+    fn default() -> DefaultState<H> { DefaultState }
+}
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 6eb98da4da4..e43cc053ba0 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -26,6 +26,7 @@ use option::Option::{Some, None};
 use ptr::{Unique, PtrExt, copy_nonoverlapping_memory, zero_memory};
 use ptr;
 use rt::heap::{allocate, deallocate};
+use collections::hash_state::HashState;
 
 const EMPTY_BUCKET: u64 = 0u64;
 
@@ -138,12 +139,18 @@ impl SafeHash {
 /// We need to remove hashes of 0. That's reserved for empty buckets.
 /// This function wraps up `hash_keyed` to be the only way outside this
 /// module to generate a SafeHash.
-pub fn make_hash<T: ?Sized + Hash<S>, S, H: Hasher<S>>(hasher: &H, t: &T) -> SafeHash {
+pub fn make_hash<T: ?Sized, S, H>(hash_state: &S, t: &T) -> SafeHash
+    where T: Hash<H>,
+          S: HashState<Hasher=H>,
+          H: Hasher<Output=u64>
+{
+    let mut state = hash_state.hasher();
+    t.hash(&mut state);
     // We need to avoid 0u64 in order to prevent collisions with
     // EMPTY_HASH. We can maintain our precious uniform distribution
     // of initial indexes by unconditionally setting the MSB,
     // effectively reducing 64-bits hashes to 63 bits.
-    SafeHash { hash: 0x8000_0000_0000_0000 | hasher.hash(t) }
+    SafeHash { hash: 0x8000_0000_0000_0000 | state.finish() }
 }
 
 // `replace` casts a `*u64` to a `*SafeHash`. Since we statically
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index 9b2a4926bcb..71ab89027ff 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -333,3 +333,10 @@ pub mod hash_set {
     //! A hashset
     pub use super::hash::set::*;
 }
+
+/// Experimental support for providing custom hash algorithms to a HashMap and
+/// HashSet.
+#[unstable = "module was recently added"]
+pub mod hash_state {
+    pub use super::hash::state::*;
+}
diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs
deleted file mode 100644
index 69e7e429d07..00000000000
--- a/src/libstd/hash.rs
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Generic hashing support.
-//!
-//! This module provides a generic way to compute the hash of a value. The
-//! simplest way to make a type hashable is to use `#[derive(Hash)]`:
-//!
-//! # Example
-//!
-//! ```rust
-//! use std::hash;
-//! use std::hash::Hash;
-//!
-//! #[derive(Hash)]
-//! struct Person {
-//!     id: uint,
-//!     name: String,
-//!     phone: u64,
-//! }
-//!
-//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
-//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
-//!
-//! assert!(hash::hash(&person1) != hash::hash(&person2));
-//! ```
-//!
-//! If you need more control over how a value is hashed, you need to implement
-//! the trait `Hash`:
-//!
-//! ```rust
-//! use std::hash;
-//! use std::hash::Hash;
-//! use std::hash::sip::SipState;
-//!
-//! struct Person {
-//!     id: uint,
-//!     name: String,
-//!     phone: u64,
-//! }
-//!
-//! impl Hash for Person {
-//!     fn hash(&self, state: &mut SipState) {
-//!         self.id.hash(state);
-//!         self.phone.hash(state);
-//!     }
-//! }
-//!
-//! let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
-//! let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
-//!
-//! assert!(hash::hash(&person1) == hash::hash(&person2));
-//! ```
-
-#![experimental]
-
-pub use core::hash::{Hash, Hasher, Writer, hash, sip};
-
-use core::marker::Sized;
-use default::Default;
-use rand::Rng;
-use rand;
-
-/// `RandomSipHasher` computes the SipHash algorithm from a stream of bytes
-/// initialized with random keys.
-#[derive(Clone)]
-pub struct RandomSipHasher {
-    hasher: sip::SipHasher,
-}
-
-impl RandomSipHasher {
-    /// Construct a new `RandomSipHasher` that is initialized with random keys.
-    #[inline]
-    pub fn new() -> RandomSipHasher {
-        let mut r = rand::thread_rng();
-        let r0 = r.gen();
-        let r1 = r.gen();
-        RandomSipHasher {
-            hasher: sip::SipHasher::new_with_keys(r0, r1),
-        }
-    }
-}
-
-impl Hasher<sip::SipState> for RandomSipHasher {
-    #[inline]
-    fn hash<T: ?Sized + Hash<sip::SipState>>(&self, value: &T) -> u64 {
-        self.hasher.hash(value)
-    }
-}
-
-#[stable]
-impl Default for RandomSipHasher {
-    #[stable]
-    #[inline]
-    fn default() -> RandomSipHasher {
-        RandomSipHasher::new()
-    }
-}
diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs
index 879f1192a4a..f824d821601 100644
--- a/src/libstd/io/process.rs
+++ b/src/libstd/io/process.rs
@@ -34,7 +34,7 @@ use sys::process::Process as ProcessImp;
 use sys;
 use thread::Thread;
 
-#[cfg(windows)] use std::hash::sip::SipState;
+#[cfg(windows)] use hash;
 #[cfg(windows)] use str;
 
 /// Signal a process to exit, without forcibly killing it. Corresponds to
@@ -98,7 +98,7 @@ pub struct Process {
 /// A representation of environment variable name
 /// It compares case-insensitive on Windows and case-sensitive everywhere else.
 #[cfg(not(windows))]
-#[derive(PartialEq, Eq, Hash, Clone, Show)]
+#[derive(Hash, PartialEq, Eq, Clone, Show)]
 struct EnvKey(CString);
 
 #[doc(hidden)]
@@ -107,8 +107,8 @@ struct EnvKey(CString);
 struct EnvKey(CString);
 
 #[cfg(windows)]
-impl Hash for EnvKey {
-    fn hash(&self, state: &mut SipState) {
+impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for EnvKey {
+    fn hash(&self, state: &mut H) {
         let &EnvKey(ref x) = self;
         match str::from_utf8(x.as_bytes()) {
             Ok(s) => for ch in s.chars() {
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index fa8cc6f4a18..c2daa08d4d3 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -96,6 +96,7 @@
 
 #![crate_name = "std"]
 #![stable]
+#![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -149,6 +150,7 @@ pub use core::clone;
 #[cfg(not(test))] pub use core::cmp;
 pub use core::default;
 pub use core::finally;
+pub use core::hash;
 pub use core::intrinsics;
 pub use core::iter;
 #[cfg(not(test))] pub use core::marker;
@@ -242,7 +244,6 @@ pub mod time;
 /* Common data structures */
 
 pub mod collections;
-pub mod hash;
 
 /* Threads and communication */
 
@@ -274,6 +275,7 @@ mod std {
     pub use clone;
     pub use cmp;
     pub use hash;
+    pub use default;
 
     pub use sync; // used for select!()
     pub use error; // used for try!()
diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs
index f433cd1e664..9c6911cf4d1 100644
--- a/src/libstd/num/mod.rs
+++ b/src/libstd/num/mod.rs
@@ -424,12 +424,14 @@ mod tests {
         assert_eq!(int::MIN.to_u32(),  None);
         assert_eq!(int::MIN.to_u64(),  None);
 
-        #[cfg(target_word_size = "32")]
+        #[cfg(any(all(stage0, target_word_size = "32"),
+                  all(not(stage0), target_pointer_width = "32")))]
         fn check_word_size() {
             assert_eq!(int::MIN.to_i32(), Some(int::MIN as i32));
         }
 
-        #[cfg(target_word_size = "64")]
+        #[cfg(any(all(stage0, target_word_size = "64"),
+                  all(not(stage0), target_pointer_width = "64")))]
         fn check_word_size() {
             assert_eq!(int::MIN.to_i32(), None);
         }
@@ -492,12 +494,14 @@ mod tests {
         assert_eq!(i64::MIN.to_u32(),  None);
         assert_eq!(i64::MIN.to_u64(),  None);
 
-        #[cfg(target_word_size = "32")]
+        #[cfg(any(all(stage0, target_word_size = "32"),
+                  all(not(stage0), target_pointer_width = "32")))]
         fn check_word_size() {
             assert_eq!(i64::MIN.to_int(), None);
         }
 
-        #[cfg(target_word_size = "64")]
+        #[cfg(any(all(stage0, target_word_size = "64"),
+                  all(not(stage0), target_pointer_width = "64")))]
         fn check_word_size() {
             assert_eq!(i64::MIN.to_int(), Some(i64::MIN as int));
         }
@@ -517,13 +521,15 @@ mod tests {
         // int::MAX.to_u32() is word-size specific
         assert_eq!(int::MAX.to_u64(),  Some(int::MAX as u64));
 
-        #[cfg(target_word_size = "32")]
+        #[cfg(any(all(stage0, target_word_size = "32"),
+                  all(not(stage0), target_pointer_width = "32")))]
         fn check_word_size() {
             assert_eq!(int::MAX.to_i32(), Some(int::MAX as i32));
             assert_eq!(int::MAX.to_u32(), Some(int::MAX as u32));
         }
 
-        #[cfg(target_word_size = "64")]
+        #[cfg(any(all(stage0, target_word_size = "64"),
+                  all(not(stage0), target_pointer_width = "64")))]
         fn check_word_size() {
             assert_eq!(int::MAX.to_i32(), None);
             assert_eq!(int::MAX.to_u32(), None);
@@ -587,13 +593,15 @@ mod tests {
         assert_eq!(i64::MAX.to_u32(),  None);
         assert_eq!(i64::MAX.to_u64(),  Some(i64::MAX as u64));
 
-        #[cfg(target_word_size = "32")]
+        #[cfg(any(all(stage0, target_word_size = "32"),
+                  all(not(stage0), target_pointer_width = "32")))]
         fn check_word_size() {
             assert_eq!(i64::MAX.to_int(),  None);
             assert_eq!(i64::MAX.to_uint(), None);
         }
 
-        #[cfg(target_word_size = "64")]
+        #[cfg(any(all(stage0, target_word_size = "64"),
+                  all(not(stage0), target_pointer_width = "64")))]
         fn check_word_size() {
             assert_eq!(i64::MAX.to_int(),  Some(i64::MAX as int));
             assert_eq!(i64::MAX.to_uint(), Some(i64::MAX as uint));
@@ -684,13 +692,15 @@ mod tests {
         // uint::MAX.to_u32() is word-size specific
         assert_eq!(uint::MAX.to_u64(),  Some(uint::MAX as u64));
 
-        #[cfg(target_word_size = "32")]
+        #[cfg(any(all(stage0, target_word_size = "32"),
+                  all(not(stage0), target_pointer_width = "32")))]
         fn check_word_size() {
             assert_eq!(uint::MAX.to_u32(), Some(uint::MAX as u32));
             assert_eq!(uint::MAX.to_i64(), Some(uint::MAX as i64));
         }
 
-        #[cfg(target_word_size = "64")]
+        #[cfg(any(all(stage0, target_word_size = "64"),
+                  all(not(stage0), target_pointer_width = "64")))]
         fn check_word_size() {
             assert_eq!(uint::MAX.to_u32(), None);
             assert_eq!(uint::MAX.to_i64(), None);
@@ -740,12 +750,14 @@ mod tests {
         assert_eq!(u32::MAX.to_u32(),  Some(u32::MAX as u32));
         assert_eq!(u32::MAX.to_u64(),  Some(u32::MAX as u64));
 
-        #[cfg(target_word_size = "32")]
+        #[cfg(any(all(stage0, target_word_size = "32"),
+                  all(not(stage0), target_pointer_width = "32")))]
         fn check_word_size() {
             assert_eq!(u32::MAX.to_int(),  None);
         }
 
-        #[cfg(target_word_size = "64")]
+        #[cfg(any(all(stage0, target_word_size = "64"),
+                  all(not(stage0), target_pointer_width = "64")))]
         fn check_word_size() {
             assert_eq!(u32::MAX.to_int(),  Some(u32::MAX as int));
         }
@@ -766,12 +778,14 @@ mod tests {
         assert_eq!(u64::MAX.to_u32(),  None);
         assert_eq!(u64::MAX.to_u64(),  Some(u64::MAX as u64));
 
-        #[cfg(target_word_size = "32")]
+        #[cfg(any(all(stage0, target_word_size = "32"),
+                  all(not(stage0), target_pointer_width = "32")))]
         fn check_word_size() {
             assert_eq!(u64::MAX.to_uint(), None);
         }
 
-        #[cfg(target_word_size = "64")]
+        #[cfg(any(all(stage0, target_word_size = "64"),
+                  all(not(stage0), target_pointer_width = "64")))]
         fn check_word_size() {
             assert_eq!(u64::MAX.to_uint(), Some(u64::MAX as uint));
         }
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index 0b7dc19fcab..b13278205b4 100644
--- a/src/libstd/path/posix.rs
+++ b/src/libstd/path/posix.rs
@@ -91,7 +91,7 @@ impl FromStr for Path {
     }
 }
 
-impl<S: hash::Writer> hash::Hash<S> for Path {
+impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
     #[inline]
     fn hash(&self, state: &mut S) {
         self.repr.hash(state)
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index 5c4e7aa9ac2..0a43c7b5140 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -118,7 +118,7 @@ impl FromStr for Path {
     }
 }
 
-impl<S: hash::Writer> hash::Hash<S> for Path {
+impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
     #[cfg(not(test))]
     #[inline]
     fn hash(&self, state: &mut S) {
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
index d3e6cd166ec..91e3b4a0687 100644
--- a/src/libstd/rand/mod.rs
+++ b/src/libstd/rand/mod.rs
@@ -230,9 +230,9 @@ use rc::Rc;
 use result::Result::{Ok, Err};
 use vec::Vec;
 
-#[cfg(not(target_word_size="64"))]
+#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
 use core_rand::IsaacRng as IsaacWordRng;
-#[cfg(target_word_size="64")]
+#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
 use core_rand::Isaac64Rng as IsaacWordRng;
 
 pub use core_rand::{Rand, Rng, SeedableRng, Open01, Closed01};
diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs
index be44aa99f49..f6161ec193d 100644
--- a/src/libstd/sys/common/backtrace.rs
+++ b/src/libstd/sys/common/backtrace.rs
@@ -12,8 +12,11 @@ use prelude::v1::*;
 
 use io::IoResult;
 
-#[cfg(target_word_size = "64")] pub const HEX_WIDTH: uint = 18;
-#[cfg(target_word_size = "32")] pub const HEX_WIDTH: uint = 10;
+#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
+pub const HEX_WIDTH: uint = 18;
+
+#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
+pub const HEX_WIDTH: uint = 10;
 
 // All rust symbols are in theory lists of "::"-separated identifiers. Some
 // assemblers, however, can't handle these characters in symbol names. To get
diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs
index cc661877bc0..1d523ed6edd 100644
--- a/src/libstd/sys/unix/c.rs
+++ b/src/libstd/sys/unix/c.rs
@@ -169,13 +169,13 @@ mod signal {
     unsafe impl ::marker::Sync for sigaction { }
 
     #[repr(C)]
-    #[cfg(target_word_size = "32")]
+    #[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
     pub struct sigset_t {
         __val: [libc::c_ulong; 32],
     }
 
     #[repr(C)]
-    #[cfg(target_word_size = "64")]
+    #[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
     pub struct sigset_t {
         __val: [libc::c_ulong; 16],
     }
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs
index 1357bbdd5a3..36bf696dba5 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -11,7 +11,8 @@
 use prelude::v1::*;
 use self::Req::*;
 
-use collections;
+use collections::HashMap;
+use collections::hash_map::Hasher;
 use ffi::CString;
 use hash::Hash;
 use io::process::{ProcessExit, ExitStatus, ExitSignal};
@@ -60,7 +61,7 @@ impl Process {
                               out_fd: Option<P>, err_fd: Option<P>)
                               -> IoResult<Process>
         where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
-              K: BytesContainer + Eq + Hash, V: BytesContainer
+              K: BytesContainer + Eq + Hash<Hasher>, V: BytesContainer
     {
         use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
         use libc::funcs::bsd44::getdtablesize;
@@ -553,11 +554,11 @@ fn with_argv<T,F>(prog: &CString, args: &[CString],
     cb(ptrs.as_ptr())
 }
 
-fn with_envp<K,V,T,F>(env: Option<&collections::HashMap<K, V>>,
+fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
                       cb: F)
                       -> T
     where F : FnOnce(*const c_void) -> T,
-          K : BytesContainer + Eq + Hash,
+          K : BytesContainer + Eq + Hash<Hasher>,
           V : BytesContainer
 {
     // On posixy systems we can pass a char** for envp, which is a
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index 1fd619a28db..48a51813ba4 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -182,12 +182,14 @@ mod imp {
             sa_restorer: *mut libc::c_void,
         }
 
-        #[cfg(target_word_size = "32")]
+        #[cfg(any(all(stage0, target_word_size = "32"),
+                  all(not(stage0), target_pointer_width = "32")))]
         #[repr(C)]
         pub struct sigset_t {
             __val: [libc::c_ulong; 32],
         }
-        #[cfg(target_word_size = "64")]
+        #[cfg(any(all(stage0, target_word_size = "64"),
+                  all(not(stage0), target_pointer_width = "64")))]
         #[repr(C)]
         pub struct sigset_t {
             __val: [libc::c_ulong; 16],
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 8e1f169b5cd..1b837385d1e 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -13,6 +13,7 @@ use prelude::v1::*;
 use collections;
 use ffi::CString;
 use hash::Hash;
+use collections::hash_map::Hasher;
 use io::fs::PathExtensions;
 use io::process::{ProcessExit, ExitStatus, ExitSignal};
 use io::{IoResult, IoError};
@@ -109,7 +110,7 @@ impl Process {
                               out_fd: Option<P>, err_fd: Option<P>)
                               -> IoResult<Process>
         where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
-              K: BytesContainer + Eq + Hash, V: BytesContainer
+              K: BytesContainer + Eq + Hash<Hasher>, V: BytesContainer
     {
         use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO};
         use libc::consts::os::extra::{
@@ -424,8 +425,10 @@ fn make_command_line(prog: &CString, args: &[CString]) -> String {
     }
 }
 
-fn with_envp<K, V, T, F>(env: Option<&collections::HashMap<K, V>>, cb: F) -> T where
-    K: BytesContainer + Eq + Hash, V: BytesContainer, F: FnOnce(*mut c_void) -> T,
+fn with_envp<K, V, T, F>(env: Option<&collections::HashMap<K, V>>, cb: F) -> T
+    where K: BytesContainer + Eq + Hash<Hasher>,
+          V: BytesContainer,
+          F: FnOnce(*mut c_void) -> T,
 {
     // On Windows we pass an "environment block" which is not a char**, but
     // rather a concatenation of null-terminated k=v\0 sequences, with a final
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 31fe23847d9..e4460ca865b 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -590,7 +590,12 @@ impl CodeMap {
                 Some(ref info) => {
                     // save the parent expn_id for next loop iteration
                     expnid = info.call_site.expn_id;
-                    if info.callee.span.is_none() {
+                    if info.callee.name == "format_args" {
+                        // This is a hack because the format_args builtin calls unstable APIs.
+                        // I spent like 6 hours trying to solve this more generally but am stupid.
+                        is_internal = true;
+                        false
+                    } else if info.callee.span.is_none() {
                         // it's a compiler built-in, we *really* don't want to mess with it
                         // so we skip it, unless it was called by a regular macro, in which case
                         // we will handle the caller macro next turn
diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs
index 844bd80d161..db99c142443 100644
--- a/src/libsyntax/ext/deriving/hash.rs
+++ b/src/libsyntax/ext/deriving/hash.rs
@@ -30,7 +30,8 @@ pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt,
     let generics = LifetimeBounds {
         lifetimes: Vec::new(),
         bounds: vec!(("__S",
-                      vec!(Path::new(vec!("std", "hash", "Writer"))))),
+                      vec!(Path::new(vec!("std", "hash", "Writer")),
+                           Path::new(vec!("std", "hash", "Hasher"))))),
     };
     let args = Path::new_local("__S");
     let inline = cx.meta_word(span, InternedString::new("inline"));
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 9e14f9dd1ea..7c8ccf3a1a1 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -16,6 +16,7 @@
 
 #![crate_name = "syntax"]
 #![experimental]
+#![staged_api]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs
index 8abb46011e6..13a14d069d7 100644
--- a/src/libsyntax/ptr.rs
+++ b/src/libsyntax/ptr.rs
@@ -37,9 +37,11 @@
 //!   Moreover, a switch to, e.g. `P<'a, T>` would be easy and mostly automated.
 
 use std::fmt::{self, Show};
-use std::hash::Hash;
+use std::hash::{Hash, Hasher};
+#[cfg(stage0)] use std::hash::Writer;
 use std::ops::Deref;
 use std::ptr;
+
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 
 /// An owned smart pointer.
@@ -105,7 +107,14 @@ impl<T: Show> Show for P<T> {
     }
 }
 
-impl<S, T: Hash<S>> Hash<S> for P<T> {
+#[cfg(stage0)]
+impl<S: Writer, T: Hash<S>> Hash<S> for P<T> {
+    fn hash(&self, state: &mut S) {
+        (**self).hash(state);
+    }
+}
+#[cfg(not(stage0))]
+impl<S: Hasher, T: Hash<S>> Hash<S> for P<T> {
     fn hash(&self, state: &mut S) {
         (**self).hash(state);
     }
diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs
index daa51203287..8e1a5860259 100644
--- a/src/libsyntax/std_inject.rs
+++ b/src/libsyntax/std_inject.rs
@@ -48,7 +48,7 @@ fn no_prelude(attrs: &[ast::Attribute]) -> bool {
 }
 
 struct StandardLibraryInjector<'a> {
-    alt_std_name: Option<String>,
+    alt_std_name: Option<String>
 }
 
 impl<'a> fold::Folder for StandardLibraryInjector<'a> {
@@ -84,14 +84,13 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> {
 
 fn inject_crates_ref(krate: ast::Crate, alt_std_name: Option<String>) -> ast::Crate {
     let mut fold = StandardLibraryInjector {
-        alt_std_name: alt_std_name,
+        alt_std_name: alt_std_name
     };
     fold.fold_crate(krate)
 }
 
 struct PreludeInjector<'a>;
 
-
 impl<'a> fold::Folder for PreludeInjector<'a> {
     fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
         // Add #![no_std] here, so we don't re-inject when compiling pretty-printed source.
@@ -104,20 +103,10 @@ impl<'a> fold::Folder for PreludeInjector<'a> {
         attr::mark_used(&no_std_attr);
         krate.attrs.push(no_std_attr);
 
+        // only add `use std::prelude::*;` if there wasn't a
+        // `#![no_implicit_prelude]` at the crate level.
+        // fold_mod() will insert glob path.
         if !no_prelude(krate.attrs.index(&FullRange)) {
-            // only add `use std::prelude::*;` if there wasn't a
-            // `#![no_implicit_prelude]` at the crate level.
-            // fold_mod() will insert glob path.
-            let globs_attr = attr::mk_attr_inner(attr::mk_attr_id(),
-                                                 attr::mk_list_item(
-                InternedString::new("feature"),
-                vec!(
-                    attr::mk_word_item(InternedString::new("globs")),
-                )));
-            // std_inject runs after feature checking so manually mark this attr
-            attr::mark_used(&globs_attr);
-            krate.attrs.push(globs_attr);
-
             krate.module = self.fold_mod(krate.module);
         }
         krate
diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs
index 93de342d487..7058fa64811 100644
--- a/src/libsyntax/util/interner.rs
+++ b/src/libsyntax/util/interner.rs
@@ -20,6 +20,7 @@ use std::cmp::Ordering;
 use std::collections::HashMap;
 use std::fmt;
 use std::hash::Hash;
+use std::collections::hash_map::Hasher;
 use std::ops::Deref;
 use std::rc::Rc;
 
@@ -28,8 +29,8 @@ pub struct Interner<T> {
     vect: RefCell<Vec<T> >,
 }
 
-// when traits can extend traits, we should extend index<Name,T> to get .index(&FullRange)
-impl<T: Eq + Hash + Clone + 'static> Interner<T> {
+// when traits can extend traits, we should extend index<Name,T> to get []
+impl<T: Eq + Hash<Hasher> + Clone + 'static> Interner<T> {
     pub fn new() -> Interner<T> {
         Interner {
             map: RefCell::new(HashMap::new()),
@@ -78,7 +79,7 @@ impl<T: Eq + Hash + Clone + 'static> Interner<T> {
     }
 
     pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
-    where Q: BorrowFrom<T> + Eq + Hash {
+    where Q: BorrowFrom<T> + Eq + Hash<Hasher> {
         let map = self.map.borrow();
         match (*map).get(val) {
             Some(v) => Some(*v),
@@ -203,7 +204,7 @@ impl StrInterner {
     }
 
     pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
-    where Q: BorrowFrom<RcStr> + Eq + Hash {
+    where Q: BorrowFrom<RcStr> + Eq + Hash<Hasher> {
         match (*self.map.borrow()).get(val) {
             Some(v) => Some(*v),
             None => None,
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
index c953f591d80..44ae00d997c 100644
--- a/src/libterm/lib.rs
+++ b/src/libterm/lib.rs
@@ -40,6 +40,7 @@
 
 #![crate_name = "term"]
 #![experimental = "use the crates.io `term` library instead"]
+#![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 68d06cc4dab..d21a73de6df 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -25,6 +25,7 @@
 
 #![crate_name = "test"]
 #![experimental]
+#![staged_api]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs
index 1abb52459e4..6061c4fd1d3 100644
--- a/src/libtest/stats.rs
+++ b/src/libtest/stats.rs
@@ -12,7 +12,7 @@
 
 use std::cmp::Ordering::{self, Less, Greater, Equal};
 use std::collections::hash_map::Entry::{Occupied, Vacant};
-use std::collections::hash_map;
+use std::collections::hash_map::{self, Hasher};
 use std::fmt;
 use std::hash::Hash;
 use std::io;
@@ -440,7 +440,7 @@ pub fn write_boxplot<W: Writer, T: Float + fmt::String + fmt::Show + FromPrimiti
 /// Returns a HashMap with the number of occurrences of every element in the
 /// sequence that the iterator exposes.
 pub fn freq_count<T, U>(mut iter: T) -> hash_map::HashMap<U, uint>
-  where T: Iterator<Item=U>, U: Eq + Clone + Hash
+  where T: Iterator<Item=U>, U: Eq + Clone + Hash<Hasher>
 {
     let mut map: hash_map::HashMap<U,uint> = hash_map::HashMap::new();
     for elem in iter {
diff --git a/src/libunicode/lib.rs b/src/libunicode/lib.rs
index db98b429e40..33b5bc4b5a4 100644
--- a/src/libunicode/lib.rs
+++ b/src/libunicode/lib.rs
@@ -22,6 +22,7 @@
 
 #![crate_name = "unicode"]
 #![experimental]
+#![staged_api]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs
index 1dcac9fe074..edeb07c960e 100644
--- a/src/test/bench/core-set.rs
+++ b/src/test/bench/core-set.rs
@@ -18,6 +18,7 @@ extern crate rand;
 use std::collections::BTreeSet;
 use std::collections::BitvSet;
 use std::collections::HashSet;
+use std::collections::hash_map::Hasher;
 use std::hash::Hash;
 use std::os;
 use std::time::Duration;
@@ -43,7 +44,7 @@ trait MutableSet<T> {
     fn contains(&self, k: &T) -> bool;
 }
 
-impl<T: Hash + Eq> MutableSet<T> for HashSet<T> {
+impl<T: Hash<Hasher> + Eq> MutableSet<T> for HashSet<T> {
     fn insert(&mut self, k: T) { self.insert(k); }
     fn remove(&mut self, k: &T) -> bool { self.remove(k) }
     fn contains(&self, k: &T) -> bool { self.contains(k) }
diff --git a/src/test/compile-fail/associated-types-multiple-types-one-trait.rs b/src/test/compile-fail/associated-types-multiple-types-one-trait.rs
new file mode 100644
index 00000000000..9436f825de8
--- /dev/null
+++ b/src/test/compile-fail/associated-types-multiple-types-one-trait.rs
@@ -0,0 +1,56 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo {
+    type X;
+    type Y;
+}
+
+fn have_x_want_x<T:Foo<X=u32>>(t: &T)
+{
+    want_x(t);
+}
+
+fn have_x_want_y<T:Foo<X=u32>>(t: &T)
+{
+    want_y(t); //~ ERROR type mismatch
+}
+
+fn have_y_want_x<T:Foo<Y=i32>>(t: &T)
+{
+    want_x(t); //~ ERROR type mismatch
+}
+
+fn have_y_want_y<T:Foo<Y=i32>>(t: &T)
+{
+    want_y(t);
+}
+
+fn have_xy_want_x<T:Foo<X=u32,Y=i32>>(t: &T)
+{
+    want_x(t);
+}
+
+fn have_xy_want_y<T:Foo<X=u32,Y=i32>>(t: &T)
+{
+    want_y(t);
+}
+
+fn have_xy_want_xy<T:Foo<X=u32,Y=i32>>(t: &T)
+{
+    want_x(t);
+    want_y(t);
+}
+
+fn want_x<T:Foo<X=u32>>(t: &T) { }
+
+fn want_y<T:Foo<Y=i32>>(t: &T) { }
+
+fn main() { }
diff --git a/src/test/compile-fail/extern-with-type-bounds.rs b/src/test/compile-fail/extern-with-type-bounds.rs
new file mode 100644
index 00000000000..8c7d00a9a11
--- /dev/null
+++ b/src/test/compile-fail/extern-with-type-bounds.rs
@@ -0,0 +1,33 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(intrinsics)]
+
+use std::intrinsics::TypeId;
+
+extern "rust-intrinsic" {
+    // Real example from libcore
+    fn type_id<T: ?Sized + 'static>() -> TypeId;
+
+    // Silent bounds made explicit to make sure they are actually
+    // resolved.
+    fn transmute<T: Sized, U: Sized>(val: T) -> U;
+
+    // Bounds aren't checked right now, so this should work
+    // even though it's incorrect.
+    fn size_of<T: Clone>() -> uint;
+
+    // Unresolved bounds should still error.
+    fn align_of<T: NoSuchTrait>() -> uint;
+    //~^ ERROR attempt to bound type parameter with a nonexistent trait `NoSuchTrait`
+}
+
+fn main() {}
+
diff --git a/src/test/compile-fail/feature-gate-feature-gate.rs b/src/test/compile-fail/feature-gate-feature-gate.rs
new file mode 100644
index 00000000000..b903b29658b
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-feature-gate.rs
@@ -0,0 +1,14 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![forbid(unstable_features)]
+#![feature(intrinsics)] //~ ERROR unstable feature
+
+fn main() { }
diff --git a/src/test/compile-fail/feature-gated-feature-in-macro-arg.rs b/src/test/compile-fail/feature-gated-feature-in-macro-arg.rs
index cd49c7c016e..1e15e67876e 100644
--- a/src/test/compile-fail/feature-gated-feature-in-macro-arg.rs
+++ b/src/test/compile-fail/feature-gated-feature-in-macro-arg.rs
@@ -8,6 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// FIXME #20661: format_args! emits calls to the unstable std::fmt::rt
+// module, so the compiler has some hacks to make that possible
+// (in span_is_internal). Unnfortunately those hacks defeat this
+// particular scenario of checking feature gates in arguments to
+// println!().
+
+// ignore-test
+
 // tests that input to a macro is checked for use of gated features. If this
 // test succeeds due to the acceptance of a feature, pick a new feature to
 // test. Not ideal, but oh well :(
diff --git a/src/test/compile-fail/huge-enum.rs b/src/test/compile-fail/huge-enum.rs
index 7c7a75abf3f..aef1fa85e0d 100644
--- a/src/test/compile-fail/huge-enum.rs
+++ b/src/test/compile-fail/huge-enum.rs
@@ -12,12 +12,12 @@
 
 // FIXME: work properly with higher limits
 
-#[cfg(target_word_size = "32")]
+#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
 fn main() {
     let big: Option<[u32; (1<<29)-1]> = None;
 }
 
-#[cfg(target_word_size = "64")]
+#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
 fn main() {
     let big: Option<[u32; (1<<45)-1]> = None;
 }
diff --git a/src/test/compile-fail/issue-17913.rs b/src/test/compile-fail/issue-17913.rs
index 3224edb381c..7ae8dfef9bc 100644
--- a/src/test/compile-fail/issue-17913.rs
+++ b/src/test/compile-fail/issue-17913.rs
@@ -10,14 +10,14 @@
 
 // error-pattern: too big for the current architecture
 
-#[cfg(target_word_size = "64")]
+#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
 fn main() {
     let n = 0u;
     let a = box [&n; 0xF000000000000000u];
     println!("{}", a[0xFFFFFFu]);
 }
 
-#[cfg(target_word_size = "32")]
+#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
 fn main() {
     let n = 0u;
     let a = box [&n; 0xFFFFFFFFu];
diff --git a/src/test/compile-fail/where-clauses-not-parameter.rs b/src/test/compile-fail/where-clauses-not-parameter.rs
index 148473f8987..d8af859c081 100644
--- a/src/test/compile-fail/where-clauses-not-parameter.rs
+++ b/src/test/compile-fail/where-clauses-not-parameter.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn equal<T>(_: &T, _: &T) -> bool where int : Eq {
+fn equal<T>(_: &T, _: &T) -> bool where isize : Eq {
     true //~^ ERROR cannot bound type `isize`, where clause bounds may only be attached
 }
 
@@ -16,24 +16,26 @@ fn equal<T>(_: &T, _: &T) -> bool where int : Eq {
 fn test<T: Eq>() -> bool where Option<T> : Eq {}
 
 // This should be rejected as well.
-fn test2() -> bool where Option<int> : Eq {}
-//~^ ERROR cannot bound type `core::option::Option<isize>`, where clause bounds
+fn test2() -> bool where Option<isize> : Eq {}
+//~^ ERROR cannot bound type `core::option::Option<isize>`, where clause bounds may
 
 #[derive(PartialEq)]
 //~^ ERROR cannot bound type `isize`, where clause bounds
-enum Foo<T> where int : Eq { MkFoo }
+enum Foo<T> where isize : Eq { MkFoo }
 //~^ ERROR cannot bound type `isize`, where clause bounds
 
 fn test3<T: Eq>() -> bool where Option<Foo<T>> : Eq {}
 
-fn test4() -> bool where Option<Foo<int>> : Eq {}
+fn test4() -> bool where Option<Foo<isize>> : Eq {}
 //~^ ERROR cannot bound type `core::option::Option<Foo<isize>>`, where clause bounds
 
-trait Baz<T> where int : Eq {
-    fn baz() where String : Eq;
+trait Baz<T> where isize : Eq {
+    //~^ ERROR cannot bound type `isize`, where clause bounds may only
+    fn baz() where String : Eq; //~ ERROR cannot bound type `collections::string::String`
+    //~^ ERROR cannot bound type `isize`, where clause
 }
 
-impl Baz<int> for int where int : Eq {
+impl Baz<int> for int where isize : Eq {
     //~^ ERROR cannot bound type `isize`, where clause bounds
     fn baz() where String : Eq {}
 }
diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp
index f20087ef677..dac6e628d10 100644
--- a/src/test/pretty/issue-4264.pp
+++ b/src/test/pretty/issue-4264.pp
@@ -1,5 +1,4 @@
 #![no_std]
-#![feature(globs)]
 #[macro_use]
 extern crate "std" as std;
 #[prelude_import]
diff --git a/src/test/run-pass/deriving-hash.rs b/src/test/run-pass/deriving-hash.rs
index ddad703d7df..02ab7e5db5b 100644
--- a/src/test/run-pass/deriving-hash.rs
+++ b/src/test/run-pass/deriving-hash.rs
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-use std::hash;
-use std::hash::Hash;
+use std::hash::{Hash, SipHasher};
 
 #[derive(Hash)]
 struct Person {
@@ -19,6 +17,10 @@ struct Person {
     phone: uint,
 }
 
+fn hash<T: Hash<SipHasher>>(t: &T) -> u64 {
+    std::hash::hash::<T, SipHasher>(t)
+}
+
 fn main() {
     let person1 = Person {
         id: 5,
@@ -30,6 +32,6 @@ fn main() {
         name: "Bob".to_string(),
         phone: 555_666_7777
     };
-    assert!(hash::hash(&person1) == hash::hash(&person1));
-    assert!(hash::hash(&person1) != hash::hash(&person2));
+    assert!(hash(&person1) == hash(&person1));
+    assert!(hash(&person1) != hash(&person2));
 }
diff --git a/src/test/run-pass/deriving-meta-multiple.rs b/src/test/run-pass/deriving-meta-multiple.rs
index c435a1f344d..f45dce9da63 100644
--- a/src/test/run-pass/deriving-meta-multiple.rs
+++ b/src/test/run-pass/deriving-meta-multiple.rs
@@ -9,7 +9,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::hash::hash;
+use std::hash::{Hash, SipHasher};
 
 // testing multiple separate deriving attributes
 #[derive(PartialEq)]
@@ -20,6 +20,8 @@ struct Foo {
     baz: int
 }
 
+fn hash<T: Hash<SipHasher>>(_t: &T) {}
+
 pub fn main() {
     let a = Foo {bar: 4, baz: -3};
 
diff --git a/src/test/run-pass/deriving-meta.rs b/src/test/run-pass/deriving-meta.rs
index 54dc2b97b77..d6a2fad08ed 100644
--- a/src/test/run-pass/deriving-meta.rs
+++ b/src/test/run-pass/deriving-meta.rs
@@ -9,7 +9,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::hash::hash;
+use std::hash::{Hash, SipHasher};
 
 #[derive(PartialEq, Clone, Hash)]
 struct Foo {
@@ -17,6 +17,8 @@ struct Foo {
     baz: int
 }
 
+fn hash<T: Hash<SipHasher>>(_t: &T) {}
+
 pub fn main() {
     let a = Foo {bar: 4, baz: -3};
 
diff --git a/src/test/run-pass/drop-trait-enum.rs b/src/test/run-pass/drop-trait-enum.rs
index f1cc4fb1724..6addfc59a3d 100644
--- a/src/test/run-pass/drop-trait-enum.rs
+++ b/src/test/run-pass/drop-trait-enum.rs
@@ -66,7 +66,7 @@ pub fn main() {
     assert_eq!(receiver.recv().ok(), None);
 
     let (sender, receiver) = channel();
-    let _t = Thread::spawn(move|| {
+    let _t = Thread::scoped(move|| {
         let v = Foo::FailingVariant { on_drop: SendOnDrop { sender: sender } };
     });
     assert_eq!(receiver.recv().unwrap(), Message::Dropped);
@@ -74,7 +74,7 @@ pub fn main() {
 
     let (sender, receiver) = channel();
     let _t = {
-        Thread::spawn(move|| {
+        Thread::scoped(move|| {
             let mut v = Foo::NestedVariant(box 42u, SendOnDrop {
                 sender: sender.clone()
             }, sender.clone());
diff --git a/src/test/run-pass/extern-stress.rs b/src/test/run-pass/extern-stress.rs
index bb9e9407382..c3e04177cce 100644
--- a/src/test/run-pass/extern-stress.rs
+++ b/src/test/run-pass/extern-stress.rs
@@ -42,7 +42,7 @@ fn count(n: libc::uintptr_t) -> libc::uintptr_t {
 
 pub fn main() {
     range(0u, 100).map(|_| {
-        Thread::spawn(move|| {
+        Thread::scoped(move|| {
             assert_eq!(count(5), 16);
         })
     }).collect::<Vec<_>>();
diff --git a/src/test/run-pass/extern-yield.rs b/src/test/run-pass/extern-yield.rs
index 46829e9ba6e..f5e91b9de67 100644
--- a/src/test/run-pass/extern-yield.rs
+++ b/src/test/run-pass/extern-yield.rs
@@ -39,7 +39,7 @@ fn count(n: libc::uintptr_t) -> libc::uintptr_t {
 
 pub fn main() {
     range(0, 10u).map(|i| {
-        Thread::spawn(move|| {
+        Thread::scoped(move|| {
             let result = count(5);
             println!("result = {}", result);
             assert_eq!(result, 16);
diff --git a/src/test/run-pass/huge-largest-array.rs b/src/test/run-pass/huge-largest-array.rs
index e24731546ed..e1b0c115365 100644
--- a/src/test/run-pass/huge-largest-array.rs
+++ b/src/test/run-pass/huge-largest-array.rs
@@ -10,12 +10,12 @@
 
 use std::mem::size_of;
 
-#[cfg(target_word_size = "32")]
+#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
 pub fn main() {
     assert_eq!(size_of::<[u8; (1 << 31) - 1]>(), (1 << 31) - 1);
 }
 
-#[cfg(target_word_size = "64")]
+#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
 pub fn main() {
     assert_eq!(size_of::<[u8; (1 << 47) - 1]>(), (1 << 47) - 1);
 }
diff --git a/src/test/run-pass/issue-9396.rs b/src/test/run-pass/issue-9396.rs
index 34bb50c5cf6..73355d15a27 100644
--- a/src/test/run-pass/issue-9396.rs
+++ b/src/test/run-pass/issue-9396.rs
@@ -15,7 +15,7 @@ use std::time::Duration;
 
 pub fn main() {
     let (tx, rx) = channel();
-    let _t = Thread::spawn(move||{
+    let _t = Thread::scoped(move||{
         let mut timer = Timer::new().unwrap();
         timer.sleep(Duration::milliseconds(10));
         tx.send(()).unwrap();
diff --git a/src/test/run-pass/simd-size-align.rs b/src/test/run-pass/simd-size-align.rs
new file mode 100644
index 00000000000..582810f0def
--- /dev/null
+++ b/src/test/run-pass/simd-size-align.rs
@@ -0,0 +1,70 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(simd)]
+#![allow(non_camel_case_types)]
+
+use std::mem;
+
+/// `T` should satisfy `size_of T (mod min_align_of T) === 0` to be stored at `Vec<T>` properly
+/// Please consult the issue #20460
+fn check<T>() {
+    assert_eq!(mem::size_of::<T>() % mem::min_align_of::<T>(), 0)
+}
+
+fn main() {
+    check::<u8x2>();
+    check::<u8x3>();
+    check::<u8x4>();
+    check::<u8x5>();
+    check::<u8x6>();
+    check::<u8x7>();
+    check::<u8x8>();
+
+    check::<i16x2>();
+    check::<i16x3>();
+    check::<i16x4>();
+    check::<i16x5>();
+    check::<i16x6>();
+    check::<i16x7>();
+    check::<i16x8>();
+
+    check::<f32x2>();
+    check::<f32x3>();
+    check::<f32x4>();
+    check::<f32x5>();
+    check::<f32x6>();
+    check::<f32x7>();
+    check::<f32x8>();
+}
+
+#[simd] struct u8x2(u8, u8);
+#[simd] struct u8x3(u8, u8, u8);
+#[simd] struct u8x4(u8, u8, u8, u8);
+#[simd] struct u8x5(u8, u8, u8, u8, u8);
+#[simd] struct u8x6(u8, u8, u8, u8, u8, u8);
+#[simd] struct u8x7(u8, u8, u8, u8, u8, u8, u8);
+#[simd] struct u8x8(u8, u8, u8, u8, u8, u8, u8, u8);
+
+#[simd] struct i16x2(i16, i16);
+#[simd] struct i16x3(i16, i16, i16);
+#[simd] struct i16x4(i16, i16, i16, i16);
+#[simd] struct i16x5(i16, i16, i16, i16, i16);
+#[simd] struct i16x6(i16, i16, i16, i16, i16, i16);
+#[simd] struct i16x7(i16, i16, i16, i16, i16, i16, i16);
+#[simd] struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
+
+#[simd] struct f32x2(f32, f32);
+#[simd] struct f32x3(f32, f32, f32);
+#[simd] struct f32x4(f32, f32, f32, f32);
+#[simd] struct f32x5(f32, f32, f32, f32, f32);
+#[simd] struct f32x6(f32, f32, f32, f32, f32, f32);
+#[simd] struct f32x7(f32, f32, f32, f32, f32, f32, f32);
+#[simd] struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32);
diff --git a/src/test/run-pass/tcp-accept-stress.rs b/src/test/run-pass/tcp-accept-stress.rs
index cd3cb872fd3..cad71732034 100644
--- a/src/test/run-pass/tcp-accept-stress.rs
+++ b/src/test/run-pass/tcp-accept-stress.rs
@@ -34,11 +34,11 @@ fn test() {
 
     let (srv_tx, srv_rx) = channel();
     let (cli_tx, cli_rx) = channel();
-    for _ in range(0, N) {
+    let _t = range(0, N).map(|_| {
         let a = a.clone();
         let cnt = cnt.clone();
         let srv_tx = srv_tx.clone();
-        Thread::spawn(move|| {
+        Thread::scoped(move|| {
             let mut a = a;
             loop {
                 match a.accept() {
@@ -52,18 +52,18 @@ fn test() {
                 }
             }
             srv_tx.send(());
-        });
-    }
+        })
+    }).collect::<Vec<_>>();
 
-    for _ in range(0, N) {
+    let _t = range(0, N).map(|_| {
         let cli_tx = cli_tx.clone();
-        Thread::spawn(move|| {
+        Thread::scoped(move|| {
             for _ in range(0, M) {
                 let _s = TcpStream::connect(addr).unwrap();
             }
             cli_tx.send(());
-        });
-    }
+        })
+    }).collect::<Vec<_>>();
     drop((cli_tx, srv_tx));
 
     // wait for senders
diff --git a/src/test/run-pass/threads.rs b/src/test/run-pass/threads.rs
index c47ca0db2a1..abc2938df00 100644
--- a/src/test/run-pass/threads.rs
+++ b/src/test/run-pass/threads.rs
@@ -13,7 +13,7 @@ use std::thread::Thread;
 pub fn main() {
     let mut i = 10;
     while i > 0 {
-        Thread::spawn({let i = i; move|| child(i)});
+        Thread::scoped({let i = i; move|| child(i)});
         i = i - 1;
     }
     println!("main thread exiting");
diff --git a/src/test/run-pass/typeid-intrinsic.rs b/src/test/run-pass/typeid-intrinsic.rs
index bba043ea8f8..e346c4ff349 100644
--- a/src/test/run-pass/typeid-intrinsic.rs
+++ b/src/test/run-pass/typeid-intrinsic.rs
@@ -14,7 +14,7 @@
 extern crate "typeid-intrinsic" as other1;
 extern crate "typeid-intrinsic2" as other2;
 
-use std::hash;
+use std::hash::{self, SipHasher};
 use std::intrinsics;
 use std::intrinsics::TypeId;
 
@@ -70,5 +70,6 @@ pub fn main() {
     // check it has a hash
     let (a, b) = (TypeId::of::<uint>(), TypeId::of::<uint>());
 
-    assert_eq!(hash::hash(&a), hash::hash(&b));
+    assert_eq!(hash::hash::<TypeId, SipHasher>(&a),
+               hash::hash::<TypeId, SipHasher>(&b));
 }
diff --git a/src/test/run-pass/unique-send-2.rs b/src/test/run-pass/unique-send-2.rs
index bb3019ede4b..ba75c7629b5 100644
--- a/src/test/run-pass/unique-send-2.rs
+++ b/src/test/run-pass/unique-send-2.rs
@@ -19,13 +19,13 @@ pub fn main() {
     let (tx, rx) = channel();
     let n = 100u;
     let mut expected = 0u;
-    for i in range(0u, n) {
+    let _t = range(0u, n).map(|i| {
+        expected += i;
         let tx = tx.clone();
-        Thread::spawn(move|| {
+        Thread::scoped(move|| {
             child(&tx, i)
-        });
-        expected += i;
-    }
+        })
+    }).collect::<Vec<_>>();
 
     let mut actual = 0u;
     for _ in range(0u, n) {
diff --git a/src/test/run-pass/unwind-resource.rs b/src/test/run-pass/unwind-resource.rs
index 3f59b2c6c76..159bac10183 100644
--- a/src/test/run-pass/unwind-resource.rs
+++ b/src/test/run-pass/unwind-resource.rs
@@ -37,7 +37,7 @@ fn f(tx: Sender<bool>) {
 
 pub fn main() {
     let (tx, rx) = channel();
-    let _t = Thread::spawn(move|| f(tx.clone()));
+    let _t = Thread::scoped(move|| f(tx.clone()));
     println!("hiiiiiiiii");
     assert!(rx.recv().unwrap());
 }
diff --git a/src/test/run-pass/vec-fixed-length.rs b/src/test/run-pass/vec-fixed-length.rs
index 20e1becd008..101999bbe08 100644
--- a/src/test/run-pass/vec-fixed-length.rs
+++ b/src/test/run-pass/vec-fixed-length.rs
@@ -21,7 +21,7 @@ pub fn main() {
 
     // FIXME #10183
     // FIXME #18069
-    //if cfg!(target_word_size = "64") {
+    //if cfg!(target_pointer_width = "64") {
     //    assert_eq!(size_of::<[u8; (1 << 32)]>(), (1u << 32));
     //}
 }