diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs
index b284d855c4515..6c597301ac204 100644
--- a/src/libcore/benches/iter.rs
+++ b/src/libcore/benches/iter.rs
@@ -281,3 +281,32 @@ bench_sums! {
     bench_take_while_chain_ref_sum,
     (0i64..1000000).chain(1000000..).take_while(|&x| x < 1111111)
 }
+
+// Checks whether Skip<Zip<A,B>> is as fast as Zip<Skip<A>, Skip<B>>, from
+// https://users.rust-lang.org/t/performance-difference-between-iterator-zip-and-skip-order/15743
+#[bench]
+fn bench_zip_then_skip(b: &mut Bencher) {
+    let v: Vec<_> = (0..100_000).collect();
+    let t: Vec<_> = (0..100_000).collect();
+
+    b.iter(|| {
+        let s = v.iter().zip(t.iter()).skip(10000)
+            .take_while(|t| *t.0 < 10100)
+            .map(|(a, b)| *a + *b)
+            .sum::<u64>();
+        assert_eq!(s, 2009900);
+    });
+}
+#[bench]
+fn bench_skip_then_zip(b: &mut Bencher) {
+    let v: Vec<_> = (0..100_000).collect();
+    let t: Vec<_> = (0..100_000).collect();
+
+    b.iter(|| {
+        let s = v.iter().skip(10000).zip(t.iter().skip(10000))
+            .take_while(|t| *t.0 < 10100)
+            .map(|(a, b)| *a + *b)
+            .sum::<u64>();
+        assert_eq!(s, 2009900);
+    });
+}
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index e6759d1bad940..b98470449827e 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -343,7 +343,7 @@ impl Ordering {
 /// v.sort_by_key(|&num| (num > 3, Reverse(num)));
 /// assert_eq!(v, vec![3, 2, 1, 6, 5, 4]);
 /// ```
-#[derive(PartialEq, Eq, Debug, Copy, Clone)]
+#[derive(PartialEq, Eq, Debug, Copy, Clone, Default, Hash)]
 #[stable(feature = "reverse_cmp_key", since = "1.19.0")]
 pub struct Reverse<T>(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T);
 
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index 623cad754dd72..257d7d6caaaf8 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -1045,6 +1045,11 @@ impl<A, B> Iterator for Zip<A, B> where A: Iterator, B: Iterator
     fn size_hint(&self) -> (usize, Option<usize>) {
         ZipImpl::size_hint(self)
     }
+
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<Self::Item> {
+        ZipImpl::nth(self, n)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1065,6 +1070,14 @@ trait ZipImpl<A, B> {
     fn new(a: A, b: B) -> Self;
     fn next(&mut self) -> Option<Self::Item>;
     fn size_hint(&self) -> (usize, Option<usize>);
+    fn nth(&mut self, n: usize) -> Option<Self::Item>;
+    fn super_nth(&mut self, mut n: usize) -> Option<Self::Item> {
+        while let Some(x) = self.next() {
+            if n == 0 { return Some(x) }
+            n -= 1;
+        }
+        None
+    }
     fn next_back(&mut self) -> Option<Self::Item>
         where A: DoubleEndedIterator + ExactSizeIterator,
               B: DoubleEndedIterator + ExactSizeIterator;
@@ -1094,6 +1107,11 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
         })
     }
 
+    #[inline]
+    default fn nth(&mut self, n: usize) -> Option<Self::Item> {
+        self.super_nth(n)
+    }
+
     #[inline]
     default fn next_back(&mut self) -> Option<(A::Item, B::Item)>
         where A: DoubleEndedIterator + ExactSizeIterator,
@@ -1174,6 +1192,24 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
         (len, Some(len))
     }
 
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<Self::Item> {
+        let delta = cmp::min(n, self.len - self.index);
+        let end = self.index + delta;
+        while self.index < end {
+            let i = self.index;
+            self.index += 1;
+            if A::may_have_side_effect() {
+                unsafe { self.a.get_unchecked(i); }
+            }
+            if B::may_have_side_effect() {
+                unsafe { self.b.get_unchecked(i); }
+            }
+        }
+
+        self.super_nth(n - delta)
+    }
+
     #[inline]
     fn next_back(&mut self) -> Option<(A::Item, B::Item)>
         where A: DoubleEndedIterator + ExactSizeIterator,
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index b266771b818e5..6270e5892b3a0 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -740,8 +740,6 @@ impl<T: ?Sized> *const T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let s: &str = "123";
     /// let ptr: *const u8 = s.as_ptr();
     ///
