From 167683da230c9685d31b9e6155b18740f9fe858e Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Thu, 1 Jan 2015 12:16:49 -0800
Subject: [PATCH 1/9] Register new snapshots

---
 src/snapshots.txt | 9 +++++++++
 1 file changed, 9 insertions(+)

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

From cc5ecaf76589a83e40136e31d211246204767465 Mon Sep 17 00:00:00 2001
From: Jorge Aparicio <japaricious@gmail.com>
Date: Fri, 2 Jan 2015 09:12:27 -0500
Subject: [PATCH 2/9] merge `*SliceExt` traits, use assoc types in `SliceExt`,
 `Raw[Mut]Ptr`

---
 src/libcollections/lib.rs      |   4 +-
 src/libcollections/slice.rs    | 551 +++++++++++++++++----------------
 src/libcollections/string.rs   |   3 +-
 src/libcollections/vec.rs      |   4 +-
 src/libcore/prelude.rs         |   1 -
 src/libcore/ptr.rs             |  24 +-
 src/libcore/slice.rs           | 365 ++++++++++------------
 src/libstd/c_str.rs            |   2 +-
 src/libstd/io/comm_adapters.rs |   2 +-
 src/libstd/io/mem.rs           |   2 +-
 src/libstd/io/mod.rs           |   2 +-
 src/libstd/io/net/ip.rs        |   2 +-
 src/libstd/lib.rs              |   1 +
 src/libstd/macros.rs           |   3 +-
 src/libstd/num/strconv.rs      |   2 +-
 src/libstd/os.rs               |   1 -
 src/libstd/path/mod.rs         |   3 +-
 src/libstd/path/posix.rs       |   5 +-
 src/libstd/path/windows.rs     |   2 +-
 src/libstd/prelude.rs          |   4 +-
 20 files changed, 489 insertions(+), 494 deletions(-)

diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index cbd8d4955b2..09cff4bc5ad 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -25,6 +25,7 @@
 #![feature(macro_rules, default_type_params, phase, globs)]
 #![feature(unsafe_destructor, slicing_syntax)]
 #![feature(unboxed_closures)]
+#![feature(associated_types)]
 #![no_std]
 
 #[phase(plugin, link)] extern crate core;
@@ -120,7 +121,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};
 
@@ -129,7 +129,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 61111d96bd0..ac271e75ea1 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -96,7 +96,7 @@ use core::mem::size_of;
 use core::mem;
 use core::ops::{FnMut,SliceMut};
 use core::prelude::{Clone, Greater, Iterator, IteratorExt, Less, None, Option};
-use core::prelude::{Ord, Ordering, PtrExt, Some, range, IteratorCloneExt, Result};
+use core::prelude::{Ord, Ordering, PartialEq, PtrExt, Some, range, IteratorCloneExt, Result};
 use core::ptr;
 use core::slice as core_slice;
 use self::Direction::*;
@@ -104,7 +104,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};
@@ -122,7 +122,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.
     ///
@@ -141,7 +143,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).
@@ -165,7 +167,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`).
     ///
@@ -174,7 +176,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.
     ///
@@ -182,7 +184,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`.
     ///
@@ -190,7 +192,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.
     ///
@@ -200,32 +202,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
@@ -247,7 +249,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
@@ -270,41 +272,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)
     }
 
@@ -316,7 +318,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.
     ///
@@ -352,7 +354,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
     ///
@@ -379,12 +381,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`).
     ///
@@ -393,7 +395,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.
     ///
@@ -401,7 +403,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`.
     ///
@@ -409,54 +411,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
@@ -467,7 +469,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.
     ///
@@ -525,7 +527,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.
     ///
@@ -541,11 +543,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)
     }
 
@@ -558,11 +560,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)
@@ -777,23 +947,71 @@ 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
-////////////////////////////////////////////////////////////////////////////////
+    /// Returns a copy of `v`.
+    #[inline]
+    fn to_vec(&self) -> Vec<T> where T: Clone {
+        let mut vector = Vec::with_capacity(self.len());
+        vector.push_all(self);
+        vector
+    }
 
