about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-01-02 12:16:41 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-01-02 13:51:50 -0800
commit340f3fd7a909b30509a63916df06f2b885d113f7 (patch)
tree344f3d621e187b41d23ef01f621ff68ebe810a03
parent8cf9929a9a901b68d4624167542924e8b181e96a (diff)
parent1abee08cbdbd62a83805aa5b5068df9e00471f06 (diff)
downloadrust-340f3fd7a909b30509a63916df06f2b885d113f7.tar.gz
rust-340f3fd7a909b30509a63916df06f2b885d113f7.zip
rollup merge of #20410: japaric/assoc-types
Conflicts:
	src/liballoc/lib.rs
	src/libcollections/lib.rs
	src/libcollections/slice.rs
	src/libcore/ops.rs
	src/libcore/prelude.rs
	src/libcore/ptr.rs
	src/librustc/middle/traits/project.rs
	src/libstd/c_str.rs
	src/libstd/io/mem.rs
	src/libstd/io/mod.rs
	src/libstd/lib.rs
	src/libstd/path/posix.rs
	src/libstd/path/windows.rs
	src/libstd/prelude.rs
	src/libstd/rt/exclusive.rs
	src/libsyntax/lib.rs
	src/test/compile-fail/issue-18566.rs
	src/test/run-pass/deref-mut-on-ref.rs
	src/test/run-pass/deref-on-ref.rs
	src/test/run-pass/dst-deref-mut.rs
	src/test/run-pass/dst-deref.rs
	src/test/run-pass/fixup-deref-mut.rs
	src/test/run-pass/issue-13264.rs
	src/test/run-pass/overloaded-autoderef-indexing.rs
-rw-r--r--src/liballoc/arc.rs4
-rw-r--r--src/liballoc/boxed.rs8
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/rc.rs4
-rw-r--r--src/libcollections/btree/map.rs6
-rw-r--r--src/libcollections/btree/node.rs48
-rw-r--r--src/libcollections/lib.rs4
-rw-r--r--src/libcollections/slice.rs499
-rw-r--r--src/libcollections/string.rs11
-rw-r--r--src/libcollections/vec.rs14
-rw-r--r--src/libcore/array.rs4
-rw-r--r--src/libcore/borrow.rs4
-rw-r--r--src/libcore/cell.rs10
-rw-r--r--src/libcore/iter.rs8
-rw-r--r--src/libcore/nonzero.rs4
-rw-r--r--src/libcore/ops.rs34
-rw-r--r--src/libcore/option.rs2
-rw-r--r--src/libcore/prelude.rs1
-rw-r--r--src/libcore/ptr.rs24
-rw-r--r--src/libcore/slice.rs319
-rw-r--r--src/librustc/middle/traits/project.rs40
-rw-r--r--src/librustc/middle/traits/select.rs46
-rw-r--r--src/librustc/middle/ty.rs2
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs6
-rw-r--r--src/librustc_resolve/check_unused.rs6
-rw-r--r--src/librustc_resolve/lib.rs1
-rw-r--r--src/librustc_resolve/record_exports.rs6
-rw-r--r--src/librustdoc/html/render.rs32
-rw-r--r--src/libstd/c_str.rs2
-rw-r--r--src/libstd/collections/hash/map.rs2
-rw-r--r--src/libstd/collections/hash/table.rs16
-rw-r--r--src/libstd/io/comm_adapters.rs2
-rw-r--r--src/libstd/io/mem.rs2
-rw-r--r--src/libstd/io/mod.rs4
-rw-r--r--src/libstd/io/net/ip.rs2
-rw-r--r--src/libstd/io/stdio.rs6
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/macros.rs3
-rw-r--r--src/libstd/num/strconv.rs2
-rw-r--r--src/libstd/os.rs1
-rw-r--r--src/libstd/path/mod.rs3
-rw-r--r--src/libstd/path/posix.rs5
-rw-r--r--src/libstd/path/windows.rs2
-rw-r--r--src/libstd/prelude/v1.rs4
-rw-r--r--src/libstd/sync/mutex.rs6
-rw-r--r--src/libstd/sync/rwlock.rs10
-rw-r--r--src/libsyntax/lib.rs1
-rw-r--r--src/libsyntax/owned_slice.rs4
-rw-r--r--src/libsyntax/parse/token.rs4
-rw-r--r--src/libsyntax/ptr.rs4
-rw-r--r--src/libsyntax/util/interner.rs4
-rw-r--r--src/snapshots.txt9
-rw-r--r--src/test/auxiliary/overloaded_autoderef_xc.rs6
-rw-r--r--src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs34
-rw-r--r--src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs8
-rw-r--r--src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs6
-rw-r--r--src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs8
-rw-r--r--src/test/compile-fail/borrowck-borrow-overloaded-deref.rs6
-rw-r--r--src/test/compile-fail/infinite-autoderef.rs6
-rw-r--r--src/test/compile-fail/issue-18566.rs6
-rw-r--r--src/test/run-pass/associated-types-conditional-dispatch.rs73
-rw-r--r--src/test/run-pass/deref-mut-on-ref.rs4
-rw-r--r--src/test/run-pass/deref-on-ref.rs2
-rw-r--r--src/test/run-pass/dst-deref-mut.rs8
-rw-r--r--src/test/run-pass/dst-deref.rs6
-rw-r--r--src/test/run-pass/fixup-deref-mut.rs8
-rw-r--r--src/test/run-pass/issue-13264.rs10
-rw-r--r--src/test/run-pass/issue-16774.rs8
-rw-r--r--src/test/run-pass/overloaded-autoderef-count.rs8
-rw-r--r--src/test/run-pass/overloaded-autoderef-indexing.rs6
-rw-r--r--src/test/run-pass/overloaded-autoderef-order.rs10
-rw-r--r--src/test/run-pass/overloaded-autoderef-vtable.rs6
-rw-r--r--src/test/run-pass/overloaded-deref-count.rs8
-rw-r--r--src/test/run-pass/tcp-stress.rs2
74 files changed, 898 insertions, 588 deletions
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index aa5a7586118..59106aa9777 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -247,7 +247,9 @@ impl<T> BorrowFrom<Arc<T>> for T {
 }
 
 #[experimental = "Deref is experimental."]