@@ -750,7 +748,7 @@ impl<T: ?Sized> *const T {
     ///     println!("{}", *ptr.add(2) as char);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn add(self, count: usize) -> Self
         where T: Sized,
@@ -799,8 +797,6 @@ impl<T: ?Sized> *const T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let s: &str = "123";
     ///
     /// unsafe {
@@ -809,7 +805,7 @@ impl<T: ?Sized> *const T {
     ///     println!("{}", *end.sub(2) as char);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn sub(self, count: usize) -> Self
         where T: Sized,
@@ -836,8 +832,6 @@ impl<T: ?Sized> *const T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// // Iterate using a raw pointer in increments of two elements
     /// let data = [1u8, 2, 3, 4, 5];
     /// let mut ptr: *const u8 = data.as_ptr();
@@ -852,7 +846,7 @@ impl<T: ?Sized> *const T {
     ///     ptr = ptr.wrapping_add(step);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub fn wrapping_add(self, count: usize) -> Self
         where T: Sized,
@@ -879,8 +873,6 @@ impl<T: ?Sized> *const T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// // Iterate using a raw pointer in increments of two elements (backwards)
     /// let data = [1u8, 2, 3, 4, 5];
     /// let mut ptr: *const u8 = data.as_ptr();
@@ -895,7 +887,7 @@ impl<T: ?Sized> *const T {
     ///     ptr = ptr.wrapping_sub(step);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub fn wrapping_sub(self, count: usize) -> Self
         where T: Sized,
@@ -922,8 +914,6 @@ impl<T: ?Sized> *const T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let x = 12;
     /// let y = &x as *const i32;
     ///
@@ -931,7 +921,7 @@ impl<T: ?Sized> *const T {
     ///     assert_eq!(y.read(), 12);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read(self) -> T
         where T: Sized,
@@ -974,8 +964,6 @@ impl<T: ?Sized> *const T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let x = 12;
     /// let y = &x as *const i32;
     ///
@@ -983,7 +971,7 @@ impl<T: ?Sized> *const T {
     ///     assert_eq!(y.read_volatile(), 12);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read_volatile(self) -> T
         where T: Sized,
@@ -1010,8 +998,6 @@ impl<T: ?Sized> *const T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let x = 12;
     /// let y = &x as *const i32;
     ///
@@ -1019,7 +1005,7 @@ impl<T: ?Sized> *const T {
     ///     assert_eq!(y.read_unaligned(), 12);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read_unaligned(self) -> T
         where T: Sized,
@@ -1046,8 +1032,6 @@ impl<T: ?Sized> *const T {
     /// Efficiently create a Rust vector from an unsafe buffer:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// # #[allow(dead_code)]
     /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
     ///     let mut dst = Vec::with_capacity(elts);
@@ -1056,7 +1040,7 @@ impl<T: ?Sized> *const T {
     ///     dst
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_to(self, dest: *mut T, count: usize)
         where T: Sized,
@@ -1085,8 +1069,6 @@ impl<T: ?Sized> *const T {
     /// Efficiently create a Rust vector from an unsafe buffer:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// # #[allow(dead_code)]
     /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
     ///     let mut dst = Vec::with_capacity(elts);
@@ -1095,7 +1077,7 @@ impl<T: ?Sized> *const T {
     ///     dst
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
         where T: Sized,
@@ -1443,8 +1425,6 @@ impl<T: ?Sized> *mut T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let s: &str = "123";
     /// let ptr: *const u8 = s.as_ptr();
     ///
@@ -1453,7 +1433,7 @@ impl<T: ?Sized> *mut T {
     ///     println!("{}", *ptr.add(2) as char);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn add(self, count: usize) -> Self
         where T: Sized,
@@ -1502,8 +1482,6 @@ impl<T: ?Sized> *mut T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let s: &str = "123";
     ///
     /// unsafe {
@@ -1512,7 +1490,7 @@ impl<T: ?Sized> *mut T {
     ///     println!("{}", *end.sub(2) as char);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn sub(self, count: usize) -> Self
         where T: Sized,
@@ -1539,8 +1517,6 @@ impl<T: ?Sized> *mut T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// // Iterate using a raw pointer in increments of two elements
     /// let data = [1u8, 2, 3, 4, 5];
     /// let mut ptr: *const u8 = data.as_ptr();
@@ -1555,7 +1531,7 @@ impl<T: ?Sized> *mut T {
     ///     ptr = ptr.wrapping_add(step);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub fn wrapping_add(self, count: usize) -> Self
         where T: Sized,
@@ -1582,8 +1558,6 @@ impl<T: ?Sized> *mut T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// // Iterate using a raw pointer in increments of two elements (backwards)
     /// let data = [1u8, 2, 3, 4, 5];
     /// let mut ptr: *const u8 = data.as_ptr();
@@ -1598,7 +1572,7 @@ impl<T: ?Sized> *mut T {
     ///     ptr = ptr.wrapping_sub(step);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub fn wrapping_sub(self, count: usize) -> Self
         where T: Sized,
@@ -1625,8 +1599,6 @@ impl<T: ?Sized> *mut T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let x = 12;
     /// let y = &x as *const i32;
     ///
@@ -1634,7 +1606,7 @@ impl<T: ?Sized> *mut T {
     ///     assert_eq!(y.read(), 12);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read(self) -> T
         where T: Sized,
@@ -1668,7 +1640,7 @@ impl<T: ?Sized> *mut T {
     /// Beyond accepting a raw pointer, this is unsafe because it semantically
     /// moves the value out of `self` without preventing further usage of `self`.
     /// If `T` is not `Copy`, then care must be taken to ensure that the value at
-    /// `src` is not used before the data is overwritten again (e.g. with `write`,
+    /// `self` is not used before the data is overwritten again (e.g. with `write`,
     /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use
     /// because it will attempt to drop the value previously at `*self`.
     ///
@@ -1677,8 +1649,6 @@ impl<T: ?Sized> *mut T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let x = 12;
     /// let y = &x as *const i32;
     ///
@@ -1686,7 +1656,7 @@ impl<T: ?Sized> *mut T {
     ///     assert_eq!(y.read_volatile(), 12);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read_volatile(self) -> T
         where T: Sized,
@@ -1713,8 +1683,6 @@ impl<T: ?Sized> *mut T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let x = 12;
     /// let y = &x as *const i32;
     ///
@@ -1722,7 +1690,7 @@ impl<T: ?Sized> *mut T {
     ///     assert_eq!(y.read_unaligned(), 12);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn read_unaligned(self) -> T
         where T: Sized,
@@ -1749,8 +1717,6 @@ impl<T: ?Sized> *mut T {
     /// Efficiently create a Rust vector from an unsafe buffer:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// # #[allow(dead_code)]
     /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
     ///     let mut dst = Vec::with_capacity(elts);
@@ -1759,7 +1725,7 @@ impl<T: ?Sized> *mut T {
     ///     dst
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_to(self, dest: *mut T, count: usize)
         where T: Sized,
@@ -1788,8 +1754,6 @@ impl<T: ?Sized> *mut T {
     /// Efficiently create a Rust vector from an unsafe buffer:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// # #[allow(dead_code)]
     /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
     ///     let mut dst = Vec::with_capacity(elts);
@@ -1798,7 +1762,7 @@ impl<T: ?Sized> *mut T {
     ///     dst
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
         where T: Sized,
@@ -1825,8 +1789,6 @@ impl<T: ?Sized> *mut T {
     /// Efficiently create a Rust vector from an unsafe buffer:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// # #[allow(dead_code)]
     /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
     ///     let mut dst: Vec<T> = Vec::with_capacity(elts);
@@ -1835,7 +1797,7 @@ impl<T: ?Sized> *mut T {
     ///     dst
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_from(self, src: *const T, count: usize)
         where T: Sized,
@@ -1864,8 +1826,6 @@ impl<T: ?Sized> *mut T {
     /// Efficiently create a Rust vector from an unsafe buffer:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// # #[allow(dead_code)]
     /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
     ///     let mut dst: Vec<T> = Vec::with_capacity(elts);
@@ -1874,7 +1834,7 @@ impl<T: ?Sized> *mut T {
     ///     dst
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
         where T: Sized,
@@ -1899,7 +1859,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// This has all the same safety problems as `ptr::read` with respect to
     /// invalid pointers, types, and double drops.
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn drop_in_place(self) {
         drop_in_place(self)
@@ -1929,8 +1889,6 @@ impl<T: ?Sized> *mut T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let mut x = 0;
     /// let y = &mut x as *mut i32;
     /// let z = 12;
@@ -1940,7 +1898,7 @@ impl<T: ?Sized> *mut T {
     ///     assert_eq!(y.read(), 12);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn write(self, val: T)
         where T: Sized,
@@ -1954,8 +1912,6 @@ impl<T: ?Sized> *mut T {
     /// # Examples
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let mut vec = vec![0; 4];
     /// unsafe {
     ///     let vec_ptr = vec.as_mut_ptr();
@@ -1963,7 +1919,7 @@ impl<T: ?Sized> *mut T {
     /// }
     /// assert_eq!(vec, [b'a', b'a', 0, 0]);
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn write_bytes(self, val: u8, count: usize)
         where T: Sized,
@@ -2008,8 +1964,6 @@ impl<T: ?Sized> *mut T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let mut x = 0;
     /// let y = &mut x as *mut i32;
     /// let z = 12;
@@ -2019,7 +1973,7 @@ impl<T: ?Sized> *mut T {
     ///     assert_eq!(y.read_volatile(), 12);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn write_volatile(self, val: T)
         where T: Sized,
@@ -2040,8 +1994,8 @@ impl<T: ?Sized> *mut T {
     /// allocations or resources, so care must be taken not to overwrite an object
     /// that should be dropped.
     ///
-    /// Additionally, it does not drop `src`. Semantically, `src` is moved into the
-    /// location pointed to by `dst`.
+    /// Additionally, it does not drop `self`. Semantically, `self` is moved into the
+    /// location pointed to by `val`.
     ///
     /// This is appropriate for initializing uninitialized memory, or overwriting
     /// memory that has previously been `read` from.
@@ -2051,8 +2005,6 @@ impl<T: ?Sized> *mut T {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(pointer_methods)]
-    ///
     /// let mut x = 0;
     /// let y = &mut x as *mut i32;
     /// let z = 12;
@@ -2062,7 +2014,7 @@ impl<T: ?Sized> *mut T {
     ///     assert_eq!(y.read_unaligned(), 12);
     /// }
     /// ```
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn write_unaligned(self, val: T)
         where T: Sized,
@@ -2077,7 +2029,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// This is only unsafe because it accepts a raw pointer.
     /// Otherwise, this operation is identical to `mem::replace`.
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn replace(self, src: T) -> T
         where T: Sized,
@@ -2095,7 +2047,7 @@ impl<T: ?Sized> *mut T {
     /// as arguments.
     ///
     /// Ensure that these pointers are valid before calling `swap`.
-    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[inline]
     pub unsafe fn swap(self, with: *mut T)
         where T: Sized,
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index edd75f7795ed7..a962efadd64e9 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -144,6 +144,43 @@ fn test_iterator_chain_find() {
     assert_eq!(iter.next(), None);
 }
 
+#[test]
+fn test_zip_nth() {
+    let xs = [0, 1, 2, 4, 5];
+    let ys = [10, 11, 12];
+
+    let mut it = xs.iter().zip(&ys);
+    assert_eq!(it.nth(0), Some((&0, &10)));
+    assert_eq!(it.nth(1), Some((&2, &12)));
+    assert_eq!(it.nth(0), None);
+
+    let mut it = xs.iter().zip(&ys);
+    assert_eq!(it.nth(3), None);
+
+    let mut it = ys.iter().zip(&xs);
+    assert_eq!(it.nth(3), None);
+}
+
+#[test]
+fn test_zip_nth_side_effects() {
+    let mut a = Vec::new();
+    let mut b = Vec::new();
+    let value = [1, 2, 3, 4, 5, 6].iter().cloned()
+        .map(|n| {
+            a.push(n);
+            n * 10
+        })
+        .zip([2, 3, 4, 5, 6, 7, 8].iter().cloned().map(|n| {
+            b.push(n * 100);
+            n * 1000
+        }))
+        .skip(1)
+        .nth(3);
+    assert_eq!(value, Some((50, 6000)));
+    assert_eq!(a, vec![1, 2, 3, 4, 5]);
+    assert_eq!(b, vec![200, 300, 400, 500, 600]);
+}
+
 #[test]
 fn test_iterator_step_by() {
     // Identity
diff --git a/src/librustc/dep_graph/debug.rs b/src/librustc/dep_graph/debug.rs
index e22552008d5a8..e56333aba9be5 100644
--- a/src/librustc/dep_graph/debug.rs
+++ b/src/librustc/dep_graph/debug.rs
@@ -54,7 +54,7 @@ pub struct EdgeFilter {
 }
 
 impl EdgeFilter {
-    pub fn new(test: &str) -> Result<EdgeFilter, Box<Error>> {
+    pub fn new(test: &str) -> Result<EdgeFilter, Box<dyn Error>> {
         let parts: Vec<_> = test.split("->").collect();
         if parts.len() != 2 {
             Err(format!("expected a filter like `a&b -> c&d`, not `{}`", test).into())
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index a41ac5bceed27..fa745bf165577 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -80,13 +80,13 @@ pub struct LoweringContext<'a> {
     // Use to assign ids to hir nodes that do not directly correspond to an ast node
     sess: &'a Session,
 
-    cstore: &'a CrateStore,
+    cstore: &'a dyn CrateStore,
 
     // As we walk the AST we must keep track of the current 'parent' def id (in
     // the form of a DefIndex) so that if we create a new node which introduces
     // a definition, then we can properly create the def id.
     parent_def: Option<DefIndex>,
-    resolver: &'a mut Resolver,
+    resolver: &'a mut dyn Resolver,
     name_map: FxHashMap<Ident, Name>,
 
     /// The items being lowered are collected here.
@@ -177,10 +177,10 @@ enum ImplTraitContext {
 }
 
 pub fn lower_crate(sess: &Session,
-                   cstore: &CrateStore,
+                   cstore: &dyn CrateStore,
                    dep_graph: &DepGraph,
                    krate: &Crate,
-                   resolver: &mut Resolver)
+                   resolver: &mut dyn Resolver)
                    -> hir::Crate {
     // We're constructing the HIR here; we don't care what we will
     // read, since we haven't even constructed the *input* to
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 99b1e5783e01e..9bbda9d74479b 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -123,7 +123,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
 
     pub(super) fn finalize_and_compute_crate_hash(self,
                                                   crate_disambiguator: CrateDisambiguator,
-                                                  cstore: &CrateStore,
+                                                  cstore: &dyn CrateStore,
                                                   codemap: &CodeMap,
                                                   commandline_args_hash: u64)
                                                   -> (Vec<MapEntry<'hir>>, Svh) {
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index d68b18dd2f17d..cdd6395747865 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -26,7 +26,7 @@ pub struct DefCollector<'a> {
     definitions: &'a mut Definitions,
     parent_def: Option<DefIndex>,
     expansion: Mark,
-    pub visit_macro_invoc: Option<&'a mut FnMut(MacroInvocationData)>,
+    pub visit_macro_invoc: Option<&'a mut dyn FnMut(MacroInvocationData)>,
 }
 
 pub struct MacroInvocationData {
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 3799bdada888e..61fae4609d54f 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -19,6 +19,8 @@ use dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex};
 
 use hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId, DefIndexAddressSpace};
 
+use middle::cstore::CrateStore;
+
 use syntax::abi::Abi;
 use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID};
 use syntax::codemap::Spanned;
@@ -1136,8 +1138,9 @@ impl Named for StructField { fn name(&self) -> Name { self.name } }
 impl Named for TraitItem { fn name(&self) -> Name { self.name } }
 impl Named for ImplItem { fn name(&self) -> Name { self.name } }
 
+
 pub fn map_crate<'hir>(sess: &::session::Session,
-                       cstore: &::middle::cstore::CrateStore,
+                       cstore: &dyn CrateStore,
                        forest: &'hir mut Forest,
                        definitions: &'hir Definitions)
                        -> Map<'hir> {
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 30c1ad01d1401..ed8cea3eb6563 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -62,7 +62,7 @@ pub trait PpAnn {
 
 pub struct NoAnn;
 impl PpAnn for NoAnn {}
-pub const NO_ANN: &'static PpAnn = &NoAnn;
+pub const NO_ANN: &'static dyn PpAnn = &NoAnn;
 
 impl PpAnn for hir::Crate {
     fn nested(&self, state: &mut State, nested: Nested) -> io::Result<()> {
@@ -83,7 +83,7 @@ pub struct State<'a> {
     literals: Peekable<vec::IntoIter<comments::Literal>>,
     cur_cmnt: usize,
     boxes: Vec<pp::Breaks>,
-    ann: &'a (PpAnn + 'a),
+    ann: &'a (dyn PpAnn + 'a),
 }
 
 impl<'a> PrintState<'a> for State<'a> {
@@ -126,9 +126,9 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
                        sess: &ParseSess,
                        krate: &hir::Crate,
                        filename: FileName,
-                       input: &mut Read,
-                       out: Box<Write + 'a>,
-                       ann: &'a PpAnn,
+                       input: &mut dyn Read,
+                       out: Box<dyn Write + 'a>,
+                       ann: &'a dyn PpAnn,
                        is_expanded: bool)
                        -> io::Result<()> {
     let mut s = State::new_from_input(cm, sess, filename, input, out, ann, is_expanded);
@@ -145,9 +145,9 @@ impl<'a> State<'a> {
     pub fn new_from_input(cm: &'a CodeMap,
                           sess: &ParseSess,
                           filename: FileName,
-                          input: &mut Read,
-                          out: Box<Write + 'a>,
-                          ann: &'a PpAnn,
+                          input: &mut dyn Read,
+                          out: Box<dyn Write + 'a>,
+                          ann: &'a dyn PpAnn,
                           is_expanded: bool)
                           -> State<'a> {
         let (cmnts, lits) = comments::gather_comments_and_literals(sess, filename, input);
@@ -167,8 +167,8 @@ impl<'a> State<'a> {
     }
 
     pub fn new(cm: &'a CodeMap,
-               out: Box<Write + 'a>,
-               ann: &'a PpAnn,
+               out: Box<dyn Write + 'a>,
+               ann: &'a dyn PpAnn,
                comments: Option<Vec<comments::Comment>>,
                literals: Option<Vec<comments::Literal>>)
                -> State<'a> {
@@ -184,7 +184,7 @@ impl<'a> State<'a> {
     }
 }
 
-pub fn to_string<F>(ann: &PpAnn, f: F) -> String
+pub fn to_string<F>(ann: &dyn PpAnn, f: F) -> String
     where F: FnOnce(&mut State) -> io::Result<()>
 {
     let mut wr = Vec::new();
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 67f6c0c2e49e8..4dcab6a04ee20 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -49,7 +49,7 @@ pub fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
 pub struct StableHashingContext<'gcx> {
     sess: &'gcx Session,
     definitions: &'gcx Definitions,
-    cstore: &'gcx CrateStore,
+    cstore: &'gcx dyn CrateStore,
     body_resolver: BodyResolver<'gcx>,
     hash_spans: bool,
     hash_bodies: bool,
@@ -88,7 +88,7 @@ impl<'gcx> StableHashingContext<'gcx> {
     pub fn new(sess: &'gcx Session,
                krate: &'gcx hir::Crate,
                definitions: &'gcx Definitions,
-               cstore: &'gcx CrateStore)
+               cstore: &'gcx dyn CrateStore)
                -> Self {
         let hash_spans_initial = !sess.opts.debugging_opts.incremental_ignore_spans;
 
diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs
index 4a75037aa5035..ed89d1d2f57a5 100644
--- a/src/librustc/infer/region_constraints/mod.rs
+++ b/src/librustc/infer/region_constraints/mod.rs
@@ -896,7 +896,7 @@ impl<'a, 'gcx, 'tcx> GenericKind<'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> VerifyBound<'tcx> {
-    fn for_each_region(&self, f: &mut FnMut(ty::Region<'tcx>)) {
+    fn for_each_region(&self, f: &mut dyn FnMut(ty::Region<'tcx>)) {
         match self {
             &VerifyBound::AnyRegion(ref rs) | &VerifyBound::AllRegions(ref rs) => for &r in rs {
                 f(r);
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index f05ed0a460d87..d08a41010ab16 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -41,8 +41,6 @@
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
-#![cfg_attr(not(stage0), allow(bare_trait_object))]
-
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(conservative_impl_trait)]
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index edea87c888c91..affd02aa51868 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -280,8 +280,8 @@ pub trait EarlyLintPass: LintPass {
 }
 
 /// A lint pass boxed up as a trait object.
-pub type EarlyLintPassObject = Box<EarlyLintPass + 'static>;
-pub type LateLintPassObject = Box<for<'a, 'tcx> LateLintPass<'a, 'tcx> + 'static>;
+pub type EarlyLintPassObject = Box<dyn EarlyLintPass + 'static>;
+pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + 'static>;
 
 /// Identifies a lint known to the compiler.
 #[derive(Clone, Copy, Debug)]
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 7f068e8f71b4b..bdb5ad525a75c 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -225,10 +225,10 @@ pub struct ExternBodyNestedBodies {
 /// (it'd break incremental compilation) and should only be called pre-HIR (e.g.
 /// during resolve)
 pub trait CrateStore {
-    fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<Any>;
+    fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<dyn Any>;
 
     // access to the metadata loader
-    fn metadata_loader(&self) -> &MetadataLoader;
+    fn metadata_loader(&self) -> &dyn MetadataLoader;
 
     // resolve
     fn def_key(&self, def: DefId) -> DefKey;
@@ -297,7 +297,7 @@ pub struct DummyCrateStore;
 
 #[allow(unused_variables)]
 impl CrateStore for DummyCrateStore {
-    fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<Any>
+    fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc<dyn Any>
         { bug!("crate_data_as_rc_any") }
     // item info
     fn visibility_untracked(&self, def: DefId) -> ty::Visibility { bug!("visibility") }
@@ -351,7 +351,7 @@ impl CrateStore for DummyCrateStore {
     fn postorder_cnums_untracked(&self) -> Vec<CrateNum> { bug!("postorder_cnums_untracked") }
 
     // access to the metadata loader
-    fn metadata_loader(&self) -> &MetadataLoader { bug!("metadata_loader") }
+    fn metadata_loader(&self) -> &dyn MetadataLoader { bug!("metadata_loader") }
 }
 
 pub trait CrateLoader {
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index db0ecb6aa5eb1..e7055827c491f 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -319,7 +319,7 @@ fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<DependencyLis
 // also skip this step entirely.
 fn activate_injected_dep(injected: Option<CrateNum>,
                          list: &mut DependencyList,
-                         replaces_injected: &Fn(CrateNum) -> bool) {
+                         replaces_injected: &dyn Fn(CrateNum) -> bool) {
     for (i, slot) in list.iter().enumerate() {
         let cnum = CrateNum::new(i + 1);
         if !replaces_injected(cnum) {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index b65046022b7f4..28524678e9916 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -239,7 +239,7 @@ impl OverloadedCallType {
 // This is the code that actually walks the tree.
 pub struct ExprUseVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     mc: mc::MemCategorizationContext<'a, 'gcx, 'tcx>,
-    delegate: &'a mut Delegate<'tcx>,
+    delegate: &'a mut dyn Delegate<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
 }
 
@@ -274,7 +274,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
     ///   `None` means that rvalues will be given more conservative lifetimes.
     ///
     /// See also `with_infer`, which is used *during* typeck.
-    pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
+    pub fn new(delegate: &'a mut (dyn Delegate<'tcx>+'a),
                tcx: TyCtxt<'a, 'tcx, 'tcx>,
                param_env: ty::ParamEnv<'tcx>,
                region_scope_tree: &'a region::ScopeTree,
@@ -294,7 +294,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
-    pub fn with_infer(delegate: &'a mut (Delegate<'tcx>+'a),
+    pub fn with_infer(delegate: &'a mut (dyn Delegate<'tcx>+'a),
                       infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
                       param_env: ty::ParamEnv<'tcx>,
                       region_scope_tree: &'a region::ScopeTree,
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 10497c95e27d0..d13b16dce8986 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -673,7 +673,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     }
 
     fn write_vars<F>(&self,
-                     wr: &mut Write,
+                     wr: &mut dyn Write,
                      ln: LiveNode,
                      mut test: F)
                      -> io::Result<()> where
@@ -694,7 +694,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn ln_str(&self, ln: LiveNode) -> String {
         let mut wr = Vec::new();
         {
-            let wr = &mut wr as &mut Write;
+            let wr = &mut wr as &mut dyn Write;
             write!(wr, "[ln({:?}) of kind {:?} reads", ln.get(), self.ir.lnk(ln));
             self.write_vars(wr, ln, |idx| self.users[idx].reader);
             write!(wr, "  writes");
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 9ebfe25c107a9..f9ea544156ce3 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -35,7 +35,7 @@ impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> {
 pub enum EvalErrorKind<'tcx> {
     /// This variant is used by machines to signal their own errors that do not
     /// match an existing variant
-    MachineError(Box<Error>),
+    MachineError(Box<dyn Error>),
     FunctionPointerTyMismatch(FnSig<'tcx>, FnSig<'tcx>),
     NoMirFor(String),
     UnterminatedCString(MemoryPointer),
@@ -248,7 +248,7 @@ impl<'tcx> Error for EvalError<'tcx> {
         }
     }
 
-    fn cause(&self) -> Option<&Error> {
+    fn cause(&self) -> Option<&dyn Error> {
         use self::EvalErrorKind::*;
         match self.kind {
             MachineError(ref inner) => Some(&**inner),
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index b69f5d6c8bdd7..157614f847a12 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -341,7 +341,7 @@ macro_rules! hash_option {
     ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [UNTRACKED]) => ({});
     ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => ({
         if $sub_hashes.insert(stringify!($opt_name),
-                              $opt_expr as &dep_tracking::DepTrackingHash).is_some() {
+                              $opt_expr as &dyn dep_tracking::DepTrackingHash).is_some() {
             bug!("Duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name))
         }
     });
@@ -420,10 +420,7 @@ top_level_options!(
         lint_cap: Option<lint::Level> [TRACKED],
         describe_lints: bool [UNTRACKED],
         output_types: OutputTypes [TRACKED],
-        // FIXME(mw): We track this for now but it actually doesn't make too
-        //            much sense: The search path can stay the same while the
-        //            things discovered there might have changed on disk.
-        search_paths: SearchPaths [TRACKED],
+        search_paths: SearchPaths [UNTRACKED],
         libs: Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> [TRACKED],
         maybe_sysroot: Option<PathBuf> [TRACKED],
 
@@ -442,10 +439,7 @@ top_level_options!(
         // version of `debugging_opts.borrowck`, which is just a plain string.
         borrowck_mode: BorrowckMode [UNTRACKED],
         cg: CodegenOptions [TRACKED],
-        // FIXME(mw): We track this for now but it actually doesn't make too
-        //            much sense: The value of this option can stay the same
-        //            while the files they refer to might have changed on disk.
-        externs: Externs [TRACKED],
+        externs: Externs [UNTRACKED],
         crate_name: Option<String> [TRACKED],
         // An optional name to use as the crate for std during std injection,
         // written `extern crate std = "name"`. Default to "std". Used by
@@ -1456,7 +1450,7 @@ pub enum OptionStability {
 }
 
 pub struct RustcOptGroup {
-    pub apply: Box<Fn(&mut getopts::Options) -> &mut getopts::Options>,
+    pub apply: Box<dyn Fn(&mut getopts::Options) -> &mut getopts::Options>,
     pub name: &'static str,
     pub stability: OptionStability,
 }
@@ -2141,13 +2135,12 @@ impl fmt::Display for CrateType {
 mod dep_tracking {
     use lint;
     use middle::cstore;
-    use session::search_paths::{PathKind, SearchPaths};
     use std::collections::BTreeMap;
     use std::hash::Hash;
     use std::path::PathBuf;
     use std::collections::hash_map::DefaultHasher;
     use super::{Passes, CrateType, OptLevel, DebugInfoLevel, Lto,
-                OutputTypes, Externs, ErrorOutputType, Sanitizer, Epoch};
+                OutputTypes, ErrorOutputType, Sanitizer, Epoch};
     use syntax::feature_gate::UnstableFeatures;
     use rustc_back::{PanicStrategy, RelroLevel};
 
@@ -2204,7 +2197,6 @@ mod dep_tracking {
     impl_dep_tracking_hash_via_hash!(Lto);
     impl_dep_tracking_hash_via_hash!(DebugInfoLevel);
     impl_dep_tracking_hash_via_hash!(UnstableFeatures);
-    impl_dep_tracking_hash_via_hash!(Externs);
     impl_dep_tracking_hash_via_hash!(OutputTypes);
     impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
     impl_dep_tracking_hash_via_hash!(Sanitizer);
@@ -2218,15 +2210,6 @@ mod dep_tracking {
     impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>,
                                                  Option<cstore::NativeLibraryKind>));
     impl_dep_tracking_hash_for_sortable_vec_of!((String, u64));
-    impl DepTrackingHash for SearchPaths {
-        fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
-            let mut elems: Vec<_> = self
-                .iter(PathKind::All)
-                .collect();
-            elems.sort();
-            Hash::hash(&elems, hasher);
-        }
-    }
 
     impl<T1, T2> DepTrackingHash for (T1, T2)
         where T1: DepTrackingHash,
@@ -2256,7 +2239,7 @@ mod dep_tracking {
     }
 
     // This is a stable hash because BTreeMap is a sorted container
-    pub fn stable_hash(sub_hashes: BTreeMap<&'static str, &DepTrackingHash>,
+    pub fn stable_hash(sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>,
                        hasher: &mut DefaultHasher,
                        error_format: ErrorOutputType) {
         for (key, sub_hash) in sub_hashes {
@@ -2413,43 +2396,6 @@ mod tests {
         assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
     }
 
-    #[test]
-    fn test_externs_tracking_hash_different_values() {
-        let mut v1 = super::basic_options();
-        let mut v2 = super::basic_options();
-        let mut v3 = super::basic_options();
-
-        v1.externs = Externs::new(mk_map(vec![
-            (String::from("a"), mk_set(vec![String::from("b"),
-                                            String::from("c")])),
-            (String::from("d"), mk_set(vec![String::from("e"),
-                                            String::from("f")])),
-        ]));
-
-        v2.externs = Externs::new(mk_map(vec![
-            (String::from("a"), mk_set(vec![String::from("b"),
-                                            String::from("c")])),
-            (String::from("X"), mk_set(vec![String::from("e"),
-                                            String::from("f")])),
-        ]));
-
-        v3.externs = Externs::new(mk_map(vec![
-            (String::from("a"), mk_set(vec![String::from("b"),
-                                            String::from("c")])),
-            (String::from("d"), mk_set(vec![String::from("X"),
-                                            String::from("f")])),
-        ]));
-
-        assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
-        assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
-        assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash());
-
-        // Check clone
-        assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
-        assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
-        assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
-    }
-
     #[test]
     fn test_externs_tracking_hash_different_construction_order() {
         let mut v1 = super::basic_options();
@@ -2540,69 +2486,6 @@ mod tests {
         assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
     }
 
-    #[test]
-    fn test_search_paths_tracking_hash_different_values() {
-        let mut v1 = super::basic_options();
-        let mut v2 = super::basic_options();
-        let mut v3 = super::basic_options();
-        let mut v4 = super::basic_options();
-        let mut v5 = super::basic_options();
-
-        // Reference
-        v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
-        v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
-        v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
-        v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
-        v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
-
-        // Native changed
-        v2.search_paths.add_path("native=XXX", super::ErrorOutputType::Json(false));
-        v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
-        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
-        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
-        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
-
-        // Crate changed
-        v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
-        v2.search_paths.add_path("crate=XXX", super::ErrorOutputType::Json(false));
-        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
-        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
-        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
-
-        // Dependency changed
-        v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
-        v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
-        v3.search_paths.add_path("dependency=XXX", super::ErrorOutputType::Json(false));
-        v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
-        v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
-
-        // Framework changed
-        v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
-        v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
-        v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
-        v4.search_paths.add_path("framework=XXX", super::ErrorOutputType::Json(false));
-        v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
-
-        // All changed
-        v5.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
-        v5.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
-        v5.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
-        v5.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
-        v5.search_paths.add_path("all=XXX", super::ErrorOutputType::Json(false));
-
-        assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
-        assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
-        assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash());
-        assert!(v1.dep_tracking_hash() != v5.dep_tracking_hash());
-
-        // Check clone
-        assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
-        assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
-        assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
-        assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
-        assert_eq!(v5.dep_tracking_hash(), v5.clone().dep_tracking_hash());
-    }
-
     #[test]
     fn test_search_paths_tracking_hash_different_order() {
         let mut v1 = super::basic_options();
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index db699349be6bb..bd87a8f918ab3 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -905,7 +905,7 @@ pub fn build_session_with_codemap(sopts: config::Options,
                                   local_crate_source_file: Option<PathBuf>,
                                   registry: errors::registry::Registry,
                                   codemap: Lrc<codemap::CodeMap>,
-                                  emitter_dest: Option<Box<Write + Send>>)
+                                  emitter_dest: Option<Box<dyn Write + Send>>)
                                   -> Session {
     // FIXME: This is not general enough to make the warning lint completely override
     // normal diagnostic warnings, since the warning lint can also be denied and changed
@@ -924,7 +924,7 @@ pub fn build_session_with_codemap(sopts: config::Options,
 
     let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
 
-    let emitter: Box<Emitter> = match (sopts.error_format, emitter_dest) {
+    let emitter: Box<dyn Emitter> = match (sopts.error_format, emitter_dest) {
         (config::ErrorOutputType::HumanReadable(color_config), None) => {
             Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()),
                      false, sopts.debugging_opts.teach)
@@ -1123,7 +1123,7 @@ pub enum IncrCompSession {
 }
 
 pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
-    let emitter: Box<Emitter> = match output {
+    let emitter: Box<dyn Emitter> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, false, false))
         }
@@ -1138,7 +1138,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
 }
 
 pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
-    let emitter: Box<Emitter> = match output {
+    let emitter: Box<dyn Emitter> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, false, false))
         }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index dba23c22647f8..b1d2142060699 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -499,7 +499,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                         item_name: ast::Name,
                                         _impl_item_def_id: DefId,
                                         trait_item_def_id: DefId,
-                                        requirement: &fmt::Display)
+                                        requirement: &dyn fmt::Display)
                                         -> DiagnosticBuilder<'tcx>
     {
         let msg = "impl has stricter requirements than trait";
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index a9b38d6a8d877..dbf15ad17079d 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -190,13 +190,13 @@ impl<'a, 'gcx, 'tcx> Children {
         Ok(Inserted::BecameNewSibling(last_lint))
     }
 
-    fn iter_mut(&'a mut self) -> Box<Iterator<Item = &'a mut DefId> + 'a> {
+    fn iter_mut(&'a mut self) -> Box<dyn Iterator<Item = &'a mut DefId> + 'a> {
         let nonblanket = self.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter_mut());
         Box::new(self.blanket_impls.iter_mut().chain(nonblanket))
     }
 
     fn filtered_mut(&'a mut self, sty: SimplifiedType)
-                    -> Box<Iterator<Item = &'a mut DefId> + 'a> {
+                    -> Box<dyn Iterator<Item = &'a mut DefId> + 'a> {
         let nonblanket = self.nonblanket_impls.entry(sty).or_insert(vec![]).iter_mut();
         Box::new(self.blanket_impls.iter_mut().chain(nonblanket))
     }
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 3ad8df879f20f..d04c477101731 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -799,7 +799,7 @@ pub struct GlobalCtxt<'tcx> {
     global_arenas: &'tcx GlobalArenas<'tcx>,
     global_interners: CtxtInterners<'tcx>,
 
-    cstore: &'tcx CrateStore,
+    cstore: &'tcx dyn CrateStore,
 
     pub sess: &'tcx Session,
 
@@ -883,7 +883,7 @@ pub struct GlobalCtxt<'tcx> {
     /// This is intended to only get used during the trans phase of the compiler
     /// when satisfying the query for a particular codegen unit. Internally in
     /// the query it'll send data along this channel to get processed later.
-    pub tx_to_llvm_workers: mpsc::Sender<Box<Any + Send>>,
+    pub tx_to_llvm_workers: mpsc::Sender<Box<dyn Any + Send>>,
 
     output_filenames: Arc<OutputFilenames>,
 }
@@ -1131,7 +1131,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
     /// reference to the context, to allow formatting values that need it.
     pub fn create_and_enter<F, R>(s: &'tcx Session,
-                                  cstore: &'tcx CrateStore,
+                                  cstore: &'tcx dyn CrateStore,
                                   local_providers: ty::maps::Providers<'tcx>,
                                   extern_providers: ty::maps::Providers<'tcx>,
                                   arenas: &'tcx AllArenas<'tcx>,
@@ -1139,7 +1139,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                   hir: hir_map::Map<'tcx>,
                                   on_disk_query_result_cache: maps::OnDiskCache<'tcx>,
                                   crate_name: &str,
-                                  tx: mpsc::Sender<Box<Any + Send>>,
+                                  tx: mpsc::Sender<Box<dyn Any + Send>>,
                                   output_filenames: &OutputFilenames,
                                   f: F) -> R
                                   where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R
@@ -1312,7 +1312,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     // Note that this is *untracked* and should only be used within the query
     // system if the result is otherwise tracked through queries
-    pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Lrc<Any> {
+    pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Lrc<dyn Any> {
         self.cstore.crate_data_as_rc_any(cnum)
     }
 
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index c5b82730e488c..4cc7406af721e 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -277,7 +277,7 @@ pub struct RegionFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     skipped_regions: &'a mut bool,
     current_depth: u32,
-    fld_r: &'a mut (FnMut(ty::Region<'tcx>, u32) -> ty::Region<'tcx> + 'a),
+    fld_r: &'a mut (dyn FnMut(ty::Region<'tcx>, u32) -> ty::Region<'tcx> + 'a),
 }
 
 impl<'a, 'gcx, 'tcx> RegionFolder<'a, 'gcx, 'tcx> {
@@ -330,7 +330,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFolder<'a, 'gcx, 'tcx> {
 struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     current_depth: u32,
-    fld_r: &'a mut (FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
+    fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
     map: BTreeMap<ty::BoundRegion, ty::Region<'tcx>>
 }
 
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 44771444c8aa8..47ad7cbcb56f7 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -419,7 +419,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn calculate_dtor(
         self,
         adt_did: DefId,
-        validate: &mut FnMut(Self, DefId) -> Result<(), ErrorReported>
+        validate: &mut dyn FnMut(Self, DefId) -> Result<(), ErrorReported>
     ) -> Option<ty::Destructor> {
         let drop_trait = if let Some(def_id) = self.lang_items().drop_trait() {
             def_id
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 55e9a98e7ef13..bdb120ea59c8a 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -38,7 +38,7 @@ pub struct ErrorReported;
 thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));
 
 lazy_static! {
-    static ref DEFAULT_HOOK: Box<Fn(&panic::PanicInfo) + Sync + Send + 'static> = {
+    static ref DEFAULT_HOOK: Box<dyn Fn(&panic::PanicInfo) + Sync + Send + 'static> = {
         let hook = panic::take_hook();
         panic::set_hook(Box::new(panic_hook));
         hook
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index 948c1ac0b1362..b6d8e14b74757 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -176,7 +176,7 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> {
         None
     }
 
-    fn def_use(&self, location: Location, thing: &MirVisitable<'tcx>) -> (bool, bool) {
+    fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> (bool, bool) {
         let mut visitor = DefUseVisitor {
             defined: false,
             used: false,
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 07e5091da9c1e..dbfb8a6d06e63 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -260,10 +260,10 @@ fn dump_annotation<'a, 'gcx, 'tcx>(
 
 fn for_each_region_constraint(
     closure_region_requirements: &ClosureRegionRequirements,
-    with_msg: &mut FnMut(&str) -> io::Result<()>,
+    with_msg: &mut dyn FnMut(&str) -> io::Result<()>,
 ) -> io::Result<()> {
     for req in &closure_region_requirements.outlives_requirements {
-        let subject: &Debug = match &req.subject {
+        let subject: &dyn Debug = match &req.subject {
             ClosureOutlivesSubject::Region(subject) => subject,
             ClosureOutlivesSubject::Ty(ty) => ty,
         };
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
index 69ecafa66aee7..631b1d0f8941d 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
@@ -23,7 +23,7 @@ const REGION_WIDTH: usize = 8;
 
 impl<'tcx> RegionInferenceContext<'tcx> {
     /// Write out our state into the `.mir` files.
-    pub(crate) fn dump_mir(&self, out: &mut Write) -> io::Result<()> {
+    pub(crate) fn dump_mir(&self, out: &mut dyn Write) -> io::Result<()> {
         writeln!(out, "| Free Region Mapping")?;
 
         for region in self.regions() {
@@ -67,7 +67,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// inference resulted in the values that it did when debugging.
     fn for_each_constraint(
         &self,
-        with_msg: &mut FnMut(&str) -> io::Result<()>,
+        with_msg: &mut dyn FnMut(&str) -> io::Result<()>,
     ) -> io::Result<()> {
         for region in self.definitions.indices() {
             let value = self.liveness_constraints.region_value_str(region);
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
index 7923b159d80dc..db773240809c5 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
@@ -20,7 +20,7 @@ use super::*;
 
 impl<'tcx> RegionInferenceContext<'tcx> {
     /// Write out the region constraint graph.
-    pub(crate) fn dump_graphviz(&self, mut w: &mut Write) -> io::Result<()> {
+    pub(crate) fn dump_graphviz(&self, mut w: &mut dyn Write) -> io::Result<()> {
         dot::render(self, &mut w)
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index d57b8e78f18a9..a06d39d225c45 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -127,7 +127,7 @@ fn type_check_internal<'gcx, 'tcx>(
     mir: &Mir<'tcx>,
     region_bound_pairs: &[(ty::Region<'tcx>, GenericKind<'tcx>)],
     implicit_region_bound: Option<ty::Region<'tcx>>,
-    extra: &mut FnMut(&mut TypeChecker<'_, 'gcx, 'tcx>),
+    extra: &mut dyn FnMut(&mut TypeChecker<'_, 'gcx, 'tcx>),
 ) -> MirTypeckRegionConstraints<'tcx> {
     let mut checker = TypeChecker::new(
         infcx,
@@ -231,7 +231,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         self.cx.infcx.tcx
     }
 
-    fn sanitize_type(&mut self, parent: &fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> {
+    fn sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> {
         if ty.has_escaping_regions() || ty.references_error() {
             span_mirbug_and_err!(self, parent, "bad type {:?}", ty)
         } else {
@@ -516,7 +516,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
 
     fn field_ty(
         &mut self,
-        parent: &fmt::Debug,
+        parent: &dyn fmt::Debug,
         base_ty: PlaceTy<'tcx>,
         field: Field,
         location: Location,
@@ -1171,7 +1171,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     fn assert_iscleanup(
         &mut self,
         mir: &Mir<'tcx>,
-        ctxt: &fmt::Debug,
+        ctxt: &dyn fmt::Debug,
         bb: BasicBlock,
         iscleanuppad: bool,
     ) {
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 9c7d9b398cc56..aa7bb6f97786c 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -61,7 +61,7 @@ pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation
 pub(crate) struct DebugFormatted(String);
 
 impl DebugFormatted {
-    pub fn new(input: &fmt::Debug) -> DebugFormatted {
+    pub fn new(input: &dyn fmt::Debug) -> DebugFormatted {
         DebugFormatted(format!("{:?}", input))
     }
 }
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index d3b084fde6ab8..bc555368f0f5f 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -168,7 +168,7 @@ impl Error for ConstEvalError {
         }
     }
 
-    fn cause(&self) -> Option<&Error> {
+    fn cause(&self) -> Option<&dyn Error> {
         None
     }
 }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 9887ac82a2ea6..8c15d1cf8b03a 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -15,7 +15,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 */
 
 #![deny(warnings)]
-#![cfg_attr(not(stage0), allow(bare_trait_object))]
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs
index 98753eaa5a354..a16ef2adea9be 100644
--- a/src/librustc_mir/transform/dump_mir.rs
+++ b/src/librustc_mir/transform/dump_mir.rs
@@ -49,7 +49,7 @@ impl fmt::Display for Disambiguator {
 
 
 pub fn on_mir_pass<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             pass_num: &fmt::Display,
+                             pass_num: &dyn fmt::Display,
                              pass_name: &str,
                              source: MirSource,
                              mir: &Mir<'tcx>,
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index e933a6cd700dc..9d1f76313759b 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -161,7 +161,7 @@ pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $
             promoted
         };
         let mut index = 0;
-        let mut run_pass = |pass: &MirPass| {
+        let mut run_pass = |pass: &dyn MirPass| {
             let run_hooks = |mir: &_, index, is_after| {
                 dump_mir::on_mir_pass($tcx, &format_args!("{:03}-{:03}", suite_index, index),
                                       &pass.name(), source, mir, is_after);
diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs
index 6251b64bb279d..42ddabddd2dcd 100644
--- a/src/librustc_mir/util/liveness.rs
+++ b/src/librustc_mir/util/liveness.rs
@@ -425,12 +425,12 @@ pub fn write_mir_fn<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     src: MirSource,
     mir: &Mir<'tcx>,
-    w: &mut Write,
+    w: &mut dyn Write,
     result: &LivenessResult,
 ) -> io::Result<()> {
     write_mir_intro(tcx, src, mir, w)?;
     for block in mir.basic_blocks().indices() {
-        let print = |w: &mut Write, prefix, result: &IndexVec<BasicBlock, LocalSet>| {
+        let print = |w: &mut dyn Write, prefix, result: &IndexVec<BasicBlock, LocalSet>| {
             let live: Vec<String> = mir.local_decls
                 .indices()
                 .filter(|i| result[block].contains(i))
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index f326b6e9274fc..4509cace794d4 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -72,14 +72,14 @@ pub enum PassWhere {
 ///   or `typeck` and `bar` both appear in the name.
 pub fn dump_mir<'a, 'gcx, 'tcx, F>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    pass_num: Option<&Display>,
+    pass_num: Option<&dyn Display>,
     pass_name: &str,
-    disambiguator: &Display,
+    disambiguator: &dyn Display,
     source: MirSource,
     mir: &Mir<'tcx>,
     extra_data: F,
 ) where
-    F: FnMut(PassWhere, &mut Write) -> io::Result<()>,
+    F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
 {
     if !dump_enabled(tcx, pass_name, source) {
         return;
@@ -127,15 +127,15 @@ pub fn dump_enabled<'a, 'gcx, 'tcx>(
 
 fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    pass_num: Option<&Display>,
+    pass_num: Option<&dyn Display>,
     pass_name: &str,
     node_path: &str,
-    disambiguator: &Display,
+    disambiguator: &dyn Display,
     source: MirSource,
     mir: &Mir<'tcx>,
     mut extra_data: F,
 ) where
-    F: FnMut(PassWhere, &mut Write) -> io::Result<()>,
+    F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
 {
     let _: io::Result<()> = do catch {
         let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?;
@@ -169,9 +169,9 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
 fn dump_path(
     tcx: TyCtxt<'_, '_, '_>,
     extension: &str,
-    pass_num: Option<&Display>,
+    pass_num: Option<&dyn Display>,
     pass_name: &str,
-    disambiguator: &Display,
+    disambiguator: &dyn Display,
     source: MirSource,
 ) -> PathBuf {
     let promotion_id = match source.promoted {
@@ -217,9 +217,9 @@ fn dump_path(
 pub(crate) fn create_dump_file(
     tcx: TyCtxt<'_, '_, '_>,
     extension: &str,
-    pass_num: Option<&Display>,
+    pass_num: Option<&dyn Display>,
     pass_name: &str,
-    disambiguator: &Display,
+    disambiguator: &dyn Display,
     source: MirSource,
 ) -> io::Result<fs::File> {
     let file_path = dump_path(tcx, extension, pass_num, pass_name, disambiguator, source);
@@ -233,7 +233,7 @@ pub(crate) fn create_dump_file(
 pub fn write_mir_pretty<'a, 'gcx, 'tcx>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     single: Option<DefId>,
-    w: &mut Write,
+    w: &mut dyn Write,
 ) -> io::Result<()> {
     writeln!(
         w,
@@ -274,10 +274,10 @@ pub fn write_mir_fn<'a, 'gcx, 'tcx, F>(
     src: MirSource,
     mir: &Mir<'tcx>,
     extra_data: &mut F,
-    w: &mut Write,
+    w: &mut dyn Write,
 ) -> io::Result<()>
 where
-    F: FnMut(PassWhere, &mut Write) -> io::Result<()>,
+    F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
 {
     write_mir_intro(tcx, src, mir, w)?;
     for block in mir.basic_blocks().indices() {
@@ -298,10 +298,10 @@ pub fn write_basic_block<'cx, 'gcx, 'tcx, F>(
     block: BasicBlock,
     mir: &Mir<'tcx>,
     extra_data: &mut F,
-    w: &mut Write,
+    w: &mut dyn Write,
 ) -> io::Result<()>
 where
-    F: FnMut(PassWhere, &mut Write) -> io::Result<()>,
+    F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
 {
     let data = &mir[block];
 
@@ -362,7 +362,7 @@ where
 /// a statement.
 fn write_extra<'cx, 'gcx, 'tcx, F>(
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
-    write: &mut Write,
+    write: &mut dyn Write,
     mut visit_op: F,
 ) -> io::Result<()>
 where
@@ -450,7 +450,7 @@ fn write_scope_tree(
     tcx: TyCtxt,
     mir: &Mir,
     scope_tree: &FxHashMap<VisibilityScope, Vec<VisibilityScope>>,
-    w: &mut Write,
+    w: &mut dyn Write,
     parent: VisibilityScope,
     depth: usize,
 ) -> io::Result<()> {
@@ -515,7 +515,7 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     src: MirSource,
     mir: &Mir,
-    w: &mut Write,
+    w: &mut dyn Write,
 ) -> io::Result<()> {
     write_mir_sig(tcx, src, mir, w)?;
     writeln!(w, "{{")?;
@@ -553,7 +553,7 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>(
     Ok(())
 }
 
-fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write) -> io::Result<()> {
+fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut dyn Write) -> io::Result<()> {
     let id = tcx.hir.as_local_node_id(src.def_id).unwrap();
     let body_owner_kind = tcx.hir.body_owner_kind(id);
     match (body_owner_kind, src.promoted) {
@@ -597,7 +597,7 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write) -> io::R
     Ok(())
 }
 
-fn write_temp_decls(mir: &Mir, w: &mut Write) -> io::Result<()> {
+fn write_temp_decls(mir: &Mir, w: &mut dyn Write) -> io::Result<()> {
     // Compiler-introduced temporary types.
     for temp in mir.temps_iter() {
         writeln!(
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index 7931d14ed1166..e28ccdb766ae5 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -259,8 +259,8 @@ impl TcpStream {
     /// Sets the read timeout to the timeout specified.
     ///
     /// If the value specified is [`None`], then [`read`] calls will block
-    /// indefinitely. It is an error to pass the zero `Duration` to this
-    /// method.
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+    /// passed to this method.
     ///
     /// # Platform-specific behavior
     ///
@@ -269,9 +269,11 @@ impl TcpStream {
     /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
     ///
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
     /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
     /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
     /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
+    /// [`Duration`]: ../../std/time/struct.Duration.html
     ///
     /// # Examples
     ///
@@ -282,6 +284,20 @@ impl TcpStream {
     ///                        .expect("Couldn't connect to the server...");
     /// stream.set_read_timeout(None).expect("set_read_timeout call failed");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::net::TcpStream;
+    /// use std::time::Duration;
+    ///
+    /// let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
+    /// let result = stream.set_read_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "socket_timeout", since = "1.4.0")]
     pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
         self.0.set_read_timeout(dur)
@@ -290,8 +306,8 @@ impl TcpStream {
     /// Sets the write timeout to the timeout specified.
     ///
     /// If the value specified is [`None`], then [`write`] calls will block
-    /// indefinitely. It is an error to pass the zero [`Duration`] to this
-    /// method.
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+    /// passed to this method.
     ///
     /// # Platform-specific behavior
     ///
@@ -300,6 +316,7 @@ impl TcpStream {
     /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
     ///
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
     /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
     /// [`Duration`]: ../../std/time/struct.Duration.html
     /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
@@ -314,6 +331,20 @@ impl TcpStream {
     ///                        .expect("Couldn't connect to the server...");
     /// stream.set_write_timeout(None).expect("set_write_timeout call failed");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::net::TcpStream;
+    /// use std::time::Duration;
+    ///
+    /// let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
+    /// let result = stream.set_write_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "socket_timeout", since = "1.4.0")]
     pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
         self.0.set_write_timeout(dur)
diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs
index b49cc78ac4073..8e56954bea439 100644
--- a/src/libstd/net/udp.rs
+++ b/src/libstd/net/udp.rs
@@ -228,8 +228,8 @@ impl UdpSocket {
     /// Sets the read timeout to the timeout specified.
     ///
     /// If the value specified is [`None`], then [`read`] calls will block
-    /// indefinitely. It is an error to pass the zero [`Duration`] to this
-    /// method.
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+    /// passed to this method.
     ///
     /// # Platform-specific behavior
     ///
@@ -238,6 +238,7 @@ impl UdpSocket {
     /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
     ///
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
     /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
     /// [`Duration`]: ../../std/time/struct.Duration.html
     /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
@@ -251,6 +252,20 @@ impl UdpSocket {
     /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
     /// socket.set_read_timeout(None).expect("set_read_timeout call failed");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::net::UdpSocket;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
+    /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "socket_timeout", since = "1.4.0")]
     pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
         self.0.set_read_timeout(dur)
@@ -259,8 +274,8 @@ impl UdpSocket {
     /// Sets the write timeout to the timeout specified.
     ///
     /// If the value specified is [`None`], then [`write`] calls will block
-    /// indefinitely. It is an error to pass the zero [`Duration`] to this
-    /// method.
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+    /// passed to this method.
     ///
     /// # Platform-specific behavior
     ///
@@ -269,6 +284,7 @@ impl UdpSocket {
     /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
     ///
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
     /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
     /// [`Duration`]: ../../std/time/struct.Duration.html
     /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
@@ -282,6 +298,20 @@ impl UdpSocket {
     /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
     /// socket.set_write_timeout(None).expect("set_write_timeout call failed");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::net::UdpSocket;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
+    /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "socket_timeout", since = "1.4.0")]
     pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
         self.0.set_write_timeout(dur)
diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs
index ab4aef1a58234..ad437658d144a 100644
--- a/src/libstd/sys/unix/ext/net.rs
+++ b/src/libstd/sys/unix/ext/net.rs
@@ -387,10 +387,11 @@ impl UnixStream {
     /// Sets the read timeout for the socket.
     ///
     /// If the provided value is [`None`], then [`read`] calls will block
-    /// indefinitely. It is an error to pass the zero [`Duration`] to this
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
     /// method.
     ///
     /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
     /// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read
     /// [`Duration`]: ../../../../std/time/struct.Duration.html
     ///
@@ -403,6 +404,20 @@ impl UnixStream {
     /// let socket = UnixStream::connect("/tmp/sock").unwrap();
     /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
         self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
@@ -411,10 +426,11 @@ impl UnixStream {
     /// Sets the write timeout for the socket.
     ///
     /// If the provided value is [`None`], then [`write`] calls will block
-    /// indefinitely. It is an error to pass the zero [`Duration`] to this
-    /// method.
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+    /// passed to this method.
     ///
     /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
     /// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write
     /// [`Duration`]: ../../../../std/time/struct.Duration.html
     ///
@@ -427,6 +443,20 @@ impl UnixStream {
     /// let socket = UnixStream::connect("/tmp/sock").unwrap();
     /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::net::UdpSocket;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
+    /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
         self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
@@ -1250,10 +1280,11 @@ impl UnixDatagram {
     /// Sets the read timeout for the socket.
     ///
     /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will
-    /// block indefinitely. It is an error to pass the zero [`Duration`] to this
-    /// method.
+    /// block indefinitely. An [`Err`] is returned if the zero [`Duration`]
+    /// is passed to this method.
     ///
     /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
     /// [`recv`]: #method.recv
     /// [`recv_from`]: #method.recv_from
     /// [`Duration`]: ../../../../std/time/struct.Duration.html
@@ -1267,6 +1298,20 @@ impl UnixDatagram {
     /// let sock = UnixDatagram::unbound().unwrap();
     /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixDatagram::unbound().unwrap();
+    /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
         self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
@@ -1275,7 +1320,7 @@ impl UnixDatagram {
     /// Sets the write timeout for the socket.
     ///
     /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will
-    /// block indefinitely. It is an error to pass the zero [`Duration`] to this
+    /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
     /// method.
     ///
     /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
@@ -1293,6 +1338,20 @@ impl UnixDatagram {
     /// sock.set_write_timeout(Some(Duration::new(1, 0)))
     ///     .expect("set_write_timeout function failed");
     /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixDatagram::unbound().unwrap();
+    /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+    /// let err = result.unwrap_err();
+    /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
         self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 881e3e412d4eb..92584f5b51946 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -652,9 +652,11 @@ impl<'a> Parser<'a> {
             } else {
                 let token_str = Parser::token_to_string(t);
                 let this_token_str = self.this_token_to_string();
-                Err(self.fatal(&format!("expected `{}`, found `{}`",
-                                   token_str,
-                                   this_token_str)))
+                let mut err = self.fatal(&format!("expected `{}`, found `{}`",
+                                                  token_str,
+                                                  this_token_str));
+                err.span_label(self.span, format!("expected `{}`", token_str));
+                Err(err)
             }
         } else {
             self.expect_one_of(unsafe { slice::from_raw_parts(t, 1) }, &[])
@@ -1172,7 +1174,7 @@ impl<'a> Parser<'a> {
                                      sep: SeqSep,
                                      f: F)
                                      -> PResult<'a, Vec<T>> where
-        F: FnMut(&mut Parser<'a>) -> PResult<'a,  T>,
+        F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     {
         self.expect(bra)?;
         let result = self.parse_seq_to_before_end(ket, sep, f)?;
@@ -1190,7 +1192,7 @@ impl<'a> Parser<'a> {
                            sep: SeqSep,
                            f: F)
                            -> PResult<'a, Spanned<Vec<T>>> where
-        F: FnMut(&mut Parser<'a>) -> PResult<'a,  T>,
+        F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     {
         let lo = self.span;
         self.expect(bra)?;
@@ -1485,7 +1487,10 @@ impl<'a> Parser<'a> {
                 }
                 _ => {
                     let token_str = self.this_token_to_string();
-                    return Err(self.fatal(&format!("expected `;` or `{{`, found `{}`", token_str)));
+                    let mut err = self.fatal(&format!("expected `;` or `{{`, found `{}`",
+                                                      token_str));
+                    err.span_label(self.span, "expected `;` or `{`");
+                    return Err(err);
                 }
             };
             (ident, ast::TraitItemKind::Method(sig, body), generics)
@@ -2216,7 +2221,12 @@ impl<'a> Parser<'a> {
                 TokenTree::Delimited(_, delimited) => Ok((delim, delimited.stream().into())),
                 _ => unreachable!(),
             },
-            _ => Err(self.fatal("expected open delimiter")),
+            _ => {
+                let msg = "expected open delimiter";
+                let mut err = self.fatal(msg);
+                err.span_label(self.span, msg);
+                Err(err)
+            }
         }
     }
 
@@ -2349,7 +2359,10 @@ impl<'a> Parser<'a> {
                     if self.eat_keyword(keywords::Loop) {
                         return self.parse_loop_expr(Some(label), lo, attrs)
                     }
-                    return Err(self.fatal("expected `while`, `for`, or `loop` after a label"))
+                    let msg = "expected `while`, `for`, or `loop` after a label";
+                    let mut err = self.fatal(msg);
+                    err.span_label(self.span, msg);
+                    return Err(err);
                 }
                 if self.eat_keyword(keywords::Loop) {
                     let lo = self.prev_span;
@@ -2408,6 +2421,7 @@ impl<'a> Parser<'a> {
                     // Catch this syntax error here, instead of in `parse_ident`, so
                     // that we can explicitly mention that let is not to be used as an expression
                     let mut db = self.fatal("expected expression, found statement (`let`)");
+                    db.span_label(self.span, "expected expression");
                     db.note("variable declaration using `let` is a statement");
                     return Err(db);
                 } else if self.token.is_path_start() {
@@ -2443,7 +2457,9 @@ impl<'a> Parser<'a> {
                             self.cancel(&mut err);
                             let msg = format!("expected expression, found {}",
                                               self.this_token_descr());
-                            return Err(self.fatal(&msg));
+                            let mut err = self.fatal(&msg);
+                            err.span_label(self.span, "expected expression");
+                            return Err(err);
                         }
                     }
                 }
@@ -2733,7 +2749,9 @@ impl<'a> Parser<'a> {
                              self.look_ahead(1, |t| t.is_ident()) => {
                 self.bump();
                 let name = match self.token { token::Ident(ident) => ident, _ => unreachable!() };
-                self.fatal(&format!("unknown macro variable `{}`", name)).emit();
+                let mut err = self.fatal(&format!("unknown macro variable `{}`", name));
+                err.span_label(self.span, "unknown macro variable");
+                err.emit();
                 return
             }
             token::Interpolated(ref nt) => {
@@ -3212,7 +3230,13 @@ impl<'a> Parser<'a> {
             err.span_label(sp, "expected if condition here");
             return Err(err)
         }
-        let thn = self.parse_block()?;
+        let not_block = self.token != token::OpenDelim(token::Brace);
+        let thn = self.parse_block().map_err(|mut err| {
+            if not_block {
+                err.span_label(lo, "this `if` statement has a condition, but no block");
+            }
+            err
+        })?;
         let mut els: Option<P<Expr>> = None;
         let mut hi = thn.span;
         if self.eat_keyword(keywords::Else) {
@@ -3404,14 +3428,52 @@ impl<'a> Parser<'a> {
         } else {
             None
         };
+        let arrow_span = self.span;
         self.expect(&token::FatArrow)?;
-        let expr = self.parse_expr_res(Restrictions::STMT_EXPR, None)?;
+        let arm_start_span = self.span;
+
+        let expr = self.parse_expr_res(Restrictions::STMT_EXPR, None)
+            .map_err(|mut err| {
+                err.span_label(arrow_span, "while parsing the `match` arm starting here");
+                err
+            })?;
 
         let require_comma = classify::expr_requires_semi_to_be_stmt(&expr)
             && self.token != token::CloseDelim(token::Brace);
 
         if require_comma {
-            self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)])?;
+            let cm = self.sess.codemap();
+            self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)])
+                .map_err(|mut err| {
+                    match (cm.span_to_lines(expr.span), cm.span_to_lines(arm_start_span)) {
+                        (Ok(ref expr_lines), Ok(ref arm_start_lines))
+                        if arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col
+                            && expr_lines.lines.len() == 2
+                            && self.token == token::FatArrow => {
+                            // We check wether there's any trailing code in the parse span, if there
+                            // isn't, we very likely have the following:
+                            //
+                            // X |     &Y => "y"
+                            //   |        --    - missing comma
+                            //   |        |
+                            //   |        arrow_span
+                            // X |     &X => "x"
+                            //   |      - ^^ self.span
+                            //   |      |
+                            //   |      parsed until here as `"y" & X`
+                            err.span_suggestion_short(
+                                cm.next_point(arm_start_span),
+                                "missing a comma here to end this `match` arm",
+                                ",".to_owned()
+                            );
+                        }
+                        _ => {
+                            err.span_label(arrow_span,
+                                           "while parsing the `match` arm starting here");
+                        }
+                    }
+                    err
+                })?;
         } else {
             self.eat(&token::Comma);
         }
@@ -3609,8 +3671,9 @@ impl<'a> Parser<'a> {
                 self.bump();
                 if self.token != token::CloseDelim(token::Brace) {
                     let token_str = self.this_token_to_string();
-                    return Err(self.fatal(&format!("expected `{}`, found `{}`", "}",
-                                       token_str)))
+                    let mut err = self.fatal(&format!("expected `{}`, found `{}`", "}", token_str));
+                    err.span_label(self.span, "expected `}`");
+                    return Err(err);
                 }
                 etc = true;
                 break;
@@ -3721,7 +3784,10 @@ impl<'a> Parser<'a> {
                 self.expect_and()?;
                 let mutbl = self.parse_mutability();
                 if let token::Lifetime(ident) = self.token {
-                    return Err(self.fatal(&format!("unexpected lifetime `{}` in pattern", ident)));
+                    let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern",
+                                                      ident));
+                    err.span_label(self.span, "unexpected lifetime");
+                    return Err(err);
                 }
                 let subpat = self.parse_pat()?;
                 pat = PatKind::Ref(subpat, mutbl);
@@ -3806,7 +3872,10 @@ impl<'a> Parser<'a> {
                     }
                     token::OpenDelim(token::Brace) => {
                         if qself.is_some() {
-                            return Err(self.fatal("unexpected `{` after qualified path"));
+                            let msg = "unexpected `{` after qualified path";
+                            let mut err = self.fatal(msg);
+                            err.span_label(self.span, msg);
+                            return Err(err);
                         }
                         // Parse struct pattern
                         self.bump();
@@ -3820,7 +3889,10 @@ impl<'a> Parser<'a> {
                     }
                     token::OpenDelim(token::Paren) => {
                         if qself.is_some() {
-                            return Err(self.fatal("unexpected `(` after qualified path"));
+                            let msg = "unexpected `(` after qualified path";
+                            let mut err = self.fatal(msg);
+                            err.span_label(self.span, msg);
+                            return Err(err);
                         }
                         // Parse tuple struct or enum pattern
                         let (fields, ddpos, _) = self.parse_parenthesized_pat_list()?;
@@ -3850,7 +3922,9 @@ impl<'a> Parser<'a> {
                     Err(mut err) => {
                         self.cancel(&mut err);
                         let msg = format!("expected pattern, found {}", self.this_token_descr());
-                        return Err(self.fatal(&msg));
+                        let mut err = self.fatal(&msg);
+                        err.span_label(self.span, "expected pattern");
+                        return Err(err);
                     }
                 }
             }
@@ -4250,9 +4324,11 @@ impl<'a> Parser<'a> {
                         ""
                     };
                     let tok_str = self.this_token_to_string();
-                    return Err(self.fatal(&format!("expected {}`(` or `{{`, found `{}`",
-                                       ident_str,
-                                       tok_str)))
+                    let mut err = self.fatal(&format!("expected {}`(` or `{{`, found `{}`",
+                                                      ident_str,
+                                                      tok_str));
+                    err.span_label(self.span, format!("expected {}`(` or `{{`", ident_str));
+                    return Err(err)
                 },
             };
 
@@ -5559,8 +5635,12 @@ impl<'a> Parser<'a> {
             body
         } else {
             let token_str = self.this_token_to_string();
-            return Err(self.fatal(&format!("expected `where`, `{{`, `(`, or `;` after struct \
-                                            name, found `{}`", token_str)))
+            let mut err = self.fatal(&format!(
+                "expected `where`, `{{`, `(`, or `;` after struct name, found `{}`",
+                token_str
+            ));
+            err.span_label(self.span, "expected `where`, `{`, `(`, or `;` after struct name");
+            return Err(err);
         };
 
         Ok((class_name, ItemKind::Struct(vdata, generics), None))
@@ -5579,8 +5659,10 @@ impl<'a> Parser<'a> {
             VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
         } else {
             let token_str = self.this_token_to_string();
-            return Err(self.fatal(&format!("expected `where` or `{{` after union \
-                                            name, found `{}`", token_str)))
+            let mut err = self.fatal(&format!(
+                "expected `where` or `{{` after union name, found `{}`", token_str));
+            err.span_label(self.span, "expected `where` or `{` after union name");
+            return Err(err);
         };
 
         Ok((class_name, ItemKind::Union(vdata, generics), None))
@@ -5627,9 +5709,10 @@ impl<'a> Parser<'a> {
             self.eat(&token::CloseDelim(token::Brace));
         } else {
             let token_str = self.this_token_to_string();
-            return Err(self.fatal(&format!("expected `where`, or `{{` after struct \
-                                name, found `{}`",
-                                token_str)));
+            let mut err = self.fatal(&format!(
+                    "expected `where`, or `{{` after struct name, found `{}`", token_str));
+            err.span_label(self.span, "expected `where`, or `{` after struct name");
+            return Err(err);
         }
 
         Ok(fields)
@@ -5802,9 +5885,11 @@ impl<'a> Parser<'a> {
         if !self.eat(term) {
             let token_str = self.this_token_to_string();
             let mut err = self.fatal(&format!("expected item, found `{}`", token_str));
-            let msg = "consider removing this semicolon";
             if token_str == ";" {
+                let msg = "consider removing this semicolon";
                 err.span_suggestion_short(self.span, msg, "".to_string());
+            } else {
+                err.span_label(self.span, "expected item");
             }
             return Err(err);
         }
@@ -6961,7 +7046,12 @@ impl<'a> Parser<'a> {
                 self.expect_no_suffix(sp, "string literal", suf);
                 Ok((s, style))
             }
-            _ =>  Err(self.fatal("expected string literal"))
+            _ => {
+                let msg = "expected string literal";
+                let mut err = self.fatal(msg);
+                err.span_label(self.span, msg);
+                Err(err)
+            }
         }
     }
 }
diff --git a/src/test/run-make/reproducible-build/Makefile b/src/test/run-make/reproducible-build/Makefile
index 8e799ca1a4303..629e618505129 100644
--- a/src/test/run-make/reproducible-build/Makefile
+++ b/src/test/run-make/reproducible-build/Makefile
@@ -1,20 +1,78 @@
 -include ../tools.mk
-all:
+all:  \
+	smoke \
+	debug \
+	opt \
+	link_paths \
+	remap_paths \
+	different_source_dirs \
+	extern_flags
+
+smoke:
+	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
 	$(RUSTC) reproducible-build-aux.rs
 	$(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build1"
 	$(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build2"
+	$(B2)
 	nm "$(TMPDIR)/reproducible-build1" | sort > "$(TMPDIR)/reproducible-build1.nm"
 	nm "$(TMPDIR)/reproducible-build2" | sort > "$(TMPDIR)/reproducible-build2.nm"
 	cmp "$(TMPDIR)/reproducible-build1.nm" "$(TMPDIR)/reproducible-build2.nm" || exit 1
+
+debug:
+	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
 	$(RUSTC) reproducible-build-aux.rs -g
-	$(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build1-debug"
-	$(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build2-debug"
-	nm "$(TMPDIR)/reproducible-build1-debug" | sort > "$(TMPDIR)/reproducible-build1-debug.nm"
-	nm "$(TMPDIR)/reproducible-build2-debug" | sort > "$(TMPDIR)/reproducible-build2-debug.nm"
+	$(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build1" -g
+	$(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build2" -g
+	nm "$(TMPDIR)/reproducible-build1" | sort > "$(TMPDIR)/reproducible-build1-debug.nm"
+	nm "$(TMPDIR)/reproducible-build2" | sort > "$(TMPDIR)/reproducible-build2-debug.nm"
 	cmp "$(TMPDIR)/reproducible-build1-debug.nm" "$(TMPDIR)/reproducible-build2-debug.nm" || exit 1
+
+opt:
+	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
 	$(RUSTC) reproducible-build-aux.rs -O
-	$(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build1-opt"
-	$(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build2-opt"
-	nm "$(TMPDIR)/reproducible-build1-opt" | sort > "$(TMPDIR)/reproducible-build1-opt.nm"
-	nm "$(TMPDIR)/reproducible-build2-opt" | sort > "$(TMPDIR)/reproducible-build2-opt.nm"
+	$(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build1" -O
+	$(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build2" -O
+	nm "$(TMPDIR)/reproducible-build1" | sort > "$(TMPDIR)/reproducible-build1-opt.nm"
+	nm "$(TMPDIR)/reproducible-build2" | sort > "$(TMPDIR)/reproducible-build2-opt.nm"
 	cmp "$(TMPDIR)/reproducible-build1-opt.nm" "$(TMPDIR)/reproducible-build2-opt.nm" || exit 1
+
+link_paths:
+	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+	$(RUSTC) reproducible-build-aux.rs
+	$(RUSTC) reproducible-build.rs --crate-type rlib -L /b
+	cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib
+	$(RUSTC) reproducible-build.rs --crate-type rlib -L /a
+	cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1
+
+remap_paths:
+	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+	$(RUSTC) reproducible-build-aux.rs
+	$(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=/a=/c
+	cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib
+	$(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=/b=/c
+	cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1
+
+different_source_dirs:
+	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+	$(RUSTC) reproducible-build-aux.rs
+	mkdir $(TMPDIR)/test
+	cp reproducible-build.rs $(TMPDIR)/test
+	$(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=$$PWD=/b
+	cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib
+	(cd $(TMPDIR)/test && $(RUSTC) reproducible-build.rs \
+		--remap-path-prefix=$(TMPDIR)/test=/b \
+		--crate-type rlib)
+	cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1
+
+extern_flags:
+	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+	$(RUSTC) reproducible-build-aux.rs
+	$(RUSTC) reproducible-build.rs \
+		--extern reproducible_build_aux=$(TMPDIR)/libreproducible_build_aux.rlib \
+		--crate-type rlib
+	cp $(TMPDIR)/libreproducible_build_aux.rlib $(TMPDIR)/libbar.rlib
+	cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib
+	$(RUSTC) reproducible-build.rs \
+		--extern reproducible_build_aux=$(TMPDIR)/libbar.rlib \
+		--crate-type rlib
+	cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1
diff --git a/src/test/run-make/reproducible-build/reproducible-build.rs b/src/test/run-make/reproducible-build/reproducible-build.rs
index b47d780e52984..a040c0f858d78 100644
--- a/src/test/run-make/reproducible-build/reproducible-build.rs
+++ b/src/test/run-make/reproducible-build/reproducible-build.rs
@@ -28,7 +28,7 @@
 // - Trait object shims
 // - Fn Pointer shims
 
-#![allow(dead_code)]
+#![allow(dead_code, warnings)]
 
 extern crate reproducible_build_aux;
 
diff --git a/src/test/ui/cross-file-errors/main.stderr b/src/test/ui/cross-file-errors/main.stderr
index 9eeea28be8fec..a9db5214e6a2e 100644
--- a/src/test/ui/cross-file-errors/main.stderr
+++ b/src/test/ui/cross-file-errors/main.stderr
@@ -2,7 +2,7 @@ error: expected expression, found `_`
   --> $DIR/underscore.rs:18:9
    |
 LL |         _
-   |         ^
+   |         ^ expected expression
    | 
   ::: $DIR/main.rs:15:5
    |
diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr
index 301441c5622f9..e576393500fea 100644
--- a/src/test/ui/did_you_mean/issue-40006.stderr
+++ b/src/test/ui/did_you_mean/issue-40006.stderr
@@ -19,7 +19,7 @@ error: expected `[`, found `#`
   --> $DIR/issue-40006.rs:20:17
    |
 LL |     fn xxx() { ### } //~ ERROR missing
-   |                 ^
+   |                 ^ expected `[`
 
 error: missing `fn`, `type`, or `const` for trait-item declaration
   --> $DIR/issue-40006.rs:20:21
diff --git a/src/test/ui/if-without-block.rs b/src/test/ui/if-without-block.rs
new file mode 100644
index 0000000000000..ce3de3b302dd3
--- /dev/null
+++ b/src/test/ui/if-without-block.rs
@@ -0,0 +1,18 @@
+// Copyright 2018 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.
+
+fn main() {
+    let n = 1;
+    if 5 == {
+    //~^ NOTE this `if` statement has a condition, but no block
+        println!("five");
+    }
+}
+//~^ ERROR expected `{`, found `}`
diff --git a/src/test/ui/if-without-block.stderr b/src/test/ui/if-without-block.stderr
new file mode 100644
index 0000000000000..bc8e7310ce371
--- /dev/null
+++ b/src/test/ui/if-without-block.stderr
@@ -0,0 +1,11 @@
+error: expected `{`, found `}`
+  --> $DIR/if-without-block.rs:17:1
+   |
+LL |     if 5 == {
+   |     -- this `if` statement has a condition, but no block
+...
+LL | }
+   | ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macro-context.stderr b/src/test/ui/macro-context.stderr
index 65bbe09a212da..4dc6bbe4d656c 100644
--- a/src/test/ui/macro-context.stderr
+++ b/src/test/ui/macro-context.stderr
@@ -38,7 +38,7 @@ error: expected expression, found reserved keyword `typeof`
   --> $DIR/macro-context.rs:13:17
    |
 LL |     () => ( i ; typeof );   //~ ERROR expected expression, found reserved keyword `typeof`
-   |                 ^^^^^^
+   |                 ^^^^^^ expected expression
 ...
 LL |     m!();
    |     ----- in this macro invocation
diff --git a/src/test/ui/missing-block-hint.stderr b/src/test/ui/missing-block-hint.stderr
index 54f394a4220dd..a48eff890b331 100644
--- a/src/test/ui/missing-block-hint.stderr
+++ b/src/test/ui/missing-block-hint.stderr
@@ -2,11 +2,15 @@ error: expected `{`, found `=>`
   --> $DIR/missing-block-hint.rs:13:18
    |
 LL |         if (foo) => {} //~ ERROR expected `{`, found `=>`
-   |                  ^^
+   |         --       ^^
+   |         |
+   |         this `if` statement has a condition, but no block
 
 error: expected `{`, found `bar`
   --> $DIR/missing-block-hint.rs:17:13
    |
+LL |         if (foo)
+   |         -- this `if` statement has a condition, but no block
 LL |             bar; //~ ERROR expected `{`, found `bar`
    |             ^^^-
    |             |
diff --git a/src/test/ui/resolve/token-error-correct.stderr b/src/test/ui/resolve/token-error-correct.stderr
index 344c288b596e0..c6d32c6726ea5 100644
--- a/src/test/ui/resolve/token-error-correct.stderr
+++ b/src/test/ui/resolve/token-error-correct.stderr
@@ -26,7 +26,7 @@ error: expected expression, found `;`
   --> $DIR/token-error-correct.rs:14:13
    |
 LL |     foo(bar(;
-   |             ^
+   |             ^ expected expression
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/suggestions/missing-comma-in-match.rs b/src/test/ui/suggestions/missing-comma-in-match.rs
new file mode 100644
index 0000000000000..6f86cdea3cf5e
--- /dev/null
+++ b/src/test/ui/suggestions/missing-comma-in-match.rs
@@ -0,0 +1,19 @@
+// Copyright 2018 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.
+
+fn main() {
+    match &Some(3) {
+        &None => 1
+        &Some(2) => { 3 }
+        //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `=>`
+        //~| NOTE expected one of `,`, `.`, `?`, `}`, or an operator here
+        _ => 2
+    };
+}
diff --git a/src/test/ui/suggestions/missing-comma-in-match.stderr b/src/test/ui/suggestions/missing-comma-in-match.stderr
new file mode 100644
index 0000000000000..b71a50b66318e
--- /dev/null
+++ b/src/test/ui/suggestions/missing-comma-in-match.stderr
@@ -0,0 +1,10 @@
+error: expected one of `,`, `.`, `?`, `}`, or an operator, found `=>`
+  --> $DIR/missing-comma-in-match.rs:14:18
+   |
+LL |         &None => 1
+   |                   - help: missing a comma here to end this `match` arm
+LL |         &Some(2) => { 3 }
+   |                  ^^ expected one of `,`, `.`, `?`, `}`, or an operator here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/token/issue-10636-2.stderr b/src/test/ui/token/issue-10636-2.stderr
index fcd2c10594a3c..26816ca0ca22a 100644
--- a/src/test/ui/token/issue-10636-2.stderr
+++ b/src/test/ui/token/issue-10636-2.stderr
@@ -20,7 +20,7 @@ error: expected expression, found `)`
   --> $DIR/issue-10636-2.rs:18:1
    |
 LL | } //~ ERROR: incorrect close delimiter
-   | ^
+   | ^ expected expression
 
 error[E0601]: main function not found