-/// 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> {
+    #[inline]
+    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> where T: Clone {
+        Permutations{
+            swaps: ElementSwaps::new(self.len()),
+            v: self.to_vec(),
+        }
+    }
+
+    fn clone_from_slice(&mut self, src: &[T]) -> uint where T: Clone {
+        core_slice::SliceExt::clone_from_slice(self, src)
+    }
+
+    #[inline]
+    fn sort(&mut self) where T: Ord {
+        self.sort_by(|a, b| a.cmp(b))
+    }
+
+    fn binary_search(&self, x: &T) -> Result<uint, uint> where T: Ord {
+        core_slice::SliceExt::binary_search(self, x)
+    }
+
+    fn next_permutation(&mut self) -> bool where T: Ord {
+        core_slice::SliceExt::next_permutation(self)
+    }
+
+    fn prev_permutation(&mut self) -> bool where T: Ord {
+        core_slice::SliceExt::prev_permutation(self)
+    }
+
+    fn position_elem(&self, t: &T) -> Option<uint> where T: PartialEq {
+        core_slice::SliceExt::position_elem(self, t)
+    }
+
+    fn rposition_elem(&self, t: &T) -> Option<uint> where T: PartialEq {
+        core_slice::SliceExt::rposition_elem(self, t)
+    }
+
+    fn contains(&self, x: &T) -> bool where T: PartialEq {
+        core_slice::SliceExt::contains(self, x)
+    }
+
+    fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq {
+        core_slice::SliceExt::starts_with(self, needle)
+    }
+
+    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);
@@ -802,204 +1020,9 @@ impl<T> BoxedSliceExt<T> for Box<[T]> {
     }
 }
 
-/// 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> {
-        let mut vector = Vec::with_capacity(self.len());
-        vector.push_all(self);
-        vector
-    }
-
-
-    #[inline]
-    fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool {
-        self.iter().cloned().partition(f)
-    }
-
-    /// Returns an iterator over all permutations of a vector.
-    fn permutations(&self) -> Permutations<T> {
-        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)
-    }
-}
-
-/// 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);
-
-    /// 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>;
-
-    /// Deprecated: use `binary_search` instead.
-    #[deprecated = "use binary_search instead"]
-    fn binary_search_elem(&self, x: &T) -> Result<uint, uint> {
-        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;
-
-    /// 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;
-}
-
-#[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 binary_search(&self, x: &T) -> Result<uint, uint> {
-        core_slice::OrdSliceExt::binary_search(self, x)
-    }
-
-    fn next_permutation(&mut self) -> bool {
-        core_slice::OrdSliceExt::next_permutation(self)
-    }
-
-    fn prev_permutation(&mut self) -> bool {
-        core_slice::OrdSliceExt::prev_permutation(self)
-    }
-}
-
+////////////////////////////////////////////////////////////////////////////////
+// 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? {
@@ -1419,7 +1442,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 37a6e690f5d..b69db8b00b5 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -27,7 +27,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};
 
@@ -94,7 +93,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
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index a1952352bad..ce0519a2395 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -63,8 +63,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
@@ -1218,7 +1216,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
diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs
index cecb4938153..19301cc2d9e 100644
--- a/src/libcore/prelude.rs
+++ b/src/libcore/prelude.rs
@@ -64,5 +64,4 @@ pub use str::{Str, StrExt};
 pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
 pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
 pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
-pub use slice::{PartialEqSliceExt, OrdSliceExt};
 pub use slice::{AsSlice, SliceExt};
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index faf1d781465..09c78d4bc2a 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> {
+pub trait PtrExt {
+    type Target;
+
     /// Returns the null pointer.
     #[deprecated = "call ptr::null instead"]
     fn null() -> Self;
@@ -271,7 +273,7 @@ pub trait PtrExt<T> {
     /// 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> {
 
 /// 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,6 +424,111 @@ impl<T> SliceExt<T> for [T] {
     fn as_mut_ptr(&mut self) -> *mut T {
         self.repr().data as *mut T
     }
+
+    #[inline]
+    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> where T: PartialEq {
+        self.iter().rposition(|x| *x == *t)
+    }
+
+    #[inline]
+    fn contains(&self, x: &T) -> bool where T: PartialEq {
+        self.iter().any(|elt| *x == *elt)
+    }
+
+    #[inline]
+    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 where T: PartialEq {
+        let (m, n) = (self.len(), needle.len());
+        m >= n && needle == self[m-n..]
+    }
+
+    #[unstable]
+    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 where T: Ord {
+        // These cases only have 1 permutation each, so we can't do anything.
+        if self.len() < 2 { return false; }
+
+        // Step 1: Identify the longest, rightmost weakly decreasing part of the vector
+        let mut i = self.len() - 1;
+        while i > 0 && self[i-1] >= self[i] {
+            i -= 1;
+        }
+
+        // If that is the entire vector, this is the last-ordered permutation.
+        if i == 0 {
+            return false;
+        }
+
+        // Step 2: Find the rightmost element larger than the pivot (i-1)
+        let mut j = self.len() - 1;
+        while j >= i && self[j] <= self[i-1]  {
+            j -= 1;
+        }
+
+        // Step 3: Swap that element with the pivot
+        self.swap(j, i-1);
+
+        // Step 4: Reverse the (previously) weakly decreasing part
+        self.slice_from_mut(i).reverse();
+
+        true
+    }
+
+    #[experimental]
+    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; }
+
+        // Step 1: Identify the longest, rightmost weakly increasing part of the vector
+        let mut i = self.len() - 1;
+        while i > 0 && self[i-1] <= self[i] {
+            i -= 1;
+        }
+
+        // If that is the entire vector, this is the first-ordered permutation.
+        if i == 0 {
+            return false;
+        }
+
+        // Step 2: Reverse the weakly increasing part
+        self.slice_from_mut(i).reverse();
+
+        // Step 3: Find the rightmost element equal to or bigger than the pivot (i-1)
+        let mut j = self.len() - 1;
+        while j >= i && self[j-1] < self[i-1]  {
+            j -= 1;
+        }
+
+        // Step 4: Swap that element with the pivot
+        self.swap(i-1, j);
+
+        true
+    }
+
+    #[inline]
+    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);
+        for i in range(0, min) {
+            dst[i].clone_from(&src[i]);
+        }
+        min
+    }
 }
 
 impl<T> ops::Index<uint, T> for [T] {
@@ -479,160 +604,6 @@ impl<T> ops::SliceMut<uint, [T]> for [T] {
     }
 }
 