-impl<T> Deref<T> for Arc<T> {
+impl<T> Deref for Arc<T> {
+    type Target = T;
+
     #[inline]
     fn deref(&self) -> &T {
         &self.inner().data
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 5f8789bf1c7..e836b08459b 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -155,11 +155,13 @@ impl fmt::Show for Box<Any> {
     }
 }
 
-impl<Sized? T> Deref<T> for Box<T> {
+impl<Sized? T> Deref for Box<T> {
+    type Target = T;
+
     fn deref(&self) -> &T { &**self }
 }
 
-impl<Sized? T> DerefMut<T> for Box<T> {
+impl<Sized? T> DerefMut for Box<T> {
     fn deref_mut(&mut self) -> &mut T { &mut **self }
 }
 
@@ -212,7 +214,7 @@ mod test {
 
     #[test]
     fn deref() {
-        fn homura<T: Deref<i32>>(_: T) { }
+        fn homura<T: Deref<Target=i32>>(_: T) { }
         homura(box 765i32);
     }
 }
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index d17a54ce6e5..aab513ddeb7 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -66,6 +66,7 @@
 #![no_std]
 #![allow(unknown_features)]
 #![feature(lang_items, phase, unsafe_destructor, default_type_params, old_orphan_check)]
+#![feature(associated_types)]
 
 #[phase(plugin, link)]
 extern crate core;
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index bd250938836..c57231fc434 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -355,7 +355,9 @@ impl<T> BorrowFrom<Rc<T>> for T {
 }
 
 #[experimental = "Deref is experimental."]
-impl<T> Deref<T> for Rc<T> {
+impl<T> Deref for Rc<T> {
+    type Target = T;
+
     #[inline(always)]
     fn deref(&self) -> &T {
         &self.inner().value
diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs
index 6d41883dc8d..da98c19e888 100644
--- a/src/libcollections/btree/map.rs
+++ b/src/libcollections/btree/map.rs
@@ -518,13 +518,15 @@ mod stack {
         marker: marker::InvariantLifetime<'id>
     }
 
-    impl<'id, T> Deref<T> for IdRef<'id, T> {
+    impl<'id, T> Deref for IdRef<'id, T> {
+        type Target = T;
+
         fn deref(&self) -> &T {
             &*self.inner
         }
     }
 
-    impl<'id, T> DerefMut<T> for IdRef<'id, T> {
+    impl<'id, T> DerefMut for IdRef<'id, T> {
         fn deref_mut(&mut self) -> &mut T {
             &mut *self.inner
         }
diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs
index 05356368365..3dddcae11ce 100644
--- a/src/libcollections/btree/node.rs
+++ b/src/libcollections/btree/node.rs
@@ -457,7 +457,9 @@ impl<K: Clone, V: Clone> Clone for Node<K, V> {
 ///     flag: &'a Cell<bool>,
 /// }
 ///
-/// impl<'a> Deref<Node<uint, uint>> for Nasty<'a> {
+/// impl<'a> Deref for Nasty<'a> {
+///     type Target = Node<uint, uint>;
+///
 ///     fn deref(&self) -> &Node<uint, uint> {
 ///         if self.flag.get() {
 ///             &*self.second
@@ -513,7 +515,7 @@ impl<K: Ord, V> Node<K, V> {
     /// Searches for the given key in the node. If it finds an exact match,
     /// `Found` will be yielded with the matching index. If it doesn't find an exact match,
     /// `GoDown` will be yielded with the index of the subtree the key must lie in.
-    pub fn search<Sized? Q, NodeRef: Deref<Node<K, V>>>(node: NodeRef, key: &Q)
+    pub fn search<Sized? Q, NodeRef: Deref<Target=Node<K, V>>>(node: NodeRef, key: &Q)
                   -> SearchResult<NodeRef> where Q: BorrowFrom<K> + Ord {
         // FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V).
         // For the B configured as of this writing (B = 6), binary search was *significantly*
@@ -590,7 +592,7 @@ impl <K, V> Node<K, V> {
     }
 }
 
-impl<K, V, NodeRef: Deref<Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, NodeType> {
+impl<K, V, NodeRef: Deref<Target=Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, NodeType> {
     /// Returns a reference to the node that contains the pointed-to edge or key/value pair. This
     /// is very different from `edge` and `edge_mut` because those return children of the node
     /// returned by `node`.
@@ -599,7 +601,9 @@ impl<K, V, NodeRef: Deref<Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, Nod
     }
 }
 
-impl<K, V, NodeRef: DerefMut<Node<K, V>>, Type, NodeType> Handle<NodeRef, Type, NodeType> {
+impl<K, V, NodeRef, Type, NodeType> Handle<NodeRef, Type, NodeType> where
+    NodeRef: Deref<Target=Node<K, V>> + DerefMut,
+{
     /// Converts a handle into one that stores the same information using a raw pointer. This can
     /// be useful in conjunction with `from_raw` when the type system is insufficient for
     /// determining the lifetimes of the nodes.
@@ -655,7 +659,7 @@ impl<'a, K: 'a, V: 'a> Handle<&'a mut Node<K, V>, handle::Edge, handle::Internal
     }
 }
 
-impl<K, V, NodeRef: Deref<Node<K, V>>> Handle<NodeRef, handle::Edge, handle::Internal> {
+impl<K, V, NodeRef: Deref<Target=Node<K, V>>> Handle<NodeRef, handle::Edge, handle::Internal> {
     // This doesn't exist because there are no uses for it,
     // but is fine to add, analagous to edge_mut.
     //
@@ -669,7 +673,7 @@ pub enum ForceResult<NodeRef, Type> {
     Internal(Handle<NodeRef, Type, handle::Internal>)
 }
 
-impl<K, V, NodeRef: Deref<Node<K, V>>, Type> Handle<NodeRef, Type, handle::LeafOrInternal> {
+impl<K, V, NodeRef: Deref<Target=Node<K, V>>, Type> Handle<NodeRef, Type, handle::LeafOrInternal> {
     /// Figure out whether this handle is pointing to something in a leaf node or to something in
     /// an internal node, clarifying the type according to the result.
     pub fn force(self) -> ForceResult<NodeRef, Type> {
@@ -686,8 +690,9 @@ impl<K, V, NodeRef: Deref<Node<K, V>>, Type> Handle<NodeRef, Type, handle::LeafO
         }
     }
 }
-
-impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::Edge, handle::Leaf> {
+impl<K, V, NodeRef> Handle<NodeRef, handle::Edge, handle::Leaf> where
+    NodeRef: Deref<Target=Node<K, V>> + DerefMut,
+{
     /// Tries to insert this key-value pair at the given index in this leaf node
     /// If the node is full, we have to split it.
     ///
@@ -719,7 +724,9 @@ impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::Edge, handle::
     }
 }
 
-impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::Edge, handle::Internal> {
+impl<K, V, NodeRef> Handle<NodeRef, handle::Edge, handle::Internal> where
+    NodeRef: Deref<Target=Node<K, V>> + DerefMut,
+{
     /// Returns a mutable reference to the edge pointed-to by this handle. This should not be
     /// confused with `node`, which references the parent node of what is returned here.
     pub fn edge_mut(&mut self) -> &mut Node<K, V> {
@@ -802,7 +809,9 @@ impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::Edge, handle::
     }
 }
 
-impl<K, V, NodeRef: DerefMut<Node<K, V>>, NodeType> Handle<NodeRef, handle::Edge, NodeType> {
+impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::Edge, NodeType> where
+    NodeRef: Deref<Target=Node<K, V>> + DerefMut,
+{
     /// Gets the handle pointing to the key/value pair just to the left of the pointed-to edge.
     /// This is unsafe because the handle might point to the first edge in the node, which has no
     /// pair to its left.
@@ -864,7 +873,7 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a mut Node<K, V>, handle::KV, NodeType
     }
 }
 
-impl<'a, K: 'a, V: 'a, NodeRef: Deref<Node<K, V>> + 'a, NodeType> Handle<NodeRef, handle::KV,
+impl<'a, K: 'a, V: 'a, NodeRef: Deref<Target=Node<K, V>> + 'a, NodeType> Handle<NodeRef, handle::KV,
                                                                          NodeType> {
     // These are fine to include, but are currently unneeded.
     //
@@ -883,8 +892,9 @@ impl<'a, K: 'a, V: 'a, NodeRef: Deref<Node<K, V>> + 'a, NodeType> Handle<NodeRef
     // }
 }
 
-impl<'a, K: 'a, V: 'a, NodeRef: DerefMut<Node<K, V>> + 'a, NodeType> Handle<NodeRef, handle::KV,
-                                                                            NodeType> {
+impl<'a, K: 'a, V: 'a, NodeRef, NodeType> Handle<NodeRef, handle::KV, NodeType> where
+    NodeRef: 'a + Deref<Target=Node<K, V>> + DerefMut,
+{
     /// Returns a mutable reference to the key pointed-to by this handle. This doesn't return a
     /// reference with a lifetime as large as `into_kv_mut`, but it also does not consume the
     /// handle.
@@ -900,7 +910,9 @@ impl<'a, K: 'a, V: 'a, NodeRef: DerefMut<Node<K, V>> + 'a, NodeType> Handle<Node
     }
 }
 
-impl<K, V, NodeRef: DerefMut<Node<K, V>>, NodeType> Handle<NodeRef, handle::KV, NodeType> {
+impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::KV, NodeType> where
+    NodeRef: Deref<Target=Node<K, V>> + DerefMut,
+{
     /// Gets the handle pointing to the edge immediately to the left of the key/value pair pointed
     /// to by this handle.
     pub fn left_edge<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> {
@@ -920,7 +932,9 @@ impl<K, V, NodeRef: DerefMut<Node<K, V>>, NodeType> Handle<NodeRef, handle::KV,
     }
 }
 
-impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::KV, handle::Leaf> {
+impl<K, V, NodeRef> Handle<NodeRef, handle::KV, handle::Leaf> where
+    NodeRef: Deref<Target=Node<K, V>> + DerefMut,
+{
     /// Removes the key/value pair at the handle's location.
     ///
     /// # Panics (in debug build)
@@ -931,7 +945,9 @@ impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::KV, handle::Le
     }
 }
 
-impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::KV, handle::Internal> {
+impl<K, V, NodeRef> Handle<NodeRef, handle::KV, handle::Internal> where
+    NodeRef: Deref<Target=Node<K, V>> + DerefMut
+{
     /// Steal! Stealing is roughly analogous to a binary tree rotation.
     /// In this case, we're "rotating" right.
     unsafe fn steal_rightward(&mut self) {
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index 82175c39494..fac9ab8107a 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -26,6 +26,7 @@
 #![feature(unsafe_destructor, slicing_syntax)]
 #![feature(unboxed_closures)]
 #![feature(old_orphan_check)]
+#![feature(associated_types)]
 #![no_std]
 
 #[phase(plugin, link)] extern crate core;
@@ -121,7 +122,6 @@ mod prelude {
     pub use core::result::Result::{Ok, Err};
 
     // in core and collections (may differ).
-    pub use slice::{PartialEqSliceExt, OrdSliceExt};
     pub use slice::{AsSlice, SliceExt};
     pub use str::{from_str, Str, StrExt};
 
@@ -130,7 +130,7 @@ mod prelude {
     pub use unicode::char::UnicodeChar;
 
     // from collections.
-    pub use slice::{CloneSliceExt, SliceConcatExt};
+    pub use slice::SliceConcatExt;
     pub use str::IntoMaybeOwned;
     pub use string::{String, ToString};
     pub use vec::Vec;
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index 9e2b4b77910..1c1b48f8cef 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -91,7 +91,7 @@ use alloc::boxed::Box;
 use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned};
 use core::clone::Clone;
 use core::cmp::Ordering::{mod, Greater, Less};
-use core::cmp::{mod, Ord};
+use core::cmp::{mod, Ord, PartialEq};
 use core::iter::{Iterator, IteratorExt, IteratorCloneExt};
 use core::iter::{range, range_step, MultiplicativeIterator};
 use core::kinds::Sized;
@@ -108,7 +108,7 @@ use self::Direction::*;
 use vec::Vec;
 
 pub use core::slice::{Chunks, AsSlice, Windows};
-pub use core::slice::{Iter, IterMut, PartialEqSliceExt};
+pub use core::slice::{Iter, IterMut};
 pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split};
 pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
 pub use core::slice::{bytes, mut_ref_slice, ref_slice};
@@ -126,7 +126,9 @@ pub type MutItems<'a, T:'a> = IterMut<'a, T>;
 
 /// Allocating extension methods for slices.
 #[unstable = "needs associated types, may merge with other traits"]
-pub trait SliceExt<T> for Sized? {
+pub trait SliceExt for Sized? {
+    type Item;
+
     /// Sorts the slice, in place, using `compare` to compare
     /// elements.
     ///
@@ -145,7 +147,7 @@ pub trait SliceExt<T> for Sized? {
     /// assert!(v == [5, 4, 3, 2, 1]);
     /// ```
     #[stable]
-    fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering;
+    fn sort_by<F>(&mut self, compare: F) where F: FnMut(&Self::Item, &Self::Item) -> Ordering;
 
     /// Consumes `src` and moves as many elements as it can into `self`
     /// from the range [start,end).
@@ -169,7 +171,7 @@ pub trait SliceExt<T> for Sized? {
     /// assert!(a == [6i, 7, 8, 4, 5]);
     /// ```
     #[experimental = "uncertain about this API approach"]
-    fn move_from(&mut self, src: Vec<T>, start: uint, end: uint) -> uint;
+    fn move_from(&mut self, src: Vec<Self::Item>, start: uint, end: uint) -> uint;
 
     /// Returns a subslice spanning the interval [`start`, `end`).
     ///
@@ -178,7 +180,7 @@ pub trait SliceExt<T> for Sized? {
     ///
     /// Slicing with `start` equal to `end` yields an empty slice.
     #[experimental = "will be replaced by slice syntax"]
-    fn slice(&self, start: uint, end: uint) -> &[T];
+    fn slice(&self, start: uint, end: uint) -> &[Self::Item];
 
     /// Returns a subslice from `start` to the end of the slice.
     ///
@@ -186,7 +188,7 @@ pub trait SliceExt<T> for Sized? {
     ///
     /// Slicing from `self.len()` yields an empty slice.
     #[experimental = "will be replaced by slice syntax"]
-    fn slice_from(&self, start: uint) -> &[T];
+    fn slice_from(&self, start: uint) -> &[Self::Item];
 
     /// Returns a subslice from the start of the slice to `end`.
     ///
@@ -194,7 +196,7 @@ pub trait SliceExt<T> for Sized? {
     ///
     /// Slicing to `0` yields an empty slice.
     #[experimental = "will be replaced by slice syntax"]
-    fn slice_to(&self, end: uint) -> &[T];
+    fn slice_to(&self, end: uint) -> &[Self::Item];
 
     /// Divides one slice into two at an index.
     ///
@@ -204,32 +206,32 @@ pub trait SliceExt<T> for Sized? {
     ///
     /// Panics if `mid > len`.
     #[stable]
-    fn split_at(&self, mid: uint) -> (&[T], &[T]);
+    fn split_at(&self, mid: uint) -> (&[Self::Item], &[Self::Item]);
 
     /// Returns an iterator over the slice
     #[stable]
-    fn iter(&self) -> Iter<T>;
+    fn iter(&self) -> Iter<Self::Item>;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`.  The matched element is not contained in the subslices.
     #[stable]
-    fn split<F>(&self, pred: F) -> Split<T, F>
-                where F: FnMut(&T) -> bool;
+    fn split<F>(&self, pred: F) -> Split<Self::Item, F>
+                where F: FnMut(&Self::Item) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`, limited to splitting at most `n` times.  The matched element is
     /// not contained in the subslices.
     #[stable]
-    fn splitn<F>(&self, n: uint, pred: F) -> SplitN<T, F>
-                 where F: FnMut(&T) -> bool;
+    fn splitn<F>(&self, n: uint, pred: F) -> SplitN<Self::Item, F>
+                 where F: FnMut(&Self::Item) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred` limited to splitting at most `n` times. This starts at the end of
     /// the slice and works backwards.  The matched element is not contained in
     /// the subslices.
     #[stable]
-    fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<T, F>
-                  where F: FnMut(&T) -> bool;
+    fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<Self::Item, F>
+                  where F: FnMut(&Self::Item) -> bool;
 
     /// Returns an iterator over all contiguous windows of length
     /// `size`. The windows overlap. If the slice is shorter than
@@ -251,7 +253,7 @@ pub trait SliceExt<T> for Sized? {
     /// }
     /// ```
     #[stable]
-    fn windows(&self, size: uint) -> Windows<T>;
+    fn windows(&self, size: uint) -> Windows<Self::Item>;
 
     /// Returns an iterator over `size` elements of the slice at a
     /// time. The chunks do not overlap. If `size` does not divide the
@@ -274,41 +276,41 @@ pub trait SliceExt<T> for Sized? {
     /// }
     /// ```
     #[stable]
-    fn chunks(&self, size: uint) -> Chunks<T>;
+    fn chunks(&self, size: uint) -> Chunks<Self::Item>;
 
     /// Returns the element of a slice at the given index, or `None` if the
     /// index is out of bounds.
     #[stable]
-    fn get(&self, index: uint) -> Option<&T>;
+    fn get(&self, index: uint) -> Option<&Self::Item>;
 
     /// Returns the first element of a slice, or `None` if it is empty.
     #[stable]
-    fn first(&self) -> Option<&T>;
+    fn first(&self) -> Option<&Self::Item>;
 
     /// Deprecated: renamed to `first`.
     #[deprecated = "renamed to `first`"]
-    fn head(&self) -> Option<&T> { self.first() }
+    fn head(&self) -> Option<&Self::Item> { self.first() }
 
     /// Returns all but the first element of a slice.
     #[experimental = "likely to be renamed"]
-    fn tail(&self) -> &[T];
+    fn tail(&self) -> &[Self::Item];
 
     /// Returns all but the last element of a slice.
     #[experimental = "likely to be renamed"]
-    fn init(&self) -> &[T];
+    fn init(&self) -> &[Self::Item];
 
     /// Returns the last element of a slice, or `None` if it is empty.
     #[stable]
-    fn last(&self) -> Option<&T>;
+    fn last(&self) -> Option<&Self::Item>;
 
     /// Returns a pointer to the element at the given index, without doing
     /// bounds checking.
     #[stable]
-    unsafe fn get_unchecked(&self, index: uint) -> &T;
+    unsafe fn get_unchecked(&self, index: uint) -> &Self::Item;
 
     /// Deprecated: renamed to `get_unchecked`.
     #[deprecated = "renamed to get_unchecked"]
-    unsafe fn unsafe_get(&self, index: uint) -> &T {
+    unsafe fn unsafe_get(&self, index: uint) -> &Self::Item {
         self.get_unchecked(index)
     }
 
@@ -320,7 +322,7 @@ pub trait SliceExt<T> for Sized? {
     /// Modifying the slice may cause its buffer to be reallocated, which
     /// would also make any pointers to it invalid.
     #[stable]
-    fn as_ptr(&self) -> *const T;
+    fn as_ptr(&self) -> *const Self::Item;
 
     /// Binary search a sorted slice with a comparator function.
     ///
@@ -356,7 +358,7 @@ pub trait SliceExt<T> for Sized? {
     /// ```
     #[stable]
     fn binary_search_by<F>(&self, f: F) -> Result<uint, uint> where
-        F: FnMut(&T) -> Ordering;
+        F: FnMut(&Self::Item) -> Ordering;
 
     /// Return the number of elements in the slice
     ///
@@ -383,12 +385,12 @@ pub trait SliceExt<T> for Sized? {
     /// Returns a mutable reference to the element at the given index,
     /// or `None` if the index is out of bounds
     #[stable]
-    fn get_mut(&mut self, index: uint) -> Option<&mut T>;
+    fn get_mut(&mut self, index: uint) -> Option<&mut Self::Item>;
 
     /// Work with `self` as a mut slice.
     /// Primarily intended for getting a &mut [T] from a [T; N].
     #[stable]
-    fn as_mut_slice(&mut self) -> &mut [T];
+    fn as_mut_slice(&mut self) -> &mut [Self::Item];
 
     /// Returns a mutable subslice spanning the interval [`start`, `end`).
     ///
@@ -397,7 +399,7 @@ pub trait SliceExt<T> for Sized? {
     ///
     /// Slicing with `start` equal to `end` yields an empty slice.
     #[experimental = "will be replaced by slice syntax"]
-    fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T];
+    fn slice_mut(&mut self, start: uint, end: uint) -> &mut [Self::Item];
 
     /// Returns a mutable subslice from `start` to the end of the slice.
     ///
@@ -405,7 +407,7 @@ pub trait SliceExt<T> for Sized? {
     ///
     /// Slicing from `self.len()` yields an empty slice.
     #[experimental = "will be replaced by slice syntax"]
-    fn slice_from_mut(&mut self, start: uint) -> &mut [T];
+    fn slice_from_mut(&mut self, start: uint) -> &mut [Self::Item];
 
     /// Returns a mutable subslice from the start of the slice to `end`.
     ///
@@ -413,54 +415,54 @@ pub trait SliceExt<T> for Sized? {
     ///
     /// Slicing to `0` yields an empty slice.
     #[experimental = "will be replaced by slice syntax"]
-    fn slice_to_mut(&mut self, end: uint) -> &mut [T];
+    fn slice_to_mut(&mut self, end: uint) -> &mut [Self::Item];
 
     /// Returns an iterator that allows modifying each value
     #[stable]
-    fn iter_mut(&mut self) -> IterMut<T>;
+    fn iter_mut(&mut self) -> IterMut<Self::Item>;
 
     /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty
     #[stable]
-    fn first_mut(&mut self) -> Option<&mut T>;
+    fn first_mut(&mut self) -> Option<&mut Self::Item>;
 
     /// Depreated: renamed to `first_mut`.
     #[deprecated = "renamed to first_mut"]
-    fn head_mut(&mut self) -> Option<&mut T> {
+    fn head_mut(&mut self) -> Option<&mut Self::Item> {
         self.first_mut()
     }
 
     /// Returns all but the first element of a mutable slice
     #[experimental = "likely to be renamed or removed"]
-    fn tail_mut(&mut self) -> &mut [T];
+    fn tail_mut(&mut self) -> &mut [Self::Item];
 
     /// Returns all but the last element of a mutable slice
     #[experimental = "likely to be renamed or removed"]
-    fn init_mut(&mut self) -> &mut [T];
+    fn init_mut(&mut self) -> &mut [Self::Item];
 
     /// Returns a mutable pointer to the last item in the slice.
     #[stable]
-    fn last_mut(&mut self) -> Option<&mut T>;
+    fn last_mut(&mut self) -> Option<&mut Self::Item>;
 
     /// Returns an iterator over mutable subslices separated by elements that
     /// match `pred`.  The matched element is not contained in the subslices.
     #[stable]
-    fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
-                    where F: FnMut(&T) -> bool;
+    fn split_mut<F>(&mut self, pred: F) -> SplitMut<Self::Item, F>
+                    where F: FnMut(&Self::Item) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`, limited to splitting at most `n` times.  The matched element is
     /// not contained in the subslices.
     #[stable]
-    fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitNMut<T, F>
-                     where F: FnMut(&T) -> bool;
+    fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitNMut<Self::Item, F>
+                     where F: FnMut(&Self::Item) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred` limited to splitting at most `n` times. This starts at the end of
     /// the slice and works backwards.  The matched element is not contained in
     /// the subslices.
     #[stable]
-    fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> RSplitNMut<T, F>
-                      where F: FnMut(&T) -> bool;
+    fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> RSplitNMut<Self::Item, F>
+                      where F: FnMut(&Self::Item) -> bool;
 
     /// Returns an iterator over `chunk_size` elements of the slice at a time.
     /// The chunks are mutable and do not overlap. If `chunk_size` does
@@ -471,7 +473,7 @@ pub trait SliceExt<T> for Sized? {
     ///
     /// Panics if `chunk_size` is 0.
     #[stable]
-    fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut<T>;
+    fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut<Self::Item>;
 
     /// Swaps two elements in a slice.
     ///
@@ -529,7 +531,7 @@ pub trait SliceExt<T> for Sized? {
     /// }
     /// ```
     #[stable]
-    fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]);
+    fn split_at_mut(&mut self, mid: uint) -> (&mut [Self::Item], &mut [Self::Item]);
 
     /// Reverse the order of elements in a slice, in place.
     ///
@@ -545,11 +547,11 @@ pub trait SliceExt<T> for Sized? {
 
     /// Returns an unsafe mutable pointer to the element in index
     #[stable]
-    unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut T;
+    unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut Self::Item;
 
     /// Deprecated: renamed to `get_unchecked_mut`.
     #[deprecated = "renamed to get_unchecked_mut"]
-    unsafe fn unchecked_mut(&mut self, index: uint) -> &mut T {
+    unsafe fn unchecked_mut(&mut self, index: uint) -> &mut Self::Item {
         self.get_unchecked_mut(index)
     }
 
@@ -562,11 +564,179 @@ pub trait SliceExt<T> for Sized? {
     /// would also make any pointers to it invalid.
     #[inline]
     #[stable]
-    fn as_mut_ptr(&mut self) -> *mut T;
+    fn as_mut_ptr(&mut self) -> *mut Self::Item;
+
+    /// Copies `self` into a new `Vec`.
+    #[stable]
+    fn to_vec(&self) -> Vec<Self::Item> where Self::Item: Clone;
+
+    /// Deprecated: use `iter().cloned().partition(f)` instead.
+    #[deprecated = "use iter().cloned().partition(f) instead"]
+    fn partitioned<F>(&self, f: F) -> (Vec<Self::Item>, Vec<Self::Item>) where
+        Self::Item: Clone,
+        F: FnMut(&Self::Item) -> bool;
+
+    /// Creates an iterator that yields every possible permutation of the
+    /// vector in succession.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let v = [1i, 2, 3];
+    /// let mut perms = v.permutations();
+    ///
+    /// for p in perms {
+    ///   println!("{}", p);
+    /// }
+    /// ```
+    ///
+    /// Iterating through permutations one by one.
+    ///
+    /// ```rust
+    /// let v = [1i, 2, 3];
+    /// let mut perms = v.permutations();
+    ///
+    /// assert_eq!(Some(vec![1i, 2, 3]), perms.next());
+    /// assert_eq!(Some(vec![1i, 3, 2]), perms.next());
+    /// assert_eq!(Some(vec![3i, 1, 2]), perms.next());
+    /// ```
+    #[unstable]
+    fn permutations(&self) -> Permutations<Self::Item> where Self::Item: Clone;
+
+    /// Copies as many elements from `src` as it can into `self` (the
+    /// shorter of `self.len()` and `src.len()`). Returns the number
+    /// of elements copied.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let mut dst = [0i, 0, 0];
+    /// let src = [1i, 2];
+    ///
+    /// assert!(dst.clone_from_slice(&src) == 2);
+    /// assert!(dst == [1, 2, 0]);
+    ///
+    /// let src2 = [3i, 4, 5, 6];
+    /// assert!(dst.clone_from_slice(&src2) == 3);
+    /// assert!(dst == [3i, 4, 5]);
+    /// ```
+    #[experimental]
+    fn clone_from_slice(&mut self, &[Self::Item]) -> uint where Self::Item: Clone;
+
+    /// Sorts the slice, in place.
+    ///
+    /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let mut v = [-5i, 4, 1, -3, 2];
+    ///
+    /// v.sort();
+    /// assert!(v == [-5i, -3, 1, 2, 4]);
+    /// ```
+    #[stable]
+    fn sort(&mut self) where Self::Item: Ord;
+
+    /// Binary search a sorted slice for a given element.
+    ///
+    /// If the value is found then `Ok` is returned, containing the
+    /// index of the matching element; if the value is not found then
+    /// `Err` is returned, containing the index where a matching
+    /// element could be inserted while maintaining sorted order.
+    ///
+    /// # Example
+    ///
+    /// Looks up a series of four elements. The first is found, with a
+    /// uniquely determined position; the second and third are not
+    /// found; the fourth could match any position in `[1,4]`.
+    ///
+    /// ```rust
+    /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+    /// let s = s.as_slice();
+    ///
+    /// assert_eq!(s.binary_search(&13),  Ok(9));
+    /// assert_eq!(s.binary_search(&4),   Err(7));
+    /// assert_eq!(s.binary_search(&100), Err(13));
+    /// let r = s.binary_search(&1);
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
+    /// ```
+    #[stable]
+    fn binary_search(&self, x: &Self::Item) -> Result<uint, uint> where Self::Item: Ord;
+
+    /// Deprecated: use `binary_search` instead.
+    #[deprecated = "use binary_search instead"]
+    fn binary_search_elem(&self, x: &Self::Item) -> Result<uint, uint> where Self::Item: Ord {
+        self.binary_search(x)
+    }
+
+    /// Mutates the slice to the next lexicographic permutation.
+    ///
+    /// Returns `true` if successful and `false` if the slice is at the
+    /// last-ordered permutation.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let v: &mut [_] = &mut [0i, 1, 2];
+    /// v.next_permutation();
+    /// let b: &mut [_] = &mut [0i, 2, 1];
+    /// assert!(v == b);
+    /// v.next_permutation();
+    /// let b: &mut [_] = &mut [1i, 0, 2];
+    /// assert!(v == b);
+    /// ```
+    #[unstable = "uncertain if this merits inclusion in std"]
+    fn next_permutation(&mut self) -> bool where Self::Item: Ord;
+
+    /// Mutates the slice to the previous lexicographic permutation.
+    ///
+    /// Returns `true` if successful and `false` if the slice is at the
+    /// first-ordered permutation.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let v: &mut [_] = &mut [1i, 0, 2];
+    /// v.prev_permutation();
+    /// let b: &mut [_] = &mut [0i, 2, 1];
+    /// assert!(v == b);
+    /// v.prev_permutation();
+    /// let b: &mut [_] = &mut [0i, 1, 2];
+    /// assert!(v == b);
+    /// ```
+    #[unstable = "uncertain if this merits inclusion in std"]
+    fn prev_permutation(&mut self) -> bool where Self::Item: Ord;
+
+    /// Find the first index containing a matching value.
+    #[experimental]
+    fn position_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq;
+
+    /// Find the last index containing a matching value.
+    #[experimental]
+    fn rposition_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq;
+
+    /// Return true if the slice contains an element with the given value.
+    #[stable]
+    fn contains(&self, x: &Self::Item) -> bool where Self::Item: PartialEq;
+
+    /// Returns true if `needle` is a prefix of the slice.
+    #[stable]
+    fn starts_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
+
+    /// Returns true if `needle` is a suffix of the slice.
+    #[stable]
+    fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
+
+    /// Convert `self` into a vector without clones or allocation.
+    #[experimental]
+    fn into_vec(self: Box<Self>) -> Vec<Self::Item>;
 }
 
 #[unstable = "trait is unstable"]
-impl<T> SliceExt<T> for [T] {
+impl<T> SliceExt for [T] {
+    type Item = T;
+
     #[inline]
     fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering {
         merge_sort(self, compare)
@@ -781,96 +951,10 @@ impl<T> SliceExt<T> for [T] {
     fn as_mut_ptr(&mut self) -> *mut T {
         core_slice::SliceExt::as_mut_ptr(self)
     }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Extension traits for slices over specifc kinds of data
-////////////////////////////////////////////////////////////////////////////////
-
-/// Extension methods for boxed slices.
-#[experimental = "likely to merge into SliceExt if it survives"]
-pub trait BoxedSliceExt<T> {
-    /// Convert `self` into a vector without clones or allocation.
-    #[experimental]
-    fn into_vec(self) -> Vec<T>;
-}
-
-#[experimental = "trait is experimental"]
-impl<T> BoxedSliceExt<T> for Box<[T]> {
-    fn into_vec(mut self) -> Vec<T> {
-        unsafe {
-            let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len());
-            mem::forget(self);
-            xs
-        }
-    }
-}
-
-/// Allocating extension methods for slices containing `Clone` elements.
-#[unstable = "likely to be merged into SliceExt"]
-pub trait CloneSliceExt<T> for Sized? {
-    /// Copies `self` into a new `Vec`.
-    #[stable]
-    fn to_vec(&self) -> Vec<T>;
-
-    /// Deprecated: use `iter().cloned().partition(f)` instead.
-    #[deprecated = "use iter().cloned().partition(f) instead"]
-    fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool;
-
-    /// Creates an iterator that yields every possible permutation of the
-    /// vector in succession.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let v = [1i, 2, 3];
-    /// let mut perms = v.permutations();
-    ///
-    /// for p in perms {
-    ///   println!("{}", p);
-    /// }
-    /// ```
-    ///
-    /// Iterating through permutations one by one.
-    ///
-    /// ```rust
-    /// let v = [1i, 2, 3];
-    /// let mut perms = v.permutations();
-    ///
-    /// assert_eq!(Some(vec![1i, 2, 3]), perms.next());
-    /// assert_eq!(Some(vec![1i, 3, 2]), perms.next());
-    /// assert_eq!(Some(vec![3i, 1, 2]), perms.next());
-    /// ```
-    #[unstable]
-    fn permutations(&self) -> Permutations<T>;
-
-    /// Copies as many elements from `src` as it can into `self` (the
-    /// shorter of `self.len()` and `src.len()`). Returns the number
-    /// of elements copied.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let mut dst = [0i, 0, 0];
-    /// let src = [1i, 2];
-    ///
-    /// assert!(dst.clone_from_slice(&src) == 2);
-    /// assert!(dst == [1, 2, 0]);
-    ///
-    /// let src2 = [3i, 4, 5, 6];
-    /// assert!(dst.clone_from_slice(&src2) == 3);
-    /// assert!(dst == [3i, 4, 5]);
-    /// ```
-    #[experimental]
-    fn clone_from_slice(&mut self, &[T]) -> uint;
-}
-
 
-#[unstable = "trait is unstable"]
-impl<T: Clone> CloneSliceExt<T> for [T] {
     /// Returns a copy of `v`.
     #[inline]
-    fn to_vec(&self) -> Vec<T> {
+    fn to_vec(&self) -> Vec<T> where T: Clone {
         let mut vector = Vec::with_capacity(self.len());
         vector.push_all(self);
         vector
@@ -878,132 +962,71 @@ impl<T: Clone> CloneSliceExt<T> for [T] {
 
 
     #[inline]
-    fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool {
+    fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool, T: Clone {
         self.iter().cloned().partition(f)
     }
 
     /// Returns an iterator over all permutations of a vector.
-    fn permutations(&self) -> Permutations<T> {
+    fn permutations(&self) -> Permutations<T> where T: Clone {
         Permutations{
             swaps: ElementSwaps::new(self.len()),
             v: self.to_vec(),
         }
     }
 
-    fn clone_from_slice(&mut self, src: &[T]) -> uint {
-        core_slice::CloneSliceExt::clone_from_slice(self, src)
+    fn clone_from_slice(&mut self, src: &[T]) -> uint where T: Clone {
+        core_slice::SliceExt::clone_from_slice(self, src)
     }
-}
 
-/// Allocating extension methods for slices on Ord values.
-#[unstable = "likely to merge with SliceExt"]
-pub trait OrdSliceExt<T> for Sized? {
-    /// Sorts the slice, in place.
-    ///
-    /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let mut v = [-5i, 4, 1, -3, 2];
-    ///
-    /// v.sort();
-    /// assert!(v == [-5i, -3, 1, 2, 4]);
-    /// ```
-    #[stable]
-    fn sort(&mut self);
+    #[inline]
+    fn sort(&mut self) where T: Ord {
+        self.sort_by(|a, b| a.cmp(b))
+    }
 
-    /// Binary search a sorted slice for a given element.
-    ///
-    /// If the value is found then `Ok` is returned, containing the
-    /// index of the matching element; if the value is not found then
-    /// `Err` is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
-    ///
-    /// # Example
-    ///
-    /// Looks up a series of four elements. The first is found, with a
-    /// uniquely determined position; the second and third are not
-    /// found; the fourth could match any position in `[1,4]`.
-    ///
-    /// ```rust
-    /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
-    /// let s = s.as_slice();
-    ///
-    /// assert_eq!(s.binary_search(&13),  Ok(9));
-    /// assert_eq!(s.binary_search(&4),   Err(7));
-    /// assert_eq!(s.binary_search(&100), Err(13));
-    /// let r = s.binary_search(&1);
-    /// assert!(match r { Ok(1...4) => true, _ => false, });
-    /// ```
-    #[stable]
-    fn binary_search(&self, x: &T) -> Result<uint, uint>;
+    fn binary_search(&self, x: &T) -> Result<uint, uint> where T: Ord {
+        core_slice::SliceExt::binary_search(self, x)
+    }
 
-    /// Deprecated: use `binary_search` instead.
-    #[deprecated = "use binary_search instead"]
-    fn binary_search_elem(&self, x: &T) -> Result<uint, uint> {
-        self.binary_search(x)
+    fn next_permutation(&mut self) -> bool where T: Ord {
+        core_slice::SliceExt::next_permutation(self)
     }
 
-    /// Mutates the slice to the next lexicographic permutation.
-    ///
-    /// Returns `true` if successful and `false` if the slice is at the
-    /// last-ordered permutation.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let v: &mut [_] = &mut [0i, 1, 2];
-    /// v.next_permutation();
-    /// let b: &mut [_] = &mut [0i, 2, 1];
-    /// assert!(v == b);
-    /// v.next_permutation();
-    /// let b: &mut [_] = &mut [1i, 0, 2];
-    /// assert!(v == b);
-    /// ```
-    #[unstable = "uncertain if this merits inclusion in std"]
-    fn next_permutation(&mut self) -> bool;
+    fn prev_permutation(&mut self) -> bool where T: Ord {
+        core_slice::SliceExt::prev_permutation(self)
+    }
 
-    /// Mutates the slice to the previous lexicographic permutation.
-    ///
-    /// Returns `true` if successful and `false` if the slice is at the
-    /// first-ordered permutation.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let v: &mut [_] = &mut [1i, 0, 2];
-    /// v.prev_permutation();
-    /// let b: &mut [_] = &mut [0i, 2, 1];
-    /// assert!(v == b);
-    /// v.prev_permutation();
-    /// let b: &mut [_] = &mut [0i, 1, 2];
-    /// assert!(v == b);
-    /// ```
-    #[unstable = "uncertain if this merits inclusion in std"]
-    fn prev_permutation(&mut self) -> bool;
-}
+    fn position_elem(&self, t: &T) -> Option<uint> where T: PartialEq {
+        core_slice::SliceExt::position_elem(self, t)
+    }
 
-#[unstable = "trait is unstable"]
-impl<T: Ord> OrdSliceExt<T> for [T] {
-    #[inline]
-    fn sort(&mut self) {
-        self.sort_by(|a, b| a.cmp(b))
+    fn rposition_elem(&self, t: &T) -> Option<uint> where T: PartialEq {
+        core_slice::SliceExt::rposition_elem(self, t)
     }
 
-    fn binary_search(&self, x: &T) -> Result<uint, uint> {
-        core_slice::OrdSliceExt::binary_search(self, x)
+    fn contains(&self, x: &T) -> bool where T: PartialEq {
+        core_slice::SliceExt::contains(self, x)
     }
 
-    fn next_permutation(&mut self) -> bool {
-        core_slice::OrdSliceExt::next_permutation(self)
+    fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq {
+        core_slice::SliceExt::starts_with(self, needle)
     }
 
-    fn prev_permutation(&mut self) -> bool {
-        core_slice::OrdSliceExt::prev_permutation(self)
+    fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq {
+        core_slice::SliceExt::ends_with(self, needle)
+    }
+
+    fn into_vec(mut self: Box<Self>) -> Vec<T> {
+        unsafe {
+            let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len());
+            mem::forget(self);
+            xs
+        }
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Extension traits for slices over specifc kinds of data
+////////////////////////////////////////////////////////////////////////////////
 #[unstable = "U should be an associated type"]
 /// An extension trait for concatenating slices
 pub trait SliceConcatExt<Sized? T, U> for Sized? {
@@ -1423,7 +1446,7 @@ mod tests {
     use std::boxed::Box;
     use prelude::{Some, None, range, Vec, ToString, Clone, Greater, Less, Equal};
     use prelude::{SliceExt, Iterator, IteratorExt, DoubleEndedIteratorExt};
-    use prelude::{OrdSliceExt, CloneSliceExt, PartialEqSliceExt, AsSlice};
+    use prelude::AsSlice;
     use prelude::{RandomAccessIterator, Ord, SliceConcatExt};
     use core::cell::Cell;
     use core::default::Default;
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index f631af6f642..769679ec4d4 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -29,7 +29,6 @@ use core::raw::Slice as RawSlice;
 use unicode::str as unicode_str;
 use unicode::str::Utf16Item;
 
-use slice::CloneSliceExt;
 use str::{mod, CharRange, FromStr, Utf8Error};
 use vec::{DerefVec, Vec, as_vec};
 
@@ -96,7 +95,7 @@ impl String {
     #[inline]
     #[experimental = "needs investigation to see if to_string() can match perf"]
     pub fn from_str(string: &str) -> String {
-        String { vec: string.as_bytes().to_vec() }
+        String { vec: ::slice::SliceExt::to_vec(string.as_bytes()) }
     }
 
     /// Returns the vector as a string buffer, if possible, taking care not to
@@ -942,7 +941,9 @@ impl ops::Slice<uint, str> for String {
 }
 
 #[experimental = "waiting on Deref stabilization"]
-impl ops::Deref<str> for String {
+impl ops::Deref for String {
+    type Target = str;
+
     fn deref<'a>(&'a self) -> &'a str {
         unsafe { mem::transmute(self.vec[]) }
     }
@@ -954,7 +955,9 @@ pub struct DerefString<'a> {
     x: DerefVec<'a, u8>
 }
 
-impl<'a> Deref<String> for DerefString<'a> {
+impl<'a> Deref for DerefString<'a> {
+    type Target = String;
+
     fn deref<'b>(&'b self) -> &'b String {
         unsafe { mem::transmute(&*self.x) }
     }
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 351151c0f07..7e367927421 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -65,8 +65,6 @@ use core::ptr;
 use core::raw::Slice as RawSlice;
 use core::uint;
 
-use slice::CloneSliceExt;
-
 /// A growable list type, written `Vec<T>` but pronounced 'vector.'
 ///
 /// # Examples
@@ -1220,7 +1218,7 @@ unsafe fn dealloc<T>(ptr: *mut T, len: uint) {
 
 #[unstable]
 impl<T:Clone> Clone for Vec<T> {
-    fn clone(&self) -> Vec<T> { self.as_slice().to_vec() }
+    fn clone(&self) -> Vec<T> { ::slice::SliceExt::to_vec(self.as_slice()) }
 
     fn clone_from(&mut self, other: &Vec<T>) {
         // drop anything in self that will not be overwritten
@@ -1305,12 +1303,14 @@ impl<T> ops::SliceMut<uint, [T]> for Vec<T> {
 }
 
 #[experimental = "waiting on Deref stability"]
-impl<T> ops::Deref<[T]> for Vec<T> {
+impl<T> ops::Deref for Vec<T> {
+    type Target = [T];
+
     fn deref<'a>(&'a self) -> &'a [T] { self.as_slice() }
 }
 
 #[experimental = "waiting on DerefMut stability"]
-impl<T> ops::DerefMut<[T]> for Vec<T> {
+impl<T> ops::DerefMut for Vec<T> {
     fn deref_mut<'a>(&'a mut self) -> &'a mut [T] { self.as_mut_slice() }
 }
 
@@ -1720,7 +1720,9 @@ pub struct DerefVec<'a, T> {
 }
 
 #[experimental]
-impl<'a, T> Deref<Vec<T>> for DerefVec<'a, T> {
+impl<'a, T> Deref for DerefVec<'a, T> {
+    type Target = Vec<T>;
+
     fn deref<'b>(&'b self) -> &'b Vec<T> {
         &self.x
     }
diff --git a/src/libcore/array.rs b/src/libcore/array.rs
index 28563a60b61..ba7714ad9bc 100644
--- a/src/libcore/array.rs
+++ b/src/libcore/array.rs
@@ -54,7 +54,7 @@ macro_rules! array_impls {
             #[stable]
             impl<'a, A, B, Rhs> PartialEq<Rhs> for [A; $N] where
                 A: PartialEq<B>,
-                Rhs: Deref<[B]>,
+                Rhs: Deref<Target=[B]>,
             {
                 #[inline(always)]
                 fn eq(&self, other: &Rhs) -> bool { PartialEq::eq(self[], &**other) }
@@ -65,7 +65,7 @@ macro_rules! array_impls {
             #[stable]
             impl<'a, A, B, Lhs> PartialEq<[B; $N]> for Lhs where
                 A: PartialEq<B>,
-                Lhs: Deref<[A]>
+                Lhs: Deref<Target=[A]>
             {
                 #[inline(always)]
                 fn eq(&self, other: &[B; $N]) -> bool { PartialEq::eq(&**self, other[]) }
diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs
index 3a2cb8ea7d9..7e4d73d598d 100644
--- a/src/libcore/borrow.rs
+++ b/src/libcore/borrow.rs
@@ -191,7 +191,9 @@ impl<'a, T, Sized? B> Cow<'a, T, B> where B: ToOwned<T> {
     }
 }
 
-impl<'a, T, Sized? B> Deref<B> for Cow<'a, T, B> where B: ToOwned<T>  {
+impl<'a, T, Sized? B> Deref for Cow<'a, T, B> where B: ToOwned<T>  {
+    type Target = B;
+
     fn deref(&self) -> &B {
         match *self {
             Borrowed(borrowed) => borrowed,
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 94e9441abc8..47204dfc422 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -424,7 +424,9 @@ pub struct Ref<'b, T:'b> {
 }
 
 #[unstable = "waiting for `Deref` to become stable"]
-impl<'b, T> Deref<T> for Ref<'b, T> {
+impl<'b, T> Deref for Ref<'b, T> {
+    type Target = T;
+
     #[inline]
     fn deref<'a>(&'a self) -> &'a T {
         self._value
@@ -480,7 +482,9 @@ pub struct RefMut<'b, T:'b> {
 }
 
 #[unstable = "waiting for `Deref` to become stable"]
-impl<'b, T> Deref<T> for RefMut<'b, T> {
+impl<'b, T> Deref for RefMut<'b, T> {
+    type Target = T;
+
     #[inline]
     fn deref<'a>(&'a self) -> &'a T {
         self._value
@@ -488,7 +492,7 @@ impl<'b, T> Deref<T> for RefMut<'b, T> {
 }
 
 #[unstable = "waiting for `DerefMut` to become stable"]
-impl<'b, T> DerefMut<T> for RefMut<'b, T> {
+impl<'b, T> DerefMut for RefMut<'b, T> {
     #[inline]
     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
         self._value
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 53b5c617300..d7a675b3104 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -1175,7 +1175,7 @@ pub trait IteratorCloneExt<A> {
 }
 
 #[unstable = "trait is unstable"]
-impl<A: Clone, D: Deref<A>, I: Iterator<D>> IteratorCloneExt<A> for I {
+impl<A: Clone, D: Deref<Target=A>, I: Iterator<D>> IteratorCloneExt<A> for I {
     fn cloned(self) -> Cloned<I> {
         Cloned { it: self }
     }
@@ -1186,7 +1186,7 @@ pub struct Cloned<I> {
     it: I,
 }
 
-impl<A: Clone, D: Deref<A>, I: Iterator<D>> Iterator<A> for Cloned<I> {
+impl<A: Clone, D: Deref<Target=A>, I: Iterator<D>> Iterator<A> for Cloned<I> {
     fn next(&mut self) -> Option<A> {
         self.it.next().cloned()
     }
@@ -1196,7 +1196,7 @@ impl<A: Clone, D: Deref<A>, I: Iterator<D>> Iterator<A> for Cloned<I> {
     }
 }
 
-impl<A: Clone, D: Deref<A>, I: DoubleEndedIterator<D>>
+impl<A: Clone, D: Deref<Target=A>, I: DoubleEndedIterator<D>>
         DoubleEndedIterator<A> for Cloned<I> {
     fn next_back(&mut self) -> Option<A> {
         self.it.next_back().cloned()
@@ -1204,7 +1204,7 @@ impl<A: Clone, D: Deref<A>, I: DoubleEndedIterator<D>>
 }
 
 #[unstable = "trait is unstable"]
-impl<A: Clone, D: Deref<A>, I: ExactSizeIterator<D>> ExactSizeIterator<A> for Cloned<I> {}
+impl<A: Clone, D: Deref<Target=A>, I: ExactSizeIterator<D>> ExactSizeIterator<A> for Cloned<I> {}
 
 #[unstable = "recently renamed for extension trait conventions"]
 /// An extension trait for cloneable iterators.
diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs
index c429e4b8212..ba9103520d8 100644
--- a/src/libcore/nonzero.rs
+++ b/src/libcore/nonzero.rs
@@ -44,7 +44,9 @@ impl<T: Zeroable> NonZero<T> {
     }
 }
 
-impl<T: Zeroable> Deref<T> for NonZero<T> {
+impl<T: Zeroable> Deref for NonZero<T> {
+    type Target = T;
+
     #[inline]
     fn deref<'a>(&'a self) -> &'a T {
         let NonZero(ref inner) = *self;
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index 15016562699..b51d4d91c2f 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -861,13 +861,17 @@ pub struct RangeTo<Idx> {
 /// struct.
 ///
 /// ```
+/// #![feature(associated_types)]
+///
 /// use std::ops::Deref;
 ///
 /// struct DerefExample<T> {
 ///     value: T
 /// }
 ///
-/// impl<T> Deref<T> for DerefExample<T> {
+/// impl<T> Deref for DerefExample<T> {
+///     type Target = T;
+///
 ///     fn deref<'a>(&'a self) -> &'a T {
 ///         &self.value
 ///     }
@@ -879,16 +883,22 @@ pub struct RangeTo<Idx> {
 /// }
 /// ```
 #[lang="deref"]
-pub trait Deref<Sized? Result> for Sized? {
+pub trait Deref for Sized? {
+    type Sized? Target;
+
     /// The method called to dereference a value
-    fn deref<'a>(&'a self) -> &'a Result;
+    fn deref<'a>(&'a self) -> &'a Self::Target;
 }
 
-impl<'a, Sized? T> Deref<T> for &'a T {
+impl<'a, Sized? T> Deref for &'a T {
+    type Target = T;
+
     fn deref(&self) -> &T { *self }
 }
 
-impl<'a, Sized? T> Deref<T> for &'a mut T {
+impl<'a, Sized? T> Deref for &'a mut T {
+    type Target = T;
+
     fn deref(&self) -> &T { *self }
 }
 
@@ -901,19 +911,23 @@ impl<'a, Sized? T> Deref<T> for &'a mut T {
 /// struct.
 ///
 /// ```
+/// #![feature(associated_types)]
+///
 /// use std::ops::{Deref, DerefMut};
 ///
 /// struct DerefMutExample<T> {
 ///     value: T
 /// }
 ///
-/// impl<T> Deref<T> for DerefMutExample<T> {
+/// impl<T> Deref for DerefMutExample<T> {
+///     type Target = T;
+///
 ///     fn deref<'a>(&'a self) -> &'a T {
 ///         &self.value
 ///     }
 /// }
 ///
-/// impl<T> DerefMut<T> for DerefMutExample<T> {
+/// impl<T> DerefMut for DerefMutExample<T> {
 ///     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
 ///         &mut self.value
 ///     }
@@ -926,12 +940,12 @@ impl<'a, Sized? T> Deref<T> for &'a mut T {
 /// }
 /// ```
 #[lang="deref_mut"]
-pub trait DerefMut<Sized? Result> for Sized? : Deref<Result> {
+pub trait DerefMut for Sized? : Deref {
     /// The method called to mutably dereference a value
-    fn deref_mut<'a>(&'a mut self) -> &'a mut Result;
+    fn deref_mut<'a>(&'a mut self) -> &'a mut <Self as Deref>::Target;
 }
 
-impl<'a, Sized? T> DerefMut<T> for &'a mut T {
+impl<'a, Sized? T> DerefMut for &'a mut T {
     fn deref_mut(&mut self) -> &mut T { *self }
 }
 
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index d831a57893b..b9749f57d58 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -699,7 +699,7 @@ impl<T> Option<T> {
     }
 }
 
-impl<'a, T: Clone, D: Deref<T>> Option<D> {
+impl<'a, T: Clone, D: Deref<Target=T>> Option<D> {
     /// Maps an Option<D> to an Option<T> by dereffing and cloning the contents of the Option.
     /// Useful for converting an Option<&T> to an Option<T>.
     #[unstable = "recently added as part of collections reform"]
diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs
index 210850be13a..8cb63138009 100644
--- a/src/libcore/prelude.rs
+++ b/src/libcore/prelude.rs
@@ -49,5 +49,4 @@ pub use option::Option::{mod, Some, None};
 pub use ptr::{PtrExt, MutPtrExt};
 pub use result::Result::{mod, Ok, Err};
 pub use slice::{AsSlice, SliceExt};
-pub use slice::{PartialEqSliceExt, OrdSliceExt};
 pub use str::{Str, StrExt};
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 38e47a5ad33..f29d7518149 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -243,7 +243,9 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 
 /// Methods on raw pointers
 #[stable]
-pub trait PtrExt<T> : Sized {
+pub trait PtrExt: Sized {
+    type Target;
+
     /// Returns the null pointer.
     #[deprecated = "call ptr::null instead"]
     fn null() -> Self;
@@ -271,7 +273,7 @@ pub trait PtrExt<T> : Sized {
     /// memory.
     #[unstable = "Option is not clearly the right return type, and we may want \
                   to tie the return lifetime to a borrow of the raw pointer"]
-    unsafe fn as_ref<'a>(&self) -> Option<&'a T>;
+    unsafe fn as_ref<'a>(&self) -> Option<&'a Self::Target>;
 
     /// Calculates the offset from a pointer. `count` is in units of T; e.g. a
     /// `count` of 3 represents a pointer offset of `3 * sizeof::<T>()` bytes.
@@ -287,7 +289,9 @@ pub trait PtrExt<T> : Sized {
 
 /// Methods on mutable raw pointers
 #[stable]
-pub trait MutPtrExt<T>{
+pub trait MutPtrExt {
+    type Target;
+
     /// Returns `None` if the pointer is null, or else returns a mutable
     /// reference to the value wrapped in `Some`.
     ///
@@ -297,11 +301,13 @@ pub trait MutPtrExt<T>{
     /// of the returned pointer.
     #[unstable = "Option is not clearly the right return type, and we may want \
                   to tie the return lifetime to a borrow of the raw pointer"]
-    unsafe fn as_mut<'a>(&self) -> Option<&'a mut T>;
+    unsafe fn as_mut<'a>(&self) -> Option<&'a mut Self::Target>;
 }
 
 #[stable]
-impl<T> PtrExt<T> for *const T {
+impl<T> PtrExt for *const T {
+    type Target = T;
+
     #[inline]
     #[deprecated = "call ptr::null instead"]
     fn null() -> *const T { null() }
@@ -333,7 +339,9 @@ impl<T> PtrExt<T> for *const T {
 }
 
 #[stable]
-impl<T> PtrExt<T> for *mut T {
+impl<T> PtrExt for *mut T {
+    type Target = T;
+
     #[inline]
     #[deprecated = "call ptr::null instead"]
     fn null() -> *mut T { null_mut() }
@@ -365,7 +373,9 @@ impl<T> PtrExt<T> for *mut T {
 }
 
 #[stable]
-impl<T> MutPtrExt<T> for *mut T {
+impl<T> MutPtrExt for *mut T {
+    type Target = T;
+
     #[inline]
     #[unstable = "return value does not necessarily convey all possible \
                   information"]
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 7d894ac697b..07addf7a569 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -64,57 +64,77 @@ use raw::Slice as RawSlice;
 
 /// Extension methods for slices.
 #[allow(missing_docs)] // docs in libcollections
-pub trait SliceExt<T> for Sized? {
-    fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [T];
-    fn slice_from<'a>(&'a self, start: uint) -> &'a [T];
-    fn slice_to<'a>(&'a self, end: uint) -> &'a [T];
-    fn split_at<'a>(&'a self, mid: uint) -> (&'a [T], &'a [T]);
-    fn iter<'a>(&'a self) -> Iter<'a, T>;
-    fn split<'a, P>(&'a self, pred: P) -> Split<'a, T, P>
-                    where P: FnMut(&T) -> bool;
-    fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitN<'a, T, P>
-                     where P: FnMut(&T) -> bool;
-    fn rsplitn<'a, P>(&'a self,  n: uint, pred: P) -> RSplitN<'a, T, P>
-                      where P: FnMut(&T) -> bool;
-    fn windows<'a>(&'a self, size: uint) -> Windows<'a, T>;
-    fn chunks<'a>(&'a self, size: uint) -> Chunks<'a, T>;
-    fn get<'a>(&'a self, index: uint) -> Option<&'a T>;
-    fn first<'a>(&'a self) -> Option<&'a T>;
-    fn tail<'a>(&'a self) -> &'a [T];
-    fn init<'a>(&'a self) -> &'a [T];
-    fn last<'a>(&'a self) -> Option<&'a T>;
-    unsafe fn get_unchecked<'a>(&'a self, index: uint) -> &'a T;
-    fn as_ptr(&self) -> *const T;
+pub trait SliceExt for Sized? {
+    type Item;
+
+    fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [Self::Item];
+    fn slice_from<'a>(&'a self, start: uint) -> &'a [Self::Item];
+    fn slice_to<'a>(&'a self, end: uint) -> &'a [Self::Item];
+    fn split_at<'a>(&'a self, mid: uint) -> (&'a [Self::Item], &'a [Self::Item]);
+    fn iter<'a>(&'a self) -> Iter<'a, Self::Item>;
+    fn split<'a, P>(&'a self, pred: P) -> Split<'a, Self::Item, P>
+                    where P: FnMut(&Self::Item) -> bool;
+    fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitN<'a, Self::Item, P>
+                     where P: FnMut(&Self::Item) -> bool;
+    fn rsplitn<'a, P>(&'a self,  n: uint, pred: P) -> RSplitN<'a, Self::Item, P>
+                      where P: FnMut(&Self::Item) -> bool;
+    fn windows<'a>(&'a self, size: uint) -> Windows<'a, Self::Item>;
+    fn chunks<'a>(&'a self, size: uint) -> Chunks<'a, Self::Item>;
+    fn get<'a>(&'a self, index: uint) -> Option<&'a Self::Item>;
+    fn first<'a>(&'a self) -> Option<&'a Self::Item>;
+    fn tail<'a>(&'a self) -> &'a [Self::Item];
+    fn init<'a>(&'a self) -> &'a [Self::Item];
+    fn last<'a>(&'a self) -> Option<&'a Self::Item>;
+    unsafe fn get_unchecked<'a>(&'a self, index: uint) -> &'a Self::Item;
+    fn as_ptr(&self) -> *const Self::Item;
     fn binary_search_by<F>(&self, f: F) -> Result<uint, uint> where
-        F: FnMut(&T) -> Ordering;
+        F: FnMut(&Self::Item) -> Ordering;
     fn len(&self) -> uint;
     fn is_empty(&self) -> bool { self.len() == 0 }
-    fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T>;
-    fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T];
-    fn slice_mut<'a>(&'a mut self, start: uint, end: uint) -> &'a mut [T];
-    fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [T];
-    fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [T];
-    fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T>;
-    fn first_mut<'a>(&'a mut self) -> Option<&'a mut T>;
-    fn tail_mut<'a>(&'a mut self) -> &'a mut [T];
-    fn init_mut<'a>(&'a mut self) -> &'a mut [T];
-    fn last_mut<'a>(&'a mut self) -> Option<&'a mut T>;
-    fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, T, P>
-                        where P: FnMut(&T) -> bool;
-    fn splitn_mut<P>(&mut self, n: uint, pred: P) -> SplitNMut<T, P>
-                     where P: FnMut(&T) -> bool;
-    fn rsplitn_mut<P>(&mut self,  n: uint, pred: P) -> RSplitNMut<T, P>
-                      where P: FnMut(&T) -> bool;
-    fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> ChunksMut<'a, T>;
+    fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut Self::Item>;
+    fn as_mut_slice<'a>(&'a mut self) -> &'a mut [Self::Item];
+    fn slice_mut<'a>(&'a mut self, start: uint, end: uint) -> &'a mut [Self::Item];
+    fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [Self::Item];
+    fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [Self::Item];
+    fn iter_mut<'a>(&'a mut self) -> IterMut<'a, Self::Item>;
+    fn first_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>;
+    fn tail_mut<'a>(&'a mut self) -> &'a mut [Self::Item];
+    fn init_mut<'a>(&'a mut self) -> &'a mut [Self::Item];
+    fn last_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>;
+    fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, Self::Item, P>
+                        where P: FnMut(&Self::Item) -> bool;
+    fn splitn_mut<P>(&mut self, n: uint, pred: P) -> SplitNMut<Self::Item, P>
+                     where P: FnMut(&Self::Item) -> bool;
+    fn rsplitn_mut<P>(&mut self,  n: uint, pred: P) -> RSplitNMut<Self::Item, P>
+                      where P: FnMut(&Self::Item) -> bool;
+    fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> ChunksMut<'a, Self::Item>;
     fn swap(&mut self, a: uint, b: uint);
-    fn split_at_mut<'a>(&'a mut self, mid: uint) -> (&'a mut [T], &'a mut [T]);
+    fn split_at_mut<'a>(&'a mut self, mid: uint) -> (&'a mut [Self::Item], &'a mut [Self::Item]);
     fn reverse(&mut self);
-    unsafe fn get_unchecked_mut<'a>(&'a mut self, index: uint) -> &'a mut T;
-    fn as_mut_ptr(&mut self) -> *mut T;
+    unsafe fn get_unchecked_mut<'a>(&'a mut self, index: uint) -> &'a mut Self::Item;
+    fn as_mut_ptr(&mut self) -> *mut Self::Item;
+
+    fn position_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq;
+
+    fn rposition_elem(&self, t: &Self::Item) -> Option<uint> where Self::Item: PartialEq;
+
+    fn contains(&self, x: &Self::Item) -> bool where Self::Item: PartialEq;
+
+    fn starts_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
+
+    fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
+
+    fn binary_search(&self, x: &Self::Item) -> Result<uint, uint> where Self::Item: Ord;
+    fn next_permutation(&mut self) -> bool where Self::Item: Ord;
+    fn prev_permutation(&mut self) -> bool where Self::Item: Ord;
+
+    fn clone_from_slice(&mut self, &[Self::Item]) -> uint where Self::Item: Clone;
 }
 
 #[unstable]
-impl<T> SliceExt<T> for [T] {
+impl<T> SliceExt for [T] {
+    type Item = T;
+
     #[inline]
     fn slice(&self, start: uint, end: uint) -> &[T] {
         assert!(start <= end);
@@ -404,153 +424,41 @@ impl<T> SliceExt<T> for [T] {
     fn as_mut_ptr(&mut self) -> *mut T {
         self.repr().data as *mut T
     }
-}
-
-impl<T> ops::Index<uint, T> for [T] {
-    fn index(&self, &index: &uint) -> &T {
-        assert!(index < self.len());
-
-        unsafe { mem::transmute(self.repr().data.offset(index as int)) }
-    }
-}
-
-impl<T> ops::IndexMut<uint, T> for [T] {
-    fn index_mut(&mut self, &index: &uint) -> &mut T {
-        assert!(index < self.len());
-
-        unsafe { mem::transmute(self.repr().data.offset(index as int)) }
-    }
-}
-
-impl<T> ops::Slice<uint, [T]> for [T] {
-    #[inline]
-    fn as_slice_<'a>(&'a self) -> &'a [T] {
-        self
-    }
-
-    #[inline]
-    fn slice_from_or_fail<'a>(&'a self, start: &uint) -> &'a [T] {
-        self.slice_or_fail(start, &self.len())
-    }
-
-    #[inline]
-    fn slice_to_or_fail<'a>(&'a self, end: &uint) -> &'a [T] {
-        self.slice_or_fail(&0, end)
-    }
-    #[inline]
-    fn slice_or_fail<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] {
-        assert!(*start <= *end);
-        assert!(*end <= self.len());
-        unsafe {
-            transmute(RawSlice {
-                    data: self.as_ptr().offset(*start as int),
-                    len: (*end - *start)
-                })
-        }
-    }
-}
-
-impl<T> ops::SliceMut<uint, [T]> for [T] {
-    #[inline]
-    fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] {
-        self
-    }
-
-    #[inline]
-    fn slice_from_or_fail_mut<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
-        let len = &self.len();
-        self.slice_or_fail_mut(start, len)
-    }
-
-    #[inline]
-    fn slice_to_or_fail_mut<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
-        self.slice_or_fail_mut(&0, end)
-    }
-    #[inline]
-    fn slice_or_fail_mut<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] {
-        assert!(*start <= *end);
-        assert!(*end <= self.len());
-        unsafe {
-            transmute(RawSlice {
-                    data: self.as_ptr().offset(*start as int),
-                    len: (*end - *start)
-                })
-        }
-    }
-}
-
-/// Extension methods for slices containing `PartialEq` elements.
-#[unstable = "may merge with SliceExt"]
-pub trait PartialEqSliceExt<T: PartialEq> for Sized? {
-    /// Find the first index containing a matching value.
-    #[experimental]
-    fn position_elem(&self, t: &T) -> Option<uint>;
-
-    /// Find the last index containing a matching value.
-    #[experimental]
-    fn rposition_elem(&self, t: &T) -> Option<uint>;
-
-    /// Return true if the slice contains an element with the given value.
-    #[stable]
-    fn contains(&self, x: &T) -> bool;
-
-    /// Returns true if `needle` is a prefix of the slice.
-    #[stable]
-    fn starts_with(&self, needle: &[T]) -> bool;
-
-    /// Returns true if `needle` is a suffix of the slice.
-    #[stable]
-    fn ends_with(&self, needle: &[T]) -> bool;
-}
 
-#[unstable = "trait is unstable"]
-impl<T: PartialEq> PartialEqSliceExt<T> for [T] {
     #[inline]
-    fn position_elem(&self, x: &T) -> Option<uint> {
+    fn position_elem(&self, x: &T) -> Option<uint> where T: PartialEq {
         self.iter().position(|y| *x == *y)
     }
 
     #[inline]
-    fn rposition_elem(&self, t: &T) -> Option<uint> {
+    fn rposition_elem(&self, t: &T) -> Option<uint> where T: PartialEq {
         self.iter().rposition(|x| *x == *t)
     }
 
     #[inline]
-    fn contains(&self, x: &T) -> bool {
+    fn contains(&self, x: &T) -> bool where T: PartialEq {
         self.iter().any(|elt| *x == *elt)
     }
 
     #[inline]
-    fn starts_with(&self, needle: &[T]) -> bool {
+    fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq {
         let n = needle.len();
         self.len() >= n && needle == self[..n]
     }
 
     #[inline]
-    fn ends_with(&self, needle: &[T]) -> bool {
+    fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq {
         let (m, n) = (self.len(), needle.len());
         m >= n && needle == self[m-n..]
     }
-}
 
-/// Extension methods for slices containing `Ord` elements.
-#[unstable = "may merge with other traits"]
-#[allow(missing_docs)] // docs in libcollections
-pub trait OrdSliceExt<T: Ord> for Sized? {
-    fn binary_search(&self, x: &T) -> Result<uint, uint>;
-    fn next_permutation(&mut self) -> bool;
-    fn prev_permutation(&mut self) -> bool;
-}
-
-#[unstable = "trait is unstable"]
-impl<T: Ord> OrdSliceExt<T> for [T] {
     #[unstable]
-    fn binary_search(&self, x: &T) -> Result<uint, uint> {
+    fn binary_search(&self, x: &T) -> Result<uint, uint> where T: Ord {
         self.binary_search_by(|p| p.cmp(x))
     }
 
     #[experimental]
-    fn next_permutation(&mut self) -> bool {
+    fn next_permutation(&mut self) -> bool where T: Ord {
         // These cases only have 1 permutation each, so we can't do anything.
         if self.len() < 2 { return false; }
 
@@ -581,7 +489,7 @@ impl<T: Ord> OrdSliceExt<T> for [T] {
     }
 
     #[experimental]
-    fn prev_permutation(&mut self) -> bool {
+    fn prev_permutation(&mut self) -> bool where T: Ord {
         // These cases only have 1 permutation each, so we can't do anything.
         if self.len() < 2 { return false; }
 
@@ -610,19 +518,9 @@ impl<T: Ord> OrdSliceExt<T> for [T] {
 
         true
     }
-}
 
-/// Extension methods for slices on Clone elements
-#[unstable = "may merge with other traits"]
-#[allow(missing_docs)] // docs in libcollections
-pub trait CloneSliceExt<T> for Sized? {
-    fn clone_from_slice(&mut self, &[T]) -> uint;
-}
-
-#[unstable = "trait is unstable"]
-impl<T: Clone> CloneSliceExt<T> for [T] {
     #[inline]
-    fn clone_from_slice(&mut self, src: &[T]) -> uint {
+    fn clone_from_slice(&mut self, src: &[T]) -> uint where T: Clone {
         let min = cmp::min(self.len(), src.len());
         let dst = self.slice_to_mut(min);
         let src = src.slice_to(min);
@@ -633,6 +531,79 @@ impl<T: Clone> CloneSliceExt<T> for [T] {
     }
 }
 
+impl<T> ops::Index<uint, T> for [T] {
+    fn index(&self, &index: &uint) -> &T {
+        assert!(index < self.len());
+
+        unsafe { mem::transmute(self.repr().data.offset(index as int)) }
+    }
+}
+
+impl<T> ops::IndexMut<uint, T> for [T] {
+    fn index_mut(&mut self, &index: &uint) -> &mut T {
+        assert!(index < self.len());
+
+        unsafe { mem::transmute(self.repr().data.offset(index as int)) }
+    }
+}
+
+impl<T> ops::Slice<uint, [T]> for [T] {
+    #[inline]
+    fn as_slice_<'a>(&'a self) -> &'a [T] {
+        self
+    }
+
+    #[inline]
+    fn slice_from_or_fail<'a>(&'a self, start: &uint) -> &'a [T] {
+        self.slice_or_fail(start, &self.len())
+    }
+
+    #[inline]
+    fn slice_to_or_fail<'a>(&'a self, end: &uint) -> &'a [T] {
+        self.slice_or_fail(&0, end)
+    }
+    #[inline]
+    fn slice_or_fail<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] {
+        assert!(*start <= *end);
+        assert!(*end <= self.len());
+        unsafe {
+            transmute(RawSlice {
+                    data: self.as_ptr().offset(*start as int),
+                    len: (*end - *start)
+                })
+        }
+    }
+}
+
+impl<T> ops::SliceMut<uint, [T]> for [T] {
+    #[inline]
+    fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] {
+        self
+    }
+
+    #[inline]
+    fn slice_from_or_fail_mut<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
+        let len = &self.len();
+        self.slice_or_fail_mut(start, len)
+    }
+
+    #[inline]
+    fn slice_to_or_fail_mut<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
+        self.slice_or_fail_mut(&0, end)
+    }
+    #[inline]
+    fn slice_or_fail_mut<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] {
+        assert!(*start <= *end);
+        assert!(*end <= self.len());
+        unsafe {
+            transmute(RawSlice {
+                    data: self.as_ptr().offset(*start as int),
+                    len: (*end - *start)
+                })
+        }
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Common traits
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs
index 0544e32b62c..d7f570df072 100644
--- a/src/librustc/middle/traits/project.rs
+++ b/src/librustc/middle/traits/project.rs
@@ -21,8 +21,10 @@ use super::VtableImplData;
 
 use middle::infer;
 use middle::subst::Subst;
-use middle::ty::{mod, AsPredicate, RegionEscape, HasProjectionTypes, ToPolyTraitRef, Ty};
+use middle::ty::{mod, AsPredicate, ReferencesError, RegionEscape,
+                 HasProjectionTypes, ToPolyTraitRef, Ty};
 use middle::ty_fold::{mod, TypeFoldable, TypeFolder};
+use std::rc::Rc;
 use util::ppaux::Repr;
 
 pub type PolyProjectionObligation<'tcx> =
@@ -372,6 +374,15 @@ fn project_type<'cx,'tcx>(
         return Err(ProjectionTyError::TraitSelectionError(Overflow));
     }
 
+    let obligation_trait_ref =
+        selcx.infcx().resolve_type_vars_if_possible(&obligation.predicate.trait_ref);
+
+    debug!("project: obligation_trait_ref={}", obligation_trait_ref.repr(selcx.tcx()));
+
+    if obligation_trait_ref.references_error() {
+        return Ok(ProjectedTy::Progress(selcx.tcx().types.err, vec!()));
+    }
+
     let mut candidates = ProjectionTyCandidateSet {
         vec: Vec::new(),
         ambiguous: false,
@@ -379,10 +390,12 @@ fn project_type<'cx,'tcx>(
 
     assemble_candidates_from_param_env(selcx,
                                        obligation,
+                                       &obligation_trait_ref,
                                        &mut candidates);
 
     if let Err(e) = assemble_candidates_from_impls(selcx,
                                                    obligation,
+                                                   &obligation_trait_ref,
                                                    &mut candidates) {
         return Err(ProjectionTyError::TraitSelectionError(e));
     }
@@ -415,17 +428,20 @@ fn project_type<'cx,'tcx>(
 /// there that can answer this question.
 fn assemble_candidates_from_param_env<'cx,'tcx>(
     selcx: &mut SelectionContext<'cx,'tcx>,
-    obligation:  &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
 {
     let env_predicates = selcx.param_env().caller_bounds.predicates.clone();
     let env_predicates = env_predicates.iter().cloned().collect();
-    assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates);
+    assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
+                                        candidate_set, env_predicates);
 }
 
 fn assemble_candidates_from_predicates<'cx,'tcx>(
     selcx: &mut SelectionContext<'cx,'tcx>,
-    obligation:  &ProjectionTyObligation<'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
     env_predicates: Vec<ty::Predicate<'tcx>>)
 {
@@ -439,7 +455,7 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
                 let is_match = infcx.probe(|_| {
                     let origin = infer::Misc(obligation.cause.span);
                     let obligation_poly_trait_ref =
-                        obligation.predicate.trait_ref.to_poly_trait_ref();
+                        obligation_trait_ref.to_poly_trait_ref();
                     let data_poly_trait_ref =
                         data.to_poly_trait_ref();
                     infcx.sub_poly_trait_refs(false,
@@ -461,6 +477,7 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
 fn assemble_candidates_from_object_type<'cx,'tcx>(
     selcx: &mut SelectionContext<'cx,'tcx>,
     obligation:  &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
     object_ty: Ty<'tcx>)
 {
@@ -480,21 +497,21 @@ fn assemble_candidates_from_object_type<'cx,'tcx>(
     let env_predicates = projection_bounds.iter()
                                           .map(|p| p.as_predicate())
                                           .collect();
-    assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates)
+    assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
+                                        candidate_set, env_predicates)
 }
 
 fn assemble_candidates_from_impls<'cx,'tcx>(
     selcx: &mut SelectionContext<'cx,'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
+    obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
     -> Result<(), SelectionError<'tcx>>
 {
     // If we are resolving `<T as TraitRef<...>>::Item == Type`,
     // start out by selecting the predicate `T as TraitRef<...>`:
-    let trait_ref =
-        obligation.predicate.trait_ref.to_poly_trait_ref();
-    let trait_obligation =
-        obligation.with(trait_ref.to_poly_trait_predicate());
+    let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
+    let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
     let vtable = match selcx.select(&trait_obligation) {
         Ok(Some(vtable)) => vtable,
         Ok(None) => {
@@ -515,7 +532,8 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
         }
         super::VtableObject(data) => {
             assemble_candidates_from_object_type(
-                selcx, obligation, candidate_set, data.object_ty);
+                selcx, obligation, obligation_trait_ref, candidate_set,
+                data.object_ty);
         }
         super::VtableParam(..) => {
             // This case tell us nothing about the value of an
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index ca4bf7863be..d09f2a250b0 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -293,6 +293,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
     }
 
+    fn evaluate_predicates_recursively<'a,'o,I>(&mut self,
+                                                stack: Option<&TraitObligationStack<'o, 'tcx>>,
+                                                mut predicates: I)
+                                                -> EvaluationResult<'tcx>
+        where I : Iterator<&'a PredicateObligation<'tcx>>, 'tcx:'a
+    {
+        let mut result = EvaluatedToOk;
+        for obligation in predicates {
+            match self.evaluate_predicate_recursively(stack, obligation) {
+                EvaluatedToErr(e) => { return EvaluatedToErr(e); }
+                EvaluatedToAmbig => { result = EvaluatedToAmbig; }
+                EvaluatedToOk => { }
+            }
+        }
+        result
+    }
+
     fn evaluate_predicate_recursively<'o>(&mut self,
                                           previous_stack: Option<&TraitObligationStack<'o, 'tcx>>,
                                           obligation: &PredicateObligation<'tcx>)
@@ -324,9 +341,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 EvaluatedToOk
             }
 
-            ty::Predicate::Projection(..) => {
-                // FIXME(#20296) -- we should be able to give a more precise answer here
-                EvaluatedToAmbig
+            ty::Predicate::Projection(ref data) => {
+                self.infcx.probe(|_| {
+                    let project_obligation = obligation.with(data.clone());
+                    match project::poly_project_and_unify_type(self, &project_obligation) {
+                        Ok(Some(subobligations)) => {
+                            self.evaluate_predicates_recursively(previous_stack,
+                                                                 subobligations.iter())
+                        }
+                        Ok(None) => {
+                            EvaluatedToAmbig
+                        }
+                        Err(_) => {
+                            EvaluatedToErr(Unimplemented)
+                        }
+                    }
+                })
             }
         }
     }
@@ -1087,15 +1117,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             selection: Selection<'tcx>)
                             -> EvaluationResult<'tcx>
     {
-        let mut result = EvaluatedToOk;
-        for obligation in selection.iter_nested() {
-            match self.evaluate_predicate_recursively(stack, obligation) {
-                EvaluatedToErr(e) => { return EvaluatedToErr(e); }
-                EvaluatedToAmbig => { result = EvaluatedToAmbig; }
-                EvaluatedToOk => { }
-            }
-        }
-        result
+        self.evaluate_predicates_recursively(stack, selection.iter_nested())
     }
 
     /// Returns true if `candidate_i` should be dropped in favor of `candidate_j`.
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 0a03a8e836b..999bc23c270 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -7265,7 +7265,7 @@ impl<T:ReferencesError> ReferencesError for Binder<T> {
 
 impl<T:ReferencesError> ReferencesError for Rc<T> {
     fn references_error(&self) -> bool {
-        (&*self).references_error()
+        (&**self).references_error()
     }
 }
 
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index c054dec7de4..aa3ac83c027 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -96,13 +96,15 @@ struct GraphBuilder<'a, 'b:'a, 'tcx:'b> {
     resolver: &'a mut Resolver<'b, 'tcx>
 }
 
-impl<'a, 'b:'a, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for GraphBuilder<'a, 'b, 'tcx> {
+impl<'a, 'b:'a, 'tcx:'b> Deref for GraphBuilder<'a, 'b, 'tcx> {
+    type Target = Resolver<'b, 'tcx>;
+
     fn deref(&self) -> &Resolver<'b, 'tcx> {
         &*self.resolver
     }
 }
 
-impl<'a, 'b:'a, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for GraphBuilder<'a, 'b, 'tcx> {
+impl<'a, 'b:'a, 'tcx:'b> DerefMut for GraphBuilder<'a, 'b, 'tcx> {
     fn deref_mut(&mut self) -> &mut Resolver<'b, 'tcx> {
         &mut *self.resolver
     }
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index b3d0d30726c..1bfe4c0407a 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -35,13 +35,15 @@ struct UnusedImportCheckVisitor<'a, 'b:'a, 'tcx:'b> {
 }
 
 // Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver.
-impl<'a, 'b, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
+impl<'a, 'b, 'tcx:'b> Deref for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
+    type Target = Resolver<'b, 'tcx>;
+
     fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> {
         &*self.resolver
     }
 }
 
-impl<'a, 'b, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
+impl<'a, 'b, 'tcx:'b> DerefMut for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
     fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> {
         &mut *self.resolver
     }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 6baecfc30e2..4ac9224969c 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -18,6 +18,7 @@
 
 #![feature(globs, phase, slicing_syntax)]
 #![feature(rustc_diagnostic_macros)]
+#![feature(associated_types)]
 
 #[phase(plugin, link)] extern crate log;
 #[phase(plugin, link)] extern crate syntax;
diff --git a/src/librustc_resolve/record_exports.rs b/src/librustc_resolve/record_exports.rs
index 4f314291da6..ff415750d64 100644
--- a/src/librustc_resolve/record_exports.rs
+++ b/src/librustc_resolve/record_exports.rs
@@ -35,13 +35,15 @@ struct ExportRecorder<'a, 'b:'a, 'tcx:'b> {
 }
 
 // Deref and DerefMut impls allow treating ExportRecorder as Resolver.
-impl<'a, 'b, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for ExportRecorder<'a, 'b, 'tcx> {
+impl<'a, 'b, 'tcx:'b> Deref for ExportRecorder<'a, 'b, 'tcx> {
+    type Target = Resolver<'b, 'tcx>;
+
     fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> {
         &*self.resolver
     }
 }
 
-impl<'a, 'b, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for ExportRecorder<'a, 'b, 'tcx> {
+impl<'a, 'b, 'tcx:'b> DerefMut for ExportRecorder<'a, 'b, 'tcx> {
     fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> {
         &mut *self.resolver
     }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 11ee16b0445..0cfc1042ae6 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1812,6 +1812,18 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     Ok(())
 }
 
+fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item,
+              typ: &clean::TyParam) -> fmt::Result {
+    try!(write!(w, "type {}", it.name.as_ref().unwrap()));
+    if typ.bounds.len() > 0 {
+        try!(write!(w, ": {}", TyParamBounds(&*typ.bounds)))
+    }
+    if let Some(ref default) = typ.default {
+        try!(write!(w, " = {}", default));
+    }
+    Ok(())
+}
+
 fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
     fn method(w: &mut fmt::Formatter, it: &clean::Item, unsafety: ast::Unsafety,
            g: &clean::Generics, selfty: &clean::SelfTy,
@@ -1828,17 +1840,6 @@ fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
                decl = Method(selfty, d),
                where_clause = WhereClause(g))
     }
-    fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item,
-                  typ: &clean::TyParam) -> fmt::Result {
-        try!(write!(w, "type {}", it.name.as_ref().unwrap()));
-        if typ.bounds.len() > 0 {
-            try!(write!(w, ": {}", TyParamBounds(&*typ.bounds)))
-        }
-        if let Some(ref default) = typ.default {
-            try!(write!(w, " = {}", default));
-        }
-        Ok(())
-    }
     match meth.inner {
         clean::TyMethodItem(ref m) => {
             method(w, meth, m.unsafety, &m.generics, &m.self_, &m.decl)
@@ -2123,6 +2124,15 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl) -> fmt::Result {
                 try!(write!(w, "type {} = {}", name, tydef.type_));
                 try!(write!(w, "</code></h4>\n"));
             }
+            clean::AssociatedTypeItem(ref typaram) => {
+                let name = item.name.as_ref().unwrap();
+                try!(write!(w, "<h4 id='assoc_type.{}' class='{}'>{}<code>",
+                            *name,
+                            shortty(item),
+                            ConciseStability(&item.stability)));
+                try!(assoc_type(w, item, typaram));
+                try!(write!(w, "</code></h4>\n"));
+            }
             _ => panic!("can't make docs for trait item with name {}", item.name)
         }
         match item.doc_value() {
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
index 33cf33848f0..b1433ad7fdc 100644
--- a/src/libstd/c_str.rs
+++ b/src/libstd/c_str.rs
@@ -549,8 +549,8 @@ pub unsafe fn from_c_multistring<F>(buf: *const libc::c_char,
 
 #[cfg(test)]
 mod tests {
-    use super::*;
     use prelude::v1::*;
+    use super::*;
     use ptr;
     use thread::Thread;
     use libc;
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 4738c830bd3..d4fc4150fae 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -311,7 +311,7 @@ fn search_hashed<K, V, M, F>(table: M,
                              hash: SafeHash,
                              mut is_match: F)
                              -> SearchResult<K, V, M> where
-    M: Deref<RawTable<K, V>>,
+    M: Deref<Target=RawTable<K, V>>,
     F: FnMut(&K) -> bool,
 {
     let size = table.size();
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 6938ab9b0b6..a687ba3da8d 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -210,7 +210,7 @@ impl<K, V, M> Bucket<K, V, M> {
     }
 }
 
-impl<K, V, M: Deref<RawTable<K, V>>> Bucket<K, V, M> {
+impl<K, V, M: Deref<Target=RawTable<K, V>>> Bucket<K, V, M> {
     pub fn new(table: M, hash: SafeHash) -> Bucket<K, V, M> {
         Bucket::at_index(table, hash.inspect() as uint)
     }
@@ -279,7 +279,7 @@ impl<K, V, M: Deref<RawTable<K, V>>> Bucket<K, V, M> {
     }
 }
 
-impl<K, V, M: Deref<RawTable<K, V>>> EmptyBucket<K, V, M> {
+impl<K, V, M: Deref<Target=RawTable<K, V>>> EmptyBucket<K, V, M> {
     #[inline]
     pub fn next(self) -> Bucket<K, V, M> {
         let mut bucket = self.into_bucket();
@@ -315,7 +315,7 @@ impl<K, V, M: Deref<RawTable<K, V>>> EmptyBucket<K, V, M> {
     }
 }
 
-impl<K, V, M: DerefMut<RawTable<K, V>>> EmptyBucket<K, V, M> {
+impl<K, V, M: Deref<Target=RawTable<K, V>> + DerefMut> EmptyBucket<K, V, M> {
     /// Puts given key and value pair, along with the key's hash,
     /// into this bucket in the hashtable. Note how `self` is 'moved' into
     /// this function, because this slot will no longer be empty when
@@ -337,7 +337,7 @@ impl<K, V, M: DerefMut<RawTable<K, V>>> EmptyBucket<K, V, M> {
     }
 }
 
-impl<K, V, M: Deref<RawTable<K, V>>> FullBucket<K, V, M> {
+impl<K, V, M: Deref<Target=RawTable<K, V>>> FullBucket<K, V, M> {
     #[inline]
     pub fn next(self) -> Bucket<K, V, M> {
         let mut bucket = self.into_bucket();
@@ -384,7 +384,7 @@ impl<K, V, M: Deref<RawTable<K, V>>> FullBucket<K, V, M> {
     }
 }
 
-impl<K, V, M: DerefMut<RawTable<K, V>>> FullBucket<K, V, M> {
+impl<K, V, M: Deref<Target=RawTable<K, V>> + DerefMut> FullBucket<K, V, M> {
     /// Removes this bucket's key and value from the hashtable.
     ///
     /// This works similarly to `put`, building an `EmptyBucket` out of the
@@ -428,7 +428,7 @@ impl<K, V, M: DerefMut<RawTable<K, V>>> FullBucket<K, V, M> {
     }
 }
 
-impl<'t, K, V, M: Deref<RawTable<K, V>> + 't> FullBucket<K, V, M> {
+impl<'t, K, V, M: Deref<Target=RawTable<K, V>> + 't> FullBucket<K, V, M> {
     /// Exchange a bucket state for immutable references into the table.
     /// Because the underlying reference to the table is also consumed,
     /// no further changes to the structure of the table are possible;
@@ -442,7 +442,7 @@ impl<'t, K, V, M: Deref<RawTable<K, V>> + 't> FullBucket<K, V, M> {
     }
 }
 
-impl<'t, K, V, M: DerefMut<RawTable<K, V>> + 't> FullBucket<K, V, M> {
+impl<'t, K, V, M: Deref<Target=RawTable<K, V>> + DerefMut + 't> FullBucket<K, V, M> {
     /// This works similarly to `into_refs`, exchanging a bucket state
     /// for mutable references into the table.
     pub fn into_mut_refs(self) -> (&'t mut K, &'t mut V) {
@@ -463,7 +463,7 @@ impl<K, V, M> BucketState<K, V, M> {
     }
 }
 
-impl<K, V, M: Deref<RawTable<K, V>>> GapThenFull<K, V, M> {
+impl<K, V, M: Deref<Target=RawTable<K, V>>> GapThenFull<K, V, M> {
     #[inline]
     pub fn full(&self) -> &FullBucket<K, V, M> {
         &self.full
diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs
index 3cdfa8beb07..f47f6237b72 100644
--- a/src/libstd/io/comm_adapters.rs
+++ b/src/libstd/io/comm_adapters.rs
@@ -14,7 +14,7 @@ use sync::mpsc::{Sender, Receiver};
 use io;
 use option::Option::{None, Some};
 use result::Result::{Ok, Err};
-use slice::{bytes, CloneSliceExt, SliceExt};
+use slice::{bytes, SliceExt};
 use super::{Buffer, Reader, Writer, IoResult};
 use vec::Vec;
 
diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs
index e5d95974edb..ad921e43c0c 100644
--- a/src/libstd/io/mem.rs
+++ b/src/libstd/io/mem.rs
@@ -402,8 +402,8 @@ mod test {
     use prelude::v1::*;
 
     use super::*;
-    use io;
     use io::{SeekSet, SeekCur, SeekEnd};
+    use io;
     use self::test_crate::Bencher;
 
     #[test]
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 8f7de1c4dca..0a7815aeb53 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -1941,8 +1941,8 @@ impl fmt::Show for FilePermission {
 #[cfg(test)]
 mod tests {
     use self::BadReaderBehavior::*;
-    use super::{IoResult, MemReader, NoProgress, InvalidInput};
-    use prelude::v1::*;
+    use super::{IoResult, Reader, MemReader, NoProgress, InvalidInput, Writer};
+    use prelude::v1::{Ok, Vec, Buffer, SliceExt};
     use uint;
 
     #[deriving(Clone, PartialEq, Show)]
diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs
index 7ce1d1fc13b..2a18b839778 100644
--- a/src/libstd/io/net/ip.rs
+++ b/src/libstd/io/net/ip.rs
@@ -25,7 +25,7 @@ use ops::FnOnce;
 use option::Option;
 use option::Option::{None, Some};
 use result::Result::{Ok, Err};
-use slice::{CloneSliceExt, SliceExt};
+use slice::SliceExt;
 use str::{FromStr, StrExt};
 use vec::Vec;
 
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index ba709b2dc74..cd991c5f884 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -117,13 +117,15 @@ pub struct StdinReaderGuard<'a> {
     inner: MutexGuard<'a, RaceBox>,
 }
 
-impl<'a> Deref<BufferedReader<StdReader>> for StdinReaderGuard<'a> {
+impl<'a> Deref for StdinReaderGuard<'a> {
+    type Target = BufferedReader<StdReader>;
+
     fn deref(&self) -> &BufferedReader<StdReader> {
         &self.inner.0
     }
 }
 
-impl<'a> DerefMut<BufferedReader<StdReader>> for StdinReaderGuard<'a> {
+impl<'a> DerefMut for StdinReaderGuard<'a> {
     fn deref_mut(&mut self) -> &mut BufferedReader<StdReader> {
         &mut self.inner.0
     }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 848d3604953..7c8aab2b31d 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -108,6 +108,7 @@
 #![feature(default_type_params, phase, lang_items, unsafe_destructor)]
 #![feature(slicing_syntax, unboxed_closures)]
 #![feature(old_orphan_check)]
+#![feature(associated_types)]
 
 // Don't link to std. We are std.
 #![no_std]
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 47be8b2dcf9..63fd3209cc0 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -317,9 +317,8 @@ macro_rules! try {
 #[macro_export]
 macro_rules! vec {
     ($($x:expr),*) => ({
-        use std::slice::BoxedSliceExt;
         let xs: ::std::boxed::Box<[_]> = box [$($x),*];
-        xs.into_vec()
+        ::std::slice::SliceExt::into_vec(xs)
     });
     ($($x:expr,)*) => (vec![$($x),*])
 }
diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs
index febdf5f6118..6c64251091a 100644
--- a/src/libstd/num/strconv.rs
+++ b/src/libstd/num/strconv.rs
@@ -20,7 +20,7 @@ use char::{mod, Char};
 use num::{mod, Int, Float, ToPrimitive};
 use num::FpCategory as Fp;
 use ops::FnMut;
-use slice::{SliceExt, CloneSliceExt};
+use slice::SliceExt;
 use str::StrExt;
 use string::String;
 use vec::Vec;
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 02e520daaf2..615a20baf89 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -52,7 +52,6 @@ use ptr;
 use result::Result;
 use result::Result::{Err, Ok};
 use slice::{AsSlice, SliceExt};
-use slice::CloneSliceExt;
 use str::{Str, StrExt};
 use string::{String, ToString};
 use sync::atomic::{AtomicInt, ATOMIC_INT_INIT, SeqCst};
diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs
index 024dc56073d..731c3bbe427 100644
--- a/src/libstd/path/mod.rs
+++ b/src/libstd/path/mod.rs
@@ -71,8 +71,7 @@ use option::Option::{None, Some};
 use str;
 use str::{CowString, MaybeOwned, Str, StrExt};
 use string::String;
-use slice::{AsSlice, CloneSliceExt};
-use slice::{PartialEqSliceExt, SliceExt};
+use slice::{AsSlice, SliceExt};
 use vec::Vec;
 
 /// Typedef for POSIX file paths.
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index 102da31a293..6075010f3b5 100644
--- a/src/libstd/path/posix.rs
+++ b/src/libstd/path/posix.rs
@@ -22,8 +22,7 @@ use option::Option::{None, Some};
 use kinds::Sized;
 use str::{FromStr, Str};
 use str;
-use slice::{CloneSliceExt, Split, AsSlice, SliceConcatExt,
-            PartialEqSliceExt, SliceExt};
+use slice::{Split, AsSlice, SliceConcatExt, SliceExt};
 use vec::Vec;
 
 use super::{BytesContainer, GenericPath, GenericPathUnsafe};
@@ -453,7 +452,7 @@ mod tests {
     use iter::{IteratorExt, DoubleEndedIteratorExt};
     use option::Option::{mod, Some, None};
     use path::GenericPath;
-    use slice::{AsSlice, SliceExt, CloneSliceExt};
+    use slice::{AsSlice, SliceExt};
     use str::{mod, Str, StrExt};
     use string::ToString;
     use vec::Vec;
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index a6d30dc5778..55086ad3a23 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -1127,7 +1127,7 @@ mod tests {
     use iter::{IteratorExt, DoubleEndedIteratorExt};
     use option::Option::{mod, Some, None};
     use path::GenericPath;
-    use slice::{AsSlice, SliceExt, CloneSliceExt};
+    use slice::{AsSlice, SliceExt};
     use str::Str;
     use string::ToString;
     use vec::Vec;
diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs
index 33146f5e622..cb5dfafb4a1 100644
--- a/src/libstd/prelude/v1.rs
+++ b/src/libstd/prelude/v1.rs
@@ -36,9 +36,7 @@
 #[stable] #[doc(no_inline)] pub use ptr::{PtrExt, MutPtrExt};
 #[stable] #[doc(no_inline)] pub use result::Result::{mod, Ok, Err};
 #[stable] #[doc(no_inline)] pub use slice::AsSlice;
-#[stable] #[doc(no_inline)] pub use slice::{BoxedSliceExt, SliceExt};
-#[stable] #[doc(no_inline)] pub use slice::{CloneSliceExt, OrdSliceExt};
-#[stable] #[doc(no_inline)] pub use slice::{PartialEqSliceExt, SliceConcatExt};
+#[stable] #[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt};
 #[stable] #[doc(no_inline)] pub use str::{Str, StrExt};
 #[stable] #[doc(no_inline)] pub use string::{String, ToString};
 #[stable] #[doc(no_inline)] pub use vec::Vec;
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 270c57f1ec0..f9f9a809221 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -291,12 +291,14 @@ impl<'mutex, T> MutexGuard<'mutex, T> {
     }
 }
 
-impl<'mutex, T> Deref<T> for MutexGuard<'mutex, T> {
+impl<'mutex, T> Deref for MutexGuard<'mutex, T> {
+    type Target = T;
+
     fn deref<'a>(&'a self) -> &'a T {
         unsafe { &*self.__data.get() }
     }
 }
-impl<'mutex, T> DerefMut<T> for MutexGuard<'mutex, T> {
+impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> {
     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
         unsafe { &mut *self.__data.get() }
     }
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index b23fff31c0a..431aeb9cae9 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -327,13 +327,17 @@ impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> {
     }
 }
 
-impl<'rwlock, T> Deref<T> for RWLockReadGuard<'rwlock, T> {
+impl<'rwlock, T> Deref for RWLockReadGuard<'rwlock, T> {
+    type Target = T;
+
     fn deref(&self) -> &T { unsafe { &*self.__data.get() } }
 }
-impl<'rwlock, T> Deref<T> for RWLockWriteGuard<'rwlock, T> {
+impl<'rwlock, T> Deref for RWLockWriteGuard<'rwlock, T> {
+    type Target = T;
+
     fn deref(&self) -> &T { unsafe { &*self.__data.get() } }
 }
-impl<'rwlock, T> DerefMut<T> for RWLockWriteGuard<'rwlock, T> {
+impl<'rwlock, T> DerefMut for RWLockWriteGuard<'rwlock, T> {
     fn deref_mut(&mut self) -> &mut T {
         unsafe { &mut *self.__data.get() }
     }
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 7a6824ac27c..18cdb3fc647 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -27,6 +27,7 @@
 #![feature(quote, unsafe_destructor)]
 #![feature(unboxed_closures)]
 #![feature(old_orphan_check)]
+#![feature(associated_types)]
 
 extern crate arena;
 extern crate fmt_macros;
diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs
index f7d2331c9ec..bc2e0923115 100644
--- a/src/libsyntax/owned_slice.rs
+++ b/src/libsyntax/owned_slice.rs
@@ -56,7 +56,9 @@ impl<T> OwnedSlice<T> {
     }
 }
 
-impl<T> Deref<[T]> for OwnedSlice<T> {
+impl<T> Deref for OwnedSlice<T> {
+    type Target = [T];
+
     fn deref(&self) -> &[T] {
         self.as_slice()
     }
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 9c6644c5204..2745b7e13e9 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -608,7 +608,9 @@ impl InternedString {
     }
 }
 
-impl Deref<str> for InternedString {
+impl Deref for InternedString {
+    type Target = str;
+
     fn deref(&self) -> &str { &*self.string }
 }
 
diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs
index 8b1aed483c3..a989b323723 100644
--- a/src/libsyntax/ptr.rs
+++ b/src/libsyntax/ptr.rs
@@ -77,7 +77,9 @@ impl<T: 'static> P<T> {
     }
 }
 
-impl<T> Deref<T> for P<T> {
+impl<T> Deref for P<T> {
+    type Target = T;
+
     fn deref<'a>(&'a self) -> &'a T {
         &*self.ptr
     }
diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs
index d25161a12a7..6e087778de9 100644
--- a/src/libsyntax/util/interner.rs
+++ b/src/libsyntax/util/interner.rs
@@ -126,7 +126,9 @@ impl BorrowFrom<RcStr> for str {
     }
 }
 
-impl Deref<str> for RcStr {
+impl Deref for RcStr {
+    type Target = str;
+
     fn deref(&self) -> &str { self.string[] }
 }
 
diff --git a/src/snapshots.txt b/src/snapshots.txt
index 6a9bfa07cf7..34beb53bd07 100644
--- a/src/snapshots.txt
+++ b/src/snapshots.txt
@@ -1,3 +1,12 @@
+S 2015-01-01 7d4f487
+  freebsd-x86_64 5dc87adb17bc33abc08f1bf4c092e0b5b92a6ca4
+  linux-i386 63bf82a5b540d8acbbf1e445ce48be0fa0f003fc
+  linux-x86_64 b1a414355ef5d2feff18ab9d008a2e9afc7b4625
+  macos-i386 26042e3e648eb40848bf02f3e05ba31fd686179c
+  macos-x86_64 f01d7c6faf5db480a18a521c6971364f4ce8ddca
+  winnt-i386 6f04af045d26a0c87d487ba7254d4ad0c166ecaf
+  winnt-x86_64 392ab49482ec926de6a167afe920518b9a502a3f
+
 S 2014-12-30 023dfb0
   freebsd-x86_64 41ecd0ac557c823831c46696c7d78dc250398f25
   linux-i386 fe6b59bf70a397e18629cb82264f7c6a70df34d4
diff --git a/src/test/auxiliary/overloaded_autoderef_xc.rs b/src/test/auxiliary/overloaded_autoderef_xc.rs
index 26d61e166f2..05960a5b8e1 100644
--- a/src/test/auxiliary/overloaded_autoderef_xc.rs
+++ b/src/test/auxiliary/overloaded_autoderef_xc.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_types)]
+
 use std::ops::Deref;
 
 struct DerefWithHelper<H, T> {
@@ -24,7 +26,9 @@ impl<T> Helper<T> for Option<T> {
     }
 }
 
-impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> {
+impl<T, H: Helper<T>> Deref for DerefWithHelper<H, T> {
+    type Target = T;
+
     fn deref(&self) -> &T {
         self.helper.helper_borrow()
     }
diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs
new file mode 100644
index 00000000000..5743216b6ca
--- /dev/null
+++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs
@@ -0,0 +1,34 @@
+// 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.
+
+// Test that we do not ICE when the self type is `ty::err`, but rather
+// just propagate the error.
+
+#![crate_type = "lib"]
+#![feature(associated_types, default_type_params, lang_items)]
+#![no_std]
+
+#[lang="sized"]
+pub trait Sized for Sized? {
+    // Empty.
+}
+
+#[lang = "add"]
+trait Add<RHS=Self> {
+    type Output;
+
+    fn add(self, RHS) -> Self::Output;
+}
+
+fn ice<A>(a: A) {
+    let r = loop {};
+    r = r + a; // here the type `r` is not yet inferred, hence `r+a` generates an error.
+    //~^ ERROR type of this value must be known
+}
diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs
index 05bc0d1e13b..7cd170f7773 100644
--- a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs
+++ b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs
@@ -11,19 +11,23 @@
 // Test how overloaded deref interacts with borrows when DerefMut
 // is implemented.
 
+#![feature(associated_types)]
+
 use std::ops::{Deref, DerefMut};
 
 struct Own<T> {
     value: *mut T
 }
 
-impl<T> Deref<T> for Own<T> {
+impl<T> Deref for Own<T> {
+    type Target = T;
+
     fn deref(&self) -> &T {
         unsafe { &*self.value }
     }
 }
 
-impl<T> DerefMut<T> for Own<T> {
+impl<T> DerefMut for Own<T> {
     fn deref_mut(&mut self) -> &mut T {
         unsafe { &mut *self.value }
     }
diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs
index 5aaefd01739..759467aeda3 100644
--- a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs
+++ b/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs
@@ -11,13 +11,17 @@
 // Test how overloaded deref interacts with borrows when only
 // Deref and not DerefMut is implemented.
 
+#![feature(associated_types)]
+
 use std::ops::Deref;
 
 struct Rc<T> {
     value: *const T
 }
 
-impl<T> Deref<T> for Rc<T> {
+impl<T> Deref for Rc<T> {
+    type Target = T;
+
     fn deref(&self) -> &T {
         unsafe { &*self.value }
     }
diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs b/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs
index 974fe3bc5d5..74dceab18ea 100644
--- a/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs
+++ b/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs
@@ -11,19 +11,23 @@
 // Test how overloaded deref interacts with borrows when DerefMut
 // is implemented.
 
+#![feature(associated_types)]
+
 use std::ops::{Deref, DerefMut};
 
 struct Own<T> {
     value: *mut T
 }
 
-impl<T> Deref<T> for Own<T> {
+impl<T> Deref for Own<T> {
+    type Target = T;
+
     fn deref<'a>(&'a self) -> &'a T {
         unsafe { &*self.value }
     }
 }
 
-impl<T> DerefMut<T> for Own<T> {
+impl<T> DerefMut for Own<T> {
     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
         unsafe { &mut *self.value }
     }
diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs b/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs
index 5397c5b8a56..635e440c6fe 100644
--- a/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs
+++ b/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs
@@ -11,13 +11,17 @@
 // Test how overloaded deref interacts with borrows when only
 // Deref and not DerefMut is implemented.
 
+#![feature(associated_types)]
+
 use std::ops::Deref;
 
 struct Rc<T> {
     value: *const T
 }
 
-impl<T> Deref<T> for Rc<T> {
+impl<T> Deref for Rc<T> {
+    type Target = T;
+
     fn deref<'a>(&'a self) -> &'a T {
         unsafe { &*self.value }
     }
diff --git a/src/test/compile-fail/infinite-autoderef.rs b/src/test/compile-fail/infinite-autoderef.rs
index e4c6fa7d47f..ab770c099e1 100644
--- a/src/test/compile-fail/infinite-autoderef.rs
+++ b/src/test/compile-fail/infinite-autoderef.rs
@@ -10,11 +10,15 @@
 
 // error-pattern: reached the recursion limit while auto-dereferencing
 
+#![feature(associated_types)]
+
 use std::ops::Deref;
 
 struct Foo;
 
-impl Deref<Foo> for Foo {
+impl Deref for Foo {
+    type Target = Foo;
+
     fn deref(&self) -> &Foo {
         self
     }
diff --git a/src/test/compile-fail/issue-18566.rs b/src/test/compile-fail/issue-18566.rs
index c2e4629e14d..491707a9e31 100644
--- a/src/test/compile-fail/issue-18566.rs
+++ b/src/test/compile-fail/issue-18566.rs
@@ -8,10 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_types)]
+
 use std::ops::Deref;
 
 struct MyPtr<'a>(&'a mut uint);
-impl<'a> Deref<uint> for MyPtr<'a> {
+impl<'a> Deref for MyPtr<'a> {
+    type Target = uint;
+
     fn deref<'b>(&'b self) -> &'b uint { self.0 }
 }
 
diff --git a/src/test/run-pass/associated-types-conditional-dispatch.rs b/src/test/run-pass/associated-types-conditional-dispatch.rs
new file mode 100644
index 00000000000..3b53203d218
--- /dev/null
+++ b/src/test/run-pass/associated-types-conditional-dispatch.rs
@@ -0,0 +1,73 @@
+// 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.
+
+// Test that we evaluate projection predicates to winnow out
+// candidates during trait selection and method resolution (#20296).
+// If we don't properly winnow out candidates based on the output type
+// `Target=[A]`, then the impl marked with `(*)` is seen to conflict
+// with all the others.
+
+#![feature(associated_types, default_type_params)]
+
+use std::ops::Deref;
+
+pub trait MyEq<Sized? U=Self> for Sized? {
+    fn eq(&self, u: &U) -> bool;
+}
+
+impl<A, B> MyEq<[B]> for [A]
+    where A : MyEq<B>
+{
+    fn eq(&self, other: &[B]) -> bool {
+        self.len() == other.len() &&
+            self.iter().zip(other.iter())
+                       .all(|(a, b)| MyEq::eq(a, b))
+    }
+}
+
+// (*) This impl conflicts with everything unless the `Target=[A]`
+// constraint is considered.
+impl<'a, A, B, Lhs> MyEq<[B; 0]> for Lhs
+    where A: MyEq<B>, Lhs: Deref<Target=[A]>
+{
+    fn eq(&self, other: &[B; 0]) -> bool {
+        MyEq::eq(&**self, other.as_slice())
+    }
+}
+
+struct DerefWithHelper<H, T> {
+    pub helper: H
+}
+
+trait Helper<T> {
+    fn helper_borrow(&self) -> &T;
+}
+
+impl<T> Helper<T> for Option<T> {
+    fn helper_borrow(&self) -> &T {
+        self.as_ref().unwrap()
+    }
+}
+
+impl<T, H: Helper<T>> Deref for DerefWithHelper<H, T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        self.helper.helper_borrow()
+    }
+}
+
+pub fn check<T: MyEq>(x: T, y: T) -> bool {
+    let d: DerefWithHelper<Option<T>, T> = DerefWithHelper { helper: Some(x) };
+    d.eq(&y)
+}
+
+pub fn main() {
+}
diff --git a/src/test/run-pass/deref-mut-on-ref.rs b/src/test/run-pass/deref-mut-on-ref.rs
index 5a98952c127..f43be177862 100644
--- a/src/test/run-pass/deref-mut-on-ref.rs
+++ b/src/test/run-pass/deref-mut-on-ref.rs
@@ -10,9 +10,9 @@
 
 // Test that `&mut T` implements `DerefMut<T>`
 
-use std::ops::DerefMut;
+use std::ops::{Deref, DerefMut};
 
-fn inc<T:DerefMut<int>>(mut t: T) {
+fn inc<T: Deref<Target=int> + DerefMut>(mut t: T) {
     *t += 1;
 }
 
diff --git a/src/test/run-pass/deref-on-ref.rs b/src/test/run-pass/deref-on-ref.rs
index f245c11f090..e95d942c8cf 100644
--- a/src/test/run-pass/deref-on-ref.rs
+++ b/src/test/run-pass/deref-on-ref.rs
@@ -12,7 +12,7 @@
 
 use std::ops::Deref;
 
-fn deref<U:Copy,T:Deref<U>>(t: T) -> U {
+fn deref<U:Copy,T:Deref<Target=U>>(t: T) -> U {
     *t
 }
 
diff --git a/src/test/run-pass/dst-deref-mut.rs b/src/test/run-pass/dst-deref-mut.rs
index 0cbcee3e253..0e0ed1f436c 100644
--- a/src/test/run-pass/dst-deref-mut.rs
+++ b/src/test/run-pass/dst-deref-mut.rs
@@ -10,19 +10,23 @@
 
 // Test that a custom deref with a fat pointer return type does not ICE
 
+#![feature(associated_types)]
+
 use std::ops::{Deref, DerefMut};
 
 pub struct Arr {
     ptr: Box<[uint]>
 }
 
-impl Deref<[uint]> for Arr {
+impl Deref for Arr {
+    type Target = [uint];
+
     fn deref(&self) -> &[uint] {
         panic!();
     }
 }
 
-impl DerefMut<[uint]> for Arr {
+impl DerefMut for Arr {
     fn deref_mut(&mut self) -> &mut [uint] {
         &mut *self.ptr
     }
diff --git a/src/test/run-pass/dst-deref.rs b/src/test/run-pass/dst-deref.rs
index 96a9c117dea..a39670a27b9 100644
--- a/src/test/run-pass/dst-deref.rs
+++ b/src/test/run-pass/dst-deref.rs
@@ -10,13 +10,17 @@
 
 // Test that a custom deref with a fat pointer return type does not ICE
 
+#![feature(associated_types)]
+
 use std::ops::Deref;
 
 pub struct Arr {
     ptr: Box<[uint]>
 }
 
-impl Deref<[uint]> for Arr {
+impl Deref for Arr {
+    type Target = [uint];
+
     fn deref(&self) -> &[uint] {
         &*self.ptr
     }
diff --git a/src/test/run-pass/fixup-deref-mut.rs b/src/test/run-pass/fixup-deref-mut.rs
index 70d14ba3623..8fb3893e5de 100644
--- a/src/test/run-pass/fixup-deref-mut.rs
+++ b/src/test/run-pass/fixup-deref-mut.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_types)]
+
 use std::ops::{Deref, DerefMut};
 
 // Generic unique/owned smaht pointer.
@@ -15,13 +17,15 @@ struct Own<T> {
     value: *mut T
 }
 
-impl<T> Deref<T> for Own<T> {
+impl<T> Deref for Own<T> {
+    type Target = T;
+
     fn deref<'a>(&'a self) -> &'a T {
         unsafe { &*self.value }
     }
 }
 
-impl<T> DerefMut<T> for Own<T> {
+impl<T> DerefMut for Own<T> {
     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
         unsafe { &mut *self.value }
     }
diff --git a/src/test/run-pass/issue-13264.rs b/src/test/run-pass/issue-13264.rs
index 5f82730c27c..00b508ab92c 100644
--- a/src/test/run-pass/issue-13264.rs
+++ b/src/test/run-pass/issue-13264.rs
@@ -8,13 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_types)]
+
 use std::ops::Deref;
 
 struct Root {
     jsref: JSRef
 }
 
-impl Deref<JSRef> for Root {
+impl Deref for Root {
+    type Target = JSRef;
+
     fn deref<'a>(&'a self) -> &'a JSRef {
         &self.jsref
     }
@@ -25,7 +29,9 @@ struct JSRef {
     node: *const Node
 }
 
-impl Deref<Node> for JSRef {
+impl Deref for JSRef {
+    type Target = Node;
+
     fn deref<'a>(&'a self) -> &'a Node {
         self.get()
     }
diff --git a/src/test/run-pass/issue-16774.rs b/src/test/run-pass/issue-16774.rs
index 0b9a85851c5..45cfabcd872 100644
--- a/src/test/run-pass/issue-16774.rs
+++ b/src/test/run-pass/issue-16774.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unboxed_closures)]
+#![feature(associated_types, unboxed_closures)]
 
 use std::ops::{Deref, DerefMut};
 
@@ -25,14 +25,16 @@ impl Drop for X {
     }
 }
 
-impl Deref<int> for X {
+impl Deref for X {
+    type Target = int;
+
     fn deref(&self) -> &int {
         let &X(box ref x) = self;
         x
     }
 }
 
-impl DerefMut<int> for X {
+impl DerefMut for X {
     fn deref_mut(&mut self) -> &mut int {
         let &X(box ref mut x) = self;
         x
diff --git a/src/test/run-pass/overloaded-autoderef-count.rs b/src/test/run-pass/overloaded-autoderef-count.rs
index baf1b1b0237..e9eb924d449 100644
--- a/src/test/run-pass/overloaded-autoderef-count.rs
+++ b/src/test/run-pass/overloaded-autoderef-count.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_types)]
+
 use std::cell::Cell;
 use std::ops::{Deref, DerefMut};
 
@@ -32,14 +34,16 @@ impl<T> DerefCounter<T> {
     }
 }
 
-impl<T> Deref<T> for DerefCounter<T> {
+impl<T> Deref for DerefCounter<T> {
+    type Target = T;
+
     fn deref(&self) -> &T {
         self.count_imm.set(self.count_imm.get() + 1);
         &self.value
     }
 }
 
-impl<T> DerefMut<T> for DerefCounter<T> {
+impl<T> DerefMut for DerefCounter<T> {
     fn deref_mut(&mut self) -> &mut T {
         self.count_mut += 1;
         &mut self.value
diff --git a/src/test/run-pass/overloaded-autoderef-indexing.rs b/src/test/run-pass/overloaded-autoderef-indexing.rs
index d1fb69b87a3..6d8d09b321e 100644
--- a/src/test/run-pass/overloaded-autoderef-indexing.rs
+++ b/src/test/run-pass/overloaded-autoderef-indexing.rs
@@ -8,13 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_types)]
+
 use std::ops::Deref;
 
 struct DerefArray<'a, T:'a> {
     inner: &'a [T]
 }
 
-impl<'a, T> Deref<&'a [T]> for DerefArray<'a, T> {
+impl<'a, T> Deref for DerefArray<'a, T> {
+    type Target = &'a [T];
+
     fn deref<'b>(&'b self) -> &'b &'a [T] {
         &self.inner
     }
diff --git a/src/test/run-pass/overloaded-autoderef-order.rs b/src/test/run-pass/overloaded-autoderef-order.rs
index 23a8285063f..cafb665fc37 100644
--- a/src/test/run-pass/overloaded-autoderef-order.rs
+++ b/src/test/run-pass/overloaded-autoderef-order.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_types)]
+
 use std::rc::Rc;
 use std::ops::Deref;
 
@@ -24,7 +26,9 @@ impl<X, Y> DerefWrapper<X, Y> {
     }
 }
 
-impl<X, Y> Deref<Y> for DerefWrapper<X, Y> {
+impl<X, Y> Deref for DerefWrapper<X, Y> {
+    type Target = Y;
+
     fn deref(&self) -> &Y {
         &self.y
     }
@@ -49,7 +53,9 @@ mod priv_test {
         }
     }
 
-    impl<X, Y> Deref<Y> for DerefWrapperHideX<X, Y> {
+    impl<X, Y> Deref for DerefWrapperHideX<X, Y> {
+        type Target = Y;
+
         fn deref(&self) -> &Y {
             &self.y
         }
diff --git a/src/test/run-pass/overloaded-autoderef-vtable.rs b/src/test/run-pass/overloaded-autoderef-vtable.rs
index f71afb96507..23efba15749 100644
--- a/src/test/run-pass/overloaded-autoderef-vtable.rs
+++ b/src/test/run-pass/overloaded-autoderef-vtable.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_types)]
+
 use std::ops::Deref;
 
 struct DerefWithHelper<H, T> {
@@ -24,7 +26,9 @@ impl<T> Helper<T> for Option<T> {
     }
 }
 
-impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> {
+impl<T, H: Helper<T>> Deref for DerefWithHelper<H, T> {
+    type Target = T;
+
     fn deref(&self) -> &T {
         self.helper.helper_borrow()
     }
diff --git a/src/test/run-pass/overloaded-deref-count.rs b/src/test/run-pass/overloaded-deref-count.rs
index 7645500c02f..b6fb38d5cc2 100644
--- a/src/test/run-pass/overloaded-deref-count.rs
+++ b/src/test/run-pass/overloaded-deref-count.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_types)]
+
 use std::cell::Cell;
 use std::ops::{Deref, DerefMut};
 use std::vec::Vec;
@@ -32,14 +34,16 @@ impl<T> DerefCounter<T> {
     }
 }
 
-impl<T> Deref<T> for DerefCounter<T> {
+impl<T> Deref for DerefCounter<T> {
+    type Target = T;
+
     fn deref(&self) -> &T {
         self.count_imm.set(self.count_imm.get() + 1);
         &self.value
     }
 }
 
-impl<T> DerefMut<T> for DerefCounter<T> {
+impl<T> DerefMut for DerefCounter<T> {
     fn deref_mut(&mut self) -> &mut T {
         self.count_mut += 1;
         &mut self.value
diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs
index 2efd0ad14bd..62b61c153c7 100644
--- a/src/test/run-pass/tcp-stress.rs
+++ b/src/test/run-pass/tcp-stress.rs
@@ -49,7 +49,7 @@ fn main() {
             stream.write(&[2]);
         }
     }).detach();
-    let addr = rx.recv().unwarp();
+    let addr = rx.recv().unwrap();
 
     let (tx, rx) = channel();
     for _ in range(0u, 1000) {