-/// 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> {
-        self.iter().position(|y| *x == *y)
-    }
-
-    #[inline]
-    fn rposition_elem(&self, t: &T) -> Option<uint> {
-        self.iter().rposition(|x| *x == *t)
-    }
-
-    #[inline]
-    fn contains(&self, x: &T) -> bool {
-        self.iter().any(|elt| *x == *elt)
-    }
-
-    #[inline]
-    fn starts_with(&self, needle: &[T]) -> bool {
-        let n = needle.len();
-        self.len() >= n && needle == self[..n]
-    }
-
-    #[inline]
-    fn ends_with(&self, needle: &[T]) -> bool {
-        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> {
-        self.binary_search_by(|p| p.cmp(x))
-    }
-
-    #[experimental]
-    fn next_permutation(&mut self) -> bool {
-        // These cases only have 1 permutation each, so we can't do anything.
-        if self.len() < 2 { return false; }
-
-        // Step 1: Identify the longest, rightmost weakly decreasing part of the vector
-        let mut i = self.len() - 1;
-        while i > 0 && self[i-1] >= self[i] {
-            i -= 1;
-        }
-
-        // If that is the entire vector, this is the last-ordered permutation.
-        if i == 0 {
-            return false;
-        }
-
-        // Step 2: Find the rightmost element larger than the pivot (i-1)
-        let mut j = self.len() - 1;
-        while j >= i && self[j] <= self[i-1]  {
-            j -= 1;
-        }
-
-        // Step 3: Swap that element with the pivot
-        self.swap(j, i-1);
-
-        // Step 4: Reverse the (previously) weakly decreasing part
-        self.slice_from_mut(i).reverse();
-
-        true
-    }
-
-    #[experimental]
-    fn prev_permutation(&mut self) -> bool {
-        // These cases only have 1 permutation each, so we can't do anything.
-        if self.len() < 2 { return false; }
-
-        // Step 1: Identify the longest, rightmost weakly increasing part of the vector
-        let mut i = self.len() - 1;
-        while i > 0 && self[i-1] <= self[i] {
-            i -= 1;
-        }
-
-        // If that is the entire vector, this is the first-ordered permutation.
-        if i == 0 {
-            return false;
-        }
-
-        // Step 2: Reverse the weakly increasing part
-        self.slice_from_mut(i).reverse();
-
-        // Step 3: Find the rightmost element equal to or bigger than the pivot (i-1)
-        let mut j = self.len() - 1;
-        while j >= i && self[j-1] < self[i-1]  {
-            j -= 1;
-        }
-
-        // Step 4: Swap that element with the pivot
-        self.swap(i-1, j);
-
-        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 {
-        let min = cmp::min(self.len(), src.len());
-        let dst = self.slice_to_mut(min);
-        let src = src.slice_to(min);
-        for i in range(0, min) {
-            dst[i].clone_from(&src[i]);
-        }
-        min
-    }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Common traits
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
index 46498610e56..a11a4408019 100644
--- a/src/libstd/c_str.rs
+++ b/src/libstd/c_str.rs
@@ -539,7 +539,7 @@ pub unsafe fn from_c_multistring<F>(buf: *const libc::c_char,
 #[cfg(test)]
 mod tests {
     use super::*;
-    use prelude::{spawn, Some, None, Option, FnOnce, ToString, CloneSliceExt};
+    use prelude::{spawn, Some, None, Option, FnOnce, ToString};
     use prelude::{Clone, PtrExt, Iterator, SliceExt, StrExt};
     use ptr;
     use thread::Thread;
diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs
index 077f75e2edd..dda37765b4a 100644
--- a/src/libstd/io/comm_adapters.rs
+++ b/src/libstd/io/comm_adapters.rs
@@ -14,7 +14,7 @@ use comm::{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 f8ea373f8f4..af5d1630ca6 100644
--- a/src/libstd/io/mem.rs
+++ b/src/libstd/io/mem.rs
@@ -401,7 +401,7 @@ mod test {
     extern crate "test" as test_crate;
     use super::*;
     use io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek};
-    use prelude::{Ok, Err, range,  Vec, Buffer,  AsSlice, SliceExt, IteratorExt, CloneSliceExt};
+    use prelude::{Ok, Err, range,  Vec, Buffer,  AsSlice, SliceExt, IteratorExt};
     use io;
     use self::test_crate::Bencher;
 
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index e8b852ee492..d01840b6da0 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -1919,7 +1919,7 @@ impl fmt::Show for FilePermission {
 mod tests {
     use self::BadReaderBehavior::*;
     use super::{IoResult, Reader, MemReader, NoProgress, InvalidInput, Writer};
-    use prelude::{Ok, Vec, Buffer, CloneSliceExt};
+    use prelude::{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 49ab9ddb924..78d8ac307c2 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/lib.rs b/src/libstd/lib.rs
index 74c387c5eea..654096ce49d 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -107,6 +107,7 @@
 #![feature(macro_rules, globs, linkage, thread_local, asm)]
 #![feature(default_type_params, phase, lang_items, unsafe_destructor)]
 #![feature(slicing_syntax, unboxed_closures)]
+#![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 ebb64bc2f2d..34693be39b3 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 df50b7f81af..7aea83a069a 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, INIT_ATOMIC_INT, SeqCst};
diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs
index 30f3f56bc1c..fae90e8d393 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 bd4031e6230..8718d509f00 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};
@@ -449,7 +448,7 @@ static dot_dot_static: &'static [u8] = b"..";
 mod tests {
     use super::*;
     use prelude::Option::{mod, Some, None};
-    use prelude::{Vec, Clone, AsSlice, SliceExt, CloneSliceExt, IteratorExt};
+    use prelude::{Vec, Clone, AsSlice, SliceExt, IteratorExt};
     use prelude::{DoubleEndedIteratorExt, Str, StrExt, ToString, GenericPath};
     use str;
 
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index 751ed4b70fb..10f4adbfe56 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -1121,7 +1121,7 @@ fn prefix_len(p: Option<PathPrefix>) -> uint {
 mod tests {
     use super::*;
     use prelude::Option::{mod, Some, None};
-    use prelude::{Vec, Clone, AsSlice, SliceExt, CloneSliceExt, IteratorExt};
+    use prelude::{Vec, Clone, AsSlice, SliceExt, IteratorExt};
     use prelude::{DoubleEndedIteratorExt, Str, ToString, GenericPath};
     use super::PathPrefix::*;
     use super::parse_prefix;
diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs
index f016683e3d0..95b82959562 100644
--- a/src/libstd/prelude.rs
+++ b/src/libstd/prelude.rs
@@ -82,9 +82,7 @@
 #[doc(no_inline)] pub use core::prelude::{Tuple9, Tuple10, Tuple11, Tuple12};
 #[doc(no_inline)] pub use str::{Str, StrExt};
 #[doc(no_inline)] pub use slice::AsSlice;
-#[doc(no_inline)] pub use slice::{SliceConcatExt, PartialEqSliceExt};
-#[doc(no_inline)] pub use slice::{CloneSliceExt, OrdSliceExt, SliceExt};
-#[doc(no_inline)] pub use slice::{BoxedSliceExt};
+#[doc(no_inline)] pub use slice::{SliceConcatExt, SliceExt};
 #[doc(no_inline)] pub use string::{IntoString, String, ToString};
 #[doc(no_inline)] pub use vec::Vec;
 

From d55577255434d1a9969b74cc4ac5dff4c04d6054 Mon Sep 17 00:00:00 2001
From: Corey Richardson <corey@octayn.net>
Date: Fri, 2 Jan 2015 08:26:55 -0500
Subject: [PATCH 3/9] rustdoc: fix rendering of associated types

---
 src/librustdoc/html/render.rs | 32 +++++++++++++++++++++-----------
 1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index f8a0b88b408..e95b8d3d8ab 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1811,6 +1811,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,
@@ -1827,17 +1839,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)
@@ -2122,6 +2123,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() {

From 64b7c22c46b204520a6fae1c5cd750a3d3c6a66a Mon Sep 17 00:00:00 2001
From: Jorge Aparicio <japaricious@gmail.com>
Date: Thu, 1 Jan 2015 14:53:20 -0500
Subject: [PATCH 4/9] core: use assoc types in `Deref[Mut]`

---
 src/liballoc/arc.rs                           |  4 +-
 src/liballoc/boxed.rs                         |  8 ++--
 src/liballoc/lib.rs                           |  1 +
 src/liballoc/rc.rs                            |  4 +-
 src/libcollections/btree/map.rs               |  6 ++-
 src/libcollections/btree/node.rs              | 48 ++++++++++++-------
 src/libcollections/string.rs                  |  8 +++-
 src/libcollections/vec.rs                     | 10 ++--
 src/libcore/array.rs                          |  4 +-
 src/libcore/borrow.rs                         |  4 +-
 src/libcore/cell.rs                           | 10 ++--
 src/libcore/iter.rs                           |  8 ++--
 src/libcore/nonzero.rs                        |  4 +-
 src/libcore/ops.rs                            | 32 +++++++++----
 src/libcore/option.rs                         |  2 +-
 src/librustc_resolve/build_reduced_graph.rs   |  6 ++-
 src/librustc_resolve/check_unused.rs          |  6 ++-
 src/librustc_resolve/lib.rs                   |  1 +
 src/librustc_resolve/record_exports.rs        |  6 ++-
 src/libstd/collections/hash/map.rs            |  2 +-
 src/libstd/collections/hash/table.rs          | 16 +++----
 src/libstd/io/stdio.rs                        |  6 ++-
 src/libstd/rt/exclusive.rs                    |  6 ++-
 src/libstd/sync/mutex.rs                      |  6 ++-
 src/libstd/sync/rwlock.rs                     | 10 ++--
 src/libsyntax/lib.rs                          |  1 +
 src/libsyntax/owned_slice.rs                  |  4 +-
 src/libsyntax/parse/token.rs                  |  4 +-
 src/libsyntax/ptr.rs                          |  4 +-
 src/libsyntax/util/interner.rs                |  4 +-
 src/test/auxiliary/overloaded_autoderef_xc.rs |  6 ++-
 ...rrowck-borrow-overloaded-auto-deref-mut.rs |  8 +++-
 .../borrowck-borrow-overloaded-auto-deref.rs  |  6 ++-
 .../borrowck-borrow-overloaded-deref-mut.rs   |  8 +++-
 .../borrowck-borrow-overloaded-deref.rs       |  6 ++-
 src/test/compile-fail/infinite-autoderef.rs   |  6 ++-
 src/test/compile-fail/issue-18566.rs          |  6 ++-
 src/test/run-pass/deref-mut-on-ref.rs         |  2 +-
 src/test/run-pass/deref-on-ref.rs             |  2 +-
 src/test/run-pass/dst-deref-mut.rs            |  8 +++-
 src/test/run-pass/dst-deref.rs                |  6 ++-
 src/test/run-pass/fixup-deref-mut.rs          |  8 +++-
 src/test/run-pass/issue-13264.rs              | 10 +++-
 src/test/run-pass/issue-16774.rs              |  8 ++--
 .../run-pass/overloaded-autoderef-count.rs    |  8 +++-
 .../run-pass/overloaded-autoderef-indexing.rs |  6 ++-
 .../run-pass/overloaded-autoderef-order.rs    | 10 +++-
 .../run-pass/overloaded-autoderef-vtable.rs   |  6 ++-
 src/test/run-pass/overloaded-deref-count.rs   |  8 +++-
 49 files changed, 256 insertions(+), 107 deletions(-)

diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index 820a3838978..d38b77eb6fd 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 74f0599e486..0d6ada4b229 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -153,11 +153,13 @@ impl fmt::Show for Box<Any+'static> {
     }
 }
 
-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 }
 }
 
@@ -210,7 +212,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 61b5d43d1cb..c4858aea022 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -65,6 +65,7 @@
 
 #![no_std]
 #![feature(lang_items, phase, unsafe_destructor, default_type_params)]
+#![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 87b40aa1cee..4b85d2da4ac 100644
--- a/src/libcollections/btree/map.rs
+++ b/src/libcollections/btree/map.rs
@@ -515,13 +515,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 3907f28092a..d1a2916a140 100644
--- a/src/libcollections/btree/node.rs
+++ b/src/libcollections/btree/node.rs
@@ -455,7 +455,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
@@ -511,7 +513,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*
@@ -588,7 +590,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`.
@@ -597,7 +599,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.
@@ -653,7 +657,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.
     //
@@ -667,7 +671,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> {
@@ -684,8 +688,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.
     ///
@@ -717,7 +722,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> {
@@ -800,7 +807,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.
@@ -862,7 +871,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.
     //
@@ -881,8 +890,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.
@@ -898,7 +908,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> {
@@ -918,7 +930,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)
@@ -929,7 +943,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/string.rs b/src/libcollections/string.rs
index b69db8b00b5..c52993ff353 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -935,7 +935,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[]) }
     }
@@ -947,7 +949,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 ce0519a2395..140c15b2f7f 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -1301,12 +1301,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() }
 }
 
@@ -1716,7 +1718,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 4b246860006..4939fc49958 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -422,7 +422,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
@@ -478,7 +480,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
@@ -486,7 +490,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 7c53503b1ce..64bbc248ee1 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -1174,7 +1174,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 }
     }
@@ -1185,7 +1185,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()
     }
@@ -1195,7 +1195,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()
@@ -1203,7 +1203,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 af07869e95f..17a3c93d980 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -827,11 +827,14 @@ pub struct RangeTo<Idx> {
 /// struct.
 ///
 /// ```
+/// #![feature(associated_types)]
 /// 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
 ///     }
@@ -843,16 +846,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 }
 }
 
@@ -865,17 +874,20 @@ impl<'a, Sized? T> Deref<T> for &'a mut T {
 /// struct.
 ///
 /// ```
+/// #![feature(associated_types)]
 /// 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
 ///     }
@@ -888,12 +900,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/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 7dbcc810b57..56459b72225 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -95,13 +95,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 78527315199..4395bb05040 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -33,13 +33,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 10756f21551..75731b5e7cd 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 9c2437c376d..9bfed1e8eb9 100644
--- a/src/librustc_resolve/record_exports.rs
+++ b/src/librustc_resolve/record_exports.rs
@@ -34,13 +34,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/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index f6063df5434..e61b9af5a12 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/stdio.rs b/src/libstd/io/stdio.rs
index b7d069eb19e..e58ff1c3ac4 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/rt/exclusive.rs b/src/libstd/rt/exclusive.rs
index 88bdb29caec..e44511169ab 100644
--- a/src/libstd/rt/exclusive.rs
+++ b/src/libstd/rt/exclusive.rs
@@ -74,10 +74,12 @@ impl<'a, T: Send> ExclusiveGuard<'a, T> {
     }
 }
 
-impl<'a, T: Send> Deref<T> for ExclusiveGuard<'a, T> {
+impl<'a, T: Send> Deref for ExclusiveGuard<'a, T> {
+    type Target = T;
+
     fn deref(&self) -> &T { &*self._data }
 }
-impl<'a, T: Send> DerefMut<T> for ExclusiveGuard<'a, T> {
+impl<'a, T: Send> DerefMut for ExclusiveGuard<'a, T> {
     fn deref_mut(&mut self) -> &mut T { &mut *self._data }
 }
 
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 52004bb4a8f..08980eb01c6 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -288,12 +288,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 7f3c77c97ad..7478e903355 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -326,13 +326,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 d5093c5055c..d86db4e177e 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -26,6 +26,7 @@
 #![feature(macro_rules, globs, default_type_params, phase, slicing_syntax)]
 #![feature(quote, unsafe_destructor)]
 #![feature(unboxed_closures)]
+#![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 3023c547fb0..8c00aaf9bee 100644
--- a/src/libsyntax/owned_slice.rs
+++ b/src/libsyntax/owned_slice.rs
@@ -54,7 +54,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 f22a4b5c6ed..61da1c25926 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -606,7 +606,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 1b3ebde2461..5d4f50f5fd2 100644
--- a/src/libsyntax/ptr.rs
+++ b/src/libsyntax/ptr.rs
@@ -75,7 +75,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 97eb4316583..5dde8db6155 100644
--- a/src/libsyntax/util/interner.rs
+++ b/src/libsyntax/util/interner.rs
@@ -124,7 +124,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/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/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 f64d8fee2d8..1ccd1753c76 100644
--- a/src/test/compile-fail/issue-18566.rs
+++ b/src/test/compile-fail/issue-18566.rs
@@ -8,8 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_types)]
+
 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/deref-mut-on-ref.rs b/src/test/run-pass/deref-mut-on-ref.rs
index dcf7c483b2c..03848b2d820 100644
--- a/src/test/run-pass/deref-mut-on-ref.rs
+++ b/src/test/run-pass/deref-mut-on-ref.rs
@@ -10,7 +10,7 @@
 
 // Test that `&mut T` implements `DerefMut<T>`
 
-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 27e7d8f3ba2..7ebf7a9cd30 100644
--- a/src/test/run-pass/deref-on-ref.rs
+++ b/src/test/run-pass/deref-on-ref.rs
@@ -10,7 +10,7 @@
 
 // Test that `&T` and `&mut T` implement `Deref<T>`
 
-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 c2707a1ae6e..72a07ca7d35 100644
--- a/src/test/run-pass/dst-deref-mut.rs
+++ b/src/test/run-pass/dst-deref-mut.rs
@@ -10,17 +10,21 @@
 
 // Test that a custom deref with a fat pointer return type does not ICE
 
+#![feature(associated_types)]
+
 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 43b7d116d30..8d32216697d 100644
--- a/src/test/run-pass/dst-deref.rs
+++ b/src/test/run-pass/dst-deref.rs
@@ -10,11 +10,15 @@
 
 // Test that a custom deref with a fat pointer return type does not ICE
 
+#![feature(associated_types)]
+
 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 d2812ce1d2c..9c2a8575bb9 100644
--- a/src/test/run-pass/fixup-deref-mut.rs
+++ b/src/test/run-pass/fixup-deref-mut.rs
@@ -8,18 +8,22 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_types)]
+
 // Generic unique/owned smaht pointer.
 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 06ab67f2f3e..aac33f3d8a6 100644
--- a/src/test/run-pass/issue-13264.rs
+++ b/src/test/run-pass/issue-13264.rs
@@ -8,11 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_types)]
+
 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
     }
@@ -23,7 +27,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 ebc879d82fb..1b5016d198d 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)]
 
 struct X(Box<int>);
 
@@ -23,14 +23,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 4cf5e074139..5b105646dac 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 5c4befcd0c8..7d550c925b7 100644
--- a/src/test/run-pass/overloaded-autoderef-indexing.rs
+++ b/src/test/run-pass/overloaded-autoderef-indexing.rs
@@ -8,11 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_types)]
+
 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 f0daf371ca7..5b45413e760 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;
 
 struct DerefWrapper<X, Y> {
@@ -23,7 +25,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
     }
@@ -46,7 +50,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

From cddb41dd1fd7ace99fbc653b8aca48a0feba9c48 Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Fri, 2 Jan 2015 04:20:34 -0500
Subject: [PATCH 5/9] Do not ICE when projecting out of a value with type
 `ty::ty_err`

---
 src/librustc/middle/traits/project.rs         | 45 +++++++++++++------
 src/librustc/middle/ty.rs                     |  2 +-
 ...ed-types-ICE-when-projecting-out-of-err.rs | 34 ++++++++++++++
 3 files changed, 66 insertions(+), 15 deletions(-)
 create mode 100644 src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs

diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs
index c84f31bf6c3..125f39b1a43 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,15 +390,18 @@ fn project_type<'cx,'tcx>(
 
     assemble_candidates_from_object_type(selcx,
                                          obligation,
+                                         &obligation_trait_ref,
                                          &mut candidates);
 
     if candidates.vec.is_empty() {
         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));
         }
@@ -421,17 +435,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>>)
 {
@@ -445,7 +462,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,
@@ -466,14 +483,14 @@ fn assemble_candidates_from_predicates<'cx,'tcx>(
 
 fn assemble_candidates_from_object_type<'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 infcx = selcx.infcx();
-    let trait_ref = infcx.resolve_type_vars_if_possible(&obligation.predicate.trait_ref);
     debug!("assemble_candidates_from_object_type(trait_ref={})",
-           trait_ref.repr(infcx.tcx));
-    let self_ty = trait_ref.self_ty();
+           obligation_trait_ref.repr(infcx.tcx));
+    let self_ty = obligation_trait_ref.self_ty();
     let data = match self_ty.sty {
         ty::ty_trait(ref data) => data,
         _ => { return; }
@@ -482,21 +499,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) => {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 7bc5d3d0708..399d537088c 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -7269,7 +7269,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/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
+}

From ea1ad792f9c182f18d865d5ff34a86a8ef0e4421 Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Fri, 2 Jan 2015 11:39:47 -0500
Subject: [PATCH 6/9] Evaluate projection predicates during trait selection.
 Fixes #20296.

---
 src/librustc/middle/traits/select.rs          | 46 +++++++++---
 .../associated-types-conditional-dispatch.rs  | 73 +++++++++++++++++++
 2 files changed, 107 insertions(+), 12 deletions(-)
 create mode 100644 src/test/run-pass/associated-types-conditional-dispatch.rs

diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index f9dced088f8..ef8fbdfaa6c 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -289,6 +289,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>)
@@ -320,9 +337,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) => {
+                let result = self.infcx.probe(|_| {
+                    let project_obligation = obligation.with(data.clone());
+                    project::poly_project_and_unify_type(self, &project_obligation)
+                });
+                match result {
+                    Ok(Some(subobligations)) => {
+                        self.evaluate_predicates_recursively(previous_stack, subobligations.iter())
+                    }
+                    Ok(None) => {
+                        EvaluatedToAmbig
+                    }
+                    Err(_) => {
+                        EvaluatedToErr(Unimplemented)
+                    }
+                }
             }
         }
     }
@@ -1026,15 +1056,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/test/run-pass/associated-types-conditional-dispatch.rs b/src/test/run-pass/associated-types-conditional-dispatch.rs
new file mode 100644
index 00000000000..4efd0ef348d
--- /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
+// `Output=[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 `Output=[A]`
+// constraint is considered.
+impl<'a, A, B, Lhs> MyEq<[B; 0]> for Lhs
+    where A: MyEq<B>, Lhs: Deref<Output=[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 Output = 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() {
+}

From 45468f37c85adb6e1339af33c2f18770b4ac9dac Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Fri, 2 Jan 2015 13:22:45 -0500
Subject: [PATCH 7/9] Temporarily do not evaluate subobligations.

---
 src/librustc/middle/traits/select.rs | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index ef8fbdfaa6c..5b5cb8ae13e 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -343,8 +343,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     project::poly_project_and_unify_type(self, &project_obligation)
                 });
                 match result {
-                    Ok(Some(subobligations)) => {
-                        self.evaluate_predicates_recursively(previous_stack, subobligations.iter())
+                    Ok(Some(_subobligations)) => {
+                        // TODO we should evaluate _subobligations, but doing so leads to an ICE
+                        // self.evaluate_predicates_recursively(previous_stack,
+                        //                                      subobligations.iter())
+                        EvaluatedToAmbig
                     }
                     Ok(None) => {
                         EvaluatedToAmbig

From fc7d8faba87716bbcaa43c3747fb8a98dc0c041a Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Fri, 2 Jan 2015 13:59:32 -0500
Subject: [PATCH 8/9] Handle recursive obligations without exiting the
 inference probe

Conflicts:
	src/librustc/middle/traits/select.rs
---
 src/librustc/middle/traits/select.rs | 29 +++++++++++++---------------
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index 5b5cb8ae13e..a7eb883f337 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -338,24 +338,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             ty::Predicate::Projection(ref data) => {
-                let result = self.infcx.probe(|_| {
+                self.infcx.probe(|_| {
                     let project_obligation = obligation.with(data.clone());
-                    project::poly_project_and_unify_type(self, &project_obligation)
-                });
-                match result {
-                    Ok(Some(_subobligations)) => {
-                        // TODO we should evaluate _subobligations, but doing so leads to an ICE
-                        // self.evaluate_predicates_recursively(previous_stack,
-                        //                                      subobligations.iter())
-                        EvaluatedToAmbig
+                    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)
+                        }
                     }
-                    Ok(None) => {
-                        EvaluatedToAmbig
-                    }
-                    Err(_) => {
-                        EvaluatedToErr(Unimplemented)
-                    }
-                }
+                })
             }
         }
     }

From 1abee08cbdbd62a83805aa5b5068df9e00471f06 Mon Sep 17 00:00:00 2001
From: Jorge Aparicio <japaricious@gmail.com>
Date: Fri, 2 Jan 2015 14:23:46 -0500
Subject: [PATCH 9/9] fix rpass test with s/Output/Target/g

---
 .../run-pass/associated-types-conditional-dispatch.rs     | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/test/run-pass/associated-types-conditional-dispatch.rs b/src/test/run-pass/associated-types-conditional-dispatch.rs
index 4efd0ef348d..3b53203d218 100644
--- a/src/test/run-pass/associated-types-conditional-dispatch.rs
+++ b/src/test/run-pass/associated-types-conditional-dispatch.rs
@@ -11,7 +11,7 @@
 // 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
-// `Output=[A]`, then the impl marked with `(*)` is seen to conflict
+// `Target=[A]`, then the impl marked with `(*)` is seen to conflict
 // with all the others.
 
 #![feature(associated_types, default_type_params)]
@@ -32,10 +32,10 @@ impl<A, B> MyEq<[B]> for [A]
     }
 }
 
-// (*) This impl conflicts with everything unless the `Output=[A]`
+// (*) 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<Output=[A]>
+    where A: MyEq<B>, Lhs: Deref<Target=[A]>
 {
     fn eq(&self, other: &[B; 0]) -> bool {
         MyEq::eq(&**self, other.as_slice())
@@ -57,7 +57,7 @@ impl<T> Helper<T> for Option<T> {
 }
 
 impl<T, H: Helper<T>> Deref for DerefWithHelper<H, T> {
-    type Output = T;
+    type Target = T;
 
     fn deref(&self) -> &T {
         self.helper.helper_borrow()