Rollup merge of #69349 - spastorino:mir-not-an-experiment, r=Dylan-DPC

MIR is not an experiment anymore

At least I hope is not :stuck_out_tongue_closed_eyes:

r? @oli-obk
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index b88ca8a..f8f987e 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -878,6 +878,52 @@
         unsafe { self.split_off_after_node(split_node, at) }
     }
 
+    /// Removes the element at the given index and returns it.
+    ///
+    /// This operation should compute in O(n) time.
+    ///
+    /// # Panics
+    /// Panics if at >= len
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(linked_list_remove)]
+    /// use std::collections::LinkedList;
+    ///
+    /// let mut d = LinkedList::new();
+    ///
+    /// d.push_front(1);
+    /// d.push_front(2);
+    /// d.push_front(3);
+    ///
+    /// assert_eq!(d.remove(1), 2);
+    /// assert_eq!(d.remove(0), 3);
+    /// assert_eq!(d.remove(0), 1);
+    /// ```
+    #[unstable(feature = "linked_list_remove", issue = "69210")]
+    pub fn remove(&mut self, at: usize) -> T {
+        let len = self.len();
+        assert!(at < len, "Cannot remove at an index outside of the list bounds");
+
+        // Below, we iterate towards the node at the given index, either from
+        // the start or the end, depending on which would be faster.
+        let offset_from_end = len - at - 1;
+        if at <= offset_from_end {
+            let mut cursor = self.cursor_front_mut();
+            for _ in 0..at {
+                cursor.move_next();
+            }
+            cursor.remove_current().unwrap()
+        } else {
+            let mut cursor = self.cursor_back_mut();
+            for _ in 0..offset_from_end {
+                cursor.move_prev();
+            }
+            cursor.remove_current().unwrap()
+        }
+    }
+
     /// Creates an iterator which uses a closure to determine if an element should be removed.
     ///
     /// If the closure returns true, then the element is removed and yielded.
diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs
index c1ae67a..ea75f89 100644
--- a/src/liballoc/tests/lib.rs
+++ b/src/liballoc/tests/lib.rs
@@ -12,6 +12,7 @@
 #![feature(binary_heap_into_iter_sorted)]
 #![feature(binary_heap_drain_sorted)]
 #![feature(vec_remove_item)]
+#![feature(split_inclusive)]
 
 use std::collections::hash_map::DefaultHasher;
 use std::hash::{Hash, Hasher};
diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs
index 51ddb5e..3d6b4bf 100644
--- a/src/liballoc/tests/slice.rs
+++ b/src/liballoc/tests/slice.rs
@@ -852,6 +852,86 @@
 }
 
 #[test]
+fn test_splitator_inclusive() {
+    let xs = &[1, 2, 3, 4, 5];
+
+    let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]];
+    assert_eq!(xs.split_inclusive(|x| *x % 2 == 0).collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[1], &[2, 3, 4, 5]];
+    assert_eq!(xs.split_inclusive(|x| *x == 1).collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
+    assert_eq!(xs.split_inclusive(|x| *x == 5).collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
+    assert_eq!(xs.split_inclusive(|x| *x == 10).collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]];
+    assert_eq!(xs.split_inclusive(|_| true).collect::<Vec<&[i32]>>(), splits);
+
+    let xs: &[i32] = &[];
+    let splits: &[&[i32]] = &[&[]];
+    assert_eq!(xs.split_inclusive(|x| *x == 5).collect::<Vec<&[i32]>>(), splits);
+}
+
+#[test]
+fn test_splitator_inclusive_reverse() {
+    let xs = &[1, 2, 3, 4, 5];
+
+    let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]];
+    assert_eq!(xs.split_inclusive(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[2, 3, 4, 5], &[1]];
+    assert_eq!(xs.split_inclusive(|x| *x == 1).rev().collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
+    assert_eq!(xs.split_inclusive(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
+    assert_eq!(xs.split_inclusive(|x| *x == 10).rev().collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]];
+    assert_eq!(xs.split_inclusive(|_| true).rev().collect::<Vec<_>>(), splits);
+
+    let xs: &[i32] = &[];
+    let splits: &[&[i32]] = &[&[]];
+    assert_eq!(xs.split_inclusive(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
+}
+
+#[test]
+fn test_splitator_mut_inclusive() {
+    let xs = &mut [1, 2, 3, 4, 5];
+
+    let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]];
+    assert_eq!(xs.split_inclusive_mut(|x| *x % 2 == 0).collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[1], &[2, 3, 4, 5]];
+    assert_eq!(xs.split_inclusive_mut(|x| *x == 1).collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
+    assert_eq!(xs.split_inclusive_mut(|x| *x == 5).collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
+    assert_eq!(xs.split_inclusive_mut(|x| *x == 10).collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]];
+    assert_eq!(xs.split_inclusive_mut(|_| true).collect::<Vec<_>>(), splits);
+
+    let xs: &mut [i32] = &mut [];
+    let splits: &[&[i32]] = &[&[]];
+    assert_eq!(xs.split_inclusive_mut(|x| *x == 5).collect::<Vec<_>>(), splits);
+}
+
+#[test]
+fn test_splitator_mut_inclusive_reverse() {
+    let xs = &mut [1, 2, 3, 4, 5];
+
+    let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]];
+    assert_eq!(xs.split_inclusive_mut(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[2, 3, 4, 5], &[1]];
+    assert_eq!(xs.split_inclusive_mut(|x| *x == 1).rev().collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
+    assert_eq!(xs.split_inclusive_mut(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
+    assert_eq!(xs.split_inclusive_mut(|x| *x == 10).rev().collect::<Vec<_>>(), splits);
+    let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]];
+    assert_eq!(xs.split_inclusive_mut(|_| true).rev().collect::<Vec<_>>(), splits);
+
+    let xs: &mut [i32] = &mut [];
+    let splits: &[&[i32]] = &[&[]];
+    assert_eq!(xs.split_inclusive_mut(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
+}
+
+#[test]
 fn test_splitnator() {
     let xs = &[1, 2, 3, 4, 5];
 
diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs
index d3c7261..b703df6 100644
--- a/src/liballoc/tests/str.rs
+++ b/src/liballoc/tests/str.rs
@@ -1248,6 +1248,49 @@
 }
 
 #[test]
+fn test_split_char_iterator_inclusive() {
+    let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+    let split: Vec<&str> = data.split_inclusive('\n').collect();
+    assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n"]);
+
+    let uppercase_separated = "SheePSharKTurtlECaT";
+    let mut first_char = true;
+    let split: Vec<&str> = uppercase_separated
+        .split_inclusive(|c: char| {
+            let split = !first_char && c.is_uppercase();
+            first_char = split;
+            split
+        })
+        .collect();
+    assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT"]);
+}
+
+#[test]
+fn test_split_char_iterator_inclusive_rev() {
+    let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+    let split: Vec<&str> = data.split_inclusive('\n').rev().collect();
+    assert_eq!(split, ["Little lämb\n", "Märy häd ä little lämb\n", "\n"]);
+
+    // Note that the predicate is stateful and thus dependent
+    // on the iteration order.
+    // (A different predicate is needed for reverse iterator vs normal iterator.)
+    // Not sure if anything can be done though.
+    let uppercase_separated = "SheePSharKTurtlECaT";
+    let mut term_char = true;
+    let split: Vec<&str> = uppercase_separated
+        .split_inclusive(|c: char| {
+            let split = term_char && c.is_uppercase();
+            term_char = c.is_uppercase();
+            split
+        })
+        .rev()
+        .collect();
+    assert_eq!(split, ["CaT", "TurtlE", "SharK", "SheeP"]);
+}
+
+#[test]
 fn test_rsplit() {
     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
 
diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs
index 7ebe01e..c4fbd9d 100644
--- a/src/libcore/hash/sip.rs
+++ b/src/libcore/hash/sip.rs
@@ -121,7 +121,9 @@
     }};
 }
 
-/// Loads an u64 using up to 7 bytes of a byte slice.
+/// Loads a u64 using up to 7 bytes of a byte slice. It looks clumsy but the
+/// `copy_nonoverlapping` calls that occur (via `load_int_le!`) all have fixed
+/// sizes and avoid calling `memcpy`, which is good for speed.
 ///
 /// Unsafe because: unchecked indexing at start..start+len
 #[inline]
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 12647fa..bca96b7 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -73,11 +73,14 @@
 #![feature(const_ascii_ctype_on_intrinsics)]
 #![feature(const_alloc_layout)]
 #![feature(const_if_match)]
+#![feature(const_loop)]
 #![feature(const_checked_int_methods)]
 #![feature(const_euclidean_int_methods)]
 #![feature(const_overflowing_int_methods)]
 #![feature(const_saturating_int_methods)]
 #![feature(const_int_unchecked_arith)]
+#![feature(const_int_pow)]
+#![feature(constctlz)]
 #![feature(const_panic)]
 #![feature(const_fn_union)]
 #![feature(const_generics)]
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 471ab96..43c5f7c 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -8,9 +8,18 @@
 use crate::fmt;
 use crate::intrinsics;
 use crate::mem;
-use crate::ops;
 use crate::str::FromStr;
 
+// Used because the `?` operator is not allowed in a const context.
+macro_rules! try_opt {
+    ($e:expr) => {
+        match $e {
+            Some(x) => x,
+            None => return None,
+        }
+    };
+}
+
 macro_rules! impl_nonzero_fmt {
     ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
         $(
@@ -993,26 +1002,27 @@
 ```"),
 
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
+            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
+            pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
                 let mut base = self;
                 let mut acc: Self = 1;
 
                 while exp > 1 {
                     if (exp & 1) == 1 {
-                        acc = acc.checked_mul(base)?;
+                        acc = try_opt!(acc.checked_mul(base));
                     }
                     exp /= 2;
-                    base = base.checked_mul(base)?;
+                    base = try_opt!(base.checked_mul(base));
                 }
 
                 // Deal with the final bit of the exponent separately, since
                 // squaring the base afterwards is not necessary and may cause a
                 // needless overflow.
                 if exp == 1 {
-                    acc = acc.checked_mul(base)?;
+                    acc = try_opt!(acc.checked_mul(base));
                 }
 
                 Some(acc)
@@ -1180,10 +1190,11 @@
 $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
+            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn saturating_pow(self, exp: u32) -> Self {
+            pub const fn saturating_pow(self, exp: u32) -> Self {
                 match self.checked_pow(exp) {
                     Some(x) => x,
                     None if self < 0 && exp % 2 == 1 => Self::min_value(),
@@ -1523,10 +1534,11 @@
 $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
+            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn wrapping_pow(self, mut exp: u32) -> Self {
+            pub const fn wrapping_pow(self, mut exp: u32) -> Self {
                 let mut base = self;
                 let mut acc: Self = 1;
 
@@ -1900,10 +1912,11 @@
 $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
+            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
+            pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
                 let mut base = self;
                 let mut acc: Self = 1;
                 let mut overflown = false;
@@ -1949,11 +1962,12 @@
 $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
             #[rustc_inherit_overflow_checks]
-            pub fn pow(self, mut exp: u32) -> Self {
+            pub const fn pow(self, mut exp: u32) -> Self {
                 let mut base = self;
                 let mut acc = 1;
 
@@ -3119,26 +3133,27 @@
 assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
+            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
+            pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
                 let mut base = self;
                 let mut acc: Self = 1;
 
                 while exp > 1 {
                     if (exp & 1) == 1 {
-                        acc = acc.checked_mul(base)?;
+                        acc = try_opt!(acc.checked_mul(base));
                     }
                     exp /= 2;
-                    base = base.checked_mul(base)?;
+                    base = try_opt!(base.checked_mul(base));
                 }
 
                 // Deal with the final bit of the exponent separately, since
                 // squaring the base afterwards is not necessary and may cause a
                 // needless overflow.
                 if exp == 1 {
-                    acc = acc.checked_mul(base)?;
+                    acc = try_opt!(acc.checked_mul(base));
                 }
 
                 Some(acc)
@@ -3234,10 +3249,11 @@
 $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
+            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn saturating_pow(self, exp: u32) -> Self {
+            pub const fn saturating_pow(self, exp: u32) -> Self {
                 match self.checked_pow(exp) {
                     Some(x) => x,
                     None => Self::max_value(),
@@ -3527,10 +3543,11 @@
 assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
+            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn wrapping_pow(self, mut exp: u32) -> Self {
+            pub const fn wrapping_pow(self, mut exp: u32) -> Self {
                 let mut base = self;
                 let mut acc: Self = 1;
 
@@ -3853,10 +3870,11 @@
 assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_pow", since = "1.34.0")]
+            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             #[inline]
-            pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
+            pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
                 let mut base = self;
                 let mut acc: Self = 1;
                 let mut overflown = false;
@@ -3899,11 +3917,12 @@
 ", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(5), 32);", $EndFeature, "
 ```"),
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
         #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
         #[inline]
         #[rustc_inherit_overflow_checks]
-        pub fn pow(self, mut exp: u32) -> Self {
+        pub const fn pow(self, mut exp: u32) -> Self {
             let mut base = self;
             let mut acc = 1;
 
@@ -4014,7 +4033,8 @@
         // overflow cases it instead ends up returning the maximum value
         // of the type, and can return 0 for 0.
         #[inline]
-        fn one_less_than_next_power_of_two(self) -> Self {
+        #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+        const fn one_less_than_next_power_of_two(self) -> Self {
             if self <= 1 { return 0; }
 
             let p = self - 1;
@@ -4042,10 +4062,11 @@
 assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);", $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
             #[inline]
-            pub fn next_power_of_two(self) -> Self {
-                // Call the trait to get overflow checks
-                ops::Add::add(self.one_less_than_next_power_of_two(), 1)
+            #[rustc_inherit_overflow_checks]
+            pub const fn next_power_of_two(self) -> Self {
+                self.one_less_than_next_power_of_two() + 1
             }
         }
 
@@ -4067,7 +4088,8 @@
 ```"),
             #[inline]
             #[stable(feature = "rust1", since = "1.0.0")]
-            pub fn checked_next_power_of_two(self) -> Option<Self> {
+            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            pub const fn checked_next_power_of_two(self) -> Option<Self> {
                 self.one_less_than_next_power_of_two().checked_add(1)
             }
         }
@@ -4091,7 +4113,8 @@
 ```"),
             #[unstable(feature = "wrapping_next_power_of_two", issue = "32463",
                        reason = "needs decision on wrapping behaviour")]
-            pub fn wrapping_next_power_of_two(self) -> Self {
+            #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")]
+            pub const fn wrapping_next_power_of_two(self) -> Self {
                 self.one_less_than_next_power_of_two().wrapping_add(1)
             }
         }
@@ -4301,8 +4324,9 @@
     /// assert!(!non_ascii.is_ascii());
     /// ```
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.43.0")]
     #[inline]
-    pub fn is_ascii(&self) -> bool {
+    pub const fn is_ascii(&self) -> bool {
         *self & 128 == 0
     }
 
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index e79a775..7c65f59 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -1156,6 +1156,69 @@
     }
 
     /// Returns an iterator over subslices separated by elements that match
+    /// `pred`. The matched element is contained in the end of the previous
+    /// subslice as a terminator.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(split_inclusive)]
+    /// let slice = [10, 40, 33, 20];
+    /// let mut iter = slice.split_inclusive(|num| num % 3 == 0);
+    ///
+    /// assert_eq!(iter.next().unwrap(), &[10, 40, 33]);
+    /// assert_eq!(iter.next().unwrap(), &[20]);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// If the last element of the slice is matched,
+    /// that element will be considered the terminator of the preceding slice.
+    /// That slice will be the last item returned by the iterator.
+    ///
+    /// ```
+    /// #![feature(split_inclusive)]
+    /// let slice = [3, 10, 40, 33];
+    /// let mut iter = slice.split_inclusive(|num| num % 3 == 0);
+    ///
+    /// assert_eq!(iter.next().unwrap(), &[3]);
+    /// assert_eq!(iter.next().unwrap(), &[10, 40, 33]);
+    /// assert!(iter.next().is_none());
+    /// ```
+    #[unstable(feature = "split_inclusive", issue = "none")]
+    #[inline]
+    pub fn split_inclusive<F>(&self, pred: F) -> SplitInclusive<'_, T, F>
+    where
+        F: FnMut(&T) -> bool,
+    {
+        SplitInclusive { v: self, pred, finished: false }
+    }
+
+    /// Returns an iterator over mutable subslices separated by elements that
+    /// match `pred`. The matched element is contained in the previous
+    /// subslice as a terminator.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(split_inclusive)]
+    /// let mut v = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in v.split_inclusive_mut(|num| *num % 3 == 0) {
+    ///     let terminator_idx = group.len()-1;
+    ///     group[terminator_idx] = 1;
+    /// }
+    /// assert_eq!(v, [10, 40, 1, 20, 1, 1]);
+    /// ```
+    #[unstable(feature = "split_inclusive", issue = "none")]
+    #[inline]
+    pub fn split_inclusive_mut<F>(&mut self, pred: F) -> SplitInclusiveMut<'_, T, F>
+    where
+        F: FnMut(&T) -> bool,
+    {
+        SplitInclusiveMut { v: self, pred, finished: false }
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
     /// `pred`, starting at the end of the slice and working backwards.
     /// The matched element is not contained in the subslices.
     ///
@@ -3675,7 +3738,106 @@
 #[stable(feature = "fused", since = "1.26.0")]
 impl<T, P> FusedIterator for Split<'_, T, P> where P: FnMut(&T) -> bool {}
 
-/// An iterator over the subslices of the vector which are separated
+/// An iterator over subslices separated by elements that match a predicate
+/// function. Unlike `Split`, it contains the matched part as a terminator
+/// of the subslice.
+///
+/// This struct is created by the [`split_inclusive`] method on [slices].
+///
+/// [`split_inclusive`]: ../../std/primitive.slice.html#method.split_inclusive
+/// [slices]: ../../std/primitive.slice.html
+#[unstable(feature = "split_inclusive", issue = "none")]
+pub struct SplitInclusive<'a, T: 'a, P>
+where
+    P: FnMut(&T) -> bool,
+{
+    v: &'a [T],
+    pred: P,
+    finished: bool,
+}
+
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<T: fmt::Debug, P> fmt::Debug for SplitInclusive<'_, T, P>
+where
+    P: FnMut(&T) -> bool,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("SplitInclusive")
+            .field("v", &self.v)
+            .field("finished", &self.finished)
+            .finish()
+    }
+}
+
+// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<T, P> Clone for SplitInclusive<'_, T, P>
+where
+    P: Clone + FnMut(&T) -> bool,
+{
+    fn clone(&self) -> Self {
+        SplitInclusive { v: self.v, pred: self.pred.clone(), finished: self.finished }
+    }
+}
+
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<'a, T, P> Iterator for SplitInclusive<'a, T, P>
+where
+    P: FnMut(&T) -> bool,
+{
+    type Item = &'a [T];
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a [T]> {
+        if self.finished {
+            return None;
+        }
+
+        let idx =
+            self.v.iter().position(|x| (self.pred)(x)).map(|idx| idx + 1).unwrap_or(self.v.len());
+        if idx == self.v.len() {
+            self.finished = true;
+        }
+        let ret = Some(&self.v[..idx]);
+        self.v = &self.v[idx..];
+        ret
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.finished { (0, Some(0)) } else { (1, Some(self.v.len() + 1)) }
+    }
+}
+
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<'a, T, P> DoubleEndedIterator for SplitInclusive<'a, T, P>
+where
+    P: FnMut(&T) -> bool,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a [T]> {
+        if self.finished {
+            return None;
+        }
+
+        // The last index of self.v is already checked and found to match
+        // by the last iteration, so we start searching a new match
+        // one index to the left.
+        let remainder = if self.v.len() == 0 { &[] } else { &self.v[..(self.v.len() - 1)] };
+        let idx = remainder.iter().rposition(|x| (self.pred)(x)).map(|idx| idx + 1).unwrap_or(0);
+        if idx == 0 {
+            self.finished = true;
+        }
+        let ret = Some(&self.v[idx..]);
+        self.v = &self.v[..idx];
+        ret
+    }
+}
+
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<T, P> FusedIterator for SplitInclusive<'_, T, P> where P: FnMut(&T) -> bool {}
+
+/// An iterator over the mutable subslices of the vector which are separated
 /// by elements that match `pred`.
 ///
 /// This struct is created by the [`split_mut`] method on [slices].
@@ -3789,6 +3951,114 @@
 #[stable(feature = "fused", since = "1.26.0")]
 impl<T, P> FusedIterator for SplitMut<'_, T, P> where P: FnMut(&T) -> bool {}
 
+/// An iterator over the mutable subslices of the vector which are separated
+/// by elements that match `pred`. Unlike `SplitMut`, it contains the matched
+/// parts in the ends of the subslices.
+///
+/// This struct is created by the [`split_inclusive_mut`] method on [slices].
+///
+/// [`split_inclusive_mut`]: ../../std/primitive.slice.html#method.split_inclusive_mut
+/// [slices]: ../../std/primitive.slice.html
+#[unstable(feature = "split_inclusive", issue = "none")]
+pub struct SplitInclusiveMut<'a, T: 'a, P>
+where
+    P: FnMut(&T) -> bool,
+{
+    v: &'a mut [T],
+    pred: P,
+    finished: bool,
+}
+
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<T: fmt::Debug, P> fmt::Debug for SplitInclusiveMut<'_, T, P>
+where
+    P: FnMut(&T) -> bool,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("SplitInclusiveMut")
+            .field("v", &self.v)
+            .field("finished", &self.finished)
+            .finish()
+    }
+}
+
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<'a, T, P> Iterator for SplitInclusiveMut<'a, T, P>
+where
+    P: FnMut(&T) -> bool,
+{
+    type Item = &'a mut [T];
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a mut [T]> {
+        if self.finished {
+            return None;
+        }
+
+        let idx_opt = {
+            // work around borrowck limitations
+            let pred = &mut self.pred;
+            self.v.iter().position(|x| (*pred)(x))
+        };
+        let idx = idx_opt.map(|idx| idx + 1).unwrap_or(self.v.len());
+        if idx == self.v.len() {
+            self.finished = true;
+        }
+        let tmp = mem::replace(&mut self.v, &mut []);
+        let (head, tail) = tmp.split_at_mut(idx);
+        self.v = tail;
+        Some(head)
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        if self.finished {
+            (0, Some(0))
+        } else {
+            // if the predicate doesn't match anything, we yield one slice
+            // if it matches every element, we yield len+1 empty slices.
+            (1, Some(self.v.len() + 1))
+        }
+    }
+}
+
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<'a, T, P> DoubleEndedIterator for SplitInclusiveMut<'a, T, P>
+where
+    P: FnMut(&T) -> bool,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a mut [T]> {
+        if self.finished {
+            return None;
+        }
+
+        let idx_opt = if self.v.len() == 0 {
+            None
+        } else {
+            // work around borrowck limitations
+            let pred = &mut self.pred;
+
+            // The last index of self.v is already checked and found to match
+            // by the last iteration, so we start searching a new match
+            // one index to the left.
+            let remainder = &self.v[..(self.v.len() - 1)];
+            remainder.iter().rposition(|x| (*pred)(x))
+        };
+        let idx = idx_opt.map(|idx| idx + 1).unwrap_or(0);
+        if idx == 0 {
+            self.finished = true;
+        }
+        let tmp = mem::replace(&mut self.v, &mut []);
+        let (head, tail) = tmp.split_at_mut(idx);
+        self.v = head;
+        Some(tail)
+    }
+}
+
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<T, P> FusedIterator for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> bool {}
+
 /// An iterator over subslices separated by elements that match a predicate
 /// function, starting from the end of the slice.
 ///
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 7c4acb0..668b3ff 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1133,6 +1133,26 @@
     }
 
     #[inline]
+    fn next_inclusive(&mut self) -> Option<&'a str> {
+        if self.finished {
+            return None;
+        }
+
+        let haystack = self.matcher.haystack();
+        match self.matcher.next_match() {
+            // SAFETY: `Searcher` guarantees that `b` lies on unicode boundary,
+            // and self.start is either the start of the original string,
+            // or `b` was assigned to it, so it also lies on unicode boundary.
+            Some((_, b)) => unsafe {
+                let elt = haystack.get_unchecked(self.start..b);
+                self.start = b;
+                Some(elt)
+            },
+            None => self.get_end(),
+        }
+    }
+
+    #[inline]
     fn next_back(&mut self) -> Option<&'a str>
     where
         P::Searcher: ReverseSearcher<'a>,
@@ -1168,6 +1188,49 @@
             },
         }
     }
+
+    #[inline]
+    fn next_back_inclusive(&mut self) -> Option<&'a str>
+    where
+        P::Searcher: ReverseSearcher<'a>,
+    {
+        if self.finished {
+            return None;
+        }
+
+        if !self.allow_trailing_empty {
+            self.allow_trailing_empty = true;
+            match self.next_back_inclusive() {
+                Some(elt) if !elt.is_empty() => return Some(elt),
+                _ => {
+                    if self.finished {
+                        return None;
+                    }
+                }
+            }
+        }
+
+        let haystack = self.matcher.haystack();
+        match self.matcher.next_match_back() {
+            // SAFETY: `Searcher` guarantees that `b` lies on unicode boundary,
+            // and self.end is either the end of the original string,
+            // or `b` was assigned to it, so it also lies on unicode boundary.
+            Some((_, b)) => unsafe {
+                let elt = haystack.get_unchecked(b..self.end);
+                self.end = b;
+                Some(elt)
+            },
+            // SAFETY: self.start is either the start of the original string,
+            // or start of a substring that represents the part of the string that hasn't
+            // iterated yet. Either way, it is guaranteed to lie on unicode boundary.
+            // self.end is either the end of the original string,
+            // or `b` was assigned to it, so it also lies on unicode boundary.
+            None => unsafe {
+                self.finished = true;
+                Some(haystack.get_unchecked(self.start..self.end))
+            },
+        }
+    }
 }
 
 generate_pattern_iterators! {
@@ -3213,6 +3276,42 @@
         })
     }
 
+    /// An iterator over substrings of this string slice, separated by
+    /// characters matched by a pattern. Differs from the iterator produced by
+    /// `split` in that `split_inclusive` leaves the matched part as the
+    /// terminator of the substring.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(split_inclusive)]
+    /// let v: Vec<&str> = "Mary had a little lamb\nlittle lamb\nlittle lamb."
+    ///     .split_inclusive('\n').collect();
+    /// assert_eq!(v, ["Mary had a little lamb\n", "little lamb\n", "little lamb."]);
+    /// ```
+    ///
+    /// If the last element of the string is matched,
+    /// that element will be considered the terminator of the preceding substring.
+    /// That substring will be the last item returned by the iterator.
+    ///
+    /// ```
+    /// #![feature(split_inclusive)]
+    /// let v: Vec<&str> = "Mary had a little lamb\nlittle lamb\nlittle lamb.\n"
+    ///     .split_inclusive('\n').collect();
+    /// assert_eq!(v, ["Mary had a little lamb\n", "little lamb\n", "little lamb.\n"]);
+    /// ```
+    #[unstable(feature = "split_inclusive", issue = "none")]
+    #[inline]
+    pub fn split_inclusive<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitInclusive<'a, P> {
+        SplitInclusive(SplitInternal {
+            start: 0,
+            end: self.len(),
+            matcher: pat.into_searcher(self),
+            allow_trailing_empty: false,
+            finished: false,
+        })
+    }
+
     /// An iterator over substrings of the given string slice, separated by
     /// characters matched by a pattern and yielded in reverse order.
     ///
@@ -4406,6 +4505,19 @@
     inner: Map<Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, BytesIsNotEmpty>, UnsafeBytesToStr>,
 }
 
+/// An iterator over the substrings of a string,
+/// terminated by a substring matching to a predicate function
+/// Unlike `Split`, it contains the matched part as a terminator
+/// of the subslice.
+///
+/// This struct is created by the [`split_inclusive`] method on [`str`].
+/// See its documentation for more.
+///
+/// [`split_inclusive`]: ../../std/primitive.str.html#method.split_inclusive
+/// [`str`]: ../../std/primitive.str.html
+#[unstable(feature = "split_inclusive", issue = "none")]
+pub struct SplitInclusive<'a, P: Pattern<'a>>(SplitInternal<'a, P>);
+
 impl_fn_for_zst! {
     #[derive(Clone)]
     struct IsWhitespace impl Fn = |c: char| -> bool {
@@ -4496,6 +4608,44 @@
 #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
 impl FusedIterator for SplitAsciiWhitespace<'_> {}
 
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<'a, P: Pattern<'a>> Iterator for SplitInclusive<'a, P> {
+    type Item = &'a str;
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a str> {
+        self.0.next_inclusive()
+    }
+}
+
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<'a, P: Pattern<'a, Searcher: fmt::Debug>> fmt::Debug for SplitInclusive<'a, P> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("SplitInclusive").field("0", &self.0).finish()
+    }
+}
+
+// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<'a, P: Pattern<'a, Searcher: Clone>> Clone for SplitInclusive<'a, P> {
+    fn clone(&self) -> Self {
+        SplitInclusive(self.0.clone())
+    }
+}
+
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator
+    for SplitInclusive<'a, P>
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a str> {
+        self.0.next_back_inclusive()
+    }
+}
+
+#[unstable(feature = "split_inclusive", issue = "none")]
+impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {}
+
 /// An iterator of [`u16`] over the string encoded as UTF-16.
 ///
 /// [`u16`]: ../../std/primitive.u16.html
diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs
index f5c83fe..ca55d41 100644
--- a/src/librustc/arena.rs
+++ b/src/librustc/arena.rs
@@ -48,6 +48,7 @@
             [] item_local_set: rustc_hir::ItemLocalSet,
             [decode] mir_const_qualif: rustc_index::bit_set::BitSet<rustc::mir::Local>,
             [] trait_impls_of: rustc::ty::trait_def::TraitImpls,
+            [] associated_items: rustc::ty::AssociatedItems,
             [] dropck_outlives:
                 rustc::infer::canonical::Canonical<'tcx,
                     rustc::infer::canonical::QueryResponse<'tcx,
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index f0879bd..c62f9a0 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -148,6 +148,10 @@
 /// Error type for `tcx.lit_to_const`.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable)]
 pub enum LitToConstError {
+    /// The literal's inferred type did not match the expected `ty` in the input.
+    /// This is used for graceful error handling (`delay_span_bug`) in
+    /// type checking (`AstConv::ast_const_to_const`).
+    TypeError,
     UnparseableFloat,
     Reported,
 }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 8330bbe..409c981 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -519,12 +519,12 @@
                         resume_arg,
                         drop: _,
                     } => {
+                        self.visit_operand(value, source_location);
                         self.visit_place(
                             resume_arg,
                             PlaceContext::MutatingUse(MutatingUseContext::Store),
                             source_location,
                         );
-                        self.visit_operand(value, source_location);
                     }
 
                 }
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 3cee10f..02c51a2 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -333,7 +333,7 @@
         query associated_item(_: DefId) -> ty::AssocItem {}
 
         /// Collects the associated items defined on a trait or impl.
-        query associated_items(key: DefId) -> &'tcx [ty::AssocItem] {
+        query associated_items(key: DefId) -> &'tcx ty::AssociatedItems {
             desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) }
         }
 
@@ -661,7 +661,7 @@
             desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(key) }
             cache_on_disk_if { true }
         }
-        query is_object_safe(key: DefId) -> bool {
+        query object_safety_violations(key: DefId) -> Vec<traits::ObjectSafetyViolation> {
             desc { |tcx| "determine object safety of trait `{}`", tcx.def_path_str(key) }
         }
 
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index c000aa7..de2ec53 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -16,8 +16,10 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_span::{Span, DUMMY_SP};
+use smallvec::SmallVec;
 use syntax::ast;
 
+use std::borrow::Cow;
 use std::fmt::Debug;
 use std::rc::Rc;
 
@@ -737,3 +739,133 @@
         tcx: TyCtxt<'tcx>,
     ) -> Option<Self::LiftedLiteral>;
 }
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+pub enum ObjectSafetyViolation {
+    /// `Self: Sized` declared on the trait.
+    SizedSelf(SmallVec<[Span; 1]>),
+
+    /// Supertrait reference references `Self` an in illegal location
+    /// (e.g., `trait Foo : Bar<Self>`).
+    SupertraitSelf(SmallVec<[Span; 1]>),
+
+    /// Method has something illegal.
+    Method(ast::Name, MethodViolationCode, Span),
+
+    /// Associated const.
+    AssocConst(ast::Name, Span),
+}
+
+impl ObjectSafetyViolation {
+    pub fn error_msg(&self) -> Cow<'static, str> {
+        match *self {
+            ObjectSafetyViolation::SizedSelf(_) => "it requires `Self: Sized`".into(),
+            ObjectSafetyViolation::SupertraitSelf(ref spans) => {
+                if spans.iter().any(|sp| *sp != DUMMY_SP) {
+                    "it uses `Self` as a type parameter in this".into()
+                } else {
+                    "it cannot use `Self` as a type parameter in a supertrait or `where`-clause"
+                        .into()
+                }
+            }
+            ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => {
+                format!("associated function `{}` has no `self` parameter", name).into()
+            }
+            ObjectSafetyViolation::Method(
+                name,
+                MethodViolationCode::ReferencesSelfInput(_),
+                DUMMY_SP,
+            ) => format!("method `{}` references the `Self` type in its parameters", name).into(),
+            ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfInput(_), _) => {
+                format!("method `{}` references the `Self` type in this parameter", name).into()
+            }
+            ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfOutput, _) => {
+                format!("method `{}` references the `Self` type in its return type", name).into()
+            }
+            ObjectSafetyViolation::Method(
+                name,
+                MethodViolationCode::WhereClauseReferencesSelf,
+                _,
+            ) => {
+                format!("method `{}` references the `Self` type in its `where` clause", name).into()
+            }
+            ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => {
+                format!("method `{}` has generic type parameters", name).into()
+            }
+            ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => {
+                format!("method `{}`'s `self` parameter cannot be dispatched on", name).into()
+            }
+            ObjectSafetyViolation::AssocConst(name, DUMMY_SP) => {
+                format!("it contains associated `const` `{}`", name).into()
+            }
+            ObjectSafetyViolation::AssocConst(..) => "it contains this associated `const`".into(),
+        }
+    }
+
+    pub fn solution(&self) -> Option<(String, Option<(String, Span)>)> {
+        Some(match *self {
+            ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) => {
+                return None;
+            }
+            ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(sugg), _) => (
+                format!(
+                    "consider turning `{}` into a method by giving it a `&self` argument or \
+                     constraining it so it does not apply to trait objects",
+                    name
+                ),
+                sugg.map(|(sugg, sp)| (sugg.to_string(), sp)),
+            ),
+            ObjectSafetyViolation::Method(
+                name,
+                MethodViolationCode::UndispatchableReceiver,
+                span,
+            ) => (
+                format!("consider changing method `{}`'s `self` parameter to be `&self`", name)
+                    .into(),
+                Some(("&Self".to_string(), span)),
+            ),
+            ObjectSafetyViolation::AssocConst(name, _)
+            | ObjectSafetyViolation::Method(name, ..) => {
+                (format!("consider moving `{}` to another trait", name), None)
+            }
+        })
+    }
+
+    pub fn spans(&self) -> SmallVec<[Span; 1]> {
+        // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
+        // diagnostics use a `note` instead of a `span_label`.
+        match self {
+            ObjectSafetyViolation::SupertraitSelf(spans)
+            | ObjectSafetyViolation::SizedSelf(spans) => spans.clone(),
+            ObjectSafetyViolation::AssocConst(_, span)
+            | ObjectSafetyViolation::Method(_, _, span)
+                if *span != DUMMY_SP =>
+            {
+                smallvec![*span]
+            }
+            _ => smallvec![],
+        }
+    }
+}
+
+/// Reasons a method might not be object-safe.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+pub enum MethodViolationCode {
+    /// e.g., `fn foo()`
+    StaticMethod(Option<(&'static str, Span)>),
+
+    /// e.g., `fn foo(&self, x: Self)`
+    ReferencesSelfInput(usize),
+
+    /// e.g., `fn foo(&self) -> Self`
+    ReferencesSelfOutput,
+
+    /// e.g., `fn foo(&self) where Self: Clone`
+    WhereClauseReferencesSelf,
+
+    /// e.g., `fn foo<A>()`
+    Generic,
+
+    /// the method's receiver (`self` argument) can't be dispatched on
+    UndispatchableReceiver,
+}
diff --git a/src/librustc/traits/specialization_graph.rs b/src/librustc/traits/specialization_graph.rs
index 36a8436..ee813bf 100644
--- a/src/librustc/traits/specialization_graph.rs
+++ b/src/librustc/traits/specialization_graph.rs
@@ -81,8 +81,8 @@
     }
 
     /// Iterate over the items defined directly by the given (impl or trait) node.
-    pub fn items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ty::AssocItem] {
-        tcx.associated_items(self.def_id())
+    pub fn items(&self, tcx: TyCtxt<'tcx>) -> impl 'tcx + Iterator<Item = &'tcx ty::AssocItem> {
+        tcx.associated_items(self.def_id()).in_definition_order()
     }
 
     /// Finds an associated item defined in this node.
@@ -99,7 +99,7 @@
         use crate::ty::AssocKind::*;
 
         tcx.associated_items(self.def_id())
-            .iter()
+            .filter_by_name_unhygienic(trait_item_name.name)
             .find(move |impl_item| {
                 match (trait_item_kind, impl_item.kind) {
                 | (Const, Const)
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index f4006a1..851bffc 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -122,7 +122,7 @@
         };
         let method_def_id = tcx
             .associated_items(trait_def_id.unwrap())
-            .iter()
+            .in_definition_order()
             .find(|m| m.kind == ty::AssocKind::Method)
             .unwrap()
             .def_id;
diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs
index df1602b..c305999 100644
--- a/src/librustc/ty/codec.rs
+++ b/src/librustc/ty/codec.rs
@@ -301,6 +301,7 @@
 macro_rules! __impl_decoder_methods {
     ($($name:ident -> $ty:ty;)*) => {
         $(
+            #[inline]
             fn $name(&mut self) -> Result<$ty, Self::Error> {
                 self.opaque.$name()
             }
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 332fd0b..0ec30bc 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -337,7 +337,7 @@
         let fn_once = tcx.lang_items().fn_once_trait().unwrap();
         let call_once = tcx
             .associated_items(fn_once)
-            .iter()
+            .in_definition_order()
             .find(|it| it.kind == ty::AssocKind::Method)
             .unwrap()
             .def_id;
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index a4b4e1d..a195c94 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -30,10 +30,11 @@
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::sorted_map::SortedIndexMultiMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator};
 use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::{Constness, GlobMap, Node, TraitMap};
 use rustc_index::vec::{Idx, IndexVec};
@@ -216,6 +217,13 @@
             ty::AssocKind::Const => "associated constant",
         }
     }
+
+    pub fn namespace(&self) -> Namespace {
+        match *self {
+            ty::AssocKind::OpaqueTy | ty::AssocKind::Type => Namespace::TypeNS,
+            ty::AssocKind::Const | ty::AssocKind::Method => Namespace::ValueNS,
+        }
+    }
 }
 
 impl AssocItem {
@@ -257,6 +265,81 @@
     }
 }
 
+/// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name.
+///
+/// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since
+/// it is relatively expensive. Instead, items are indexed by `Symbol` and hygienic comparison is
+/// done only on items with the same name.
+#[derive(Debug, Clone, PartialEq, HashStable)]
+pub struct AssociatedItems {
+    items: SortedIndexMultiMap<u32, Symbol, ty::AssocItem>,
+}
+
+impl AssociatedItems {
+    /// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order.
+    pub fn new(items_in_def_order: impl IntoIterator<Item = ty::AssocItem>) -> Self {
+        let items = items_in_def_order.into_iter().map(|item| (item.ident.name, item)).collect();
+        AssociatedItems { items }
+    }
+
+    /// Returns a slice of associated items in the order they were defined.
+    ///
+    /// New code should avoid relying on definition order. If you need a particular associated item
+    /// for a known trait, make that trait a lang item instead of indexing this array.
+    pub fn in_definition_order(&self) -> impl '_ + Iterator<Item = &ty::AssocItem> {
+        self.items.iter().map(|(_, v)| v)
+    }
+
+    /// Returns an iterator over all associated items with the given name, ignoring hygiene.
+    pub fn filter_by_name_unhygienic(
+        &self,
+        name: Symbol,
+    ) -> impl '_ + Iterator<Item = &ty::AssocItem> {
+        self.items.get_by_key(&name)
+    }
+
+    /// Returns an iterator over all associated items with the given name.
+    ///
+    /// Multiple items may have the same name if they are in different `Namespace`s. For example,
+    /// an associated type can have the same name as a method. Use one of the `find_by_name_and_*`
+    /// methods below if you know which item you are looking for.
+    pub fn filter_by_name(
+        &'a self,
+        tcx: TyCtxt<'a>,
+        ident: Ident,
+        parent_def_id: DefId,
+    ) -> impl 'a + Iterator<Item = &'a ty::AssocItem> {
+        self.filter_by_name_unhygienic(ident.name)
+            .filter(move |item| tcx.hygienic_eq(ident, item.ident, parent_def_id))
+    }
+
+    /// Returns the associated item with the given name and `AssocKind`, if one exists.
+    pub fn find_by_name_and_kind(
+        &self,
+        tcx: TyCtxt<'_>,
+        ident: Ident,
+        kind: AssocKind,
+        parent_def_id: DefId,
+    ) -> Option<&ty::AssocItem> {
+        self.filter_by_name_unhygienic(ident.name)
+            .filter(|item| item.kind == kind)
+            .find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id))
+    }
+
+    /// Returns the associated item with the given name in the given `Namespace`, if one exists.
+    pub fn find_by_name_and_namespace(
+        &self,
+        tcx: TyCtxt<'_>,
+        ident: Ident,
+        ns: Namespace,
+        parent_def_id: DefId,
+    ) -> Option<&ty::AssocItem> {
+        self.filter_by_name_unhygienic(ident.name)
+            .filter(|item| item.kind.namespace() == ns)
+            .find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id))
+    }
+}
+
 #[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable)]
 pub enum Visibility {
     /// Visible everywhere (including in other crates).
@@ -2731,14 +2814,14 @@
             .for_each(|&body_id| f(self.hir().body_owner_def_id(body_id)));
     }
 
-    pub fn provided_trait_methods(self, id: DefId) -> impl Iterator<Item = &'tcx AssocItem> {
+    pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'tcx AssocItem> {
         self.associated_items(id)
-            .iter()
+            .in_definition_order()
             .filter(|item| item.kind == AssocKind::Method && item.defaultness.has_value())
     }
 
     pub fn trait_relevant_for_never(self, did: DefId) -> bool {
-        self.associated_items(did).iter().any(|item| item.relevant_for_never())
+        self.associated_items(did).in_definition_order().any(|item| item.relevant_for_never())
     }
 
     pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> {
@@ -2998,6 +3081,10 @@
         };
         (ident, scope)
     }
+
+    pub fn is_object_safe(self, key: DefId) -> bool {
+        self.object_safety_violations(key).is_empty()
+    }
 }
 
 #[derive(Clone, HashStable)]
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index b92081f..0fb5f66 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -943,6 +943,7 @@
 
 macro_rules! encoder_methods {
     ($($name:ident($ty:ty);)*) => {
+        #[inline]
         $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
             self.encoder.$name(value)
         })*
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 9cf61eb..c3698f4 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1066,11 +1066,7 @@
     ) -> ProjectionTy<'tcx> {
         let item_def_id = tcx
             .associated_items(trait_ref.def_id)
-            .iter()
-            .find(|item| {
-                item.kind == ty::AssocKind::Type
-                    && tcx.hygienic_eq(item_name, item.ident, trait_ref.def_id)
-            })
+            .find_by_name_and_kind(tcx, item_name, ty::AssocKind::Type, trait_ref.def_id)
             .unwrap()
             .def_id;
 
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index cb43f74..eec6893 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -357,7 +357,7 @@
         let mut dtor_did = None;
         let ty = self.type_of(adt_did);
         self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
-            if let Some(item) = self.associated_items(impl_did).first() {
+            if let Some(item) = self.associated_items(impl_did).in_definition_order().nth(0) {
                 if validate(self, impl_did).is_ok() {
                     dtor_did = Some(item.def_id);
                 }
diff --git a/src/librustc_data_structures/sip128.rs b/src/librustc_data_structures/sip128.rs
index 430f2f4..af0e9f7 100644
--- a/src/librustc_data_structures/sip128.rs
+++ b/src/librustc_data_structures/sip128.rs
@@ -51,17 +51,48 @@
     }};
 }
 
-/// Loads up to 8 bytes from a byte-slice into a little-endian u64.
-#[inline]
-fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
-    assert!(len <= 8 && start + len <= buf.len());
+/// Loads an integer of the desired type from a byte stream, in LE order. Uses
+/// `copy_nonoverlapping` to let the compiler generate the most efficient way
+/// to load it from a possibly unaligned address.
+///
+/// Unsafe because: unchecked indexing at i..i+size_of(int_ty)
+macro_rules! load_int_le {
+    ($buf:expr, $i:expr, $int_ty:ident) => {{
+        debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len());
+        let mut data = 0 as $int_ty;
+        ptr::copy_nonoverlapping(
+            $buf.get_unchecked($i),
+            &mut data as *mut _ as *mut u8,
+            mem::size_of::<$int_ty>(),
+        );
+        data.to_le()
+    }};
+}
 
-    let mut out = 0u64;
-    unsafe {
-        let out_ptr = &mut out as *mut _ as *mut u8;
-        ptr::copy_nonoverlapping(buf.as_ptr().offset(start as isize), out_ptr, len);
+/// Loads a u64 using up to 7 bytes of a byte slice. It looks clumsy but the
+/// `copy_nonoverlapping` calls that occur (via `load_int_le!`) all have fixed
+/// sizes and avoid calling `memcpy`, which is good for speed.
+///
+/// Unsafe because: unchecked indexing at start..start+len
+#[inline]
+unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
+    debug_assert!(len < 8);
+    let mut i = 0; // current byte index (from LSB) in the output u64
+    let mut out = 0;
+    if i + 3 < len {
+        out = load_int_le!(buf, start + i, u32) as u64;
+        i += 4;
     }
-    out.to_le()
+    if i + 1 < len {
+        out |= (load_int_le!(buf, start + i, u16) as u64) << (i * 8);
+        i += 2
+    }
+    if i < len {
+        out |= (*buf.get_unchecked(start + i) as u64) << (i * 8);
+        i += 1;
+    }
+    debug_assert_eq!(i, len);
+    out
 }
 
 impl SipHasher128 {
@@ -243,7 +274,7 @@
 
         if self.ntail != 0 {
             needed = 8 - self.ntail;
-            self.tail |= u8to64_le(msg, 0, cmp::min(length, needed)) << (8 * self.ntail);
+            self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << 8 * self.ntail;
             if length < needed {
                 self.ntail += length;
                 return;
@@ -261,7 +292,7 @@
 
         let mut i = needed;
         while i < len - left {
-            let mi = u8to64_le(msg, i, 8);
+            let mi = unsafe { load_int_le!(msg, i, u64) };
 
             self.state.v3 ^= mi;
             Sip24Rounds::c_rounds(&mut self.state);
@@ -270,7 +301,7 @@
             i += 8;
         }
 
-        self.tail = u8to64_le(msg, i, left);
+        self.tail = unsafe { u8to64_le(msg, i, left) };
         self.ntail = left;
     }
 
diff --git a/src/librustc_data_structures/sorted_map.rs b/src/librustc_data_structures/sorted_map.rs
index 08706aa..8c42b74 100644
--- a/src/librustc_data_structures/sorted_map.rs
+++ b/src/librustc_data_structures/sorted_map.rs
@@ -4,6 +4,10 @@
 use std::mem;
 use std::ops::{Bound, Index, IndexMut, RangeBounds};
 
+mod index_map;
+
+pub use index_map::SortedIndexMultiMap;
+
 /// `SortedMap` is a data structure with similar characteristics as BTreeMap but
 /// slightly different trade-offs: lookup, insertion, and removal are O(log(N))
 /// and elements can be iterated in order cheaply.
diff --git a/src/librustc_data_structures/sorted_map/index_map.rs b/src/librustc_data_structures/sorted_map/index_map.rs
new file mode 100644
index 0000000..b7005cc
--- /dev/null
+++ b/src/librustc_data_structures/sorted_map/index_map.rs
@@ -0,0 +1,218 @@
+//! A variant of `SortedMap` that preserves insertion order.
+
+use std::borrow::Borrow;
+use std::hash::{Hash, Hasher};
+use std::iter::FromIterator;
+
+use crate::stable_hasher::{HashStable, StableHasher};
+use rustc_index::vec::{Idx, IndexVec};
+
+/// An indexed multi-map that preserves insertion order while permitting both `O(log n)` lookup of
+/// an item by key and `O(1)` lookup by index.
+///
+/// This data structure is a hybrid of an [`IndexVec`] and a [`SortedMap`]. Like `IndexVec`,
+/// `SortedIndexMultiMap` assigns a typed index to each item while preserving insertion order.
+/// Like `SortedMap`, `SortedIndexMultiMap` has efficient lookup of items by key. However, this
+/// is accomplished by sorting an array of item indices instead of the items themselves.
+///
+/// Unlike `SortedMap`, this data structure can hold multiple equivalent items at once, so the
+/// `get_by_key` method and its variants return an iterator instead of an `Option`. Equivalent
+/// items will be yielded in insertion order.
+///
+/// Unlike a general-purpose map like `BTreeSet` or `HashSet`, `SortedMap` and
+/// `SortedIndexMultiMap` require `O(n)` time to insert a single item. This is because we may need
+/// to insert into the middle of the sorted array. Users should avoid mutating this data structure
+/// in-place.
+///
+/// [`IndexVec`]: ../../rustc_index/vec/struct.IndexVec.html
+/// [`SortedMap`]: ../sorted_map/struct.SortedMap.html
+#[derive(Clone, Debug)]
+pub struct SortedIndexMultiMap<I: Idx, K, V> {
+    /// The elements of the map in insertion order.
+    items: IndexVec<I, (K, V)>,
+
+    /// Indices of the items in the set, sorted by the item's key.
+    idx_sorted_by_item_key: Vec<I>,
+}
+
+impl<I: Idx, K: Ord, V> SortedIndexMultiMap<I, K, V> {
+    pub fn new() -> Self {
+        SortedIndexMultiMap { items: IndexVec::new(), idx_sorted_by_item_key: Vec::new() }
+    }
+
+    pub fn len(&self) -> usize {
+        self.items.len()
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.items.is_empty()
+    }
+
+    /// Returns an iterator over the items in the map in insertion order.
+    pub fn into_iter(self) -> impl DoubleEndedIterator<Item = (K, V)> {
+        self.items.into_iter()
+    }
+
+    /// Returns an iterator over the items in the map in insertion order along with their indices.
+    pub fn into_iter_enumerated(self) -> impl DoubleEndedIterator<Item = (I, (K, V))> {
+        self.items.into_iter_enumerated()
+    }
+
+    /// Returns an iterator over the items in the map in insertion order.
+    pub fn iter(&self) -> impl '_ + DoubleEndedIterator<Item = (&K, &V)> {
+        self.items.iter().map(|(ref k, ref v)| (k, v))
+    }
+
+    /// Returns an iterator over the items in the map in insertion order along with their indices.
+    pub fn iter_enumerated(&self) -> impl '_ + DoubleEndedIterator<Item = (I, (&K, &V))> {
+        self.items.iter_enumerated().map(|(i, (ref k, ref v))| (i, (k, v)))
+    }
+
+    /// Returns the item in the map with the given index.
+    pub fn get(&self, idx: I) -> Option<&(K, V)> {
+        self.items.get(idx)
+    }
+
+    /// Returns an iterator over the items in the map that are equal to `key`.
+    ///
+    /// If there are multiple items that are equivalent to `key`, they will be yielded in
+    /// insertion order.
+    pub fn get_by_key<Q: 'a>(&'a self, key: &Q) -> impl 'a + Iterator<Item = &'a V>
+    where
+        Q: Ord + ?Sized,
+        K: Borrow<Q>,
+    {
+        self.get_by_key_enumerated(key).map(|(_, v)| v)
+    }
+
+    /// Returns an iterator over the items in the map that are equal to `key` along with their
+    /// indices.
+    ///
+    /// If there are multiple items that are equivalent to `key`, they will be yielded in
+    /// insertion order.
+    pub fn get_by_key_enumerated<Q>(&self, key: &Q) -> impl '_ + Iterator<Item = (I, &V)>
+    where
+        Q: Ord + ?Sized,
+        K: Borrow<Q>,
+    {
+        // FIXME: This should be in the standard library as `equal_range`. See rust-lang/rfcs#2184.
+        match self.binary_search_idx(key) {
+            Err(_) => self.idxs_to_items_enumerated(&[]),
+
+            Ok(idx) => {
+                let start = self.find_lower_bound(key, idx);
+                let end = self.find_upper_bound(key, idx);
+                self.idxs_to_items_enumerated(&self.idx_sorted_by_item_key[start..end])
+            }
+        }
+    }
+
+    fn binary_search_idx<Q>(&self, key: &Q) -> Result<usize, usize>
+    where
+        Q: Ord + ?Sized,
+        K: Borrow<Q>,
+    {
+        self.idx_sorted_by_item_key.binary_search_by(|&idx| self.items[idx].0.borrow().cmp(key))
+    }
+
+    /// Returns the index into the `idx_sorted_by_item_key` array of the first item equal to
+    /// `key`.
+    ///
+    /// `initial` must be an index into that same array for an item that is equal to `key`.
+    fn find_lower_bound<Q>(&self, key: &Q, initial: usize) -> usize
+    where
+        Q: Ord + ?Sized,
+        K: Borrow<Q>,
+    {
+        debug_assert!(self.items[self.idx_sorted_by_item_key[initial]].0.borrow() == key);
+
+        // FIXME: At present, this uses linear search, meaning lookup is only `O(log n)` if duplicate
+        // entries are rare. It would be better to start with a linear search for the common case but
+        // fall back to an exponential search if many duplicates are found. This applies to
+        // `upper_bound` as well.
+        let mut start = initial;
+        while start != 0 && self.items[self.idx_sorted_by_item_key[start - 1]].0.borrow() == key {
+            start -= 1;
+        }
+
+        start
+    }
+
+    /// Returns the index into the `idx_sorted_by_item_key` array of the first item greater than
+    /// `key`, or `self.len()` if no such item exists.
+    ///
+    /// `initial` must be an index into that same array for an item that is equal to `key`.
+    fn find_upper_bound<Q>(&self, key: &Q, initial: usize) -> usize
+    where
+        Q: Ord + ?Sized,
+        K: Borrow<Q>,
+    {
+        debug_assert!(self.items[self.idx_sorted_by_item_key[initial]].0.borrow() == key);
+
+        // See the FIXME for `find_lower_bound`.
+        let mut end = initial + 1;
+        let len = self.items.len();
+        while end < len && self.items[self.idx_sorted_by_item_key[end]].0.borrow() == key {
+            end += 1;
+        }
+
+        end
+    }
+
+    fn idxs_to_items_enumerated(&'a self, idxs: &'a [I]) -> impl 'a + Iterator<Item = (I, &'a V)> {
+        idxs.iter().map(move |&idx| (idx, &self.items[idx].1))
+    }
+}
+
+impl<I: Idx, K: Eq, V: Eq> Eq for SortedIndexMultiMap<I, K, V> {}
+impl<I: Idx, K: PartialEq, V: PartialEq> PartialEq for SortedIndexMultiMap<I, K, V> {
+    fn eq(&self, other: &Self) -> bool {
+        // No need to compare the sorted index. If the items are the same, the index will be too.
+        self.items == other.items
+    }
+}
+
+impl<I: Idx, K, V> Hash for SortedIndexMultiMap<I, K, V>
+where
+    K: Hash,
+    V: Hash,
+{
+    fn hash<H: Hasher>(&self, hasher: &mut H) {
+        self.items.hash(hasher)
+    }
+}
+impl<I: Idx, K, V, C> HashStable<C> for SortedIndexMultiMap<I, K, V>
+where
+    K: HashStable<C>,
+    V: HashStable<C>,
+{
+    fn hash_stable(&self, ctx: &mut C, hasher: &mut StableHasher) {
+        self.items.hash_stable(ctx, hasher)
+    }
+}
+
+impl<I: Idx, K: Ord, V> FromIterator<(K, V)> for SortedIndexMultiMap<I, K, V> {
+    fn from_iter<J>(iter: J) -> Self
+    where
+        J: IntoIterator<Item = (K, V)>,
+    {
+        let items = IndexVec::from_iter(iter);
+        let mut idx_sorted_by_item_key: Vec<_> = items.indices().collect();
+
+        // `sort_by_key` is stable, so insertion order is preserved for duplicate items.
+        idx_sorted_by_item_key.sort_by_key(|&idx| &items[idx].0);
+
+        SortedIndexMultiMap { items, idx_sorted_by_item_key }
+    }
+}
+
+impl<I: Idx, K, V> std::ops::Index<I> for SortedIndexMultiMap<I, K, V> {
+    type Output = V;
+
+    fn index(&self, idx: I) -> &Self::Output {
+        &self.items[idx].1
+    }
+}
+
+#[cfg(tests)]
+mod tests;
diff --git a/src/librustc_data_structures/sorted_map/tests.rs b/src/librustc_data_structures/sorted_map/tests.rs
index 692e1deb..7d91e1f 100644
--- a/src/librustc_data_structures/sorted_map/tests.rs
+++ b/src/librustc_data_structures/sorted_map/tests.rs
@@ -1,4 +1,30 @@
-use super::SortedMap;
+use super::{SortedIndexMultiMap, SortedMap};
+
+#[test]
+fn test_sorted_index_multi_map() {
+    let entries: Vec<_> = vec![(2, 0), (1, 0), (2, 1), (3, 0), (2, 2)];
+    let set: SortedIndexMultiMap<usize, _, _> = entries.iter().copied().collect();
+
+    // Insertion order is preserved.
+    assert!(entries.iter().map(|(ref k, ref v)| (k, v)).eq(set.iter()));
+
+    // Indexing
+    for (i, expect) in entries.iter().enumerate() {
+        assert_eq!(set[i], expect.1);
+    }
+
+    // `get_by_key` works.
+    assert_eq!(set.get_by_key(&3).copied().collect::<Vec<_>>(), vec![0]);
+    assert!(set.get_by_key(&4).next().is_none());
+
+    // `get_by_key` returns items in insertion order.
+    let twos: Vec<_> = set.get_by_key_enumerated(&2).collect();
+    let idxs: Vec<usize> = twos.iter().map(|(i, _)| *i).collect();
+    let values: Vec<usize> = twos.iter().map(|(_, &v)| v).collect();
+
+    assert_eq!(idxs, vec![0, 2, 4]);
+    assert_eq!(values, vec![0, 1, 2]);
+}
 
 #[test]
 fn test_insert_and_iter() {
diff --git a/src/librustc_error_codes/error_codes/E0317.md b/src/librustc_error_codes/error_codes/E0317.md
index e31a2b5..230911c 100644
--- a/src/librustc_error_codes/error_codes/E0317.md
+++ b/src/librustc_error_codes/error_codes/E0317.md
@@ -1,14 +1,30 @@
-This error occurs when an `if` expression without an `else` block is used in a
-context where a type other than `()` is expected, for example a `let`
-expression:
+An `if` expression is missing an `else` block.
+
+Erroneous code example:
 
 ```compile_fail,E0317
-fn main() {
-    let x = 5;
-    let a = if x == 5 { 1 };
-}
+let x = 5;
+let a = if x == 5 {
+    1
+};
 ```
 
+This error occurs when an `if` expression without an `else` block is used in a
+context where a type other than `()` is expected. In the previous code example,
+the `let` expression was expecting a value but since there was no `else`, no
+value was returned.
+
 An `if` expression without an `else` block has the type `()`, so this is a type
 error. To resolve it, add an `else` block having the same type as the `if`
 block.
+
+So to fix the previous code example:
+
+```
+let x = 5;
+let a = if x == 5 {
+    1
+} else {
+    2
+};
+```
diff --git a/src/librustc_error_codes/error_codes/E0321.md b/src/librustc_error_codes/error_codes/E0321.md
index 49cec94..bfcdabf 100644
--- a/src/librustc_error_codes/error_codes/E0321.md
+++ b/src/librustc_error_codes/error_codes/E0321.md
@@ -1,5 +1,7 @@
 A cross-crate opt-out trait was implemented on something which wasn't a struct
-or enum type. Erroneous code example:
+or enum type.
+
+Erroneous code example:
 
 ```compile_fail,E0321
 #![feature(optin_builtin_traits)]
diff --git a/src/librustc_error_codes/error_codes/E0322.md b/src/librustc_error_codes/error_codes/E0322.md
index d2ee426..ccef868 100644
--- a/src/librustc_error_codes/error_codes/E0322.md
+++ b/src/librustc_error_codes/error_codes/E0322.md
@@ -1,3 +1,13 @@
+The `Sized` trait was implemented explicitly.
+
+Erroneous code example:
+
+```compile_fail,E0322
+struct Foo;
+
+impl Sized for Foo {} // error!
+```
+
 The `Sized` trait is a special trait built-in to the compiler for types with a
 constant size known at compile-time. This trait is automatically implemented
 for types as needed by the compiler, and it is currently disallowed to
diff --git a/src/librustc_error_codes/error_codes/E0323.md b/src/librustc_error_codes/error_codes/E0323.md
index 6d34c35..0bf42d1 100644
--- a/src/librustc_error_codes/error_codes/E0323.md
+++ b/src/librustc_error_codes/error_codes/E0323.md
@@ -1,4 +1,5 @@
 An associated const was implemented when another trait item was expected.
+
 Erroneous code example:
 
 ```compile_fail,E0323
diff --git a/src/librustc_error_codes/error_codes/E0324.md b/src/librustc_error_codes/error_codes/E0324.md
index b8c9e59..1442cb7 100644
--- a/src/librustc_error_codes/error_codes/E0324.md
+++ b/src/librustc_error_codes/error_codes/E0324.md
@@ -1,5 +1,6 @@
-A method was implemented when another trait item was expected. Erroneous
-code example:
+A method was implemented when another trait item was expected.
+
+Erroneous code example:
 
 ```compile_fail,E0324
 struct Bar;
diff --git a/src/librustc_error_codes/error_codes/E0325.md b/src/librustc_error_codes/error_codes/E0325.md
index f685b92..656fd1e 100644
--- a/src/librustc_error_codes/error_codes/E0325.md
+++ b/src/librustc_error_codes/error_codes/E0325.md
@@ -1,4 +1,5 @@
 An associated type was implemented when another trait item was expected.
+
 Erroneous code example:
 
 ```compile_fail,E0325
diff --git a/src/librustc_error_codes/error_codes/E0326.md b/src/librustc_error_codes/error_codes/E0326.md
index 0702d00..3d35781 100644
--- a/src/librustc_error_codes/error_codes/E0326.md
+++ b/src/librustc_error_codes/error_codes/E0326.md
@@ -1,7 +1,6 @@
-The types of any associated constants in a trait implementation must match the
-types in the trait definition. This error indicates that there was a mismatch.
+An implementation of a trait doesn't match the type contraint.
 
-Here's an example of this error:
+Erroneous code example:
 
 ```compile_fail,E0326
 trait Foo {
@@ -14,3 +13,6 @@
     const BAR: u32 = 5; // error, expected bool, found u32
 }
 ```
+
+The types of any associated constants in a trait implementation must match the
+types in the trait definition.
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 56a8e2c..8496a6e 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -1,4 +1,4 @@
-use crate::def::{DefKind, Res};
+use crate::def::{DefKind, Namespace, Res};
 use crate::def_id::DefId;
 crate use crate::hir_id::HirId;
 use crate::itemlikevisit;
@@ -1897,6 +1897,15 @@
     OpaqueTy(GenericBounds<'hir>),
 }
 
+impl ImplItemKind<'_> {
+    pub fn namespace(&self) -> Namespace {
+        match self {
+            ImplItemKind::OpaqueTy(..) | ImplItemKind::TyAlias(..) => Namespace::TypeNS,
+            ImplItemKind::Const(..) | ImplItemKind::Method(..) => Namespace::ValueNS,
+        }
+    }
+}
+
 // The name of the associated type for `Fn` return types.
 pub const FN_OUTPUT_NAME: Symbol = sym::Output;
 
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index c5e7486..1fa57f1 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -78,7 +78,7 @@
 const BASE_TRAIT_DEF: &[&str] = &[
     label_strs::associated_item_def_ids,
     label_strs::generics_of,
-    label_strs::is_object_safe,
+    label_strs::object_safety_violations,
     label_strs::predicates_of,
     label_strs::specialization_graph_of,
     label_strs::trait_def,
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs
index 77119b8..359b417 100644
--- a/src/librustc_infer/infer/error_reporting/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/mod.rs
@@ -52,7 +52,6 @@
 use crate::infer::opaque_types;
 use crate::infer::{self, SuppressRegionErrors};
 use crate::traits::error_reporting::report_object_safety_error;
-use crate::traits::object_safety_violations;
 use crate::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
 };
@@ -1618,7 +1617,7 @@
         let failure_code = trace.cause.as_failure_code(terr);
         let mut diag = match failure_code {
             FailureCode::Error0038(did) => {
-                let violations = object_safety_violations(self.tcx, did);
+                let violations = self.tcx.object_safety_violations(did);
                 report_object_safety_error(self.tcx, span, did, violations)
             }
             FailureCode::Error0317(failure_str) => {
@@ -1781,14 +1780,7 @@
             bound_kind: GenericKind<'tcx>,
             sub: S,
         ) {
-            let consider = format!(
-                "consider adding an explicit lifetime bound {}",
-                if type_param_span.map(|(_, _, is_impl_trait)| is_impl_trait).unwrap_or(false) {
-                    format!(" `{}` to `{}`...", sub, bound_kind)
-                } else {
-                    format!("`{}: {}`...", bound_kind, sub)
-                },
-            );
+            let msg = "consider adding an explicit lifetime bound";
             if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span {
                 let suggestion = if is_impl_trait {
                     format!("{} + {}", bound_kind, sub)
@@ -1796,13 +1788,22 @@
                     let tail = if has_lifetimes { " + " } else { "" };
                     format!("{}: {}{}", bound_kind, sub, tail)
                 };
-                err.span_suggestion_short(
+                err.span_suggestion(
                     sp,
-                    &consider,
+                    &format!("{}...", msg),
                     suggestion,
                     Applicability::MaybeIncorrect, // Issue #41966
                 );
             } else {
+                let consider = format!(
+                    "{} {}...",
+                    msg,
+                    if type_param_span.map(|(_, _, is_impl_trait)| is_impl_trait).unwrap_or(false) {
+                        format!(" `{}` to `{}`", sub, bound_kind)
+                    } else {
+                        format!("`{}: {}`", bound_kind, sub)
+                    },
+                );
                 err.help(&consider);
             }
         }
diff --git a/src/librustc_infer/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs
index 4bc8ffc..2fc7c17 100644
--- a/src/librustc_infer/traits/error_reporting/mod.rs
+++ b/src/librustc_infer/traits/error_reporting/mod.rs
@@ -12,7 +12,6 @@
 use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::{self, InferCtxt, TyCtxtInferExt};
-use crate::traits::object_safety_violations;
 use rustc::mir::interpret::ErrorHandled;
 use rustc::session::DiagnosticMessageId;
 use rustc::ty::error::ExpectedFound;
@@ -748,7 +747,7 @@
                     }
 
                     ty::Predicate::ObjectSafe(trait_def_id) => {
-                        let violations = object_safety_violations(self.tcx, trait_def_id);
+                        let violations = self.tcx.object_safety_violations(trait_def_id);
                         report_object_safety_error(self.tcx, span, trait_def_id, violations)
                     }
 
@@ -912,7 +911,7 @@
             }
 
             TraitNotObjectSafe(did) => {
-                let violations = object_safety_violations(self.tcx, did);
+                let violations = self.tcx.object_safety_violations(did);
                 report_object_safety_error(self.tcx, span, did, violations)
             }
 
diff --git a/src/librustc_infer/traits/error_reporting/suggestions.rs b/src/librustc_infer/traits/error_reporting/suggestions.rs
index 50ae7c4..f1206dd 100644
--- a/src/librustc_infer/traits/error_reporting/suggestions.rs
+++ b/src/librustc_infer/traits/error_reporting/suggestions.rs
@@ -5,7 +5,6 @@
 
 use crate::infer::InferCtxt;
 use crate::traits::error_reporting::suggest_constraining_type_param;
-use crate::traits::object_safety::object_safety_violations;
 
 use rustc::ty::TypeckTables;
 use rustc::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
@@ -587,7 +586,7 @@
                 // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
                 predicates
                     .principal_def_id()
-                    .map_or(true, |def_id| object_safety_violations(self.tcx, def_id).is_empty())
+                    .map_or(true, |def_id| self.tcx.object_safety_violations(def_id).is_empty())
             }
             // We only want to suggest `impl Trait` to `dyn Trait`s.
             // For example, `fn foo() -> str` needs to be filtered out.
diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs
index 06c6d65..fcaab09 100644
--- a/src/librustc_infer/traits/mod.rs
+++ b/src/librustc_infer/traits/mod.rs
@@ -47,7 +47,6 @@
 pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
 pub use self::object_safety::astconv_object_safety_violations;
 pub use self::object_safety::is_vtable_safe_method;
-pub use self::object_safety::object_safety_violations;
 pub use self::object_safety::MethodViolationCode;
 pub use self::object_safety::ObjectSafetyViolation;
 pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
@@ -537,7 +536,7 @@
     tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| {
         let trait_methods = tcx
             .associated_items(trait_ref.def_id())
-            .iter()
+            .in_definition_order()
             .filter(|item| item.kind == ty::AssocKind::Method);
 
         // Now list each method's DefId and InternalSubsts (for within its trait).
@@ -636,8 +635,8 @@
 }
 
 pub fn provide(providers: &mut ty::query::Providers<'_>) {
+    object_safety::provide(providers);
     *providers = ty::query::Providers {
-        is_object_safe: object_safety::is_object_safe_provider,
         specialization_graph_of: specialize::specialization_graph_provider,
         specializes: specialize::specializes,
         codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
diff --git a/src/librustc_infer/traits/object_safety.rs b/src/librustc_infer/traits/object_safety.rs
index d36d66e..f5bab7c 100644
--- a/src/librustc_infer/traits/object_safety.rs
+++ b/src/librustc_infer/traits/object_safety.rs
@@ -19,142 +19,12 @@
 use rustc_hir::def_id::DefId;
 use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
 use rustc_span::symbol::Symbol;
-use rustc_span::{Span, DUMMY_SP};
-use smallvec::{smallvec, SmallVec};
-use syntax::ast;
+use rustc_span::Span;
+use smallvec::SmallVec;
 
-use std::borrow::Cow;
-use std::iter::{self};
+use std::iter;
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub enum ObjectSafetyViolation {
-    /// `Self: Sized` declared on the trait.
-    SizedSelf(SmallVec<[Span; 1]>),
-
-    /// Supertrait reference references `Self` an in illegal location
-    /// (e.g., `trait Foo : Bar<Self>`).
-    SupertraitSelf(SmallVec<[Span; 1]>),
-
-    /// Method has something illegal.
-    Method(ast::Name, MethodViolationCode, Span),
-
-    /// Associated const.
-    AssocConst(ast::Name, Span),
-}
-
-impl ObjectSafetyViolation {
-    pub fn error_msg(&self) -> Cow<'static, str> {
-        match *self {
-            ObjectSafetyViolation::SizedSelf(_) => "it requires `Self: Sized`".into(),
-            ObjectSafetyViolation::SupertraitSelf(ref spans) => {
-                if spans.iter().any(|sp| *sp != DUMMY_SP) {
-                    "it uses `Self` as a type parameter in this".into()
-                } else {
-                    "it cannot use `Self` as a type parameter in a supertrait or `where`-clause"
-                        .into()
-                }
-            }
-            ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => {
-                format!("associated function `{}` has no `self` parameter", name).into()
-            }
-            ObjectSafetyViolation::Method(
-                name,
-                MethodViolationCode::ReferencesSelfInput(_),
-                DUMMY_SP,
-            ) => format!("method `{}` references the `Self` type in its parameters", name).into(),
-            ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfInput(_), _) => {
-                format!("method `{}` references the `Self` type in this parameter", name).into()
-            }
-            ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfOutput, _) => {
-                format!("method `{}` references the `Self` type in its return type", name).into()
-            }
-            ObjectSafetyViolation::Method(
-                name,
-                MethodViolationCode::WhereClauseReferencesSelf,
-                _,
-            ) => {
-                format!("method `{}` references the `Self` type in its `where` clause", name).into()
-            }
-            ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => {
-                format!("method `{}` has generic type parameters", name).into()
-            }
-            ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => {
-                format!("method `{}`'s `self` parameter cannot be dispatched on", name).into()
-            }
-            ObjectSafetyViolation::AssocConst(name, DUMMY_SP) => {
-                format!("it contains associated `const` `{}`", name).into()
-            }
-            ObjectSafetyViolation::AssocConst(..) => "it contains this associated `const`".into(),
-        }
-    }
-
-    pub fn solution(&self) -> Option<(String, Option<(String, Span)>)> {
-        Some(match *self {
-            ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) => {
-                return None;
-            }
-            ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(sugg), _) => (
-                format!(
-                    "consider turning `{}` into a method by giving it a `&self` argument or \
-                     constraining it so it does not apply to trait objects",
-                    name
-                ),
-                sugg.map(|(sugg, sp)| (sugg.to_string(), sp)),
-            ),
-            ObjectSafetyViolation::Method(
-                name,
-                MethodViolationCode::UndispatchableReceiver,
-                span,
-            ) => (
-                format!("consider changing method `{}`'s `self` parameter to be `&self`", name)
-                    .into(),
-                Some(("&Self".to_string(), span)),
-            ),
-            ObjectSafetyViolation::AssocConst(name, _)
-            | ObjectSafetyViolation::Method(name, ..) => {
-                (format!("consider moving `{}` to another trait", name), None)
-            }
-        })
-    }
-
-    pub fn spans(&self) -> SmallVec<[Span; 1]> {
-        // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
-        // diagnostics use a `note` instead of a `span_label`.
-        match self {
-            ObjectSafetyViolation::SupertraitSelf(spans)
-            | ObjectSafetyViolation::SizedSelf(spans) => spans.clone(),
-            ObjectSafetyViolation::AssocConst(_, span)
-            | ObjectSafetyViolation::Method(_, _, span)
-                if *span != DUMMY_SP =>
-            {
-                smallvec![*span]
-            }
-            _ => smallvec![],
-        }
-    }
-}
-
-/// Reasons a method might not be object-safe.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub enum MethodViolationCode {
-    /// e.g., `fn foo()`
-    StaticMethod(Option<(&'static str, Span)>),
-
-    /// e.g., `fn foo(&self, x: Self)`
-    ReferencesSelfInput(usize),
-
-    /// e.g., `fn foo(&self) -> Self`
-    ReferencesSelfOutput,
-
-    /// e.g., `fn foo(&self) where Self: Clone`
-    WhereClauseReferencesSelf,
-
-    /// e.g., `fn foo<A>()`
-    Generic,
-
-    /// the method's receiver (`self` argument) can't be dispatched on
-    UndispatchableReceiver,
-}
+pub use crate::traits::{MethodViolationCode, ObjectSafetyViolation};
 
 /// Returns the object safety violations that affect
 /// astconv -- currently, `Self` in supertraits. This is needed
@@ -176,10 +46,7 @@
     violations
 }
 
-pub fn object_safety_violations(
-    tcx: TyCtxt<'_>,
-    trait_def_id: DefId,
-) -> Vec<ObjectSafetyViolation> {
+fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> Vec<ObjectSafetyViolation> {
     debug_assert!(tcx.generics_of(trait_def_id).has_self);
     debug!("object_safety_violations: {:?}", trait_def_id);
 
@@ -213,7 +80,7 @@
     // Check methods for violations.
     let mut violations: Vec<_> = tcx
         .associated_items(trait_def_id)
-        .iter()
+        .in_definition_order()
         .filter(|item| item.kind == ty::AssocKind::Method)
         .filter_map(|item| {
             object_safety_violation_for_method(tcx, trait_def_id, &item)
@@ -289,7 +156,7 @@
 
     violations.extend(
         tcx.associated_items(trait_def_id)
-            .iter()
+            .in_definition_order()
             .filter(|item| item.kind == ty::AssocKind::Const)
             .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)),
     );
@@ -646,7 +513,7 @@
     let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref))
         .flat_map(|super_trait_ref| {
             tcx.associated_items(super_trait_ref.def_id())
-                .iter()
+                .in_definition_order()
                 .map(move |item| (super_trait_ref, item))
         })
         .filter(|(_, item)| item.kind == ty::AssocKind::Type)
@@ -905,6 +772,6 @@
     error
 }
 
-pub(super) fn is_object_safe_provider(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
-    object_safety_violations(tcx, trait_def_id).is_empty()
+pub fn provide(providers: &mut ty::query::Providers<'_>) {
+    *providers = ty::query::Providers { object_safety_violations, ..*providers };
 }
diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs
index c1612a3..1dca01b 100644
--- a/src/librustc_infer/traits/util.rs
+++ b/src/librustc_infer/traits/util.rs
@@ -586,7 +586,7 @@
     let mut entries = 0;
     // Count number of methods and add them to the total offset.
     // Skip over associated types and constants.
-    for trait_item in tcx.associated_items(trait_ref.def_id()) {
+    for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() {
         if trait_item.kind == ty::AssocKind::Method {
             entries += 1;
         }
@@ -606,7 +606,7 @@
     // add them to the total offset.
     // Skip over associated types and constants.
     let mut entries = object.vtable_base;
-    for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()) {
+    for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() {
         if trait_item.def_id == method_def_id {
             // The item with the ID we were given really ought to be a method.
             assert_eq!(trait_item.kind, ty::AssocKind::Method);
diff --git a/src/librustc_infer/traits/wf.rs b/src/librustc_infer/traits/wf.rs
index 89a271d..993eb41 100644
--- a/src/librustc_infer/traits/wf.rs
+++ b/src/librustc_infer/traits/wf.rs
@@ -318,7 +318,10 @@
             };
 
         if let Elaborate::All = elaborate {
-            let trait_assoc_items = tcx.associated_items(trait_ref.def_id);
+            // FIXME: Make `extend_cause_with_original_assoc_item_obligation` take an iterator
+            // instead of a slice.
+            let trait_assoc_items: Vec<_> =
+                tcx.associated_items(trait_ref.def_id).in_definition_order().copied().collect();
 
             let predicates = obligations.iter().map(|obligation| obligation.predicate).collect();
             let implied_obligations = traits::elaborate_predicates(tcx, predicates);
@@ -327,7 +330,7 @@
                 extend_cause_with_original_assoc_item_obligation(
                     &mut cause,
                     &pred,
-                    trait_assoc_items,
+                    &*trait_assoc_items,
                 );
                 traits::Obligation::new(cause, param_env, pred)
             });
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 2204e10..0e7625d 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -305,6 +305,7 @@
     store.register_renamed("unstable_name_collision", "unstable_name_collisions");
     store.register_renamed("unused_doc_comment", "unused_doc_comments");
     store.register_renamed("async_idents", "keyword_idents");
+    store.register_renamed("exceeding_bitshifts", "arithmetic_overflow");
     store.register_removed("unknown_features", "replaced by an error");
     store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate");
     store.register_removed("negate_unsigned", "cast a signed value instead");
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index c924862..f4e1bce 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -313,6 +313,7 @@
                 );
             }
         } else {
+            let tcx = self.tcx();
             if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.literal.val {
                 if let Some(promoted) = promoted {
                     let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
@@ -362,10 +363,23 @@
                         );
                     }
                 }
-            }
-            if let ty::FnDef(def_id, substs) = constant.literal.ty.kind {
-                let tcx = self.tcx();
+            } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
+                let unnormalized_ty = tcx.type_of(static_def_id);
+                let locations = location.to_locations();
+                let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
+                let literal_ty = constant.literal.ty.builtin_deref(true).unwrap().ty;
 
+                if let Err(terr) = self.cx.eq_types(
+                    normalized_ty,
+                    literal_ty,
+                    locations,
+                    ConstraintCategory::Boring,
+                ) {
+                    span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
+                }
+            }
+
+            if let ty::FnDef(def_id, substs) = constant.literal.ty.kind {
                 let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
                 self.cx.normalize_and_prove_instantiated_predicates(
                     instantiated_predicates,
@@ -470,33 +484,6 @@
 
         let mut place_ty = PlaceTy::from_ty(self.body.local_decls[place.local].ty);
 
-        if place.projection.is_empty() {
-            if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
-                let tcx = self.tcx();
-                let trait_ref = ty::TraitRef {
-                    def_id: tcx.lang_items().copy_trait().unwrap(),
-                    substs: tcx.mk_substs_trait(place_ty.ty, &[]),
-                };
-
-                // To have a `Copy` operand, the type `T` of the
-                // value must be `Copy`. Note that we prove that `T: Copy`,
-                // rather than using the `is_copy_modulo_regions`
-                // test. This is important because
-                // `is_copy_modulo_regions` ignores the resulting region
-                // obligations and assumes they pass. This can result in
-                // bounds from `Copy` impls being unsoundly ignored (e.g.,
-                // #29149). Note that we decide to use `Copy` before knowing
-                // whether the bounds fully apply: in effect, the rule is
-                // that if a value of some type could implement `Copy`, then
-                // it must.
-                self.cx.prove_trait_ref(
-                    trait_ref,
-                    location.to_locations(),
-                    ConstraintCategory::CopyBound,
-                );
-            }
-        }
-
         for elem in place.projection.iter() {
             if place_ty.variant_index.is_none() {
                 if place_ty.ty.references_error() {
@@ -507,6 +494,31 @@
             place_ty = self.sanitize_projection(place_ty, elem, place, location)
         }
 
+        if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
+            let tcx = self.tcx();
+            let trait_ref = ty::TraitRef {
+                def_id: tcx.lang_items().copy_trait().unwrap(),
+                substs: tcx.mk_substs_trait(place_ty.ty, &[]),
+            };
+
+            // To have a `Copy` operand, the type `T` of the
+            // value must be `Copy`. Note that we prove that `T: Copy`,
+            // rather than using the `is_copy_modulo_regions`
+            // test. This is important because
+            // `is_copy_modulo_regions` ignores the resulting region
+            // obligations and assumes they pass. This can result in
+            // bounds from `Copy` impls being unsoundly ignored (e.g.,
+            // #29149). Note that we decide to use `Copy` before knowing
+            // whether the bounds fully apply: in effect, the rule is
+            // that if a value of some type could implement `Copy`, then
+            // it must.
+            self.cx.prove_trait_ref(
+                trait_ref,
+                location.to_locations(),
+                ConstraintCategory::CopyBound,
+            );
+        }
+
         place_ty
     }
 
diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs
index 7508d71..659b668 100644
--- a/src/librustc_mir/dataflow/impls/storage_liveness.rs
+++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs
@@ -118,18 +118,25 @@
         self.borrowed_locals.borrow().analysis().statement_effect(sets, stmt, loc);
 
         // If a place is assigned to in a statement, it needs storage for that statement.
-        match stmt.kind {
-            StatementKind::StorageDead(l) => sets.kill(l),
-            StatementKind::Assign(box (ref place, _))
-            | StatementKind::SetDiscriminant { box ref place, .. } => {
+        match &stmt.kind {
+            StatementKind::StorageDead(l) => sets.kill(*l),
+            StatementKind::Assign(box (place, _))
+            | StatementKind::SetDiscriminant { box place, .. } => {
                 sets.gen(place.local);
             }
-            StatementKind::InlineAsm(box InlineAsm { ref outputs, .. }) => {
+            StatementKind::InlineAsm(box InlineAsm { outputs, .. }) => {
                 for place in &**outputs {
                     sets.gen(place.local);
                 }
             }
-            _ => (),
+
+            // Nothing to do for these. Match exhaustively so this fails to compile when new
+            // variants are added.
+            StatementKind::AscribeUserType(..)
+            | StatementKind::FakeRead(..)
+            | StatementKind::Nop
+            | StatementKind::Retag(..)
+            | StatementKind::StorageLive(..) => {}
         }
     }
 
@@ -145,23 +152,58 @@
         // If a place is borrowed in a terminator, it needs storage for that terminator.
         self.borrowed_locals.borrow().analysis().terminator_effect(sets, terminator, loc);
 
-        if let TerminatorKind::Call { destination: Some((place, _)), .. } = terminator.kind {
-            sets.gen(place.local);
+        match &terminator.kind {
+            TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. }
+            | TerminatorKind::Yield { resume_arg: Place { local, .. }, .. } => {
+                sets.gen(*local);
+            }
+
+            // Nothing to do for these. Match exhaustively so this fails to compile when new
+            // variants are added.
+            TerminatorKind::Call { destination: None, .. }
+            | TerminatorKind::Abort
+            | TerminatorKind::Assert { .. }
+            | TerminatorKind::Drop { .. }
+            | TerminatorKind::DropAndReplace { .. }
+            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseUnwind { .. }
+            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::Goto { .. }
+            | TerminatorKind::Resume
+            | TerminatorKind::Return
+            | TerminatorKind::SwitchInt { .. }
+            | TerminatorKind::Unreachable => {}
         }
     }
 
     fn terminator_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
-        // For call terminators the destination requires storage for the call
-        // and after the call returns successfully, but not after a panic.
-        // Since `propagate_call_unwind` doesn't exist, we have to kill the
-        // destination here, and then gen it again in `propagate_call_return`.
-        if let TerminatorKind::Call { destination: Some((ref place, _)), .. } =
-            self.body[loc.block].terminator().kind
-        {
-            if let Some(local) = place.as_local() {
-                sets.kill(local);
+        match &self.body[loc.block].terminator().kind {
+            // For call terminators the destination requires storage for the call
+            // and after the call returns successfully, but not after a panic.
+            // Since `propagate_call_unwind` doesn't exist, we have to kill the
+            // destination here, and then gen it again in `propagate_call_return`.
+            TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. } => {
+                sets.kill(*local);
             }
+
+            // Nothing to do for these. Match exhaustively so this fails to compile when new
+            // variants are added.
+            TerminatorKind::Call { destination: None, .. }
+            | TerminatorKind::Yield { .. }
+            | TerminatorKind::Abort
+            | TerminatorKind::Assert { .. }
+            | TerminatorKind::Drop { .. }
+            | TerminatorKind::DropAndReplace { .. }
+            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseUnwind { .. }
+            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::Goto { .. }
+            | TerminatorKind::Resume
+            | TerminatorKind::Return
+            | TerminatorKind::SwitchInt { .. }
+            | TerminatorKind::Unreachable => {}
         }
+
         self.check_for_move(sets, loc);
     }
 
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 6f8caca..57aa5de 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -381,9 +381,9 @@
             }
 
             TerminatorKind::Yield { ref value, resume_arg: ref place, .. } => {
+                self.gather_operand(value);
                 self.create_move_path(place);
                 self.gather_init(place.as_ref(), InitKind::Deep);
-                self.gather_operand(value);
             }
 
             TerminatorKind::Drop { ref location, target: _, unwind: _ } => {
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 0bcdf9a..1df389d 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -560,7 +560,7 @@
 
         // # Function pointers
         // (both global from `alloc_map` and local from `extra_fn_ptr_map`)
-        if let Ok(_) = self.get_fn_alloc(id) {
+        if let Some(_) = self.get_fn_alloc(id) {
             return if let AllocCheck::Dereferenceable = liveness {
                 // The caller requested no function pointers.
                 throw_unsup!(DerefFunctionPointer)
@@ -602,14 +602,14 @@
         }
     }
 
-    fn get_fn_alloc(&self, id: AllocId) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
+    fn get_fn_alloc(&self, id: AllocId) -> Option<FnVal<'tcx, M::ExtraFnVal>> {
         trace!("reading fn ptr: {}", id);
         if let Some(extra) = self.extra_fn_ptr_map.get(&id) {
-            Ok(FnVal::Other(*extra))
+            Some(FnVal::Other(*extra))
         } else {
             match self.tcx.alloc_map.lock().get(id) {
-                Some(GlobalAlloc::Function(instance)) => Ok(FnVal::Instance(instance)),
-                _ => throw_unsup!(ExecuteMemory),
+                Some(GlobalAlloc::Function(instance)) => Some(FnVal::Instance(instance)),
+                _ => None,
             }
         }
     }
@@ -622,7 +622,7 @@
         if ptr.offset.bytes() != 0 {
             throw_unsup!(InvalidFunctionPointer)
         }
-        self.get_fn_alloc(ptr.alloc_id)
+        self.get_fn_alloc(ptr.alloc_id).ok_or_else(|| err_unsup!(ExecuteMemory).into())
     }
 
     pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> {
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index bfd30ff..1f7db28 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -68,7 +68,7 @@
             let fn_mut = tcx.lang_items().fn_mut_trait().unwrap();
             let call_mut = tcx
                 .associated_items(fn_mut)
-                .iter()
+                .in_definition_order()
                 .find(|it| it.kind == ty::AssocKind::Method)
                 .unwrap()
                 .def_id;
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 91d134f..9e05133 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -4,7 +4,8 @@
 use std::borrow::Cow;
 use std::cell::Cell;
 
-use rustc::mir::interpret::{InterpError, InterpResult, Scalar};
+use rustc::lint;
+use rustc::mir::interpret::{InterpResult, Scalar};
 use rustc::mir::visit::{
     MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
 };
@@ -292,7 +293,6 @@
 struct ConstPropagator<'mir, 'tcx> {
     ecx: InterpCx<'mir, 'tcx, ConstPropMachine>,
     tcx: TyCtxt<'tcx>,
-    source: MirSource<'tcx>,
     can_const_prop: IndexVec<Local, ConstPropMode>,
     param_env: ParamEnv<'tcx>,
     // FIXME(eddyb) avoid cloning these two fields more than once,
@@ -372,7 +372,6 @@
         ConstPropagator {
             ecx,
             tcx,
-            source,
             param_env,
             can_const_prop,
             // FIXME(eddyb) avoid cloning these two fields more than once,
@@ -501,19 +500,20 @@
         }
     }
 
-    fn report_panic_as_lint(&self, source_info: SourceInfo, panic: AssertKind<u64>) -> Option<()> {
-        // Somewhat convoluted way to re-use the CTFE error reporting code.
+    fn report_assert_as_lint(
+        &self,
+        lint: &'static lint::Lint,
+        source_info: SourceInfo,
+        message: &'static str,
+        panic: AssertKind<u64>,
+    ) -> Option<()> {
         let lint_root = self.lint_root(source_info)?;
-        let error = InterpError::MachineStop(Box::new(format!("{:?}", panic)));
-        let mut diagnostic = error_to_const_error(&self.ecx, error.into());
-        diagnostic.span = source_info.span; // fix the span
-        diagnostic.report_as_lint(
-            self.tcx.at(source_info.span),
-            "this expression will panic at runtime",
-            lint_root,
-            None,
-        );
-        None
+        self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
+            let mut err = lint.build(message);
+            err.span_label(source_info.span, format!("{:?}", panic));
+            err.emit()
+        });
+        return None;
     }
 
     fn check_unary_op(
@@ -530,7 +530,12 @@
             // `AssertKind` only has an `OverflowNeg` variant, so make sure that is
             // appropriate to use.
             assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow");
-            self.report_panic_as_lint(source_info, AssertKind::OverflowNeg)?;
+            self.report_assert_as_lint(
+                lint::builtin::ARITHMETIC_OVERFLOW,
+                source_info,
+                "this arithmetic operation will overflow",
+                AssertKind::OverflowNeg,
+            )?;
         }
 
         Some(())
@@ -542,27 +547,24 @@
         left: &Operand<'tcx>,
         right: &Operand<'tcx>,
         source_info: SourceInfo,
-        place_layout: TyLayout<'tcx>,
     ) -> Option<()> {
         let r =
             self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?))?;
         // Check for exceeding shifts *even if* we cannot evaluate the LHS.
         if op == BinOp::Shr || op == BinOp::Shl {
-            let left_bits = place_layout.size.bits();
+            // We need the type of the LHS. We cannot use `place_layout` as that is the type
+            // of the result, which for checked binops is not the same!
+            let left_ty = left.ty(&self.local_decls, self.tcx);
+            let left_size_bits = self.ecx.layout_of(left_ty).ok()?.size.bits();
             let right_size = r.layout.size;
             let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
-            if r_bits.map_or(false, |b| b >= left_bits as u128) {
-                let lint_root = self.lint_root(source_info)?;
-                self.tcx.struct_span_lint_hir(
-                    ::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
-                    lint_root,
-                    source_info.span,
-                    |lint| {
-                        let dir = if op == BinOp::Shr { "right" } else { "left" };
-                        lint.build(&format!("attempt to shift {} with overflow", dir)).emit()
-                    },
-                );
-                return None;
+            if r_bits.map_or(false, |b| b >= left_size_bits as u128) {
+                self.report_assert_as_lint(
+                    lint::builtin::ARITHMETIC_OVERFLOW,
+                    source_info,
+                    "this arithmetic operation will overflow",
+                    AssertKind::Overflow(op),
+                )?;
             }
         }
 
@@ -572,7 +574,12 @@
             let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?;
             Ok(overflow)
         })? {
-            self.report_panic_as_lint(source_info, AssertKind::Overflow(op))?;
+            self.report_assert_as_lint(
+                lint::builtin::ARITHMETIC_OVERFLOW,
+                source_info,
+                "this arithmetic operation will overflow",
+                AssertKind::Overflow(op),
+            )?;
         }
 
         Some(())
@@ -595,8 +602,6 @@
             return None;
         }
 
-        let overflow_check = self.tcx.sess.overflow_checks();
-
         // Perform any special handling for specific Rvalue types.
         // Generally, checks here fall into one of two categories:
         //   1. Additional checking to provide useful lints to the user
@@ -606,20 +611,25 @@
         //        - In this case, we'll return `None` from this function to stop evaluation.
         match rvalue {
             // Additional checking: give lints to the user if an overflow would occur.
-            // If `overflow_check` is set, running const-prop on the `Assert` terminators
-            // will already generate the appropriate messages.
-            Rvalue::UnaryOp(op, arg) if !overflow_check => {
+            // We do this here and not in the `Assert` terminator as that terminator is
+            // only sometimes emitted (overflow checks can be disabled), but we want to always
+            // lint.
+            Rvalue::UnaryOp(op, arg) => {
                 trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg);
                 self.check_unary_op(*op, arg, source_info)?;
             }
-
-            // Additional checking: check for overflows on integer binary operations and report
-            // them to the user as lints.
-            // If `overflow_check` is set, running const-prop on the `Assert` terminators
-            // will already generate the appropriate messages.
-            Rvalue::BinaryOp(op, left, right) if !overflow_check => {
+            Rvalue::BinaryOp(op, left, right) => {
                 trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
-                self.check_binary_op(*op, left, right, source_info, place_layout)?;
+                self.check_binary_op(*op, left, right, source_info)?;
+            }
+            Rvalue::CheckedBinaryOp(op, left, right) => {
+                trace!(
+                    "checking CheckedBinaryOp(op = {:?}, left = {:?}, right = {:?})",
+                    op,
+                    left,
+                    right
+                );
+                self.check_binary_op(*op, left, right, source_info)?;
             }
 
             // Do not try creating references (#67862)
@@ -898,54 +908,39 @@
                             }
                             Operand::Constant(_) => {}
                         }
-                        let span = terminator.source_info.span;
-                        let hir_id = self
-                            .tcx
-                            .hir()
-                            .as_local_hir_id(self.source.def_id())
-                            .expect("some part of a failing const eval must be local");
-                        self.tcx.struct_span_lint_hir(
-                            ::rustc::lint::builtin::CONST_ERR,
-                            hir_id,
-                            span,
-                            |lint| {
-                                let msg = match msg {
-                                    AssertKind::Overflow(_)
-                                    | AssertKind::OverflowNeg
-                                    | AssertKind::DivisionByZero
-                                    | AssertKind::RemainderByZero => msg.description().to_owned(),
-                                    AssertKind::BoundsCheck { ref len, ref index } => {
-                                        let len = self
-                                            .eval_operand(len, source_info)
-                                            .expect("len must be const");
-                                        let len = match self.ecx.read_scalar(len) {
-                                            Ok(ScalarMaybeUndef::Scalar(Scalar::Raw {
-                                                data,
-                                                ..
-                                            })) => data,
-                                            other => bug!("const len not primitive: {:?}", other),
-                                        };
-                                        let index = self
-                                            .eval_operand(index, source_info)
-                                            .expect("index must be const");
-                                        let index = match self.ecx.read_scalar(index) {
-                                            Ok(ScalarMaybeUndef::Scalar(Scalar::Raw {
-                                                data,
-                                                ..
-                                            })) => data,
-                                            other => bug!("const index not primitive: {:?}", other),
-                                        };
-                                        format!(
-                                            "index out of bounds: \
-                                            the len is {} but the index is {}",
-                                            len, index,
-                                        )
-                                    }
-                                    // Need proper const propagator for these
-                                    _ => return,
-                                };
-                                lint.build(&msg).emit()
-                            },
+                        let msg = match msg {
+                            AssertKind::DivisionByZero => AssertKind::DivisionByZero,
+                            AssertKind::RemainderByZero => AssertKind::RemainderByZero,
+                            AssertKind::BoundsCheck { ref len, ref index } => {
+                                let len =
+                                    self.eval_operand(len, source_info).expect("len must be const");
+                                let len = self
+                                    .ecx
+                                    .read_scalar(len)
+                                    .unwrap()
+                                    .to_machine_usize(&self.tcx)
+                                    .unwrap();
+                                let index = self
+                                    .eval_operand(index, source_info)
+                                    .expect("index must be const");
+                                let index = self
+                                    .ecx
+                                    .read_scalar(index)
+                                    .unwrap()
+                                    .to_machine_usize(&self.tcx)
+                                    .unwrap();
+                                AssertKind::BoundsCheck { len, index }
+                            }
+                            // Overflow is are already covered by checks on the binary operators.
+                            AssertKind::Overflow(_) | AssertKind::OverflowNeg => return,
+                            // Need proper const propagator for these.
+                            _ => return,
+                        };
+                        self.report_assert_as_lint(
+                            lint::builtin::UNCONDITIONAL_PANIC,
+                            source_info,
+                            "this operation will panic at runtime",
+                            msg,
                         );
                     } else {
                         if self.should_const_prop(value) {
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index b3dc87d..3621ca6 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -186,18 +186,24 @@
     Local::new(1)
 }
 
-/// Generator have not been resumed yet
+/// Generator has not been resumed yet.
 const UNRESUMED: usize = GeneratorSubsts::UNRESUMED;
-/// Generator has returned / is completed
+/// Generator has returned / is completed.
 const RETURNED: usize = GeneratorSubsts::RETURNED;
-/// Generator has been poisoned
+/// Generator has panicked and is poisoned.
 const POISONED: usize = GeneratorSubsts::POISONED;
 
+/// A `yield` point in the generator.
 struct SuspensionPoint<'tcx> {
+    /// State discriminant used when suspending or resuming at this point.
     state: usize,
+    /// The block to jump to after resumption.
     resume: BasicBlock,
+    /// Where to move the resume argument after resumption.
     resume_arg: Place<'tcx>,
+    /// Which block to jump to if the generator is dropped in this state.
     drop: Option<BasicBlock>,
+    /// Set of locals that have live storage while at this suspension point.
     storage_liveness: liveness::LiveVarSet,
 }
 
@@ -325,6 +331,15 @@
                 // Yield
                 let state = 3 + self.suspension_points.len();
 
+                // The resume arg target location might itself be remapped if its base local is
+                // live across a yield.
+                let resume_arg =
+                    if let Some(&(ty, variant, idx)) = self.remap.get(&resume_arg.local) {
+                        self.make_field(variant, idx, ty)
+                    } else {
+                        resume_arg
+                    };
+
                 self.suspension_points.push(SuspensionPoint {
                     state,
                     resume,
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 091ae1b..fab64e3 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -539,7 +539,7 @@
         debug!("destructor_call_block({:?}, {:?})", self, succ);
         let tcx = self.tcx();
         let drop_trait = tcx.lang_items().drop_trait().unwrap();
-        let drop_fn = tcx.associated_items(drop_trait)[0];
+        let drop_fn = tcx.associated_items(drop_trait).in_definition_order().nth(0).unwrap();
         let ty = self.place_ty(self.place);
         let substs = tcx.mk_substs_trait(ty, &[]);
 
diff --git a/src/librustc_mir_build/hair/constant.rs b/src/librustc_mir_build/hair/constant.rs
index e594e1e..e9dd785 100644
--- a/src/librustc_mir_build/hair/constant.rs
+++ b/src/librustc_mir_build/hair/constant.rs
@@ -1,7 +1,7 @@
 use rustc::mir::interpret::{
     truncate, Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
 };
-use rustc::ty::{self, layout::Size, ParamEnv, TyCtxt};
+use rustc::ty::{self, layout::Size, ParamEnv, TyCtxt, TyS};
 use rustc_span::symbol::Symbol;
 use syntax::ast;
 
@@ -20,50 +20,35 @@
         Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
     };
 
-    let lit = match *lit {
-        ast::LitKind::Str(ref s, _) => {
+    let lit = match (lit, &ty.kind) {
+        (ast::LitKind::Str(s, _), ty::Ref(_, TyS { kind: ty::Str, .. }, _)) => {
             let s = s.as_str();
             let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes());
             let allocation = tcx.intern_const_alloc(allocation);
             ConstValue::Slice { data: allocation, start: 0, end: s.len() }
         }
-        ast::LitKind::ByteStr(ref data) => {
-            if let ty::Ref(_, ref_ty, _) = ty.kind {
-                match ref_ty.kind {
-                    ty::Slice(_) => {
-                        let allocation = Allocation::from_byte_aligned_bytes(data as &Vec<u8>);
-                        let allocation = tcx.intern_const_alloc(allocation);
-                        ConstValue::Slice { data: allocation, start: 0, end: data.len() }
-                    }
-                    ty::Array(_, _) => {
-                        let id = tcx.allocate_bytes(data);
-                        ConstValue::Scalar(Scalar::Ptr(id.into()))
-                    }
-                    _ => {
-                        bug!("bytestring should have type of either &[u8] or &[u8; _], not {}", ty)
-                    }
-                }
-            } else {
-                bug!("bytestring should have type of either &[u8] or &[u8; _], not {}", ty)
-            }
+        (ast::LitKind::ByteStr(data), ty::Ref(_, TyS { kind: ty::Slice(_), .. }, _)) => {
+            let allocation = Allocation::from_byte_aligned_bytes(data as &Vec<u8>);
+            let allocation = tcx.intern_const_alloc(allocation);
+            ConstValue::Slice { data: allocation, start: 0, end: data.len() }
         }
-        ast::LitKind::Byte(n) => ConstValue::Scalar(Scalar::from_uint(n, Size::from_bytes(1))),
-        ast::LitKind::Int(n, _) if neg => {
-            let n = n as i128;
-            let n = n.overflowing_neg().0;
-            trunc(n as u128)?
+        (ast::LitKind::ByteStr(data), ty::Ref(_, TyS { kind: ty::Array(_, _), .. }, _)) => {
+            let id = tcx.allocate_bytes(data);
+            ConstValue::Scalar(Scalar::Ptr(id.into()))
         }
-        ast::LitKind::Int(n, _) => trunc(n)?,
-        ast::LitKind::Float(n, _) => {
-            let fty = match ty.kind {
-                ty::Float(fty) => fty,
-                _ => bug!(),
-            };
-            parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)?
+        (ast::LitKind::Byte(n), ty::Uint(ast::UintTy::U8)) => {
+            ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
         }
-        ast::LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)),
-        ast::LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
-        ast::LitKind::Err(_) => return Err(LitToConstError::Reported),
+        (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
+            trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
+        }
+        (ast::LitKind::Float(n, _), ty::Float(fty)) => {
+            parse_float(*n, *fty, neg).map_err(|_| LitToConstError::UnparseableFloat)?
+        }
+        (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
+        (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
+        (ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
+        _ => return Err(LitToConstError::TypeError),
     };
     Ok(ty::Const::from_value(tcx, lit, ty))
 }
diff --git a/src/librustc_mir_build/hair/cx/mod.rs b/src/librustc_mir_build/hair/cx/mod.rs
index ee62af7..f486073 100644
--- a/src/librustc_mir_build/hair/cx/mod.rs
+++ b/src/librustc_mir_build/hair/cx/mod.rs
@@ -148,6 +148,7 @@
                 // create a dummy value and continue compiling
                 Const::from_bits(self.tcx, 0, self.param_env.and(ty))
             }
+            Err(LitToConstError::TypeError) => bug!("const_eval_literal: had type error"),
         }
     }
 
@@ -167,17 +168,19 @@
         params: &[GenericArg<'tcx>],
     ) -> &'tcx ty::Const<'tcx> {
         let substs = self.tcx.mk_substs_trait(self_ty, params);
-        for item in self.tcx.associated_items(trait_def_id) {
-            // The unhygienic comparison here is acceptable because this is only
-            // used on known traits.
-            if item.kind == ty::AssocKind::Method && item.ident.name == method_name {
-                let method_ty = self.tcx.type_of(item.def_id);
-                let method_ty = method_ty.subst(self.tcx, substs);
-                return ty::Const::zero_sized(self.tcx, method_ty);
-            }
-        }
 
-        bug!("found no method `{}` in `{:?}`", method_name, trait_def_id);
+        // The unhygienic comparison here is acceptable because this is only
+        // used on known traits.
+        let item = self
+            .tcx
+            .associated_items(trait_def_id)
+            .filter_by_name_unhygienic(method_name)
+            .find(|item| item.kind == ty::AssocKind::Method)
+            .expect("trait method not found");
+
+        let method_ty = self.tcx.type_of(item.def_id);
+        let method_ty = method_ty.subst(self.tcx, substs);
+        ty::Const::zero_sized(self.tcx, method_ty)
     }
 
     crate fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec<Field> {
diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs
index 651f2f7..3dfe826 100644
--- a/src/librustc_mir_build/hair/pattern/check_match.rs
+++ b/src/librustc_mir_build/hair/pattern/check_match.rs
@@ -659,7 +659,7 @@
             });
             if !conflicts_ref.is_empty() {
                 let occurs_because = format!(
-                    "move occurs because `{}` has type `{}` which does implement the `Copy` trait",
+                    "move occurs because `{}` has type `{}` which does not implement the `Copy` trait",
                     name,
                     tables.node_type(pat.hir_id),
                 );
diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs
index 9101174..6979a98 100644
--- a/src/librustc_mir_build/hair/pattern/mod.rs
+++ b/src/librustc_mir_build/hair/pattern/mod.rs
@@ -846,6 +846,7 @@
                     PatKind::Wild
                 }
                 Err(LitToConstError::Reported) => PatKind::Wild,
+                Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
             }
         }
     }
diff --git a/src/librustc_passes/region.rs b/src/librustc_passes/region.rs
index e79ca5c..d0f49fd 100644
--- a/src/librustc_passes/region.rs
+++ b/src/librustc_passes/region.rs
@@ -4,7 +4,7 @@
 //! For more information about how MIR-based region-checking works,
 //! see the [rustc guide].
 //!
-//! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/borrow_check.html
 
 use rustc::hir::map::Map;
 use rustc::middle::region::*;
diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs
index d9296de..0c7f64f 100644
--- a/src/librustc_passes/stability.rs
+++ b/src/librustc_passes/stability.rs
@@ -523,8 +523,8 @@
                         let trait_item_def_id = self
                             .tcx
                             .associated_items(trait_did)
-                            .iter()
-                            .find(|item| item.ident.name == impl_item.ident.name)
+                            .filter_by_name_unhygienic(impl_item.ident.name)
+                            .next()
                             .map(|item| item.def_id);
                         if let Some(def_id) = trait_item_def_id {
                             // Pass `None` to skip deprecation warnings.
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 6a34e47..6e7ecf9 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -408,7 +408,6 @@
                         qualname.push_str(&self.tcx.hir().hir_to_pretty_string(self_ty.hir_id));
 
                         let trait_id = self.tcx.trait_id_of_impl(impl_id);
-                        let mut decl_id = None;
                         let mut docs = String::new();
                         let mut attrs = vec![];
                         let hir_id = self.tcx.hir().node_to_hir_id(id);
@@ -417,15 +416,18 @@
                             attrs = item.attrs.to_vec();
                         }
 
+                        let mut decl_id = None;
                         if let Some(def_id) = trait_id {
                             // A method in a trait impl.
                             qualname.push_str(" as ");
                             qualname.push_str(&self.tcx.def_path_str(def_id));
-                            self.tcx
+
+                            decl_id = self
+                                .tcx
                                 .associated_items(def_id)
-                                .iter()
-                                .find(|item| item.ident.name == ident.name)
-                                .map(|item| decl_id = Some(item.def_id));
+                                .filter_by_name_unhygienic(ident.name)
+                                .next()
+                                .map(|item| item.def_id);
                         }
                         qualname.push_str(">");
 
@@ -716,12 +718,11 @@
             Res::Def(HirDefKind::Method, decl_id) => {
                 let def_id = if decl_id.is_local() {
                     let ti = self.tcx.associated_item(decl_id);
+
                     self.tcx
                         .associated_items(ti.container.id())
-                        .iter()
-                        .find(|item| {
-                            item.ident.name == ti.ident.name && item.defaultness.has_value()
-                        })
+                        .filter_by_name_unhygienic(ti.ident.name)
+                        .find(|item| item.defaultness.has_value())
                         .map(|item| item.def_id)
                 } else {
                     None
diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs
index 5a360b4..603ed46 100644
--- a/src/librustc_session/lint/builtin.rs
+++ b/src/librustc_session/lint/builtin.rs
@@ -41,9 +41,15 @@
 }
 
 declare_lint! {
-    pub EXCEEDING_BITSHIFTS,
+    pub ARITHMETIC_OVERFLOW,
     Deny,
-    "shift exceeds the type's number of bits"
+    "arithmetic operation overflows"
+}
+
+declare_lint! {
+    pub UNCONDITIONAL_PANIC,
+    Deny,
+    "operation will cause a panic at runtime"
 }
 
 declare_lint! {
@@ -495,7 +501,8 @@
     /// that are used by other parts of the compiler.
     HardwiredLints => [
         ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
-        EXCEEDING_BITSHIFTS,
+        ARITHMETIC_OVERFLOW,
+        UNCONDITIONAL_PANIC,
         UNUSED_IMPORTS,
         UNUSED_EXTERN_CRATES,
         UNUSED_QUALIFICATIONS,
diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs
index 8f00b76..f9f3a90 100644
--- a/src/librustc_span/lib.rs
+++ b/src/librustc_span/lib.rs
@@ -1075,7 +1075,7 @@
         unmapped_path: FileName,
         mut src: String,
         start_pos: BytePos,
-    ) -> Result<SourceFile, OffsetOverflowError> {
+    ) -> Self {
         let normalized_pos = normalize_src(&mut src, start_pos);
 
         let src_hash = {
@@ -1089,14 +1089,12 @@
             hasher.finish::<u128>()
         };
         let end_pos = start_pos.to_usize() + src.len();
-        if end_pos > u32::max_value() as usize {
-            return Err(OffsetOverflowError);
-        }
+        assert!(end_pos <= u32::max_value() as usize);
 
         let (lines, multibyte_chars, non_narrow_chars) =
             analyze_source_file::analyze_source_file(&src[..], start_pos);
 
-        Ok(SourceFile {
+        SourceFile {
             name,
             name_was_remapped,
             unmapped_path: Some(unmapped_path),
@@ -1111,7 +1109,7 @@
             non_narrow_chars,
             normalized_pos,
             name_hash,
-        })
+        }
     }
 
     /// Returns the `BytePos` of the beginning of the current line.
diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs
index 45c4d6d..31d397f 100644
--- a/src/librustc_span/source_map.rs
+++ b/src/librustc_span/source_map.rs
@@ -12,10 +12,12 @@
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
-use rustc_data_structures::sync::{Lock, LockGuard, Lrc, MappedLockGuard};
+use rustc_data_structures::sync::{AtomicU32, Lock, LockGuard, Lrc, MappedLockGuard};
 use std::cmp;
+use std::convert::TryFrom;
 use std::hash::Hash;
 use std::path::{Path, PathBuf};
+use std::sync::atomic::Ordering;
 
 use log::debug;
 use std::env;
@@ -131,6 +133,9 @@
 }
 
 pub struct SourceMap {
+    /// The address space below this value is currently used by the files in the source map.
+    used_address_space: AtomicU32,
+
     files: Lock<SourceMapFiles>,
     file_loader: Box<dyn FileLoader + Sync + Send>,
     // This is used to apply the file path remapping as specified via
@@ -140,14 +145,24 @@
 
 impl SourceMap {
     pub fn new(path_mapping: FilePathMapping) -> SourceMap {
-        SourceMap { files: Default::default(), file_loader: Box::new(RealFileLoader), path_mapping }
+        SourceMap {
+            used_address_space: AtomicU32::new(0),
+            files: Default::default(),
+            file_loader: Box::new(RealFileLoader),
+            path_mapping,
+        }
     }
 
     pub fn with_file_loader(
         file_loader: Box<dyn FileLoader + Sync + Send>,
         path_mapping: FilePathMapping,
     ) -> SourceMap {
-        SourceMap { files: Default::default(), file_loader, path_mapping }
+        SourceMap {
+            used_address_space: AtomicU32::new(0),
+            files: Default::default(),
+            file_loader,
+            path_mapping,
+        }
     }
 
     pub fn path_mapping(&self) -> &FilePathMapping {
@@ -194,12 +209,25 @@
         self.files.borrow().stable_id_to_source_file.get(&stable_id).map(|sf| sf.clone())
     }
 
-    fn next_start_pos(&self) -> usize {
-        match self.files.borrow().source_files.last() {
-            None => 0,
-            // Add one so there is some space between files. This lets us distinguish
-            // positions in the `SourceMap`, even in the presence of zero-length files.
-            Some(last) => last.end_pos.to_usize() + 1,
+    fn allocate_address_space(&self, size: usize) -> Result<usize, OffsetOverflowError> {
+        let size = u32::try_from(size).map_err(|_| OffsetOverflowError)?;
+
+        loop {
+            let current = self.used_address_space.load(Ordering::Relaxed);
+            let next = current
+                .checked_add(size)
+                // Add one so there is some space between files. This lets us distinguish
+                // positions in the `SourceMap`, even in the presence of zero-length files.
+                .and_then(|next| next.checked_add(1))
+                .ok_or(OffsetOverflowError)?;
+
+            if self
+                .used_address_space
+                .compare_exchange(current, next, Ordering::Relaxed, Ordering::Relaxed)
+                .is_ok()
+            {
+                return Ok(usize::try_from(current).unwrap());
+            }
         }
     }
 
@@ -218,8 +246,6 @@
         filename: FileName,
         src: String,
     ) -> Result<Lrc<SourceFile>, OffsetOverflowError> {
-        let start_pos = self.next_start_pos();
-
         // The path is used to determine the directory for loading submodules and
         // include files, so it must be before remapping.
         // Note that filename may not be a valid path, eg it may be `<anon>` etc,
@@ -241,13 +267,15 @@
         let lrc_sf = match self.source_file_by_stable_id(file_id) {
             Some(lrc_sf) => lrc_sf,
             None => {
+                let start_pos = self.allocate_address_space(src.len())?;
+
                 let source_file = Lrc::new(SourceFile::new(
                     filename,
                     was_remapped,
                     unmapped_path,
                     src,
                     Pos::from_usize(start_pos),
-                )?);
+                ));
 
                 let mut files = self.files.borrow_mut();
 
@@ -277,7 +305,9 @@
         mut file_local_non_narrow_chars: Vec<NonNarrowChar>,
         mut file_local_normalized_pos: Vec<NormalizedPos>,
     ) -> Lrc<SourceFile> {
-        let start_pos = self.next_start_pos();
+        let start_pos = self
+            .allocate_address_space(source_len)
+            .expect("not enough address space for imported source file");
 
         let end_pos = Pos::from_usize(start_pos + source_len);
         let start_pos = Pos::from_usize(start_pos);
diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs
index f9b2ee3..d466bbc 100644
--- a/src/librustc_ty/ty.rs
+++ b/src/librustc_ty/ty.rs
@@ -210,10 +210,9 @@
     }
 }
 
-fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [ty::AssocItem] {
-    tcx.arena.alloc_from_iter(
-        tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)),
-    )
+fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::AssociatedItems {
+    let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did));
+    tcx.arena.alloc(ty::AssociatedItems::new(items))
 }
 
 fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 69970fa..78c05a5 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -9,7 +9,6 @@
 use crate::lint;
 use crate::middle::lang_items::SizedTraitLangItem;
 use crate::middle::resolve_lifetime as rl;
-use crate::namespace::Namespace;
 use crate::require_c_abi_if_c_variadic;
 use crate::util::common::ErrorReported;
 use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
@@ -20,7 +19,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId};
 use rustc_hir as hir;
-use rustc_hir::def::{CtorOf, DefKind, Res};
+use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::print;
@@ -1109,10 +1108,10 @@
         trait_def_id: DefId,
         assoc_name: ast::Ident,
     ) -> bool {
-        self.tcx().associated_items(trait_def_id).iter().any(|item| {
-            item.kind == ty::AssocKind::Type
-                && self.tcx().hygienic_eq(assoc_name, item.ident, trait_def_id)
-        })
+        self.tcx()
+            .associated_items(trait_def_id)
+            .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id)
+            .is_some()
     }
 
     // Returns `true` if a bounds list includes `?Sized`.
@@ -1345,9 +1344,12 @@
 
         let (assoc_ident, def_scope) =
             tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
+
+        // We have already adjusted the item name above, so compare with `ident.modern()` instead
+        // of calling `filter_by_name_and_kind`.
         let assoc_ty = tcx
             .associated_items(candidate.def_id())
-            .iter()
+            .filter_by_name_unhygienic(assoc_ident.name)
             .find(|i| i.kind == ty::AssocKind::Type && i.ident.modern() == assoc_ident)
             .expect("missing associated type");
 
@@ -1513,7 +1515,7 @@
                     ty::Predicate::Trait(pred, _) => {
                         associated_types.entry(span).or_default().extend(
                             tcx.associated_items(pred.def_id())
-                                .iter()
+                                .in_definition_order()
                                 .filter(|item| item.kind == ty::AssocKind::Type)
                                 .map(|item| item.def_id),
                         );
@@ -1968,14 +1970,11 @@
 
             let mut where_bounds = vec![];
             for bound in bounds {
+                let bound_id = bound.def_id();
                 let bound_span = self
                     .tcx()
-                    .associated_items(bound.def_id())
-                    .iter()
-                    .find(|item| {
-                        item.kind == ty::AssocKind::Type
-                            && self.tcx().hygienic_eq(assoc_name, item.ident, bound.def_id())
-                    })
+                    .associated_items(bound_id)
+                    .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, bound_id)
                     .and_then(|item| self.tcx().hir().span_if_local(item.def_id));
 
                 if let Some(bound_span) = bound_span {
@@ -2053,7 +2052,7 @@
         );
 
         let all_candidate_names: Vec<_> = all_candidates()
-            .map(|r| self.tcx().associated_items(r.def_id()))
+            .map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
             .flatten()
             .filter_map(
                 |item| if item.kind == ty::AssocKind::Type { Some(item.ident.name) } else { None },
@@ -2199,10 +2198,13 @@
         let trait_did = bound.def_id();
         let (assoc_ident, def_scope) =
             tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id);
+
+        // We have already adjusted the item name above, so compare with `ident.modern()` instead
+        // of calling `filter_by_name_and_kind`.
         let item = tcx
             .associated_items(trait_did)
-            .iter()
-            .find(|i| Namespace::from(i.kind) == Namespace::Type && i.ident.modern() == assoc_ident)
+            .in_definition_order()
+            .find(|i| i.kind.namespace() == Namespace::TypeNS && i.ident.modern() == assoc_ident)
             .expect("missing associated type");
 
         let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound);
@@ -2740,6 +2742,8 @@
             // mir.
             if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) {
                 return c;
+            } else {
+                tcx.sess.delay_span_bug(expr.span, "ast_const_to_const: couldn't lit_to_const");
             }
         }
 
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 18f6a78..a67ceb8 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -45,7 +45,6 @@
 use rustc_hir as hir;
 use rustc_infer::traits;
 use rustc_infer::traits::error_reporting::report_object_safety_error;
-use rustc_infer::traits::object_safety_violations;
 use rustc_span::Span;
 use syntax::ast;
 
@@ -517,7 +516,7 @@
     }
 
     fn report_object_unsafe_cast(&self, fcx: &FnCtxt<'a, 'tcx>, did: DefId) {
-        let violations = object_safety_violations(fcx.tcx, did);
+        let violations = fcx.tcx.object_safety_violations(did);
         let mut err = report_object_safety_error(fcx.tcx, self.cast_span, did, violations);
         err.note(&format!("required by cast to type '{}'", fcx.ty_to_string(self.cast_ty)));
         err.emit();
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index e17c65f..816de5d 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -248,7 +248,8 @@
         if is_gen {
             // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return`
             // associated item and not yield.
-            let return_assoc_item = self.tcx.associated_items(gen_trait)[1].def_id;
+            let return_assoc_item =
+                self.tcx.associated_items(gen_trait).in_definition_order().nth(1).unwrap().def_id;
             if return_assoc_item != projection.projection_def_id() {
                 debug!("deduce_sig_from_projection: not return assoc item of generator");
                 return None;
@@ -673,7 +674,8 @@
 
         // The `Future` trait has only one associted item, `Output`,
         // so check that this is what we see.
-        let output_assoc_item = self.tcx.associated_items(future_trait)[0].def_id;
+        let output_assoc_item =
+            self.tcx.associated_items(future_trait).in_definition_order().nth(0).unwrap().def_id;
         if output_assoc_item != predicate.projection_ty.item_def_id {
             span_bug!(
                 cause_span,
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index c327a79..3720b74 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -66,7 +66,6 @@
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{Coercion, InferOk, InferResult};
-use rustc_infer::traits::object_safety_violations;
 use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc_span::symbol::sym;
 use rustc_span::{self, Span};
@@ -1404,7 +1403,7 @@
                         // Are of this `impl Trait`'s traits object safe?
                         is_object_safe = bounds.iter().all(|bound| {
                             bound.trait_def_id().map_or(false, |def_id| {
-                                object_safety_violations(fcx.tcx, def_id).is_empty()
+                                fcx.tcx.object_safety_violations(def_id).is_empty()
                             })
                         })
                     }
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index bf74ab6..63ebf61 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -539,7 +539,7 @@
                 let item_def_id = self
                     .tcx
                     .associated_items(deref_trait)
-                    .iter()
+                    .in_definition_order()
                     .find(|item| item.kind == ty::AssocKind::Type)
                     .unwrap()
                     .def_id;
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 1856157..de82464 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -11,7 +11,6 @@
 pub use self::MethodError::*;
 
 use crate::check::FnCtxt;
-use crate::namespace::Namespace;
 use rustc::ty::subst::Subst;
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::ty::GenericParamDefKind;
@@ -19,7 +18,7 @@
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::def::{CtorOf, DefKind};
+use rustc_hir::def::{CtorOf, DefKind, Namespace};
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::{self, InferOk};
 use rustc_infer::traits;
@@ -342,7 +341,7 @@
         // Trait must have a method named `m_name` and it should not have
         // type parameters or early-bound regions.
         let tcx = self.tcx;
-        let method_item = match self.associated_item(trait_def_id, m_name, Namespace::Value) {
+        let method_item = match self.associated_item(trait_def_id, m_name, Namespace::ValueNS) {
             Some(method_item) => method_item,
             None => {
                 tcx.sess.delay_span_bug(
@@ -484,11 +483,7 @@
     ) -> Option<ty::AssocItem> {
         self.tcx
             .associated_items(def_id)
-            .iter()
-            .find(|item| {
-                Namespace::from(item.kind) == ns
-                    && self.tcx.hygienic_eq(item_name, item.ident, def_id)
-            })
+            .find_by_name_and_namespace(self.tcx, item_name, ns, def_id)
             .copied()
     }
 }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 346406f..ea90aef 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -7,7 +7,6 @@
 use crate::check::FnCtxt;
 use crate::hir::def::DefKind;
 use crate::hir::def_id::DefId;
-use crate::namespace::Namespace;
 
 use rustc::lint;
 use rustc::middle::stability;
@@ -22,6 +21,7 @@
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_hir::def::Namespace;
 use rustc_infer::infer::canonical::OriginalQueryValues;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -1696,20 +1696,20 @@
                 let max_dist = max(name.as_str().len(), 3) / 3;
                 self.tcx
                     .associated_items(def_id)
-                    .iter()
+                    .in_definition_order()
                     .filter(|x| {
                         let dist = lev_distance(&*name.as_str(), &x.ident.as_str());
-                        Namespace::from(x.kind) == Namespace::Value && dist > 0 && dist <= max_dist
+                        x.kind.namespace() == Namespace::ValueNS && dist > 0 && dist <= max_dist
                     })
                     .copied()
                     .collect()
             } else {
                 self.fcx
-                    .associated_item(def_id, name, Namespace::Value)
+                    .associated_item(def_id, name, Namespace::ValueNS)
                     .map_or(Vec::new(), |x| vec![x])
             }
         } else {
-            self.tcx.associated_items(def_id).to_vec()
+            self.tcx.associated_items(def_id).in_definition_order().copied().collect()
         }
     }
 }
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 83f063a..ea83b40 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -3,7 +3,6 @@
 
 use crate::check::FnCtxt;
 use crate::middle::lang_items::FnOnceTraitLangItem;
-use crate::namespace::Namespace;
 use rustc::hir::map as hir_map;
 use rustc::hir::map::Map;
 use rustc::ty::print::with_crate_prefix;
@@ -11,7 +10,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def::{DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::intravisit;
 use rustc_hir::{ExprKind, Node, QPath};
@@ -97,13 +96,13 @@
                         // Provide the best span we can. Use the item, if local to crate, else
                         // the impl, if local to crate (item may be defaulted), else nothing.
                         let item = match self
-                            .associated_item(impl_did, item_name, Namespace::Value)
+                            .associated_item(impl_did, item_name, Namespace::ValueNS)
                             .or_else(|| {
                                 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
                                 self.associated_item(
                                     impl_trait_ref.def_id,
                                     item_name,
-                                    Namespace::Value,
+                                    Namespace::ValueNS,
                                 )
                             }) {
                             Some(item) => item,
@@ -185,7 +184,7 @@
                     }
                     CandidateSource::TraitSource(trait_did) => {
                         let item =
-                            match self.associated_item(trait_did, item_name, Namespace::Value) {
+                            match self.associated_item(trait_did, item_name, Namespace::ValueNS) {
                                 Some(item) => item,
                                 None => continue,
                             };
@@ -264,7 +263,7 @@
                     // be used exists at all, and the type is an ambiguous numeric type
                     // ({integer}/{float}).
                     let mut candidates = all_traits(self.tcx).into_iter().filter_map(|info| {
-                        self.associated_item(info.def_id, item_name, Namespace::Value)
+                        self.associated_item(info.def_id, item_name, Namespace::ValueNS)
                     });
                     if let (true, false, SelfSource::MethodCall(expr), Some(_)) = (
                         actual.is_numeric(),
@@ -779,7 +778,7 @@
                 // here).
                 (type_is_local || info.def_id.is_local())
                     && self
-                        .associated_item(info.def_id, item_name, Namespace::Value)
+                        .associated_item(info.def_id, item_name, Namespace::ValueNS)
                         .filter(|item| {
                             // We only want to suggest public or local traits (#45781).
                             item.vis == ty::Visibility::Public || info.def_id.is_local()
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index f714514..4f6eb20 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -89,7 +89,6 @@
 
 use crate::astconv::{AstConv, PathSeg};
 use crate::middle::lang_items;
-use crate::namespace::Namespace;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::hir::map::Map;
 use rustc::middle::region;
@@ -1972,19 +1971,16 @@
     // Check existing impl methods to see if they are both present in trait
     // and compatible with trait signature
     for impl_item in impl_items() {
+        let namespace = impl_item.kind.namespace();
         let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id));
         let ty_trait_item = tcx
             .associated_items(impl_trait_ref.def_id)
-            .iter()
-            .find(|ac| {
-                Namespace::from(&impl_item.kind) == Namespace::from(ac.kind)
-                    && tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id)
-            })
+            .find_by_name_and_namespace(tcx, ty_impl_item.ident, namespace, impl_trait_ref.def_id)
             .or_else(|| {
                 // Not compatible, but needed for the error message
                 tcx.associated_items(impl_trait_ref.def_id)
-                    .iter()
-                    .find(|ac| tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id))
+                    .filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id)
+                    .next()
             });
 
         // Check that impl definition matches trait definition
@@ -2088,7 +2084,7 @@
     let mut missing_items = Vec::new();
     let mut invalidated_items = Vec::new();
     let associated_type_overridden = overridden_associated_type.is_some();
-    for trait_item in tcx.associated_items(impl_trait_ref.def_id) {
+    for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() {
         let is_implemented = trait_def
             .ancestors(tcx, impl_id)
             .leaf_def(tcx, trait_item.ident, trait_item.kind)
@@ -3843,17 +3839,58 @@
                                  error_code: &str,
                                  c_variadic: bool,
                                  sugg_unit: bool| {
+            let (span, start_span, args) = match &expr.kind {
+                hir::ExprKind::Call(hir::Expr { span, .. }, args) => (*span, *span, &args[..]),
+                hir::ExprKind::MethodCall(path_segment, span, args) => (
+                    *span,
+                    // `sp` doesn't point at the whole `foo.bar()`, only at `bar`.
+                    path_segment
+                        .args
+                        .and_then(|args| args.args.iter().last())
+                        // Account for `foo.bar::<T>()`.
+                        .map(|arg| {
+                            // Skip the closing `>`.
+                            tcx.sess
+                                .source_map()
+                                .next_point(tcx.sess.source_map().next_point(arg.span()))
+                        })
+                        .unwrap_or(*span),
+                    &args[1..], // Skip the receiver.
+                ),
+                k => span_bug!(sp, "checking argument types on a non-call: `{:?}`", k),
+            };
+            let arg_spans = if args.is_empty() {
+                // foo()
+                // ^^^-- supplied 0 arguments
+                // |
+                // expected 2 arguments
+                vec![tcx.sess.source_map().next_point(start_span).with_hi(sp.hi())]
+            } else {
+                // foo(1, 2, 3)
+                // ^^^ -  -  - supplied 3 arguments
+                // |
+                // expected 2 arguments
+                args.iter().map(|arg| arg.span).collect::<Vec<Span>>()
+            };
+
             let mut err = tcx.sess.struct_span_err_with_code(
-                sp,
+                span,
                 &format!(
                     "this function takes {}{} but {} {} supplied",
                     if c_variadic { "at least " } else { "" },
-                    potentially_plural_count(expected_count, "parameter"),
-                    potentially_plural_count(arg_count, "parameter"),
+                    potentially_plural_count(expected_count, "argument"),
+                    potentially_plural_count(arg_count, "argument"),
                     if arg_count == 1 { "was" } else { "were" }
                 ),
                 DiagnosticId::Error(error_code.to_owned()),
             );
+            let label = format!("supplied {}", potentially_plural_count(arg_count, "argument"));
+            for (i, span) in arg_spans.into_iter().enumerate() {
+                err.span_label(
+                    span,
+                    if arg_count == 0 || i + 1 == arg_count { &label } else { "" },
+                );
+            }
 
             if let Some(def_s) = def_span.map(|sp| tcx.sess.source_map().def_span(sp)) {
                 err.span_label(def_s, "defined here");
@@ -3870,11 +3907,11 @@
                 );
             } else {
                 err.span_label(
-                    sp,
+                    span,
                     format!(
                         "expected {}{}",
                         if c_variadic { "at least " } else { "" },
-                        potentially_plural_count(expected_count, "parameter")
+                        potentially_plural_count(expected_count, "argument")
                     ),
                 );
             }
@@ -5224,7 +5261,13 @@
                 // Check for `Future` implementations by constructing a predicate to
                 // prove: `<T as Future>::Output == U`
                 let future_trait = self.tcx.lang_items().future_trait().unwrap();
-                let item_def_id = self.tcx.associated_items(future_trait)[0].def_id;
+                let item_def_id = self
+                    .tcx
+                    .associated_items(future_trait)
+                    .in_definition_order()
+                    .nth(0)
+                    .unwrap()
+                    .def_id;
                 let predicate =
                     ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate {
                         // `<T as Future>::Output`
@@ -5622,8 +5665,7 @@
 
         self.tcx.sess.span_err(
             span,
-            "this function can only be invoked \
-                                      directly, not through a function pointer",
+            "this function can only be invoked directly, not through a function pointer",
         );
     }
 
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 4ffc3bf..12e6087 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -223,7 +223,7 @@
         _ => {}
     }
     if !trait_should_be_self.is_empty() {
-        if rustc_infer::traits::object_safety_violations(tcx, trait_def_id).is_empty() {
+        if tcx.object_safety_violations(trait_def_id).is_empty() {
             return;
         }
         let sugg = trait_should_be_self.iter().map(|span| (*span, "Self".to_string())).collect();
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
index 2a0d19b..fcded27 100644
--- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs
+++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
@@ -1,5 +1,4 @@
-use crate::namespace::Namespace;
-use rustc::ty::{AssocItem, TyCtxt};
+use rustc::ty::TyCtxt;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
@@ -23,18 +22,18 @@
         let impl_items1 = self.tcx.associated_items(impl1);
         let impl_items2 = self.tcx.associated_items(impl2);
 
-        for item1 in &impl_items1[..] {
-            for item2 in &impl_items2[..] {
-                // Avoid costly `.modern()` calls as much as possible by doing them as late as we
-                // can. Compare raw symbols first.
-                if item1.ident.name == item2.ident.name
-                    && Namespace::from(item1.kind) == Namespace::from(item2.kind)
-                {
+        for item1 in impl_items1.in_definition_order() {
+            let collision = impl_items2
+                .filter_by_name_unhygienic(item1.ident.name)
+                .find(|item2| {
                     // Symbols and namespace match, compare hygienically.
-                    if item1.ident.modern() == item2.ident.modern() {
-                        return true;
-                    }
-                }
+                    item1.kind.namespace() == item2.kind.namespace()
+                        && item1.ident.modern() == item2.ident.modern()
+                })
+                .is_some();
+
+            if collision {
+                return true;
             }
         }
 
@@ -47,43 +46,43 @@
         impl2: DefId,
         overlap: traits::OverlapResult<'_>,
     ) {
-        let name_and_namespace =
-            |assoc: &AssocItem| (assoc.ident.modern(), Namespace::from(assoc.kind));
-
         let impl_items1 = self.tcx.associated_items(impl1);
         let impl_items2 = self.tcx.associated_items(impl2);
 
-        for item1 in &impl_items1[..] {
-            let (name, namespace) = name_and_namespace(item1);
+        for item1 in impl_items1.in_definition_order() {
+            let collision = impl_items2.filter_by_name_unhygienic(item1.ident.name).find(|item2| {
+                // Symbols and namespace match, compare hygienically.
+                item1.kind.namespace() == item2.kind.namespace()
+                    && item1.ident.modern() == item2.ident.modern()
+            });
 
-            for item2 in &impl_items2[..] {
-                if (name, namespace) == name_and_namespace(item2) {
-                    let mut err = struct_span_err!(
-                        self.tcx.sess,
-                        self.tcx.span_of_impl(item1.def_id).unwrap(),
-                        E0592,
-                        "duplicate definitions with name `{}`",
-                        name
-                    );
-                    err.span_label(
-                        self.tcx.span_of_impl(item1.def_id).unwrap(),
-                        format!("duplicate definitions for `{}`", name),
-                    );
-                    err.span_label(
-                        self.tcx.span_of_impl(item2.def_id).unwrap(),
-                        format!("other definition for `{}`", name),
-                    );
+            if let Some(item2) = collision {
+                let name = item1.ident.modern();
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    self.tcx.span_of_impl(item1.def_id).unwrap(),
+                    E0592,
+                    "duplicate definitions with name `{}`",
+                    name
+                );
+                err.span_label(
+                    self.tcx.span_of_impl(item1.def_id).unwrap(),
+                    format!("duplicate definitions for `{}`", name),
+                );
+                err.span_label(
+                    self.tcx.span_of_impl(item2.def_id).unwrap(),
+                    format!("other definition for `{}`", name),
+                );
 
-                    for cause in &overlap.intercrate_ambiguity_causes {
-                        cause.add_intercrate_ambiguity_hint(&mut err);
-                    }
-
-                    if overlap.involves_placeholder {
-                        traits::add_placeholder_note(&mut err);
-                    }
-
-                    err.emit();
+                for cause in &overlap.intercrate_ambiguity_causes {
+                    cause.add_intercrate_ambiguity_hint(&mut err);
                 }
+
+                if overlap.involves_placeholder {
+                    traits::add_placeholder_note(&mut err);
+                }
+
+                err.emit();
             }
         }
     }
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 0a1c61b..c5f339d 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -83,7 +83,6 @@
 mod constrained_generic_params;
 mod impl_wf_check;
 mod mem_categorization;
-mod namespace;
 mod outlives;
 mod structured_errors;
 mod variance;
diff --git a/src/librustc_typeck/namespace.rs b/src/librustc_typeck/namespace.rs
deleted file mode 100644
index 2aa97aa..0000000
--- a/src/librustc_typeck/namespace.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-use rustc::ty;
-use rustc_hir as hir;
-
-// Whether an item exists in the type or value namespace.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum Namespace {
-    Type,
-    Value,
-}
-
-impl From<ty::AssocKind> for Namespace {
-    fn from(a_kind: ty::AssocKind) -> Self {
-        match a_kind {
-            ty::AssocKind::OpaqueTy | ty::AssocKind::Type => Namespace::Type,
-            ty::AssocKind::Const | ty::AssocKind::Method => Namespace::Value,
-        }
-    }
-}
-
-impl<'a> From<&'a hir::ImplItemKind<'_>> for Namespace {
-    fn from(impl_kind: &'a hir::ImplItemKind<'_>) -> Self {
-        match *impl_kind {
-            hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => Namespace::Type,
-            hir::ImplItemKind::Const(..) | hir::ImplItemKind::Method(..) => Namespace::Value,
-        }
-    }
-}
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index f7968bf..4a1e257 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -114,8 +114,7 @@
                             .cx
                             .tcx
                             .associated_items(impl_def_id)
-                            .iter()
-                            .copied()
+                            .in_definition_order()
                             .collect::<Vec<_>>()
                             .clean(self.cx),
                         polarity: None,
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 90ce880..78222d2 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -190,8 +190,10 @@
 }
 
 pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
+    let trait_items =
+        cx.tcx.associated_items(did).in_definition_order().map(|item| item.clean(cx)).collect();
+
     let auto_trait = cx.tcx.trait_def(did).has_auto_impl;
-    let trait_items = cx.tcx.associated_items(did).iter().map(|item| item.clean(cx)).collect();
     let predicates = cx.tcx.predicates_of(did);
     let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
     let generics = filter_non_trait_generics(did, generics);
@@ -376,7 +378,7 @@
     } else {
         (
             tcx.associated_items(did)
-                .iter()
+                .in_definition_order()
                 .filter_map(|item| {
                     if associated_trait.is_some() || item.vis == ty::Visibility::Public {
                         Some(item.clean(cx))
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 79bcfe7..0b27e5c 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -95,7 +95,7 @@
                     .tcx
                     .inherent_impls(did)
                     .iter()
-                    .flat_map(|imp| cx.tcx.associated_items(*imp))
+                    .flat_map(|imp| cx.tcx.associated_items(*imp).in_definition_order())
                     .any(|item| item.ident.name == variant_name)
                 {
                     return Err(ErrorKind::ResolutionFailure);
@@ -206,8 +206,8 @@
                 return cx
                     .tcx
                     .associated_items(did)
-                    .iter()
-                    .find(|item| item.ident.name == item_name)
+                    .filter_by_name_unhygienic(item_name)
+                    .next()
                     .and_then(|item| match item.kind {
                         ty::AssocKind::Method => Some("method"),
                         _ => None,
@@ -234,7 +234,7 @@
                         .tcx
                         .inherent_impls(did)
                         .iter()
-                        .flat_map(|imp| cx.tcx.associated_items(*imp))
+                        .flat_map(|imp| cx.tcx.associated_items(*imp).in_definition_order())
                         .find(|item| item.ident.name == item_name);
                     if let Some(item) = item {
                         let out = match item.kind {
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index 61c4d0c..b99b4d8 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -331,14 +331,14 @@
     ///   * `call_once` was called, but has not yet completed,
     ///   * the `Once` instance is poisoned
     ///
-    /// It is also possible that immediately after `is_completed`
-    /// returns false, some other thread finishes executing
-    /// `call_once`.
+    /// This function returning `false` does not mean that `Once` has not been
+    /// executed. For example, it may have been executed in the time between
+    /// when `is_completed` starts executing and when it returns, in which case
+    /// the `false` return value would be stale (but still permissible).
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(once_is_completed)]
     /// use std::sync::Once;
     ///
     /// static INIT: Once = Once::new();
@@ -351,7 +351,6 @@
     /// ```
     ///
     /// ```
-    /// #![feature(once_is_completed)]
     /// use std::sync::Once;
     /// use std::thread;
     ///
@@ -364,7 +363,7 @@
     /// assert!(handle.join().is_err());
     /// assert_eq!(INIT.is_completed(), false);
     /// ```
-    #[unstable(feature = "once_is_completed", issue = "54890")]
+    #[stable(feature = "once_is_completed", since = "1.44.0")]
     #[inline]
     pub fn is_completed(&self) -> bool {
         // An `Acquire` load is enough because that makes all the initialization
diff --git a/src/test/codegen/issue-56927.rs b/src/test/codegen/issue-56927.rs
index 0544ff8..d502673 100644
--- a/src/test/codegen/issue-56927.rs
+++ b/src/test/codegen/issue-56927.rs
@@ -23,7 +23,7 @@
 
 // CHECK-LABEL: @test2
 // CHECK: store i32 4, i32* %{{.+}}, align 4
-#[allow(const_err)]
+#[allow(unconditional_panic)]
 #[no_mangle]
 pub fn test2(s: &mut S) {
     s.arr[usize::MAX / 4 + 1] = 4;
diff --git a/src/test/compile-fail/consts/const-err3.rs b/src/test/compile-fail/consts/const-err3.rs
deleted file mode 100644
index fc10824..0000000
--- a/src/test/compile-fail/consts/const-err3.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-#![feature(rustc_attrs)]
-#![deny(const_err)]
-
-fn black_box<T>(_: T) {
-    unimplemented!()
-}
-
-fn main() {
-    let b = 200u8 + 200u8 + 200u8;
-    //~^ ERROR const_err
-    let c = 200u8 * 4;
-    //~^ ERROR const_err
-    let d = 42u8 - (42u8 + 1);
-    //~^ ERROR const_err
-    let _e = [5u8][1];
-    //~^ ERROR const_err
-    black_box(b);
-    black_box(c);
-    black_box(d);
-}
diff --git a/src/test/incremental/warnings-reemitted.rs b/src/test/incremental/warnings-reemitted.rs
index 5fc8939..0eac2a1 100644
--- a/src/test/incremental/warnings-reemitted.rs
+++ b/src/test/incremental/warnings-reemitted.rs
@@ -2,8 +2,8 @@
 // compile-flags: -Coverflow-checks=on
 // build-pass (FIXME(62277): could be check-pass?)
 
-#![warn(const_err)]
+#![warn(arithmetic_overflow)]
 
 fn main() {
-    let _ = 255u8 + 1; //~ WARNING attempt to add with overflow
+    let _ = 255u8 + 1; //~ WARNING operation will overflow
 }
diff --git a/src/test/run-fail/mir_indexing_oob_1.rs b/src/test/run-fail/mir_indexing_oob_1.rs
index 0ae0320..1cd53e3 100644
--- a/src/test/run-fail/mir_indexing_oob_1.rs
+++ b/src/test/run-fail/mir_indexing_oob_1.rs
@@ -2,7 +2,7 @@
 
 const C: [u32; 5] = [0; 5];
 
-#[allow(const_err)]
+#[allow(unconditional_panic)]
 fn test() -> u32 {
     C[10]
 }
diff --git a/src/test/run-fail/mir_indexing_oob_2.rs b/src/test/run-fail/mir_indexing_oob_2.rs
index a7a1177..64b2609 100644
--- a/src/test/run-fail/mir_indexing_oob_2.rs
+++ b/src/test/run-fail/mir_indexing_oob_2.rs
@@ -2,7 +2,7 @@
 
 const C: &'static [u8; 5] = b"hello";
 
-#[allow(const_err)]
+#[allow(unconditional_panic)]
 fn test() -> u8 {
     C[10]
 }
diff --git a/src/test/run-fail/mir_indexing_oob_3.rs b/src/test/run-fail/mir_indexing_oob_3.rs
index 188460f..3688088 100644
--- a/src/test/run-fail/mir_indexing_oob_3.rs
+++ b/src/test/run-fail/mir_indexing_oob_3.rs
@@ -2,7 +2,7 @@
 
 const C: &'static [u8; 5] = b"hello";
 
-#[allow(const_err)]
+#[allow(unconditional_panic)]
 fn mir() -> u8 {
     C[10]
 }
diff --git a/src/test/run-fail/overflowing-add.rs b/src/test/run-fail/overflowing-add.rs
index 24602ac..5ca9131 100644
--- a/src/test/run-fail/overflowing-add.rs
+++ b/src/test/run-fail/overflowing-add.rs
@@ -1,7 +1,7 @@
 // error-pattern:thread 'main' panicked at 'attempt to add with overflow'
 // compile-flags: -C debug-assertions
 
-#![allow(const_err)]
+#![allow(arithmetic_overflow)]
 
 fn main() {
     let _x = 200u8 + 200u8 + 200u8;
diff --git a/src/test/run-fail/overflowing-lsh-1.rs b/src/test/run-fail/overflowing-lsh-1.rs
index 37fbf01..977cfea 100644
--- a/src/test/run-fail/overflowing-lsh-1.rs
+++ b/src/test/run-fail/overflowing-lsh-1.rs
@@ -1,7 +1,7 @@
 // error-pattern:thread 'main' panicked at 'attempt to shift left with overflow'
 // compile-flags: -C debug-assertions
 
-#![warn(exceeding_bitshifts)]
+#![warn(arithmetic_overflow)]
 #![warn(const_err)]
 
 fn main() {
diff --git a/src/test/run-fail/overflowing-lsh-2.rs b/src/test/run-fail/overflowing-lsh-2.rs
index 7b0b37d..3517dac 100644
--- a/src/test/run-fail/overflowing-lsh-2.rs
+++ b/src/test/run-fail/overflowing-lsh-2.rs
@@ -1,7 +1,7 @@
 // error-pattern:thread 'main' panicked at 'attempt to shift left with overflow'
 // compile-flags: -C debug-assertions
 
-#![warn(exceeding_bitshifts)]
+#![warn(arithmetic_overflow)]
 #![warn(const_err)]
 
 fn main() {
diff --git a/src/test/run-fail/overflowing-lsh-3.rs b/src/test/run-fail/overflowing-lsh-3.rs
index 1768a8e..4a575c3 100644
--- a/src/test/run-fail/overflowing-lsh-3.rs
+++ b/src/test/run-fail/overflowing-lsh-3.rs
@@ -1,7 +1,7 @@
 // error-pattern:thread 'main' panicked at 'attempt to shift left with overflow'
 // compile-flags: -C debug-assertions
 
-#![warn(exceeding_bitshifts)]
+#![warn(arithmetic_overflow)]
 #![warn(const_err)]
 
 fn main() {
diff --git a/src/test/run-fail/overflowing-lsh-4.rs b/src/test/run-fail/overflowing-lsh-4.rs
index ec304b4..0d3912c 100644
--- a/src/test/run-fail/overflowing-lsh-4.rs
+++ b/src/test/run-fail/overflowing-lsh-4.rs
@@ -4,7 +4,7 @@
 // This function is checking that our automatic truncation does not
 // sidestep the overflow checking.
 
-#![warn(exceeding_bitshifts)]
+#![warn(arithmetic_overflow)]
 #![warn(const_err)]
 
 fn main() {
diff --git a/src/test/run-fail/overflowing-mul.rs b/src/test/run-fail/overflowing-mul.rs
index 4811036..2dfc9bb 100644
--- a/src/test/run-fail/overflowing-mul.rs
+++ b/src/test/run-fail/overflowing-mul.rs
@@ -1,7 +1,7 @@
 // error-pattern:thread 'main' panicked at 'attempt to multiply with overflow'
 // compile-flags: -C debug-assertions
 
-#![allow(const_err)]
+#![allow(arithmetic_overflow)]
 
 fn main() {
     let x = 200u8 * 4;
diff --git a/src/test/run-fail/overflowing-neg.rs b/src/test/run-fail/overflowing-neg.rs
index c4afd74..f512aa3 100644
--- a/src/test/run-fail/overflowing-neg.rs
+++ b/src/test/run-fail/overflowing-neg.rs
@@ -1,7 +1,7 @@
 // error-pattern:thread 'main' panicked at 'attempt to negate with overflow'
 // compile-flags: -C debug-assertions
 
-#![allow(const_err)]
+#![allow(arithmetic_overflow)]
 
 fn main() {
     let _x = -std::i8::MIN;
diff --git a/src/test/run-fail/overflowing-rsh-1.rs b/src/test/run-fail/overflowing-rsh-1.rs
index 1451454..4592b2b 100644
--- a/src/test/run-fail/overflowing-rsh-1.rs
+++ b/src/test/run-fail/overflowing-rsh-1.rs
@@ -1,7 +1,7 @@
 // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow'
 // compile-flags: -C debug-assertions
 
-#![warn(exceeding_bitshifts)]
+#![warn(arithmetic_overflow)]
 #![warn(const_err)]
 
 fn main() {
diff --git a/src/test/run-fail/overflowing-rsh-2.rs b/src/test/run-fail/overflowing-rsh-2.rs
index 83dcbd1..066267b 100644
--- a/src/test/run-fail/overflowing-rsh-2.rs
+++ b/src/test/run-fail/overflowing-rsh-2.rs
@@ -1,7 +1,7 @@
 // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow'
 // compile-flags: -C debug-assertions
 
-#![warn(exceeding_bitshifts)]
+#![warn(arithmetic_overflow)]
 #![warn(const_err)]
 
 fn main() {
diff --git a/src/test/run-fail/overflowing-rsh-3.rs b/src/test/run-fail/overflowing-rsh-3.rs
index 3521c05..67e7848 100644
--- a/src/test/run-fail/overflowing-rsh-3.rs
+++ b/src/test/run-fail/overflowing-rsh-3.rs
@@ -1,7 +1,7 @@
 // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow'
 // compile-flags: -C debug-assertions
 
-#![warn(exceeding_bitshifts)]
+#![warn(arithmetic_overflow)]
 #![warn(const_err)]
 
 fn main() {
diff --git a/src/test/run-fail/overflowing-rsh-4.rs b/src/test/run-fail/overflowing-rsh-4.rs
index ed11918..1877d5c 100644
--- a/src/test/run-fail/overflowing-rsh-4.rs
+++ b/src/test/run-fail/overflowing-rsh-4.rs
@@ -4,7 +4,7 @@
 // This function is checking that our (type-based) automatic
 // truncation does not sidestep the overflow checking.
 
-#![warn(exceeding_bitshifts)]
+#![warn(arithmetic_overflow)]
 #![warn(const_err)]
 
 fn main() {
diff --git a/src/test/run-fail/overflowing-rsh-5.rs b/src/test/run-fail/overflowing-rsh-5.rs
index 58dfc57..20ef324 100644
--- a/src/test/run-fail/overflowing-rsh-5.rs
+++ b/src/test/run-fail/overflowing-rsh-5.rs
@@ -1,7 +1,7 @@
 // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow'
 // compile-flags: -C debug-assertions
 
-#![warn(exceeding_bitshifts)]
+#![warn(arithmetic_overflow)]
 #![warn(const_err)]
 
 fn main() {
diff --git a/src/test/run-fail/overflowing-rsh-6.rs b/src/test/run-fail/overflowing-rsh-6.rs
index c2fec5e..589a98b 100644
--- a/src/test/run-fail/overflowing-rsh-6.rs
+++ b/src/test/run-fail/overflowing-rsh-6.rs
@@ -1,7 +1,7 @@
 // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow'
 // compile-flags: -C debug-assertions
 
-#![warn(exceeding_bitshifts)]
+#![warn(arithmetic_overflow)]
 #![warn(const_err)]
 #![feature(const_indexing)]
 
diff --git a/src/test/run-fail/overflowing-sub.rs b/src/test/run-fail/overflowing-sub.rs
index e3b111dd..fb096c3 100644
--- a/src/test/run-fail/overflowing-sub.rs
+++ b/src/test/run-fail/overflowing-sub.rs
@@ -1,7 +1,7 @@
 // error-pattern:thread 'main' panicked at 'attempt to subtract with overflow'
 // compile-flags: -C debug-assertions
 
-#![allow(const_err)]
+#![allow(arithmetic_overflow)]
 
 fn main() {
     let _x = 42u8 - (42u8 + 1);
diff --git a/src/test/run-fail/promoted_div_by_zero.rs b/src/test/run-fail/promoted_div_by_zero.rs
index 3fe51a1..dc6719c 100644
--- a/src/test/run-fail/promoted_div_by_zero.rs
+++ b/src/test/run-fail/promoted_div_by_zero.rs
@@ -1,4 +1,4 @@
-#![allow(const_err)]
+#![allow(unconditional_panic, const_err)]
 
 // error-pattern: attempt to divide by zero
 
diff --git a/src/test/run-fail/promoted_overflow.rs b/src/test/run-fail/promoted_overflow.rs
index 139bf54..3c42da4 100644
--- a/src/test/run-fail/promoted_overflow.rs
+++ b/src/test/run-fail/promoted_overflow.rs
@@ -1,4 +1,4 @@
-#![allow(const_err)]
+#![allow(arithmetic_overflow)]
 
 // error-pattern: overflow
 // compile-flags: -C overflow-checks=yes
diff --git a/src/test/ui/arg-count-mismatch.rs b/src/test/ui/arg-count-mismatch.rs
index cf74870..18926f5 100644
--- a/src/test/ui/arg-count-mismatch.rs
+++ b/src/test/ui/arg-count-mismatch.rs
@@ -1,4 +1,4 @@
-// error-pattern: parameters were supplied
+// error-pattern: arguments were supplied
 
 fn f(x: isize) { }
 
diff --git a/src/test/ui/arg-count-mismatch.stderr b/src/test/ui/arg-count-mismatch.stderr
index 44f1604..7bc0613 100644
--- a/src/test/ui/arg-count-mismatch.stderr
+++ b/src/test/ui/arg-count-mismatch.stderr
@@ -1,11 +1,13 @@
-error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/arg-count-mismatch.rs:5:28
    |
 LL | fn f(x: isize) { }
    | -------------- defined here
 LL | 
 LL | fn main() { let i: (); i = f(); }
-   |                            ^^^ expected 1 parameter
+   |                            ^-- supplied 0 arguments
+   |                            |
+   |                            expected 1 argument
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
index 2fdb383..999a583 100644
--- a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
@@ -4,7 +4,7 @@
 LL | impl <T: Sync> Foo for T { }
    |       --       ^^^
    |       |
-   |       help: consider adding an explicit lifetime bound `T: 'static`...
+   |       help: consider adding an explicit lifetime bound...: `T: 'static +`
    |
 note: ...so that the type `T` will meet its required lifetime bounds
   --> $DIR/builtin-superkinds-self-type.rs:10:16
diff --git a/src/test/ui/c-variadic/variadic-ffi-1.rs b/src/test/ui/c-variadic/variadic-ffi-1.rs
index 6a3ff24..e7197a9 100644
--- a/src/test/ui/c-variadic/variadic-ffi-1.rs
+++ b/src/test/ui/c-variadic/variadic-ffi-1.rs
@@ -13,8 +13,8 @@
 
 fn main() {
     unsafe {
-        foo();  //~ ERROR this function takes at least 2 parameters but 0 parameters were supplied
-        foo(1); //~ ERROR this function takes at least 2 parameters but 1 parameter was supplied
+        foo();  //~ ERROR this function takes at least 2 arguments but 0 arguments were supplied
+        foo(1); //~ ERROR this function takes at least 2 arguments but 1 argument was supplied
 
         let x: unsafe extern "C" fn(f: isize, x: u8) = foo; //~ ERROR mismatched types
         let y: extern "C" fn(f: isize, x: u8, ...) = bar; //~ ERROR mismatched types
diff --git a/src/test/ui/c-variadic/variadic-ffi-1.stderr b/src/test/ui/c-variadic/variadic-ffi-1.stderr
index 05d839a..318b8aa 100644
--- a/src/test/ui/c-variadic/variadic-ffi-1.stderr
+++ b/src/test/ui/c-variadic/variadic-ffi-1.stderr
@@ -4,23 +4,27 @@
 LL |     fn printf(_: *const u8, ...);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadics require C or cdecl calling convention
 
-error[E0060]: this function takes at least 2 parameters but 0 parameters were supplied
+error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied
   --> $DIR/variadic-ffi-1.rs:16:9
    |
 LL |     fn foo(f: isize, x: u8, ...);
    |     ----------------------------- defined here
 ...
 LL |         foo();
-   |         ^^^^^ expected at least 2 parameters
+   |         ^^^-- supplied 0 arguments
+   |         |
+   |         expected at least 2 arguments
 
-error[E0060]: this function takes at least 2 parameters but 1 parameter was supplied
+error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
   --> $DIR/variadic-ffi-1.rs:17:9
    |
 LL |     fn foo(f: isize, x: u8, ...);
    |     ----------------------------- defined here
 ...
 LL |         foo(1);
-   |         ^^^^^^ expected at least 2 parameters
+   |         ^^^ - supplied 1 argument
+   |         |
+   |         expected at least 2 arguments
 
 error[E0308]: mismatched types
   --> $DIR/variadic-ffi-1.rs:19:56
diff --git a/src/test/ui/consts/array-literal-index-oob.rs b/src/test/ui/consts/array-literal-index-oob.rs
index af63d1f..492afa9 100644
--- a/src/test/ui/consts/array-literal-index-oob.rs
+++ b/src/test/ui/consts/array-literal-index-oob.rs
@@ -1,11 +1,11 @@
 // build-pass
 // ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors)
 
-#![warn(const_err)]
+#![warn(const_err, unconditional_panic)]
 
 fn main() {
     &{ [1, 2, 3][4] };
-    //~^ WARN index out of bounds
+    //~^ WARN operation will panic
     //~| WARN reaching this expression at runtime will panic or abort
     //~| WARN erroneous constant used [const_err]
 }
diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr
index 59e1169..6e0e7fe 100644
--- a/src/test/ui/consts/array-literal-index-oob.stderr
+++ b/src/test/ui/consts/array-literal-index-oob.stderr
@@ -1,14 +1,14 @@
-warning: index out of bounds: the len is 3 but the index is 4
+warning: this operation will panic at runtime
   --> $DIR/array-literal-index-oob.rs:7:8
    |
 LL |     &{ [1, 2, 3][4] };
-   |        ^^^^^^^^^^^^
+   |        ^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 4
    |
 note: the lint level is defined here
-  --> $DIR/array-literal-index-oob.rs:4:9
+  --> $DIR/array-literal-index-oob.rs:4:20
    |
-LL | #![warn(const_err)]
-   |         ^^^^^^^^^
+LL | #![warn(const_err, unconditional_panic)]
+   |                    ^^^^^^^^^^^^^^^^^^^
 
 warning: reaching this expression at runtime will panic or abort
   --> $DIR/array-literal-index-oob.rs:7:8
@@ -17,6 +17,12 @@
    |     ---^^^^^^^^^^^^--
    |        |
    |        indexing out of bounds: the len is 3 but the index is 4
+   |
+note: the lint level is defined here
+  --> $DIR/array-literal-index-oob.rs:4:9
+   |
+LL | #![warn(const_err, unconditional_panic)]
+   |         ^^^^^^^^^
 
 warning: erroneous constant used
   --> $DIR/array-literal-index-oob.rs:7:5
diff --git a/src/test/ui/consts/const-err.rs b/src/test/ui/consts/const-err.rs
index b204f70..d1c5f4f 100644
--- a/src/test/ui/consts/const-err.rs
+++ b/src/test/ui/consts/const-err.rs
@@ -1,7 +1,7 @@
 // build-fail
 // compile-flags: -Zforce-overflow-checks=on
 
-#![allow(exceeding_bitshifts)]
+#![allow(arithmetic_overflow)]
 #![warn(const_err)]
 
 fn black_box<T>(_: T) {
diff --git a/src/test/ui/consts/const-err2.noopt.stderr b/src/test/ui/consts/const-err2.noopt.stderr
new file mode 100644
index 0000000..5aeeec4
--- /dev/null
+++ b/src/test/ui/consts/const-err2.noopt.stderr
@@ -0,0 +1,48 @@
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:19:13
+   |
+LL |     let a = -std::i8::MIN;
+   |             ^^^^^^^^^^^^^ attempt to negate with overflow
+   |
+   = note: `#[deny(arithmetic_overflow)]` on by default
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:21:18
+   |
+LL |     let a_i128 = -std::i128::MIN;
+   |                  ^^^^^^^^^^^^^^^ attempt to negate with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:23:13
+   |
+LL |     let b = 200u8 + 200u8 + 200u8;
+   |             ^^^^^^^^^^^^^ attempt to add with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:25:18
+   |
+LL |     let b_i128 = std::i128::MIN - std::i128::MAX;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:27:13
+   |
+LL |     let c = 200u8 * 4;
+   |             ^^^^^^^^^ attempt to multiply with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:29:13
+   |
+LL |     let d = 42u8 - (42u8 + 1);
+   |             ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+
+error: this operation will panic at runtime
+  --> $DIR/const-err2.rs:31:14
+   |
+LL |     let _e = [5u8][1];
+   |              ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/consts/const-err2.opt.stderr b/src/test/ui/consts/const-err2.opt.stderr
new file mode 100644
index 0000000..5aeeec4
--- /dev/null
+++ b/src/test/ui/consts/const-err2.opt.stderr
@@ -0,0 +1,48 @@
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:19:13
+   |
+LL |     let a = -std::i8::MIN;
+   |             ^^^^^^^^^^^^^ attempt to negate with overflow
+   |
+   = note: `#[deny(arithmetic_overflow)]` on by default
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:21:18
+   |
+LL |     let a_i128 = -std::i128::MIN;
+   |                  ^^^^^^^^^^^^^^^ attempt to negate with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:23:13
+   |
+LL |     let b = 200u8 + 200u8 + 200u8;
+   |             ^^^^^^^^^^^^^ attempt to add with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:25:18
+   |
+LL |     let b_i128 = std::i128::MIN - std::i128::MAX;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:27:13
+   |
+LL |     let c = 200u8 * 4;
+   |             ^^^^^^^^^ attempt to multiply with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:29:13
+   |
+LL |     let d = 42u8 - (42u8 + 1);
+   |             ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+
+error: this operation will panic at runtime
+  --> $DIR/const-err2.rs:31:14
+   |
+LL |     let _e = [5u8][1];
+   |              ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr b/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr
new file mode 100644
index 0000000..5aeeec4
--- /dev/null
+++ b/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr
@@ -0,0 +1,48 @@
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:19:13
+   |
+LL |     let a = -std::i8::MIN;
+   |             ^^^^^^^^^^^^^ attempt to negate with overflow
+   |
+   = note: `#[deny(arithmetic_overflow)]` on by default
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:21:18
+   |
+LL |     let a_i128 = -std::i128::MIN;
+   |                  ^^^^^^^^^^^^^^^ attempt to negate with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:23:13
+   |
+LL |     let b = 200u8 + 200u8 + 200u8;
+   |             ^^^^^^^^^^^^^ attempt to add with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:25:18
+   |
+LL |     let b_i128 = std::i128::MIN - std::i128::MAX;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:27:13
+   |
+LL |     let c = 200u8 * 4;
+   |             ^^^^^^^^^ attempt to multiply with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/const-err2.rs:29:13
+   |
+LL |     let d = 42u8 - (42u8 + 1);
+   |             ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+
+error: this operation will panic at runtime
+  --> $DIR/const-err2.rs:31:14
+   |
+LL |     let _e = [5u8][1];
+   |              ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs
index 7c5aaed..2c6a987 100644
--- a/src/test/ui/consts/const-err2.rs
+++ b/src/test/ui/consts/const-err2.rs
@@ -2,13 +2,14 @@
 // optimized compilation and unoptimized compilation and thus would
 // lead to different lints being emitted
 
+// revisions: noopt opt opt_with_overflow_checks
+//[noopt]compile-flags: -C opt-level=0
+//[opt]compile-flags: -O
+//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O
+
 // build-fail
-// compile-flags: -O
 
 #![feature(rustc_attrs)]
-#![allow(exceeding_bitshifts)]
-
-#![deny(const_err)]
 
 fn black_box<T>(_: T) {
     unimplemented!()
@@ -16,19 +17,19 @@
 
 fn main() {
     let a = -std::i8::MIN;
-    //~^ ERROR const_err
+    //~^ ERROR arithmetic operation will overflow
     let a_i128 = -std::i128::MIN;
-    //~^ ERROR const_err
+    //~^ ERROR arithmetic operation will overflow
     let b = 200u8 + 200u8 + 200u8;
-    //~^ ERROR const_err
+    //~^ ERROR arithmetic operation will overflow
     let b_i128 = std::i128::MIN - std::i128::MAX;
-    //~^ ERROR const_err
+    //~^ ERROR arithmetic operation will overflow
     let c = 200u8 * 4;
-    //~^ ERROR const_err
+    //~^ ERROR arithmetic operation will overflow
     let d = 42u8 - (42u8 + 1);
-    //~^ ERROR const_err
+    //~^ ERROR arithmetic operation will overflow
     let _e = [5u8][1];
-    //~^ ERROR const_err
+    //~^ ERROR operation will panic
     black_box(a);
     black_box(a_i128);
     black_box(b);
diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr
deleted file mode 100644
index f135bf0..0000000
--- a/src/test/ui/consts/const-err2.stderr
+++ /dev/null
@@ -1,50 +0,0 @@
-error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:18:13
-   |
-LL |     let a = -std::i8::MIN;
-   |             ^^^^^^^^^^^^^ attempt to negate with overflow
-   |
-note: the lint level is defined here
-  --> $DIR/const-err2.rs:11:9
-   |
-LL | #![deny(const_err)]
-   |         ^^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:20:18
-   |
-LL |     let a_i128 = -std::i128::MIN;
-   |                  ^^^^^^^^^^^^^^^ attempt to negate with overflow
-
-error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:22:13
-   |
-LL |     let b = 200u8 + 200u8 + 200u8;
-   |             ^^^^^^^^^^^^^ attempt to add with overflow
-
-error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:24:18
-   |
-LL |     let b_i128 = std::i128::MIN - std::i128::MAX;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
-
-error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:26:13
-   |
-LL |     let c = 200u8 * 4;
-   |             ^^^^^^^^^ attempt to multiply with overflow
-
-error: this expression will panic at runtime
-  --> $DIR/const-err2.rs:28:13
-   |
-LL |     let d = 42u8 - (42u8 + 1);
-   |             ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
-
-error: index out of bounds: the len is 1 but the index is 1
-  --> $DIR/const-err2.rs:30:14
-   |
-LL |     let _e = [5u8][1];
-   |              ^^^^^^^^
-
-error: aborting due to 7 previous errors
-
diff --git a/src/test/ui/consts/const-err3.rs b/src/test/ui/consts/const-err3.rs
deleted file mode 100644
index 43aba4a..0000000
--- a/src/test/ui/consts/const-err3.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-// needed because negating int::MIN will behave differently between
-// optimized compilation and unoptimized compilation and thus would
-// lead to different lints being emitted
-
-// build-fail
-// compile-flags: -C overflow-checks=on -O
-
-#![feature(rustc_attrs)]
-#![allow(exceeding_bitshifts)]
-
-#![deny(const_err)]
-
-fn black_box<T>(_: T) {
-    unimplemented!()
-}
-
-fn main() {
-    let a = -std::i8::MIN;
-    //~^ ERROR const_err
-    let a_i128 = -std::i128::MIN;
-    //~^ ERROR const_err
-    let b = 200u8 + 200u8 + 200u8;
-    //~^ ERROR const_err
-    let b_i128 = std::i128::MIN - std::i128::MAX;
-    //~^ ERROR const_err
-    let c = 200u8 * 4;
-    //~^ ERROR const_err
-    let d = 42u8 - (42u8 + 1);
-    //~^ ERROR const_err
-    let _e = [5u8][1];
-    //~^ ERROR const_err
-    black_box(a);
-    black_box(a_i128);
-    black_box(b);
-    black_box(b_i128);
-    black_box(c);
-    black_box(d);
-}
diff --git a/src/test/ui/consts/const-err3.stderr b/src/test/ui/consts/const-err3.stderr
deleted file mode 100644
index 05f64b8..0000000
--- a/src/test/ui/consts/const-err3.stderr
+++ /dev/null
@@ -1,50 +0,0 @@
-error: attempt to negate with overflow
-  --> $DIR/const-err3.rs:18:13
-   |
-LL |     let a = -std::i8::MIN;
-   |             ^^^^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/const-err3.rs:11:9
-   |
-LL | #![deny(const_err)]
-   |         ^^^^^^^^^
-
-error: attempt to negate with overflow
-  --> $DIR/const-err3.rs:20:18
-   |
-LL |     let a_i128 = -std::i128::MIN;
-   |                  ^^^^^^^^^^^^^^^
-
-error: attempt to add with overflow
-  --> $DIR/const-err3.rs:22:13
-   |
-LL |     let b = 200u8 + 200u8 + 200u8;
-   |             ^^^^^^^^^^^^^
-
-error: attempt to subtract with overflow
-  --> $DIR/const-err3.rs:24:18
-   |
-LL |     let b_i128 = std::i128::MIN - std::i128::MAX;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: attempt to multiply with overflow
-  --> $DIR/const-err3.rs:26:13
-   |
-LL |     let c = 200u8 * 4;
-   |             ^^^^^^^^^
-
-error: attempt to subtract with overflow
-  --> $DIR/const-err3.rs:28:13
-   |
-LL |     let d = 42u8 - (42u8 + 1);
-   |             ^^^^^^^^^^^^^^^^^
-
-error: index out of bounds: the len is 1 but the index is 1
-  --> $DIR/const-err3.rs:30:14
-   |
-LL |     let _e = [5u8][1];
-   |              ^^^^^^^^
-
-error: aborting due to 7 previous errors
-
diff --git a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs
index 6d6bb94..608e6e1 100644
--- a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs
+++ b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs
@@ -2,5 +2,5 @@
 
 fn main() {
     let array = [std::env::args().len()];
-    array[1]; //~ ERROR index out of bounds
+    array[1]; //~ ERROR operation will panic
 }
diff --git a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr
index 9519ccd..4188efd 100644
--- a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr
+++ b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr
@@ -1,10 +1,10 @@
-error: index out of bounds: the len is 1 but the index is 1
+error: this operation will panic at runtime
   --> $DIR/index_out_of_bounds_propagated.rs:5:5
    |
 LL |     array[1];
-   |     ^^^^^^^^
+   |     ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
    |
-   = note: `#[deny(const_err)]` on by default
+   = note: `#[deny(unconditional_panic)]` on by default
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr b/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr
new file mode 100644
index 0000000..94c1593
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr
@@ -0,0 +1,78 @@
+warning: this arithmetic operation will overflow
+  --> $DIR/promoted_errors.rs:12:20
+   |
+LL |     println!("{}", 0u32 - 1);
+   |                    ^^^^^^^^ attempt to subtract with overflow
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:9:20
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |                    ^^^^^^^^^^^^^^^^^^^
+
+warning: this arithmetic operation will overflow
+  --> $DIR/promoted_errors.rs:14:14
+   |
+LL |     let _x = 0u32 - 1;
+   |              ^^^^^^^^ attempt to subtract with overflow
+
+warning: this operation will panic at runtime
+  --> $DIR/promoted_errors.rs:16:20
+   |
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ attempt to divide by zero
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:9:41
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |                                         ^^^^^^^^^^^^^^^^^^^
+
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors.rs:16:20
+   |
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ dividing by zero
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:9:9
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |         ^^^^^^^^^
+
+warning: erroneous constant used
+  --> $DIR/promoted_errors.rs:16:20
+   |
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ referenced constant has errors
+
+warning: this operation will panic at runtime
+  --> $DIR/promoted_errors.rs:20:14
+   |
+LL |     let _x = 1 / (1 - 1);
+   |              ^^^^^^^^^^^ attempt to divide by zero
+
+warning: this operation will panic at runtime
+  --> $DIR/promoted_errors.rs:22:20
+   |
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ attempt to divide by zero
+
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors.rs:22:20
+   |
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ dividing by zero
+
+warning: erroneous constant used
+  --> $DIR/promoted_errors.rs:22:20
+   |
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+warning: this operation will panic at runtime
+  --> $DIR/promoted_errors.rs:26:14
+   |
+LL |     let _x = 1 / (false as u32);
+   |              ^^^^^^^^^^^^^^^^^^ attempt to divide by zero
+
diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr
new file mode 100644
index 0000000..034dea0
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr
@@ -0,0 +1,72 @@
+warning: this arithmetic operation will overflow
+  --> $DIR/promoted_errors.rs:14:14
+   |
+LL |     let _x = 0u32 - 1;
+   |              ^^^^^^^^ attempt to subtract with overflow
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:9:20
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |                    ^^^^^^^^^^^^^^^^^^^
+
+warning: this operation will panic at runtime
+  --> $DIR/promoted_errors.rs:16:20
+   |
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ attempt to divide by zero
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:9:41
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |                                         ^^^^^^^^^^^^^^^^^^^
+
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors.rs:16:20
+   |
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ dividing by zero
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:9:9
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |         ^^^^^^^^^
+
+warning: erroneous constant used
+  --> $DIR/promoted_errors.rs:16:20
+   |
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ referenced constant has errors
+
+warning: this operation will panic at runtime
+  --> $DIR/promoted_errors.rs:20:14
+   |
+LL |     let _x = 1 / (1 - 1);
+   |              ^^^^^^^^^^^ attempt to divide by zero
+
+warning: this operation will panic at runtime
+  --> $DIR/promoted_errors.rs:22:20
+   |
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ attempt to divide by zero
+
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors.rs:22:20
+   |
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ dividing by zero
+
+warning: erroneous constant used
+  --> $DIR/promoted_errors.rs:22:20
+   |
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+warning: this operation will panic at runtime
+  --> $DIR/promoted_errors.rs:26:14
+   |
+LL |     let _x = 1 / (false as u32);
+   |              ^^^^^^^^^^^^^^^^^^ attempt to divide by zero
+
diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr
new file mode 100644
index 0000000..94c1593
--- /dev/null
+++ b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr
@@ -0,0 +1,78 @@
+warning: this arithmetic operation will overflow
+  --> $DIR/promoted_errors.rs:12:20
+   |
+LL |     println!("{}", 0u32 - 1);
+   |                    ^^^^^^^^ attempt to subtract with overflow
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:9:20
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |                    ^^^^^^^^^^^^^^^^^^^
+
+warning: this arithmetic operation will overflow
+  --> $DIR/promoted_errors.rs:14:14
+   |
+LL |     let _x = 0u32 - 1;
+   |              ^^^^^^^^ attempt to subtract with overflow
+
+warning: this operation will panic at runtime
+  --> $DIR/promoted_errors.rs:16:20
+   |
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ attempt to divide by zero
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:9:41
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |                                         ^^^^^^^^^^^^^^^^^^^
+
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors.rs:16:20
+   |
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ dividing by zero
+   |
+note: the lint level is defined here
+  --> $DIR/promoted_errors.rs:9:9
+   |
+LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
+   |         ^^^^^^^^^
+
+warning: erroneous constant used
+  --> $DIR/promoted_errors.rs:16:20
+   |
+LL |     println!("{}", 1 / (1 - 1));
+   |                    ^^^^^^^^^^^ referenced constant has errors
+
+warning: this operation will panic at runtime
+  --> $DIR/promoted_errors.rs:20:14
+   |
+LL |     let _x = 1 / (1 - 1);
+   |              ^^^^^^^^^^^ attempt to divide by zero
+
+warning: this operation will panic at runtime
+  --> $DIR/promoted_errors.rs:22:20
+   |
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ attempt to divide by zero
+
+warning: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors.rs:22:20
+   |
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ dividing by zero
+
+warning: erroneous constant used
+  --> $DIR/promoted_errors.rs:22:20
+   |
+LL |     println!("{}", 1 / (false as u32));
+   |                    ^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+warning: this operation will panic at runtime
+  --> $DIR/promoted_errors.rs:26:14
+   |
+LL |     let _x = 1 / (false as u32);
+   |              ^^^^^^^^^^^^^^^^^^ attempt to divide by zero
+
diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs
index 22f863f..3ab6ce2 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.rs
+++ b/src/test/ui/consts/const-eval/promoted_errors.rs
@@ -1,23 +1,28 @@
+// revisions: noopt opt opt_with_overflow_checks
+//[noopt]compile-flags: -C opt-level=0
+//[opt]compile-flags: -O
+//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O
+
 // build-pass
 // ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors)
-// compile-flags: -O
 
-#![warn(const_err)]
+#![warn(const_err, arithmetic_overflow, unconditional_panic)]
 
 fn main() {
     println!("{}", 0u32 - 1);
+    //[opt_with_overflow_checks,noopt]~^ WARN [arithmetic_overflow]
     let _x = 0u32 - 1;
-    //~^ WARN const_err
+    //~^ WARN [arithmetic_overflow]
     println!("{}", 1 / (1 - 1));
-    //~^ WARN attempt to divide by zero [const_err]
-    //~| WARN const_err
+    //~^ WARN [unconditional_panic]
+    //~| WARN panic or abort [const_err]
     //~| WARN erroneous constant used [const_err]
     let _x = 1 / (1 - 1);
-    //~^ WARN const_err
+    //~^ WARN [unconditional_panic]
     println!("{}", 1 / (false as u32));
-    //~^ WARN attempt to divide by zero [const_err]
-    //~| WARN const_err
+    //~^ WARN [unconditional_panic]
+    //~| WARN panic or abort [const_err]
     //~| WARN erroneous constant used [const_err]
     let _x = 1 / (false as u32);
-    //~^ WARN const_err
+    //~^ WARN [unconditional_panic]
 }
diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr
deleted file mode 100644
index 08ae5c7..0000000
--- a/src/test/ui/consts/const-eval/promoted_errors.stderr
+++ /dev/null
@@ -1,60 +0,0 @@
-warning: this expression will panic at runtime
-  --> $DIR/promoted_errors.rs:9:14
-   |
-LL |     let _x = 0u32 - 1;
-   |              ^^^^^^^^ attempt to subtract with overflow
-   |
-note: the lint level is defined here
-  --> $DIR/promoted_errors.rs:5:9
-   |
-LL | #![warn(const_err)]
-   |         ^^^^^^^^^
-
-warning: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:11:20
-   |
-LL |     println!("{}", 1 / (1 - 1));
-   |                    ^^^^^^^^^^^
-
-warning: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors.rs:11:20
-   |
-LL |     println!("{}", 1 / (1 - 1));
-   |                    ^^^^^^^^^^^ dividing by zero
-
-warning: erroneous constant used
-  --> $DIR/promoted_errors.rs:11:20
-   |
-LL |     println!("{}", 1 / (1 - 1));
-   |                    ^^^^^^^^^^^ referenced constant has errors
-
-warning: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:15:14
-   |
-LL |     let _x = 1 / (1 - 1);
-   |              ^^^^^^^^^^^
-
-warning: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:17:20
-   |
-LL |     println!("{}", 1 / (false as u32));
-   |                    ^^^^^^^^^^^^^^^^^^
-
-warning: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors.rs:17:20
-   |
-LL |     println!("{}", 1 / (false as u32));
-   |                    ^^^^^^^^^^^^^^^^^^ dividing by zero
-
-warning: erroneous constant used
-  --> $DIR/promoted_errors.rs:17:20
-   |
-LL |     println!("{}", 1 / (false as u32));
-   |                    ^^^^^^^^^^^^^^^^^^ referenced constant has errors
-
-warning: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:21:14
-   |
-LL |     let _x = 1 / (false as u32);
-   |              ^^^^^^^^^^^^^^^^^^
-
diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs
deleted file mode 100644
index 62c77f7..0000000
--- a/src/test/ui/consts/const-eval/promoted_errors2.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-// build-pass
-// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors)
-// compile-flags: -C overflow-checks=on -O
-
-#![warn(const_err)]
-
-fn main() {
-    println!("{}", 0u32 - 1);
-    //~^ WARN attempt to subtract with overflow
-    let _x = 0u32 - 1;
-    //~^ WARN attempt to subtract with overflow
-    println!("{}", 1 / (1 - 1));
-    //~^ WARN attempt to divide by zero [const_err]
-    //~| WARN const_err
-    //~| WARN erroneous constant used [const_err]
-    let _x = 1 / (1 - 1);
-    //~^ WARN const_err
-    println!("{}", 1 / (false as u32));
-    //~^ WARN attempt to divide by zero [const_err]
-    //~| WARN const_err
-    //~| WARN erroneous constant used [const_err]
-    let _x = 1 / (false as u32);
-    //~^ WARN const_err
-}
diff --git a/src/test/ui/consts/const-eval/promoted_errors2.stderr b/src/test/ui/consts/const-eval/promoted_errors2.stderr
deleted file mode 100644
index d1a9cb9..0000000
--- a/src/test/ui/consts/const-eval/promoted_errors2.stderr
+++ /dev/null
@@ -1,66 +0,0 @@
-warning: attempt to subtract with overflow
-  --> $DIR/promoted_errors2.rs:8:20
-   |
-LL |     println!("{}", 0u32 - 1);
-   |                    ^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/promoted_errors2.rs:5:9
-   |
-LL | #![warn(const_err)]
-   |         ^^^^^^^^^
-
-warning: attempt to subtract with overflow
-  --> $DIR/promoted_errors2.rs:10:14
-   |
-LL |     let _x = 0u32 - 1;
-   |              ^^^^^^^^
-
-warning: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:12:20
-   |
-LL |     println!("{}", 1 / (1 - 1));
-   |                    ^^^^^^^^^^^
-
-warning: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors2.rs:12:20
-   |
-LL |     println!("{}", 1 / (1 - 1));
-   |                    ^^^^^^^^^^^ dividing by zero
-
-warning: erroneous constant used
-  --> $DIR/promoted_errors2.rs:12:20
-   |
-LL |     println!("{}", 1 / (1 - 1));
-   |                    ^^^^^^^^^^^ referenced constant has errors
-
-warning: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:16:14
-   |
-LL |     let _x = 1 / (1 - 1);
-   |              ^^^^^^^^^^^
-
-warning: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:18:20
-   |
-LL |     println!("{}", 1 / (false as u32));
-   |                    ^^^^^^^^^^^^^^^^^^
-
-warning: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors2.rs:18:20
-   |
-LL |     println!("{}", 1 / (false as u32));
-   |                    ^^^^^^^^^^^^^^^^^^ dividing by zero
-
-warning: erroneous constant used
-  --> $DIR/promoted_errors2.rs:18:20
-   |
-LL |     println!("{}", 1 / (false as u32));
-   |                    ^^^^^^^^^^^^^^^^^^ referenced constant has errors
-
-warning: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:22:14
-   |
-LL |     let _x = 1 / (false as u32);
-   |              ^^^^^^^^^^^^^^^^^^
-
diff --git a/src/test/ui/consts/const-int-pow-rpass.rs b/src/test/ui/consts/const-int-pow-rpass.rs
index 8e84a90..b0fba19 100644
--- a/src/test/ui/consts/const-int-pow-rpass.rs
+++ b/src/test/ui/consts/const-int-pow-rpass.rs
@@ -1,11 +1,48 @@
 // run-pass
 
+#![feature(const_int_pow)]
+#![feature(wrapping_next_power_of_two)]
+
 const IS_POWER_OF_TWO_A: bool = 0u32.is_power_of_two();
 const IS_POWER_OF_TWO_B: bool = 32u32.is_power_of_two();
 const IS_POWER_OF_TWO_C: bool = 33u32.is_power_of_two();
 
+const POW: u8 = 3u8.pow(5);
+
+const CHECKED_POW_OK: Option<u8> = 3u8.checked_pow(5);
+const CHECKED_POW_OVERFLOW: Option<u8> = 3u8.checked_pow(6);
+
+const WRAPPING_POW: u8 = 3u8.wrapping_pow(6);
+const OVERFLOWING_POW: (u8, bool) = 3u8.overflowing_pow(6);
+const SATURATING_POW: u8 = 3u8.saturating_pow(6);
+
+const NEXT_POWER_OF_TWO: u32 = 3u32.next_power_of_two();
+
+const CHECKED_NEXT_POWER_OF_TWO_OK: Option<u32> = 3u32.checked_next_power_of_two();
+const CHECKED_NEXT_POWER_OF_TWO_OVERFLOW: Option<u32> =
+    u32::max_value().checked_next_power_of_two();
+
+const WRAPPING_NEXT_POWER_OF_TWO: u32 =
+    u32::max_value().wrapping_next_power_of_two();
+
 fn main() {
     assert!(!IS_POWER_OF_TWO_A);
     assert!(IS_POWER_OF_TWO_B);
     assert!(!IS_POWER_OF_TWO_C);
+
+    assert_eq!(POW, 243);
+
+    assert_eq!(CHECKED_POW_OK, Some(243));
+    assert_eq!(CHECKED_POW_OVERFLOW, None);
+
+    assert_eq!(WRAPPING_POW, 217);
+    assert_eq!(OVERFLOWING_POW, (217, true));
+    assert_eq!(SATURATING_POW, u8::max_value());
+
+    assert_eq!(NEXT_POWER_OF_TWO, 4);
+
+    assert_eq!(CHECKED_NEXT_POWER_OF_TWO_OK, Some(4));
+    assert_eq!(CHECKED_NEXT_POWER_OF_TWO_OVERFLOW, None);
+
+    assert_eq!(WRAPPING_NEXT_POWER_OF_TWO, 0);
 }
diff --git a/src/test/ui/consts/const-prop-ice.rs b/src/test/ui/consts/const-prop-ice.rs
index 8682d2e..5bffe02 100644
--- a/src/test/ui/consts/const-prop-ice.rs
+++ b/src/test/ui/consts/const-prop-ice.rs
@@ -1,5 +1,5 @@
 // build-fail
 
 fn main() {
-    [0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3
+    [0; 3][3u64 as usize]; //~ ERROR this operation will panic at runtime
 }
diff --git a/src/test/ui/consts/const-prop-ice.stderr b/src/test/ui/consts/const-prop-ice.stderr
index 65502a4..7bb4acb 100644
--- a/src/test/ui/consts/const-prop-ice.stderr
+++ b/src/test/ui/consts/const-prop-ice.stderr
@@ -1,10 +1,10 @@
-error: index out of bounds: the len is 3 but the index is 3
+error: this operation will panic at runtime
   --> $DIR/const-prop-ice.rs:4:5
    |
 LL |     [0; 3][3u64 as usize];
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 3
    |
-   = note: `#[deny(const_err)]` on by default
+   = note: `#[deny(unconditional_panic)]` on by default
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-prop-ice2.rs b/src/test/ui/consts/const-prop-ice2.rs
index 6a73483..d533e39 100644
--- a/src/test/ui/consts/const-prop-ice2.rs
+++ b/src/test/ui/consts/const-prop-ice2.rs
@@ -3,5 +3,5 @@
 fn main() {
     enum Enum { One=1 }
     let xs=[0;1 as usize];
-    println!("{}", xs[Enum::One as usize]); //~ ERROR the len is 1 but the index is 1
+    println!("{}", xs[Enum::One as usize]); //~ ERROR this operation will panic at runtime
 }
diff --git a/src/test/ui/consts/const-prop-ice2.stderr b/src/test/ui/consts/const-prop-ice2.stderr
index cbb8fde..73405ec 100644
--- a/src/test/ui/consts/const-prop-ice2.stderr
+++ b/src/test/ui/consts/const-prop-ice2.stderr
@@ -1,10 +1,10 @@
-error: index out of bounds: the len is 1 but the index is 1
+error: this operation will panic at runtime
   --> $DIR/const-prop-ice2.rs:6:20
    |
 LL |     println!("{}", xs[Enum::One as usize]);
-   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
    |
-   = note: `#[deny(const_err)]` on by default
+   = note: `#[deny(unconditional_panic)]` on by default
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/is_ascii.rs b/src/test/ui/consts/is_ascii.rs
new file mode 100644
index 0000000..d842454
--- /dev/null
+++ b/src/test/ui/consts/is_ascii.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+static X: bool = 'a'.is_ascii();
+static Y: bool = 'ä'.is_ascii();
+
+static BX: bool = b'a'.is_ascii();
+static BY: bool = 192u8.is_ascii();
+
+fn main() {
+    assert!(X);
+    assert!(!Y);
+
+    assert!(BX);
+    assert!(!BY);
+}
diff --git a/src/test/ui/consts/issue-64059-2.rs b/src/test/ui/consts/issue-64059-2.rs
deleted file mode 100644
index 38911c3..0000000
--- a/src/test/ui/consts/issue-64059-2.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// compile-flags: -C overflow-checks=on -O
-// run-pass
-
-fn main() {
-    let _ = -(-0.0);
-}
diff --git a/src/test/ui/consts/issue-64059.rs b/src/test/ui/consts/issue-64059.rs
index c4c895f..02c8b72 100644
--- a/src/test/ui/consts/issue-64059.rs
+++ b/src/test/ui/consts/issue-64059.rs
@@ -1,3 +1,8 @@
+// revisions: noopt opt opt_with_overflow_checks
+//[noopt]compile-flags: -C opt-level=0
+//[opt]compile-flags: -O
+//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O
+
 // run-pass
 
 fn main() {
diff --git a/src/test/ui/consts/issue-69020.noopt.stderr b/src/test/ui/consts/issue-69020.noopt.stderr
new file mode 100644
index 0000000..c48a106
--- /dev/null
+++ b/src/test/ui/consts/issue-69020.noopt.stderr
@@ -0,0 +1,30 @@
+error: this arithmetic operation will overflow
+  --> $DIR/issue-69020.rs:21:22
+   |
+LL |     const NEG: i32 = -i32::MIN + T::NEG;
+   |                      ^^^^^^^^^ attempt to negate with overflow
+   |
+   = note: `#[deny(arithmetic_overflow)]` on by default
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-69020.rs:23:22
+   |
+LL |     const ADD: i32 = (i32::MAX+1) + T::ADD;
+   |                      ^^^^^^^^^^^^ attempt to add with overflow
+
+error: this operation will panic at runtime
+  --> $DIR/issue-69020.rs:25:22
+   |
+LL |     const DIV: i32 = (1/0) + T::DIV;
+   |                      ^^^^^ attempt to divide by zero
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+  --> $DIR/issue-69020.rs:27:22
+   |
+LL |     const OOB: i32 = [1][1] + T::OOB;
+   |                      ^^^^^^ index out of bounds: the len is 1 but the index is 1
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/consts/issue-69020.opt.stderr b/src/test/ui/consts/issue-69020.opt.stderr
new file mode 100644
index 0000000..c48a106
--- /dev/null
+++ b/src/test/ui/consts/issue-69020.opt.stderr
@@ -0,0 +1,30 @@
+error: this arithmetic operation will overflow
+  --> $DIR/issue-69020.rs:21:22
+   |
+LL |     const NEG: i32 = -i32::MIN + T::NEG;
+   |                      ^^^^^^^^^ attempt to negate with overflow
+   |
+   = note: `#[deny(arithmetic_overflow)]` on by default
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-69020.rs:23:22
+   |
+LL |     const ADD: i32 = (i32::MAX+1) + T::ADD;
+   |                      ^^^^^^^^^^^^ attempt to add with overflow
+
+error: this operation will panic at runtime
+  --> $DIR/issue-69020.rs:25:22
+   |
+LL |     const DIV: i32 = (1/0) + T::DIV;
+   |                      ^^^^^ attempt to divide by zero
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+  --> $DIR/issue-69020.rs:27:22
+   |
+LL |     const OOB: i32 = [1][1] + T::OOB;
+   |                      ^^^^^^ index out of bounds: the len is 1 but the index is 1
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr b/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr
new file mode 100644
index 0000000..c48a106
--- /dev/null
+++ b/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr
@@ -0,0 +1,30 @@
+error: this arithmetic operation will overflow
+  --> $DIR/issue-69020.rs:21:22
+   |
+LL |     const NEG: i32 = -i32::MIN + T::NEG;
+   |                      ^^^^^^^^^ attempt to negate with overflow
+   |
+   = note: `#[deny(arithmetic_overflow)]` on by default
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-69020.rs:23:22
+   |
+LL |     const ADD: i32 = (i32::MAX+1) + T::ADD;
+   |                      ^^^^^^^^^^^^ attempt to add with overflow
+
+error: this operation will panic at runtime
+  --> $DIR/issue-69020.rs:25:22
+   |
+LL |     const DIV: i32 = (1/0) + T::DIV;
+   |                      ^^^^^ attempt to divide by zero
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+  --> $DIR/issue-69020.rs:27:22
+   |
+LL |     const OOB: i32 = [1][1] + T::OOB;
+   |                      ^^^^^^ index out of bounds: the len is 1 but the index is 1
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/consts/issue-69020.rs b/src/test/ui/consts/issue-69020.rs
new file mode 100644
index 0000000..e079feb
--- /dev/null
+++ b/src/test/ui/consts/issue-69020.rs
@@ -0,0 +1,29 @@
+// revisions: noopt opt opt_with_overflow_checks
+//[noopt]compile-flags: -C opt-level=0
+//[opt]compile-flags: -O
+//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O
+
+#![crate_type="lib"]
+
+use std::i32;
+
+pub trait Foo {
+    const NEG: i32;
+    const ADD: i32;
+    const DIV: i32;
+    const OOB: i32;
+}
+
+// These constants cannot be evaluated already (they depend on `T::N`), so
+// they can just be linted like normal run-time code.  But codegen works
+// a bit different in const context, so this test makes sure that we still catch overflow.
+impl<T: Foo> Foo for Vec<T> {
+    const NEG: i32 = -i32::MIN + T::NEG;
+    //~^ ERROR arithmetic operation will overflow
+    const ADD: i32 = (i32::MAX+1) + T::ADD;
+    //~^ ERROR arithmetic operation will overflow
+    const DIV: i32 = (1/0) + T::DIV;
+    //~^ ERROR operation will panic
+    const OOB: i32 = [1][1] + T::OOB;
+    //~^ ERROR operation will panic
+}
diff --git a/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs b/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs
new file mode 100644
index 0000000..98be8c3
--- /dev/null
+++ b/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs
@@ -0,0 +1,11 @@
+// This is a regression test for #69310, which was injected by #68118.
+// The issue here was that as a performance optimization,
+// we call the query `lit_to_const(input);`.
+// However, the literal `input.lit` would not be of the type expected by `input.ty`.
+// As a result, we immediately called `bug!(...)` instead of bubbling up the problem
+// so that it could be handled by the caller of `lit_to_const` (`ast_const_to_const`).
+
+fn main() {}
+
+const A: [(); 0.1] = [()]; //~ ERROR mismatched types
+const B: [(); b"a"] = [()]; //~ ERROR mismatched types
diff --git a/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.stderr b/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.stderr
new file mode 100644
index 0000000..7078b4b
--- /dev/null
+++ b/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-69310-array-size-lit-wrong-ty.rs:10:15
+   |
+LL | const A: [(); 0.1] = [()];
+   |               ^^^ expected `usize`, found floating-point number
+
+error[E0308]: mismatched types
+  --> $DIR/issue-69310-array-size-lit-wrong-ty.rs:11:15
+   |
+LL | const B: [(); b"a"] = [()];
+   |               ^^^^ expected `usize`, found `&[u8; 1]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/consts/issue-69312.rs b/src/test/ui/consts/issue-69312.rs
new file mode 100644
index 0000000..413c675
--- /dev/null
+++ b/src/test/ui/consts/issue-69312.rs
@@ -0,0 +1,10 @@
+// build-pass
+
+// Verify that the compiler doesn't ICE during const prop while evaluating the index operation.
+
+#![allow(unconditional_panic)]
+
+fn main() {
+    let cols = [0u32; 0];
+    cols[0];
+}
diff --git a/src/test/ui/consts/std/char.rs b/src/test/ui/consts/std/char.rs
deleted file mode 100644
index fe79059..0000000
--- a/src/test/ui/consts/std/char.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// run-pass
-
-static X: bool = 'a'.is_ascii();
-static Y: bool = 'ä'.is_ascii();
-
-fn main() {
-    assert!(X);
-    assert!(!Y);
-}
diff --git a/src/test/ui/error-codes/E0057.stderr b/src/test/ui/error-codes/E0057.stderr
index 6b5890c..31579e2 100644
--- a/src/test/ui/error-codes/E0057.stderr
+++ b/src/test/ui/error-codes/E0057.stderr
@@ -1,14 +1,18 @@
-error[E0057]: this function takes 1 parameter but 0 parameters were supplied
+error[E0057]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/E0057.rs:3:13
    |
 LL |     let a = f();
-   |             ^^^ expected 1 parameter
+   |             ^-- supplied 0 arguments
+   |             |
+   |             expected 1 argument
 
-error[E0057]: this function takes 1 parameter but 2 parameters were supplied
+error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/E0057.rs:5:13
    |
 LL |     let c = f(2, 3);
-   |             ^^^^^^^ expected 1 parameter
+   |             ^ -  - supplied 2 arguments
+   |             |
+   |             expected 1 argument
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/error-codes/E0060.rs b/src/test/ui/error-codes/E0060.rs
index 2bb490f..941eb2a2 100644
--- a/src/test/ui/error-codes/E0060.rs
+++ b/src/test/ui/error-codes/E0060.rs
@@ -5,5 +5,5 @@
 fn main() {
     unsafe { printf(); }
     //~^ ERROR E0060
-    //~| expected at least 1 parameter
+    //~| expected at least 1 argument
 }
diff --git a/src/test/ui/error-codes/E0060.stderr b/src/test/ui/error-codes/E0060.stderr
index 8a2e7d1..a600592 100644
--- a/src/test/ui/error-codes/E0060.stderr
+++ b/src/test/ui/error-codes/E0060.stderr
@@ -1,11 +1,13 @@
-error[E0060]: this function takes at least 1 parameter but 0 parameters were supplied
+error[E0060]: this function takes at least 1 argument but 0 arguments were supplied
   --> $DIR/E0060.rs:6:14
    |
 LL |     fn printf(_: *const u8, ...) -> u32;
    |     ------------------------------------ defined here
 ...
 LL |     unsafe { printf(); }
-   |              ^^^^^^^^ expected at least 1 parameter
+   |              ^^^^^^-- supplied 0 arguments
+   |              |
+   |              expected at least 1 argument
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0061.rs b/src/test/ui/error-codes/E0061.rs
index e64ea36..c7b5fe4 100644
--- a/src/test/ui/error-codes/E0061.rs
+++ b/src/test/ui/error-codes/E0061.rs
@@ -5,9 +5,9 @@
 fn main() {
     f(0);
     //~^ ERROR E0061
-    //~| expected 2 parameters
+    //~| expected 2 arguments
 
     f2();
     //~^ ERROR E0061
-    //~| expected 1 parameter
+    //~| expected 1 argument
 }
diff --git a/src/test/ui/error-codes/E0061.stderr b/src/test/ui/error-codes/E0061.stderr
index 7310324..dfefa0d 100644
--- a/src/test/ui/error-codes/E0061.stderr
+++ b/src/test/ui/error-codes/E0061.stderr
@@ -1,20 +1,24 @@
-error[E0061]: this function takes 2 parameters but 1 parameter was supplied
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/E0061.rs:6:5
    |
 LL | fn f(a: u16, b: &str) {}
    | --------------------- defined here
 ...
 LL |     f(0);
-   |     ^^^^ expected 2 parameters
+   |     ^ - supplied 1 argument
+   |     |
+   |     expected 2 arguments
 
-error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/E0061.rs:10:5
    |
 LL | fn f2(a: u16) {}
    | ------------- defined here
 ...
 LL |     f2();
-   |     ^^^^ expected 1 parameter
+   |     ^^-- supplied 0 arguments
+   |     |
+   |     expected 1 argument
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr
index 689a375..fbc4e8a 100644
--- a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr
+++ b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr
@@ -2,7 +2,7 @@
   --> $DIR/feature-gate-infer_static_outlives_requirements.rs:5:5
    |
 LL | struct Foo<U> {
-   |            - help: consider adding an explicit lifetime bound `U: 'static`...
+   |            - help: consider adding an explicit lifetime bound...: `U: 'static`
 LL |     bar: Bar<U>
    |     ^^^^^^^^^^^
    |
diff --git a/src/test/ui/generator/issue-69039.rs b/src/test/ui/generator/issue-69039.rs
new file mode 100644
index 0000000..60004f3
--- /dev/null
+++ b/src/test/ui/generator/issue-69039.rs
@@ -0,0 +1,30 @@
+// run-pass
+
+#![feature(generators, generator_trait)]
+
+use std::ops::{Generator, GeneratorState};
+
+fn my_scenario() -> impl Generator<String, Yield = &'static str, Return = String> {
+    |_arg: String| {
+        let my_name = yield "What is your name?";
+        let my_mood = yield "How are you feeling?";
+        format!("{} is {}", my_name.trim(), my_mood.trim())
+    }
+}
+
+fn main() {
+    let mut my_session = Box::pin(my_scenario());
+
+    assert_eq!(
+        my_session.as_mut().resume("_arg".to_string()),
+        GeneratorState::Yielded("What is your name?")
+    );
+    assert_eq!(
+        my_session.as_mut().resume("Your Name".to_string()),
+        GeneratorState::Yielded("How are you feeling?")
+    );
+    assert_eq!(
+        my_session.as_mut().resume("Sensory Organs".to_string()),
+        GeneratorState::Complete("Your Name is Sensory Organs".to_string())
+    );
+}
diff --git a/src/test/ui/hrtb/issue-58451.rs b/src/test/ui/hrtb/issue-58451.rs
index 229e505..f36d549 100644
--- a/src/test/ui/hrtb/issue-58451.rs
+++ b/src/test/ui/hrtb/issue-58451.rs
@@ -9,5 +9,5 @@
 {}
 
 fn main() {
-    f(&[f()]); //~ ERROR this function takes 1 parameter
+    f(&[f()]); //~ ERROR this function takes 1 argument
 }
diff --git a/src/test/ui/hrtb/issue-58451.stderr b/src/test/ui/hrtb/issue-58451.stderr
index 4648c01..c091580 100644
--- a/src/test/ui/hrtb/issue-58451.stderr
+++ b/src/test/ui/hrtb/issue-58451.stderr
@@ -1,4 +1,4 @@
-error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/issue-58451.rs:12:9
    |
 LL | / fn f<I>(i: I)
@@ -9,7 +9,9 @@
    | |__- defined here
 ...
 LL |       f(&[f()]);
-   |           ^^^ expected 1 parameter
+   |           ^-- supplied 0 arguments
+   |           |
+   |           expected 1 argument
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/huge-array-simple-32.rs b/src/test/ui/huge-array-simple-32.rs
index 3e574df..2290e3d 100644
--- a/src/test/ui/huge-array-simple-32.rs
+++ b/src/test/ui/huge-array-simple-32.rs
@@ -4,7 +4,7 @@
 // FIXME https://github.com/rust-lang/rust/issues/59774
 // normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
 // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
-#![allow(exceeding_bitshifts)]
+#![allow(arithmetic_overflow)]
 
 fn main() {
     let _fat: [u8; (1<<31)+(1<<15)] = //~ ERROR too big for the current architecture
diff --git a/src/test/ui/huge-array-simple-64.rs b/src/test/ui/huge-array-simple-64.rs
index d4c9330..02c961f 100644
--- a/src/test/ui/huge-array-simple-64.rs
+++ b/src/test/ui/huge-array-simple-64.rs
@@ -4,7 +4,7 @@
 // FIXME https://github.com/rust-lang/rust/issues/59774
 // normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
 // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
-#![allow(exceeding_bitshifts)]
+#![allow(arithmetic_overflow)]
 
 fn main() {
     let _fat: [u8; (1<<61)+(1<<31)] = //~ ERROR too big for the current architecture
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index 7f92e70..cffa5ee 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -67,7 +67,7 @@
 LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
    |                                 --                ^^^^^^^^^^^^^^^^^^^^
    |                                 |
-   |                                 help: consider adding an explicit lifetime bound `T: 'static`...
+   |                                 help: consider adding an explicit lifetime bound...: `T: 'static +`
    |
 note: ...so that the type `T` will meet its required lifetime bounds
   --> $DIR/must_outlive_least_region_or_bound.rs:22:51
diff --git a/src/test/ui/impl-trait/type_parameters_captured.stderr b/src/test/ui/impl-trait/type_parameters_captured.stderr
index 708b479..34f0f7f 100644
--- a/src/test/ui/impl-trait/type_parameters_captured.stderr
+++ b/src/test/ui/impl-trait/type_parameters_captured.stderr
@@ -4,7 +4,7 @@
 LL | fn foo<T>(x: T) -> impl Any + 'static {
    |        -           ^^^^^^^^^^^^^^^^^^
    |        |
-   |        help: consider adding an explicit lifetime bound `T: 'static`...
+   |        help: consider adding an explicit lifetime bound...: `T: 'static`
    |
 note: ...so that the type `T` will meet its required lifetime bounds
   --> $DIR/type_parameters_captured.rs:7:20
diff --git a/src/test/ui/issues/issue-16939.stderr b/src/test/ui/issues/issue-16939.stderr
index 5df2119..103f56f 100644
--- a/src/test/ui/issues/issue-16939.stderr
+++ b/src/test/ui/issues/issue-16939.stderr
@@ -1,8 +1,10 @@
-error[E0057]: this function takes 0 parameters but 1 parameter was supplied
+error[E0057]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/issue-16939.rs:5:9
    |
 LL |     |t| f(t);
-   |         ^^^^ expected 0 parameters
+   |         ^ - supplied 1 argument
+   |         |
+   |         expected 0 arguments
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-18819.stderr b/src/test/ui/issues/issue-18819.stderr
index 41e8470..a952c9b 100644
--- a/src/test/ui/issues/issue-18819.stderr
+++ b/src/test/ui/issues/issue-18819.stderr
@@ -1,11 +1,13 @@
-error[E0061]: this function takes 2 parameters but 1 parameter was supplied
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/issue-18819.rs:16:5
    |
 LL | fn print_x(_: &dyn Foo<Item=bool>, extra: &str) {
    | ----------------------------------------------- defined here
 ...
 LL |     print_x(X);
-   |     ^^^^^^^^^^ expected 2 parameters
+   |     ^^^^^^^ - supplied 1 argument
+   |     |
+   |     expected 2 arguments
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-26094.rs b/src/test/ui/issues/issue-26094.rs
index b943384..78fb049 100644
--- a/src/test/ui/issues/issue-26094.rs
+++ b/src/test/ui/issues/issue-26094.rs
@@ -1,13 +1,13 @@
 macro_rules! some_macro {
     ($other: expr) => ({
-        $other(None)
-        //~^ this function takes 0 parameters but 1 parameter was supplied
+        $other(None) //~ NOTE supplied 1 argument
     })
 }
 
-fn some_function() {}
+fn some_function() {} //~ NOTE defined here
 
 fn main() {
     some_macro!(some_function);
-    //~^ in this expansion of some_macro!
+    //~^ ERROR this function takes 0 arguments but 1 argument was supplied
+    //~| NOTE expected 0 arguments
 }
diff --git a/src/test/ui/issues/issue-26094.stderr b/src/test/ui/issues/issue-26094.stderr
index 0b5b6d5..2038d88 100644
--- a/src/test/ui/issues/issue-26094.stderr
+++ b/src/test/ui/issues/issue-26094.stderr
@@ -1,16 +1,14 @@
-error[E0061]: this function takes 0 parameters but 1 parameter was supplied
-  --> $DIR/issue-26094.rs:3:9
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+  --> $DIR/issue-26094.rs:10:17
    |
 LL |         $other(None)
-   |         ^^^^^^^^^^^^ expected 0 parameters
+   |                ---- supplied 1 argument
 ...
 LL | fn some_function() {}
    | ------------------ defined here
 ...
 LL |     some_macro!(some_function);
-   |     --------------------------- in this macro invocation
-   |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   |                 ^^^^^^^^^^^^^ expected 0 arguments
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3044.rs b/src/test/ui/issues/issue-3044.rs
index 26db04b..81d76a9 100644
--- a/src/test/ui/issues/issue-3044.rs
+++ b/src/test/ui/issues/issue-3044.rs
@@ -2,5 +2,5 @@
     let needlesArr: Vec<char> = vec!['a', 'f'];
     needlesArr.iter().fold(|x, y| {
     });
-    //~^^ ERROR this function takes 2 parameters but 1 parameter was supplied
+    //~^^ ERROR this function takes 2 arguments but 1 argument was supplied
 }
diff --git a/src/test/ui/issues/issue-3044.stderr b/src/test/ui/issues/issue-3044.stderr
index 35a85b6..d2c0106 100644
--- a/src/test/ui/issues/issue-3044.stderr
+++ b/src/test/ui/issues/issue-3044.stderr
@@ -1,8 +1,12 @@
-error[E0061]: this function takes 2 parameters but 1 parameter was supplied
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/issue-3044.rs:3:23
    |
-LL |     needlesArr.iter().fold(|x, y| {
-   |                       ^^^^ expected 2 parameters
+LL |       needlesArr.iter().fold(|x, y| {
+   |  _______________________^^^^_-
+   | |                       |
+   | |                       expected 2 arguments
+LL | |     });
+   | |_____- supplied 1 argument
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-4935.rs b/src/test/ui/issues/issue-4935.rs
index 3b258c3..b342bbb 100644
--- a/src/test/ui/issues/issue-4935.rs
+++ b/src/test/ui/issues/issue-4935.rs
@@ -3,4 +3,4 @@
 fn foo(a: usize) {}
 //~^ defined here
 fn main() { foo(5, 6) }
-//~^ ERROR this function takes 1 parameter but 2 parameters were supplied
+//~^ ERROR this function takes 1 argument but 2 arguments were supplied
diff --git a/src/test/ui/issues/issue-4935.stderr b/src/test/ui/issues/issue-4935.stderr
index a99581f..0cc686e 100644
--- a/src/test/ui/issues/issue-4935.stderr
+++ b/src/test/ui/issues/issue-4935.stderr
@@ -1,11 +1,13 @@
-error[E0061]: this function takes 1 parameter but 2 parameters were supplied
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/issue-4935.rs:5:13
    |
 LL | fn foo(a: usize) {}
    | ---------------- defined here
 LL |
 LL | fn main() { foo(5, 6) }
-   |             ^^^^^^^^^ expected 1 parameter
+   |             ^^^ -  - supplied 2 arguments
+   |             |
+   |             expected 1 argument
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-54348.rs b/src/test/ui/issues/issue-54348.rs
index fd9a9e0..5c38d7c 100644
--- a/src/test/ui/issues/issue-54348.rs
+++ b/src/test/ui/issues/issue-54348.rs
@@ -2,6 +2,6 @@
 
 fn main() {
     [1][0u64 as usize];
-    [1][1.5 as usize]; //~ ERROR index out of bounds
-    [1][1u64 as usize]; //~ ERROR index out of bounds
+    [1][1.5 as usize]; //~ ERROR operation will panic
+    [1][1u64 as usize]; //~ ERROR operation will panic
 }
diff --git a/src/test/ui/issues/issue-54348.stderr b/src/test/ui/issues/issue-54348.stderr
index 7619cd7..6b67125 100644
--- a/src/test/ui/issues/issue-54348.stderr
+++ b/src/test/ui/issues/issue-54348.stderr
@@ -1,16 +1,16 @@
-error: index out of bounds: the len is 1 but the index is 1
+error: this operation will panic at runtime
   --> $DIR/issue-54348.rs:5:5
    |
 LL |     [1][1.5 as usize];
-   |     ^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
    |
-   = note: `#[deny(const_err)]` on by default
+   = note: `#[deny(unconditional_panic)]` on by default
 
-error: index out of bounds: the len is 1 but the index is 1
+error: this operation will panic at runtime
   --> $DIR/issue-54348.rs:6:5
    |
 LL |     [1][1u64 as usize];
-   |     ^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-8460-const.noopt.stderr b/src/test/ui/issues/issue-8460-const.noopt.stderr
new file mode 100644
index 0000000..3556ec0
--- /dev/null
+++ b/src/test/ui/issues/issue-8460-const.noopt.stderr
@@ -0,0 +1,150 @@
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:14:36
+   |
+LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^^ attempt to divide with overflow
+   |
+   = note: `#[deny(arithmetic_overflow)]` on by default
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:16:36
+   |
+LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:18:36
+   |
+LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:20:36
+   |
+LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:22:36
+   |
+LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:24:36
+   |
+LL |     assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:26:36
+   |
+LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
+   |                                    ^^^^^^^^^^ attempt to divide by zero
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:28:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
+   |                                    ^^^^^^^ attempt to divide by zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:30:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to divide by zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:32:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to divide by zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:34:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to divide by zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:36:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
+   |                                    ^^^^^^^^^ attempt to divide by zero
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:38:36
+   |
+LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:40:36
+   |
+LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:42:36
+   |
+LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:44:36
+   |
+LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:46:36
+   |
+LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:48:36
+   |
+LL |     assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:50:36
+   |
+LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
+   |                                    ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:52:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
+   |                                    ^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:54:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:56:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:58:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:60:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
+   |                                    ^^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: aborting due to 24 previous errors
+
diff --git a/src/test/ui/issues/issue-8460-const.opt.stderr b/src/test/ui/issues/issue-8460-const.opt.stderr
new file mode 100644
index 0000000..3556ec0
--- /dev/null
+++ b/src/test/ui/issues/issue-8460-const.opt.stderr
@@ -0,0 +1,150 @@
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:14:36
+   |
+LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^^ attempt to divide with overflow
+   |
+   = note: `#[deny(arithmetic_overflow)]` on by default
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:16:36
+   |
+LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:18:36
+   |
+LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:20:36
+   |
+LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:22:36
+   |
+LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:24:36
+   |
+LL |     assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:26:36
+   |
+LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
+   |                                    ^^^^^^^^^^ attempt to divide by zero
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:28:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
+   |                                    ^^^^^^^ attempt to divide by zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:30:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to divide by zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:32:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to divide by zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:34:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to divide by zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:36:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
+   |                                    ^^^^^^^^^ attempt to divide by zero
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:38:36
+   |
+LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:40:36
+   |
+LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:42:36
+   |
+LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:44:36
+   |
+LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:46:36
+   |
+LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:48:36
+   |
+LL |     assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:50:36
+   |
+LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
+   |                                    ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:52:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
+   |                                    ^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:54:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:56:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:58:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:60:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
+   |                                    ^^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: aborting due to 24 previous errors
+
diff --git a/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr b/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr
new file mode 100644
index 0000000..3556ec0
--- /dev/null
+++ b/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr
@@ -0,0 +1,150 @@
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:14:36
+   |
+LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^^ attempt to divide with overflow
+   |
+   = note: `#[deny(arithmetic_overflow)]` on by default
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:16:36
+   |
+LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:18:36
+   |
+LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:20:36
+   |
+LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:22:36
+   |
+LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:24:36
+   |
+LL |     assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^ attempt to divide with overflow
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:26:36
+   |
+LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
+   |                                    ^^^^^^^^^^ attempt to divide by zero
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:28:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
+   |                                    ^^^^^^^ attempt to divide by zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:30:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to divide by zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:32:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to divide by zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:34:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to divide by zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:36:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
+   |                                    ^^^^^^^^^ attempt to divide by zero
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:38:36
+   |
+LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:40:36
+   |
+LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:42:36
+   |
+LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:44:36
+   |
+LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:46:36
+   |
+LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-8460-const.rs:48:36
+   |
+LL |     assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
+   |                                    ^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:50:36
+   |
+LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
+   |                                    ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:52:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
+   |                                    ^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:54:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:56:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:58:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
+   |                                    ^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-8460-const.rs:60:36
+   |
+LL |     assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
+   |                                    ^^^^^^^^^ attempt to calculate the remainder with a divisor of zero
+
+error: aborting due to 24 previous errors
+
diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs
index 5866cef..53005e4 100644
--- a/src/test/ui/issues/issue-8460-const.rs
+++ b/src/test/ui/issues/issue-8460-const.rs
@@ -1,5 +1,9 @@
+// revisions: noopt opt opt_with_overflow_checks
+//[noopt]compile-flags: -C opt-level=0
+//[opt]compile-flags: -O
+//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O
+
 // build-fail
-// compile-flags: -O
 
 #![deny(const_err)]
 
@@ -8,63 +12,51 @@
 
 fn main() {
     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
-    //~^ ERROR attempt to divide with overflow
-    //~| ERROR this expression will panic at runtime
+    //~^ ERROR arithmetic operation will overflow
     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
-    //~^ ERROR attempt to divide with overflow
-    //~| ERROR this expression will panic at runtime
+    //~^ ERROR arithmetic operation will overflow
     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
-    //~^ ERROR attempt to divide with overflow
-    //~| ERROR this expression will panic at runtime
+    //~^ ERROR arithmetic operation will overflow
     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
-    //~^ ERROR attempt to divide with overflow
-    //~| ERROR this expression will panic at runtime
+    //~^ ERROR arithmetic operation will overflow
     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
-    //~^ ERROR attempt to divide with overflow
-    //~| ERROR this expression will panic at runtime
+    //~^ ERROR arithmetic operation will overflow
     assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
-    //~^ ERROR attempt to divide with overflow
-    //~| ERROR this expression will panic at runtime
+    //~^ ERROR arithmetic operation will overflow
     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
-    //~^ ERROR attempt to divide by zero
+    //~^ ERROR operation will panic
     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
-    //~^ ERROR attempt to divide by zero
+    //~^ ERROR operation will panic
     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
-    //~^ ERROR attempt to divide by zero
+    //~^ ERROR operation will panic
     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
-    //~^ ERROR attempt to divide by zero
+    //~^ ERROR operation will panic
     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
-    //~^ ERROR attempt to divide by zero
+    //~^ ERROR operation will panic
     assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
-    //~^ ERROR attempt to divide by zero
+    //~^ ERROR operation will panic
     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR this expression will panic at runtime
+    //~^ ERROR arithmetic operation will overflow
     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR this expression will panic at runtime
+    //~^ ERROR arithmetic operation will overflow
     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR this expression will panic at runtime
+    //~^ ERROR arithmetic operation will overflow
     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR this expression will panic at runtime
+    //~^ ERROR arithmetic operation will overflow
     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR this expression will panic at runtime
+    //~^ ERROR arithmetic operation will overflow
     assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR this expression will panic at runtime
+    //~^ ERROR arithmetic operation will overflow
     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with a divisor of zero
+    //~^ ERROR operation will panic
     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with a divisor of zero
+    //~^ ERROR operation will panic
     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with a divisor of zero
+    //~^ ERROR operation will panic
     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with a divisor of zero
+    //~^ ERROR operation will panic
     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with a divisor of zero
+    //~^ ERROR operation will panic
     assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with a divisor of zero
+    //~^ ERROR operation will panic
 }
diff --git a/src/test/ui/issues/issue-8460-const.stderr b/src/test/ui/issues/issue-8460-const.stderr
deleted file mode 100644
index d737394..0000000
--- a/src/test/ui/issues/issue-8460-const.stderr
+++ /dev/null
@@ -1,224 +0,0 @@
-error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:10:36
-   |
-LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-8460-const.rs:4:9
-   |
-LL | #![deny(const_err)]
-   |         ^^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:10:36
-   |
-LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^ attempt to divide with overflow
-
-error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:13:36
-   |
-LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:13:36
-   |
-LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^ attempt to divide with overflow
-
-error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:16:36
-   |
-LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:16:36
-   |
-LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
-
-error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:19:36
-   |
-LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:19:36
-   |
-LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
-
-error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:22:36
-   |
-LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:22:36
-   |
-LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to divide with overflow
-
-error: attempt to divide with overflow
-  --> $DIR/issue-8460-const.rs:25:36
-   |
-LL |     assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:25:36
-   |
-LL |     assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^ attempt to divide with overflow
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:28:36
-   |
-LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
-   |                                    ^^^^^^^^^^
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:30:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
-   |                                    ^^^^^^^
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:32:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:34:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:36:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const.rs:38:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
-   |                                    ^^^^^^^^^
-
-error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:40:36
-   |
-LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:40:36
-   |
-LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
-
-error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:43:36
-   |
-LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:43:36
-   |
-LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^ attempt to calculate the remainder with overflow
-
-error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:46:36
-   |
-LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:46:36
-   |
-LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
-
-error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:49:36
-   |
-LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:49:36
-   |
-LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
-
-error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:52:36
-   |
-LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:52:36
-   |
-LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
-
-error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const.rs:55:36
-   |
-LL |     assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^
-
-error: this expression will panic at runtime
-  --> $DIR/issue-8460-const.rs:55:36
-   |
-LL |     assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:58:36
-   |
-LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
-   |                                    ^^^^^^^^^^
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:60:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
-   |                                    ^^^^^^^
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:62:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:64:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:66:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const.rs:68:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
-   |                                    ^^^^^^^^^
-
-error: aborting due to 36 previous errors
-
diff --git a/src/test/ui/issues/issue-8460-const2.rs b/src/test/ui/issues/issue-8460-const2.rs
deleted file mode 100644
index afea859..0000000
--- a/src/test/ui/issues/issue-8460-const2.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-// build-fail
-// compile-flags: -C overflow-checks=on -O
-
-#![deny(const_err)]
-
-use std::{isize, i8, i16, i32, i64, i128};
-use std::thread;
-
-fn main() {
-    assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
-    //~^ ERROR attempt to divide with overflow
-    assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
-    //~^ ERROR attempt to divide with overflow
-    assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
-    //~^ ERROR attempt to divide with overflow
-    assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
-    //~^ ERROR attempt to divide with overflow
-    assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
-    //~^ ERROR attempt to divide with overflow
-    assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
-    //~^ ERROR attempt to divide with overflow
-    assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
-    //~^ ERROR attempt to divide by zero
-    assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
-    //~^ ERROR attempt to divide by zero
-    assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
-    //~^ ERROR attempt to divide by zero
-    assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
-    //~^ ERROR attempt to divide by zero
-    assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
-    //~^ ERROR attempt to divide by zero
-    assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
-    //~^ ERROR attempt to divide by zero
-    assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with overflow
-    assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with overflow
-    assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with overflow
-    assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with overflow
-    assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with overflow
-    assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with overflow
-    assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
-    //~^ ERROR attempt to calculate the remainder with a divisor of zero
-}
diff --git a/src/test/ui/issues/issue-8460-const2.stderr b/src/test/ui/issues/issue-8460-const2.stderr
deleted file mode 100644
index e25d560..0000000
--- a/src/test/ui/issues/issue-8460-const2.stderr
+++ /dev/null
@@ -1,152 +0,0 @@
-error: attempt to divide with overflow
-  --> $DIR/issue-8460-const2.rs:10:36
-   |
-LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-8460-const2.rs:4:9
-   |
-LL | #![deny(const_err)]
-   |         ^^^^^^^^^
-
-error: attempt to divide with overflow
-  --> $DIR/issue-8460-const2.rs:12:36
-   |
-LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^
-
-error: attempt to divide with overflow
-  --> $DIR/issue-8460-const2.rs:14:36
-   |
-LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^
-
-error: attempt to divide with overflow
-  --> $DIR/issue-8460-const2.rs:16:36
-   |
-LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^
-
-error: attempt to divide with overflow
-  --> $DIR/issue-8460-const2.rs:18:36
-   |
-LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^
-
-error: attempt to divide with overflow
-  --> $DIR/issue-8460-const2.rs:20:36
-   |
-LL |     assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:22:36
-   |
-LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
-   |                                    ^^^^^^^^^^
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:24:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
-   |                                    ^^^^^^^
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:26:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:28:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:30:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: attempt to divide by zero
-  --> $DIR/issue-8460-const2.rs:32:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
-   |                                    ^^^^^^^^^
-
-error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:34:36
-   |
-LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^
-
-error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:36:36
-   |
-LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^
-
-error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:38:36
-   |
-LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^
-
-error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:40:36
-   |
-LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^
-
-error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:42:36
-   |
-LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^
-
-error: attempt to calculate the remainder with overflow
-  --> $DIR/issue-8460-const2.rs:44:36
-   |
-LL |     assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:46:36
-   |
-LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
-   |                                    ^^^^^^^^^^
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:48:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
-   |                                    ^^^^^^^
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:50:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:52:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:54:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
-   |                                    ^^^^^^^^
-
-error: attempt to calculate the remainder with a divisor of zero
-  --> $DIR/issue-8460-const2.rs:56:36
-   |
-LL |     assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
-   |                                    ^^^^^^^^^
-
-error: aborting due to 24 previous errors
-
diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
index 4e50064..e60c461 100644
--- a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
+++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
@@ -2,7 +2,7 @@
   --> $DIR/lifetime-doesnt-live-long-enough.rs:19:5
    |
 LL | struct Foo<T> {
-   |            - help: consider adding an explicit lifetime bound `T: 'static`...
+   |            - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     foo: &'static T
    |     ^^^^^^^^^^^^^^^
    |
@@ -16,7 +16,7 @@
   --> $DIR/lifetime-doesnt-live-long-enough.rs:24:19
    |
 LL | trait X<K>: Sized {
-   |         - help: consider adding an explicit lifetime bound `K: 'a`...
+   |         - help: consider adding an explicit lifetime bound...: `K: 'a`
 LL |     fn foo<'a, L: X<&'a Nested<K>>>();
    |                   ^^^^^^^^^^^^^^^^
    |
@@ -45,7 +45,7 @@
 LL |     fn baz<'a, L, M: X<&'a Nested<L>>>() {
    |                -     ^^^^^^^^^^^^^^^^
    |                |
-   |                help: consider adding an explicit lifetime bound `L: 'a`...
+   |                help: consider adding an explicit lifetime bound...: `L: 'a`
    |
 note: ...so that the reference type `&'a Nested<L>` does not outlive the data it points at
   --> $DIR/lifetime-doesnt-live-long-enough.rs:32:22
@@ -57,7 +57,7 @@
   --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33
    |
 LL | impl<K> Nested<K> {
-   |      - help: consider adding an explicit lifetime bound `K: 'a`...
+   |      - help: consider adding an explicit lifetime bound...: `K: 'a`
 LL |     fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
    |                                 ^^^^^^^^^^^^^^^^
    |
@@ -71,7 +71,7 @@
   --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36
    |
 LL |     fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
-   |                                    ^^^^^^^^^^^^^^^^  -- help: consider adding an explicit lifetime bound `M: 'a`...
+   |                                    ^^^^^^^^^^^^^^^^  -- help: consider adding an explicit lifetime bound...: `M: 'a +`
    |
 note: ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
   --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr
new file mode 100644
index 0000000..ce9b02b
--- /dev/null
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr
@@ -0,0 +1,146 @@
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:22:13
+   |
+LL |     let _ = x << 42;
+   |             ^^^^^^^ attempt to shift left with overflow
+   |
+note: the lint level is defined here
+  --> $DIR/lint-exceeding-bitshifts.rs:9:9
+   |
+LL | #![deny(arithmetic_overflow, const_err)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:27:15
+   |
+LL |       let n = 1u8 << 8;
+   |               ^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:29:15
+   |
+LL |       let n = 1u16 << 16;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:31:15
+   |
+LL |       let n = 1u32 << 32;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:33:15
+   |
+LL |       let n = 1u64 << 64;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:35:15
+   |
+LL |       let n = 1i8 << 8;
+   |               ^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:37:15
+   |
+LL |       let n = 1i16 << 16;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:39:15
+   |
+LL |       let n = 1i32 << 32;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:41:15
+   |
+LL |       let n = 1i64 << 64;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:44:15
+   |
+LL |       let n = 1u8 >> 8;
+   |               ^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:46:15
+   |
+LL |       let n = 1u16 >> 16;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:48:15
+   |
+LL |       let n = 1u32 >> 32;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:50:15
+   |
+LL |       let n = 1u64 >> 64;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:52:15
+   |
+LL |       let n = 1i8 >> 8;
+   |               ^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:54:15
+   |
+LL |       let n = 1i16 >> 16;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:56:15
+   |
+LL |       let n = 1i32 >> 32;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:58:15
+   |
+LL |       let n = 1i64 >> 64;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:62:15
+   |
+LL |       let n = n << 8;
+   |               ^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:64:15
+   |
+LL |       let n = 1u8 << -8;
+   |               ^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:69:15
+   |
+LL |       let n = 1u8 << (4+4);
+   |               ^^^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:71:15
+   |
+LL |       let n = 1i64 >> [64][0];
+   |               ^^^^^^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:77:15
+   |
+LL |       let n = 1_isize << BITS;
+   |               ^^^^^^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:78:15
+   |
+LL |       let n = 1_usize << BITS;
+   |               ^^^^^^^^^^^^^^^ attempt to shift left with overflow
+
+error: aborting due to 23 previous errors
+
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr
new file mode 100644
index 0000000..ce9b02b
--- /dev/null
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr
@@ -0,0 +1,146 @@
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:22:13
+   |
+LL |     let _ = x << 42;
+   |             ^^^^^^^ attempt to shift left with overflow
+   |
+note: the lint level is defined here
+  --> $DIR/lint-exceeding-bitshifts.rs:9:9
+   |
+LL | #![deny(arithmetic_overflow, const_err)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:27:15
+   |
+LL |       let n = 1u8 << 8;
+   |               ^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:29:15
+   |
+LL |       let n = 1u16 << 16;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:31:15
+   |
+LL |       let n = 1u32 << 32;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:33:15
+   |
+LL |       let n = 1u64 << 64;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:35:15
+   |
+LL |       let n = 1i8 << 8;
+   |               ^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:37:15
+   |
+LL |       let n = 1i16 << 16;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:39:15
+   |
+LL |       let n = 1i32 << 32;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:41:15
+   |
+LL |       let n = 1i64 << 64;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:44:15
+   |
+LL |       let n = 1u8 >> 8;
+   |               ^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:46:15
+   |
+LL |       let n = 1u16 >> 16;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:48:15
+   |
+LL |       let n = 1u32 >> 32;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:50:15
+   |
+LL |       let n = 1u64 >> 64;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:52:15
+   |
+LL |       let n = 1i8 >> 8;
+   |               ^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:54:15
+   |
+LL |       let n = 1i16 >> 16;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:56:15
+   |
+LL |       let n = 1i32 >> 32;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:58:15
+   |
+LL |       let n = 1i64 >> 64;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:62:15
+   |
+LL |       let n = n << 8;
+   |               ^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:64:15
+   |
+LL |       let n = 1u8 << -8;
+   |               ^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:69:15
+   |
+LL |       let n = 1u8 << (4+4);
+   |               ^^^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:71:15
+   |
+LL |       let n = 1i64 >> [64][0];
+   |               ^^^^^^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:77:15
+   |
+LL |       let n = 1_isize << BITS;
+   |               ^^^^^^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:78:15
+   |
+LL |       let n = 1_usize << BITS;
+   |               ^^^^^^^^^^^^^^^ attempt to shift left with overflow
+
+error: aborting due to 23 previous errors
+
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr
new file mode 100644
index 0000000..ce9b02b
--- /dev/null
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr
@@ -0,0 +1,146 @@
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:22:13
+   |
+LL |     let _ = x << 42;
+   |             ^^^^^^^ attempt to shift left with overflow
+   |
+note: the lint level is defined here
+  --> $DIR/lint-exceeding-bitshifts.rs:9:9
+   |
+LL | #![deny(arithmetic_overflow, const_err)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:27:15
+   |
+LL |       let n = 1u8 << 8;
+   |               ^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:29:15
+   |
+LL |       let n = 1u16 << 16;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:31:15
+   |
+LL |       let n = 1u32 << 32;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:33:15
+   |
+LL |       let n = 1u64 << 64;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:35:15
+   |
+LL |       let n = 1i8 << 8;
+   |               ^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:37:15
+   |
+LL |       let n = 1i16 << 16;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:39:15
+   |
+LL |       let n = 1i32 << 32;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:41:15
+   |
+LL |       let n = 1i64 << 64;
+   |               ^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:44:15
+   |
+LL |       let n = 1u8 >> 8;
+   |               ^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:46:15
+   |
+LL |       let n = 1u16 >> 16;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:48:15
+   |
+LL |       let n = 1u32 >> 32;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:50:15
+   |
+LL |       let n = 1u64 >> 64;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:52:15
+   |
+LL |       let n = 1i8 >> 8;
+   |               ^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:54:15
+   |
+LL |       let n = 1i16 >> 16;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:56:15
+   |
+LL |       let n = 1i32 >> 32;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:58:15
+   |
+LL |       let n = 1i64 >> 64;
+   |               ^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:62:15
+   |
+LL |       let n = n << 8;
+   |               ^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:64:15
+   |
+LL |       let n = 1u8 << -8;
+   |               ^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:69:15
+   |
+LL |       let n = 1u8 << (4+4);
+   |               ^^^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:71:15
+   |
+LL |       let n = 1i64 >> [64][0];
+   |               ^^^^^^^^^^^^^^^ attempt to shift right with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:77:15
+   |
+LL |       let n = 1_isize << BITS;
+   |               ^^^^^^^^^^^^^^^ attempt to shift left with overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-exceeding-bitshifts.rs:78:15
+   |
+LL |       let n = 1_usize << BITS;
+   |               ^^^^^^^^^^^^^^^ attempt to shift left with overflow
+
+error: aborting due to 23 previous errors
+
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.rs b/src/test/ui/lint/lint-exceeding-bitshifts.rs
index 121e5b7..7deee53 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts.rs
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.rs
@@ -1,50 +1,79 @@
-// build-fail
-// compile-flags: -O
+// revisions: noopt opt opt_with_overflow_checks
+//[noopt]compile-flags: -C opt-level=0
+//[opt]compile-flags: -O
+//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O
 
-#![deny(exceeding_bitshifts, const_err)]
+// build-fail
+
+#![crate_type="lib"]
+#![deny(arithmetic_overflow, const_err)]
 #![allow(unused_variables)]
 #![allow(dead_code)]
 
-fn main() {
+pub trait Foo {
+    const N: i32;
+}
+
+impl<T: Foo> Foo for Vec<T> {
+    const N: i32 = T::N << 42; // FIXME this should warn
+}
+
+pub fn foo(x: i32) {
+    let _ = x << 42; //~ ERROR: arithmetic operation will overflow
+}
+
+pub fn main() {
       let n = 1u8 << 7;
-      let n = 1u8 << 8;   //~ ERROR: attempt to shift left with overflow
+      let n = 1u8 << 8;   //~ ERROR: arithmetic operation will overflow
       let n = 1u16 << 15;
-      let n = 1u16 << 16; //~ ERROR: attempt to shift left with overflow
+      let n = 1u16 << 16; //~ ERROR: arithmetic operation will overflow
       let n = 1u32 << 31;
-      let n = 1u32 << 32; //~ ERROR: attempt to shift left with overflow
+      let n = 1u32 << 32; //~ ERROR: arithmetic operation will overflow
       let n = 1u64 << 63;
-      let n = 1u64 << 64; //~ ERROR: attempt to shift left with overflow
+      let n = 1u64 << 64; //~ ERROR: arithmetic operation will overflow
       let n = 1i8 << 7;
-      let n = 1i8 << 8;   //~ ERROR: attempt to shift left with overflow
+      let n = 1i8 << 8;   //~ ERROR: arithmetic operation will overflow
       let n = 1i16 << 15;
-      let n = 1i16 << 16; //~ ERROR: attempt to shift left with overflow
+      let n = 1i16 << 16; //~ ERROR: arithmetic operation will overflow
       let n = 1i32 << 31;
-      let n = 1i32 << 32; //~ ERROR: attempt to shift left with overflow
+      let n = 1i32 << 32; //~ ERROR: arithmetic operation will overflow
       let n = 1i64 << 63;
-      let n = 1i64 << 64; //~ ERROR: attempt to shift left with overflow
+      let n = 1i64 << 64; //~ ERROR: arithmetic operation will overflow
 
       let n = 1u8 >> 7;
-      let n = 1u8 >> 8;   //~ ERROR: attempt to shift right with overflow
+      let n = 1u8 >> 8;   //~ ERROR: arithmetic operation will overflow
       let n = 1u16 >> 15;
-      let n = 1u16 >> 16; //~ ERROR: attempt to shift right with overflow
+      let n = 1u16 >> 16; //~ ERROR: arithmetic operation will overflow
       let n = 1u32 >> 31;
-      let n = 1u32 >> 32; //~ ERROR: attempt to shift right with overflow
+      let n = 1u32 >> 32; //~ ERROR: arithmetic operation will overflow
       let n = 1u64 >> 63;
-      let n = 1u64 >> 64; //~ ERROR: attempt to shift right with overflow
+      let n = 1u64 >> 64; //~ ERROR: arithmetic operation will overflow
       let n = 1i8 >> 7;
-      let n = 1i8 >> 8;   //~ ERROR: attempt to shift right with overflow
+      let n = 1i8 >> 8;   //~ ERROR: arithmetic operation will overflow
       let n = 1i16 >> 15;
-      let n = 1i16 >> 16; //~ ERROR: attempt to shift right with overflow
+      let n = 1i16 >> 16; //~ ERROR: arithmetic operation will overflow
       let n = 1i32 >> 31;
-      let n = 1i32 >> 32; //~ ERROR: attempt to shift right with overflow
+      let n = 1i32 >> 32; //~ ERROR: arithmetic operation will overflow
       let n = 1i64 >> 63;
-      let n = 1i64 >> 64; //~ ERROR: attempt to shift right with overflow
+      let n = 1i64 >> 64; //~ ERROR: arithmetic operation will overflow
 
       let n = 1u8;
       let n = n << 7;
-      let n = n << 8; //~ ERROR: attempt to shift left with overflow
+      let n = n << 8; //~ ERROR: arithmetic operation will overflow
 
-      let n = 1u8 << -8; //~ ERROR: attempt to shift left with overflow
+      let n = 1u8 << -8; //~ ERROR: arithmetic operation will overflow
 
       let n = 1i8<<(1isize+-1);
+
+      let n = 1u8 << (4+3);
+      let n = 1u8 << (4+4); //~ ERROR: arithmetic operation will overflow
+      let n = 1i64 >> [63][0];
+      let n = 1i64 >> [64][0]; //~ ERROR: arithmetic operation will overflow
+
+      #[cfg(target_pointer_width = "32")]
+      const BITS: usize = 32;
+      #[cfg(target_pointer_width = "64")]
+      const BITS: usize = 64;
+      let n = 1_isize << BITS; //~ ERROR: arithmetic operation will overflow
+      let n = 1_usize << BITS; //~ ERROR: arithmetic operation will overflow
 }
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.stderr
deleted file mode 100644
index 6585772..0000000
--- a/src/test/ui/lint/lint-exceeding-bitshifts.stderr
+++ /dev/null
@@ -1,116 +0,0 @@
-error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:10:15
-   |
-LL |       let n = 1u8 << 8;
-   |               ^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/lint-exceeding-bitshifts.rs:4:9
-   |
-LL | #![deny(exceeding_bitshifts, const_err)]
-   |         ^^^^^^^^^^^^^^^^^^^
-
-error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:12:15
-   |
-LL |       let n = 1u16 << 16;
-   |               ^^^^^^^^^^
-
-error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:14:15
-   |
-LL |       let n = 1u32 << 32;
-   |               ^^^^^^^^^^
-
-error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:16:15
-   |
-LL |       let n = 1u64 << 64;
-   |               ^^^^^^^^^^
-
-error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:18:15
-   |
-LL |       let n = 1i8 << 8;
-   |               ^^^^^^^^
-
-error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:20:15
-   |
-LL |       let n = 1i16 << 16;
-   |               ^^^^^^^^^^
-
-error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:22:15
-   |
-LL |       let n = 1i32 << 32;
-   |               ^^^^^^^^^^
-
-error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:24:15
-   |
-LL |       let n = 1i64 << 64;
-   |               ^^^^^^^^^^
-
-error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:27:15
-   |
-LL |       let n = 1u8 >> 8;
-   |               ^^^^^^^^
-
-error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:29:15
-   |
-LL |       let n = 1u16 >> 16;
-   |               ^^^^^^^^^^
-
-error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:31:15
-   |
-LL |       let n = 1u32 >> 32;
-   |               ^^^^^^^^^^
-
-error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:33:15
-   |
-LL |       let n = 1u64 >> 64;
-   |               ^^^^^^^^^^
-
-error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:35:15
-   |
-LL |       let n = 1i8 >> 8;
-   |               ^^^^^^^^
-
-error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:37:15
-   |
-LL |       let n = 1i16 >> 16;
-   |               ^^^^^^^^^^
-
-error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:39:15
-   |
-LL |       let n = 1i32 >> 32;
-   |               ^^^^^^^^^^
-
-error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:41:15
-   |
-LL |       let n = 1i64 >> 64;
-   |               ^^^^^^^^^^
-
-error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:45:15
-   |
-LL |       let n = n << 8;
-   |               ^^^^^^
-
-error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:47:15
-   |
-LL |       let n = 1u8 << -8;
-   |               ^^^^^^^^^
-
-error: aborting due to 18 previous errors
-
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.rs b/src/test/ui/lint/lint-exceeding-bitshifts2.rs
deleted file mode 100644
index 2a7cbc1..0000000
--- a/src/test/ui/lint/lint-exceeding-bitshifts2.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// build-fail
-// compile-flags: -O
-
-#![deny(exceeding_bitshifts, const_err)]
-#![allow(unused_variables)]
-#![allow(dead_code)]
-
-fn main() {
-      let n = 1u8 << (4+3);
-      let n = 1u8 << (4+4); //~ ERROR: attempt to shift left with overflow
-      let n = 1i64 >> [63][0];
-      let n = 1i64 >> [64][0]; //~ ERROR: attempt to shift right with overflow
-
-      #[cfg(target_pointer_width = "32")]
-      const BITS: usize = 32;
-      #[cfg(target_pointer_width = "64")]
-      const BITS: usize = 64;
-      let n = 1_isize << BITS; //~ ERROR: attempt to shift left with overflow
-      let n = 1_usize << BITS; //~ ERROR: attempt to shift left with overflow
-}
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr
deleted file mode 100644
index ac9f3b1..0000000
--- a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr
+++ /dev/null
@@ -1,32 +0,0 @@
-error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts2.rs:10:15
-   |
-LL |       let n = 1u8 << (4+4);
-   |               ^^^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/lint-exceeding-bitshifts2.rs:4:9
-   |
-LL | #![deny(exceeding_bitshifts, const_err)]
-   |         ^^^^^^^^^^^^^^^^^^^
-
-error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts2.rs:12:15
-   |
-LL |       let n = 1i64 >> [64][0];
-   |               ^^^^^^^^^^^^^^^
-
-error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts2.rs:18:15
-   |
-LL |       let n = 1_isize << BITS;
-   |               ^^^^^^^^^^^^^^^
-
-error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts2.rs:19:15
-   |
-LL |       let n = 1_usize << BITS;
-   |               ^^^^^^^^^^^^^^^
-
-error: aborting due to 4 previous errors
-
diff --git a/src/test/ui/methods/method-call-err-msg.rs b/src/test/ui/methods/method-call-err-msg.rs
index 5ff4b41..9bfacc7 100644
--- a/src/test/ui/methods/method-call-err-msg.rs
+++ b/src/test/ui/methods/method-call-err-msg.rs
@@ -5,16 +5,18 @@
     fn zero(self) -> Foo { self }
     fn one(self, _: isize) -> Foo { self }
     fn two(self, _: isize, _: isize) -> Foo { self }
+    fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
 }
 
 fn main() {
     let x = Foo;
-    x.zero(0)   //~ ERROR this function takes 0 parameters but 1 parameter was supplied
-     .one()     //~ ERROR this function takes 1 parameter but 0 parameters were supplied
-     .two(0);   //~ ERROR this function takes 2 parameters but 1 parameter was supplied
+    x.zero(0)   //~ ERROR this function takes 0 arguments but 1 argument was supplied
+     .one()     //~ ERROR this function takes 1 argument but 0 arguments were supplied
+     .two(0);   //~ ERROR this function takes 2 arguments but 1 argument was supplied
 
     let y = Foo;
     y.zero()
      .take()    //~ ERROR no method named `take` found
      .one(0);
+    y.three::<usize>(); //~ ERROR this function takes 3 arguments but 0 arguments were supplied
 }
diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr
index 7efdd91..ab1ef5b 100644
--- a/src/test/ui/methods/method-call-err-msg.stderr
+++ b/src/test/ui/methods/method-call-err-msg.stderr
@@ -1,32 +1,38 @@
-error[E0061]: this function takes 0 parameters but 1 parameter was supplied
-  --> $DIR/method-call-err-msg.rs:12:7
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+  --> $DIR/method-call-err-msg.rs:13:7
    |
 LL |     fn zero(self) -> Foo { self }
    |     -------------------- defined here
 ...
 LL |     x.zero(0)
-   |       ^^^^ expected 0 parameters
+   |       ^^^^ - supplied 1 argument
+   |       |
+   |       expected 0 arguments
 
-error[E0061]: this function takes 1 parameter but 0 parameters were supplied
-  --> $DIR/method-call-err-msg.rs:13:7
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+  --> $DIR/method-call-err-msg.rs:14:7
    |
 LL |     fn one(self, _: isize) -> Foo { self }
    |     ----------------------------- defined here
 ...
 LL |      .one()
-   |       ^^^ expected 1 parameter
+   |       ^^^- supplied 0 arguments
+   |       |
+   |       expected 1 argument
 
-error[E0061]: this function takes 2 parameters but 1 parameter was supplied
-  --> $DIR/method-call-err-msg.rs:14:7
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
+  --> $DIR/method-call-err-msg.rs:15:7
    |
 LL |     fn two(self, _: isize, _: isize) -> Foo { self }
    |     --------------------------------------- defined here
 ...
 LL |      .two(0);
-   |       ^^^ expected 2 parameters
+   |       ^^^ - supplied 1 argument
+   |       |
+   |       expected 2 arguments
 
 error[E0599]: no method named `take` found for struct `Foo` in the current scope
-  --> $DIR/method-call-err-msg.rs:18:7
+  --> $DIR/method-call-err-msg.rs:19:7
    |
 LL | pub struct Foo;
    | --------------- method `take` not found for this
@@ -41,7 +47,18 @@
            candidate #1: `std::io::Read`
            candidate #2: `std::iter::Iterator`
 
-error: aborting due to 4 previous errors
+error[E0061]: this function takes 3 arguments but 0 arguments were supplied
+  --> $DIR/method-call-err-msg.rs:21:7
+   |
+LL |     fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
+   |     ------------------------------------------ defined here
+...
+LL |     y.three::<usize>();
+   |       ^^^^^--------- supplied 0 arguments
+   |       |
+   |       expected 3 arguments
+
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0061, E0599.
 For more information about an error, try `rustc --explain E0061`.
diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.rs b/src/test/ui/mismatched_types/overloaded-calls-bad.rs
index 73e74a9..902a6ec 100644
--- a/src/test/ui/mismatched_types/overloaded-calls-bad.rs
+++ b/src/test/ui/mismatched_types/overloaded-calls-bad.rs
@@ -27,7 +27,7 @@
     };
     let ans = s("what");    //~ ERROR mismatched types
     let ans = s();
-    //~^ ERROR this function takes 1 parameter but 0 parameters were supplied
+    //~^ ERROR this function takes 1 argument but 0 arguments were supplied
     let ans = s("burma", "shave");
-    //~^ ERROR this function takes 1 parameter but 2 parameters were supplied
+    //~^ ERROR this function takes 1 argument but 2 arguments were supplied
 }
diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
index 5a5dd05..706e255 100644
--- a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
+++ b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
@@ -4,17 +4,21 @@
 LL |     let ans = s("what");
    |                 ^^^^^^ expected `isize`, found `&str`
 
-error[E0057]: this function takes 1 parameter but 0 parameters were supplied
+error[E0057]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/overloaded-calls-bad.rs:29:15
    |
 LL |     let ans = s();
-   |               ^^^ expected 1 parameter
+   |               ^-- supplied 0 arguments
+   |               |
+   |               expected 1 argument
 
-error[E0057]: this function takes 1 parameter but 2 parameters were supplied
+error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/overloaded-calls-bad.rs:31:15
    |
 LL |     let ans = s("burma", "shave");
-   |               ^^^^^^^^^^^^^^^^^^^ expected 1 parameter
+   |               ^ -------  ------- supplied 2 arguments
+   |               |
+   |               expected 1 argument
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs
new file mode 100644
index 0000000..96c8719
--- /dev/null
+++ b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs
@@ -0,0 +1,12 @@
+// Test that the 'static bound from the Copy impl is respected. Regression test for #29149.
+
+#[derive(Clone)]
+struct Foo<'a>(&'a u32);
+impl Copy for Foo<'static> {}
+
+fn main() {
+    let s = 2;
+    let a = (Foo(&s),); //~ ERROR `s` does not live long enough [E0597]
+    drop(a.0);
+    drop(a.0);
+}
diff --git a/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr
new file mode 100644
index 0000000..65be3b3
--- /dev/null
+++ b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr
@@ -0,0 +1,14 @@
+error[E0597]: `s` does not live long enough
+  --> $DIR/do-not-ignore-lifetime-bounds-in-copy-proj.rs:9:18
+   |
+LL |     let a = (Foo(&s),);
+   |                  ^^ borrowed value does not live long enough
+LL |     drop(a.0);
+   |          --- copying this value requires that `s` is borrowed for `'static`
+LL |     drop(a.0);
+LL | }
+   | - `s` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-69114-static-mut-ty.rs b/src/test/ui/nll/issue-69114-static-mut-ty.rs
new file mode 100644
index 0000000..ce37da0
--- /dev/null
+++ b/src/test/ui/nll/issue-69114-static-mut-ty.rs
@@ -0,0 +1,30 @@
+// Check that borrowck ensures that `static mut` items have the expected type.
+
+static FOO: u8 = 42;
+static mut BAR: &'static u8 = &FOO;
+static mut BAR_ELIDED: &u8 = &FOO;
+
+fn main() {
+    unsafe {
+        println!("{} {}", BAR, BAR_ELIDED);
+        set_bar();
+        set_bar_elided();
+        println!("{} {}", BAR, BAR_ELIDED);
+    }
+}
+
+fn set_bar() {
+    let n = 42;
+    unsafe {
+        BAR = &n;
+        //~^ ERROR does not live long enough
+    }
+}
+
+fn set_bar_elided() {
+    let n = 42;
+    unsafe {
+        BAR_ELIDED = &n;
+        //~^ ERROR does not live long enough
+    }
+}
diff --git a/src/test/ui/nll/issue-69114-static-mut-ty.stderr b/src/test/ui/nll/issue-69114-static-mut-ty.stderr
new file mode 100644
index 0000000..5e55cb5
--- /dev/null
+++ b/src/test/ui/nll/issue-69114-static-mut-ty.stderr
@@ -0,0 +1,27 @@
+error[E0597]: `n` does not live long enough
+  --> $DIR/issue-69114-static-mut-ty.rs:19:15
+   |
+LL |         BAR = &n;
+   |         ------^^
+   |         |     |
+   |         |     borrowed value does not live long enough
+   |         assignment requires that `n` is borrowed for `'static`
+...
+LL | }
+   | - `n` dropped here while still borrowed
+
+error[E0597]: `n` does not live long enough
+  --> $DIR/issue-69114-static-mut-ty.rs:27:22
+   |
+LL |         BAR_ELIDED = &n;
+   |         -------------^^
+   |         |            |
+   |         |            borrowed value does not live long enough
+   |         assignment requires that `n` is borrowed for `'static`
+...
+LL | }
+   | - `n` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-69114-static-ty.rs b/src/test/ui/nll/issue-69114-static-ty.rs
new file mode 100644
index 0000000..3318433
--- /dev/null
+++ b/src/test/ui/nll/issue-69114-static-ty.rs
@@ -0,0 +1,9 @@
+// Check that borrowck ensures that `static` items have the expected type.
+
+static FOO: &'static (dyn Fn(&'static u8) + Send + Sync) = &drop;
+
+fn main() {
+    let n = 42;
+    FOO(&n);
+    //~^ ERROR does not live long enough
+}
diff --git a/src/test/ui/nll/issue-69114-static-ty.stderr b/src/test/ui/nll/issue-69114-static-ty.stderr
new file mode 100644
index 0000000..0815e74
--- /dev/null
+++ b/src/test/ui/nll/issue-69114-static-ty.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `n` does not live long enough
+  --> $DIR/issue-69114-static-ty.rs:7:9
+   |
+LL |     FOO(&n);
+   |     ----^^-
+   |     |   |
+   |     |   borrowed value does not live long enough
+   |     argument requires that `n` is borrowed for `'static`
+LL |
+LL | }
+   | - `n` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/not-enough-arguments.rs b/src/test/ui/not-enough-arguments.rs
index 309283e..631bb1d 100644
--- a/src/test/ui/not-enough-arguments.rs
+++ b/src/test/ui/not-enough-arguments.rs
@@ -8,5 +8,5 @@
 
 fn main() {
   foo(1, 2, 3);
-  //~^ ERROR this function takes 4 parameters but 3
+  //~^ ERROR this function takes 4 arguments but 3
 }
diff --git a/src/test/ui/not-enough-arguments.stderr b/src/test/ui/not-enough-arguments.stderr
index c1ee43e..f2b57f7 100644
--- a/src/test/ui/not-enough-arguments.stderr
+++ b/src/test/ui/not-enough-arguments.stderr
@@ -1,11 +1,13 @@
-error[E0061]: this function takes 4 parameters but 3 parameters were supplied
+error[E0061]: this function takes 4 arguments but 3 arguments were supplied
   --> $DIR/not-enough-arguments.rs:10:3
    |
 LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
    | --------------------------------------------- defined here
 ...
 LL |   foo(1, 2, 3);
-   |   ^^^^^^^^^^^^ expected 4 parameters
+   |   ^^^ -  -  - supplied 3 arguments
+   |   |
+   |   expected 4 arguments
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
index 026747c..f2186b9 100644
--- a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
+++ b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
@@ -15,7 +15,7 @@
    |              |    |
    |              |    value borrowed here after move
    |              value moved into `_z` here
-   |              move occurs because `_z` has type `X` which does implement the `Copy` trait
+   |              move occurs because `_z` has type `X` which does not implement the `Copy` trait
 
 error: cannot move out of value because it is borrowed
   --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:29:14
@@ -34,7 +34,7 @@
    |              |    |
    |              |    value borrowed here after move
    |              value moved into `_z` here
-   |              move occurs because `_z` has type `X` which does implement the `Copy` trait
+   |              move occurs because `_z` has type `X` which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
   --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:21:19
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr
index 91fdfd4..54900e9 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr
@@ -6,7 +6,7 @@
    |         |   |
    |         |   value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `main::U` which does implement the `Copy` trait
+   |         move occurs because `a` has type `main::U` which does not implement the `Copy` trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
index ec86692..f819e67 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
@@ -6,7 +6,7 @@
    |         |   |
    |         |   value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `main::U` which does implement the `Copy` trait
+   |         move occurs because `a` has type `main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9
@@ -17,7 +17,7 @@
    |         |            |              value borrowed here after move
    |         |            value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `(main::U, main::U)` which does implement the `Copy` trait
+   |         move occurs because `a` has type `(main::U, main::U)` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:14
@@ -27,7 +27,7 @@
    |              |       |
    |              |       value borrowed here after move
    |              value moved into `b` here
-   |              move occurs because `b` has type `main::U` which does implement the `Copy` trait
+   |              move occurs because `b` has type `main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:33
@@ -37,7 +37,7 @@
    |                                 |   |
    |                                 |   value borrowed here after move
    |                                 value moved into `d` here
-   |                                 move occurs because `d` has type `main::U` which does implement the `Copy` trait
+   |                                 move occurs because `d` has type `main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:9
@@ -48,7 +48,7 @@
    |         |    |          value borrowed here after move
    |         |    value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `[main::U; 2]` which does implement the `Copy` trait
+   |         move occurs because `a` has type `[main::U; 2]` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:41:9
@@ -58,7 +58,7 @@
    |         |   |
    |         |   value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `main::U` which does implement the `Copy` trait
+   |         move occurs because `a` has type `main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:9
@@ -69,7 +69,7 @@
    |         |            |              value borrowed here after move
    |         |            value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `(main::U, main::U)` which does implement the `Copy` trait
+   |         move occurs because `a` has type `(main::U, main::U)` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:14
@@ -79,7 +79,7 @@
    |              |       |
    |              |       value borrowed here after move
    |              value moved into `b` here
-   |              move occurs because `b` has type `main::U` which does implement the `Copy` trait
+   |              move occurs because `b` has type `main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:33
@@ -89,7 +89,7 @@
    |                                 |   |
    |                                 |   value borrowed here after move
    |                                 value moved into `d` here
-   |                                 move occurs because `d` has type `main::U` which does implement the `Copy` trait
+   |                                 move occurs because `d` has type `main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:51:9
@@ -100,7 +100,7 @@
    |         |    |          value borrowed here after move
    |         |    value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `[main::U; 2]` which does implement the `Copy` trait
+   |         move occurs because `a` has type `[main::U; 2]` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:56:9
@@ -110,7 +110,7 @@
    |         |        |
    |         |        value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `std::option::Option<main::U>` which does implement the `Copy` trait
+   |         move occurs because `a` has type `std::option::Option<main::U>` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9
@@ -121,7 +121,7 @@
    |         |                 |              value borrowed here after move
    |         |                 value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `std::option::Option<(main::U, main::U)>` which does implement the `Copy` trait
+   |         move occurs because `a` has type `std::option::Option<(main::U, main::U)>` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:19
@@ -131,7 +131,7 @@
    |                   |       |
    |                   |       value borrowed here after move
    |                   value moved into `b` here
-   |                   move occurs because `b` has type `main::U` which does implement the `Copy` trait
+   |                   move occurs because `b` has type `main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:38
@@ -141,7 +141,7 @@
    |                                      |   |
    |                                      |   value borrowed here after move
    |                                      value moved into `d` here
-   |                                      move occurs because `d` has type `main::U` which does implement the `Copy` trait
+   |                                      move occurs because `d` has type `main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:71:9
@@ -152,7 +152,7 @@
    |         |             |      value borrowed here after move
    |         |             value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `std::option::Option<[main::U; 2]>` which does implement the `Copy` trait
+   |         move occurs because `a` has type `std::option::Option<[main::U; 2]>` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:77:9
@@ -162,7 +162,7 @@
    |         |        |
    |         |        value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `std::option::Option<main::U>` which does implement the `Copy` trait
+   |         move occurs because `a` has type `std::option::Option<main::U>` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:9
@@ -173,7 +173,7 @@
    |         |                 |              value borrowed here after move
    |         |                 value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `std::option::Option<(main::U, main::U)>` which does implement the `Copy` trait
+   |         move occurs because `a` has type `std::option::Option<(main::U, main::U)>` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:19
@@ -183,7 +183,7 @@
    |                   |       |
    |                   |       value borrowed here after move
    |                   value moved into `b` here
-   |                   move occurs because `b` has type `main::U` which does implement the `Copy` trait
+   |                   move occurs because `b` has type `main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:38
@@ -193,7 +193,7 @@
    |                                      |   |
    |                                      |   value borrowed here after move
    |                                      value moved into `d` here
-   |                                      move occurs because `d` has type `main::U` which does implement the `Copy` trait
+   |                                      move occurs because `d` has type `main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:93:9
@@ -204,7 +204,7 @@
    |         |             |      value borrowed here after move
    |         |             value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `std::option::Option<[main::U; 2]>` which does implement the `Copy` trait
+   |         move occurs because `a` has type `std::option::Option<[main::U; 2]>` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11
@@ -214,7 +214,7 @@
    |           |   |
    |           |   value borrowed here after move
    |           value moved into `a` here
-   |           move occurs because `a` has type `main::U` which does implement the `Copy` trait
+   |           move occurs because `a` has type `main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:11
@@ -225,7 +225,7 @@
    |           |            |              value borrowed here after move
    |           |            value borrowed here after move
    |           value moved into `a` here
-   |           move occurs because `a` has type `(main::U, main::U)` which does implement the `Copy` trait
+   |           move occurs because `a` has type `(main::U, main::U)` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:20
@@ -235,7 +235,7 @@
    |                    |   |
    |                    |   value borrowed here after move
    |                    value moved into `b` here
-   |                    move occurs because `b` has type `main::U` which does implement the `Copy` trait
+   |                    move occurs because `b` has type `main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:31
@@ -245,7 +245,7 @@
    |                               |       |
    |                               |       value borrowed here after move
    |                               value moved into `d` here
-   |                               move occurs because `d` has type `main::U` which does implement the `Copy` trait
+   |                               move occurs because `d` has type `main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:25:11
@@ -256,7 +256,7 @@
    |           |    |          value borrowed here after move
    |           |    value borrowed here after move
    |           value moved into `a` here
-   |           move occurs because `a` has type `[main::U; 2]` which does implement the `Copy` trait
+   |           move occurs because `a` has type `[main::U; 2]` which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:22
diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
index 4e96c6e..e74f227 100644
--- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
+++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
@@ -96,7 +96,7 @@
    |         |    |          value borrowed here after move
    |         |    value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `(main::U, main::U)` which does implement the `Copy` trait
+   |         move occurs because `a` has type `(main::U, main::U)` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9
@@ -108,7 +108,7 @@
    |         |    |   value borrowed here after move
    |         |    value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `&mut (main::U, [main::U; 2])` which does implement the `Copy` trait
+   |         move occurs because `a` has type `&mut (main::U, [main::U; 2])` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-ref-mut-twice.rs:74:9
@@ -118,7 +118,7 @@
    |         |        |
    |         |        value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `&mut main::U` which does implement the `Copy` trait
+   |         move occurs because `a` has type `&mut main::U` which does not implement the `Copy` trait
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-ref-mut-twice.rs:77:9
@@ -129,7 +129,7 @@
    |         |         |          value borrowed here after move
    |         |         value borrowed here after move
    |         value moved into `a` here
-   |         move occurs because `a` has type `&mut (main::U, main::U)` which does implement the `Copy` trait
+   |         move occurs because `a` has type `&mut (main::U, main::U)` which does not implement the `Copy` trait
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:82:9
diff --git a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
index 697a8b9..19e815a 100644
--- a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
+++ b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
@@ -33,7 +33,7 @@
    |                             |   |
    |                             |   value borrowed here after move
    |                             value moved into `b` here
-   |                             move occurs because `b` has type `main::NotCopy` which does implement the `Copy` trait
+   |                             move occurs because `b` has type `main::NotCopy` which does not implement the `Copy` trait
 
 error: cannot move out of value because it is borrowed
   --> $DIR/default-binding-modes-both-sides-independent.rs:44:9
diff --git a/src/test/ui/regions/regions-close-object-into-object-5.stderr b/src/test/ui/regions/regions-close-object-into-object-5.stderr
index 7c530ce..1472700 100644
--- a/src/test/ui/regions/regions-close-object-into-object-5.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-5.stderr
@@ -2,7 +2,7 @@
   --> $DIR/regions-close-object-into-object-5.rs:17:5
    |
 LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
-   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // oh dear!
 LL |     box B(&*v) as Box<X>
    |     ^^^^^^^^^^
@@ -17,7 +17,7 @@
   --> $DIR/regions-close-object-into-object-5.rs:17:5
    |
 LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
-   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // oh dear!
 LL |     box B(&*v) as Box<X>
    |     ^^^^^^^^^^^^^^^^^^^^
@@ -32,7 +32,7 @@
   --> $DIR/regions-close-object-into-object-5.rs:17:9
    |
 LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
-   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // oh dear!
 LL |     box B(&*v) as Box<X>
    |         ^
@@ -47,7 +47,7 @@
   --> $DIR/regions-close-object-into-object-5.rs:17:9
    |
 LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
-   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // oh dear!
 LL |     box B(&*v) as Box<X>
    |         ^^^^^^
@@ -62,7 +62,7 @@
   --> $DIR/regions-close-object-into-object-5.rs:17:11
    |
 LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
-   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // oh dear!
 LL |     box B(&*v) as Box<X>
    |           ^^^
@@ -77,7 +77,7 @@
   --> $DIR/regions-close-object-into-object-5.rs:17:11
    |
 LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
-   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // oh dear!
 LL |     box B(&*v) as Box<X>
    |           ^^^
@@ -92,7 +92,7 @@
   --> $DIR/regions-close-object-into-object-5.rs:17:11
    |
 LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
-   |          - help: consider adding an explicit lifetime bound `T: 'static`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // oh dear!
 LL |     box B(&*v) as Box<X>
    |           ^^^
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr
index 81534b7..ed9a604 100644
--- a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr
+++ b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr
@@ -2,7 +2,7 @@
   --> $DIR/regions-close-over-type-parameter-1.rs:10:5
    |
 LL | fn make_object1<A:SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
-   |                 -- help: consider adding an explicit lifetime bound `A: 'static`...
+   |                 -- help: consider adding an explicit lifetime bound...: `A: 'static +`
 LL |     box v as Box<dyn SomeTrait + 'static>
    |     ^^^^^
    |
@@ -16,7 +16,7 @@
   --> $DIR/regions-close-over-type-parameter-1.rs:10:5
    |
 LL | fn make_object1<A:SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
-   |                 -- help: consider adding an explicit lifetime bound `A: 'static`...
+   |                 -- help: consider adding an explicit lifetime bound...: `A: 'static +`
 LL |     box v as Box<dyn SomeTrait + 'static>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
@@ -30,7 +30,7 @@
   --> $DIR/regions-close-over-type-parameter-1.rs:20:5
    |
 LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'b> {
-   |                       -- help: consider adding an explicit lifetime bound `A: 'b`...
+   |                       -- help: consider adding an explicit lifetime bound...: `A: 'b +`
 LL |     box v as Box<dyn SomeTrait + 'b>
    |     ^^^^^
    |
@@ -44,7 +44,7 @@
   --> $DIR/regions-close-over-type-parameter-1.rs:20:5
    |
 LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'b> {
-   |                       -- help: consider adding an explicit lifetime bound `A: 'b`...
+   |                       -- help: consider adding an explicit lifetime bound...: `A: 'b +`
 LL |     box v as Box<dyn SomeTrait + 'b>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
diff --git a/src/test/ui/regions/regions-close-param-into-object.stderr b/src/test/ui/regions/regions-close-param-into-object.stderr
index 7f2c646..3b1a89d 100644
--- a/src/test/ui/regions/regions-close-param-into-object.stderr
+++ b/src/test/ui/regions/regions-close-param-into-object.stderr
@@ -2,7 +2,7 @@
   --> $DIR/regions-close-param-into-object.rs:6:5
    |
 LL | fn p1<T>(v: T) -> Box<dyn X + 'static>
-   |       - help: consider adding an explicit lifetime bound `T: 'static`...
+   |       - help: consider adding an explicit lifetime bound...: `T: 'static`
 ...
 LL |     Box::new(v)
    |     ^^^^^^^^^^^
@@ -17,7 +17,7 @@
   --> $DIR/regions-close-param-into-object.rs:12:5
    |
 LL | fn p2<T>(v: Box<T>) -> Box<dyn X + 'static>
-   |       - help: consider adding an explicit lifetime bound `T: 'static`...
+   |       - help: consider adding an explicit lifetime bound...: `T: 'static`
 ...
 LL |     Box::new(v)
    |     ^^^^^^^^^^^
@@ -32,7 +32,7 @@
   --> $DIR/regions-close-param-into-object.rs:18:5
    |
 LL | fn p3<'a,T>(v: T) -> Box<dyn X + 'a>
-   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 ...
 LL |     Box::new(v)
    |     ^^^^^^^^^^^
@@ -47,7 +47,7 @@
   --> $DIR/regions-close-param-into-object.rs:24:5
    |
 LL | fn p4<'a,T>(v: Box<T>) -> Box<dyn X + 'a>
-   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 ...
 LL |     Box::new(v)
    |     ^^^^^^^^^^^
diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr
index 8701408..297fcb0 100644
--- a/src/test/ui/regions/regions-enum-not-wf.stderr
+++ b/src/test/ui/regions/regions-enum-not-wf.stderr
@@ -2,7 +2,7 @@
   --> $DIR/regions-enum-not-wf.rs:18:18
    |
 LL | enum Ref1<'a, T> {
-   |               - help: consider adding an explicit lifetime bound `T: 'a`...
+   |               - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     Ref1Variant1(RequireOutlives<'a, T>)
    |                  ^^^^^^^^^^^^^^^^^^^^^^
    |
@@ -16,7 +16,7 @@
   --> $DIR/regions-enum-not-wf.rs:23:25
    |
 LL | enum Ref2<'a, T> {
-   |               - help: consider adding an explicit lifetime bound `T: 'a`...
+   |               - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     Ref2Variant1,
 LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
    |                         ^^^^^^^^^^^^^^^^^^^^^^
@@ -31,7 +31,7 @@
   --> $DIR/regions-enum-not-wf.rs:35:1
    |
 LL |   enum RefDouble<'a, 'b, T> {
-   |   ^                      - help: consider adding an explicit lifetime bound `T: 'b`...
+   |   ^                      - help: consider adding an explicit lifetime bound...: `T: 'b`
    |  _|
    | |
 LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
@@ -52,7 +52,7 @@
   --> $DIR/regions-enum-not-wf.rs:36:23
    |
 LL | enum RefDouble<'a, 'b, T> {
-   |                        - help: consider adding an explicit lifetime bound `T: 'b`...
+   |                        - help: consider adding an explicit lifetime bound...: `T: 'b`
 LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr
index 7fbc162..2f1a4ce 100644
--- a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr
@@ -2,7 +2,7 @@
   --> $DIR/regions-implied-bounds-projection-gap-1.rs:16:10
    |
 LL | fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
-   |             -- help: consider adding an explicit lifetime bound `T: 'x`...
+   |             -- help: consider adding an explicit lifetime bound...: `T: 'x +`
 LL | {
 LL |     wf::<&'x T>();
    |          ^^^^^
diff --git a/src/test/ui/regions/regions-infer-bound-from-trait.stderr b/src/test/ui/regions/regions-infer-bound-from-trait.stderr
index 382d932..a5a0ff5 100644
--- a/src/test/ui/regions/regions-infer-bound-from-trait.stderr
+++ b/src/test/ui/regions/regions-infer-bound-from-trait.stderr
@@ -2,7 +2,7 @@
   --> $DIR/regions-infer-bound-from-trait.rs:33:5
    |
 LL | fn bar1<'a,A>(x: Inv<'a>, a: A) {
-   |            - help: consider adding an explicit lifetime bound `A: 'a`...
+   |            - help: consider adding an explicit lifetime bound...: `A: 'a`
 LL |     check_bound(x, a)
    |     ^^^^^^^^^^^
    |
@@ -16,7 +16,7 @@
   --> $DIR/regions-infer-bound-from-trait.rs:37:5
    |
 LL | fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) {
-   |               -- help: consider adding an explicit lifetime bound `A: 'a`...
+   |               -- help: consider adding an explicit lifetime bound...: `A: 'a +`
 LL |     check_bound(x, a)
    |     ^^^^^^^^^^^
    |
diff --git a/src/test/ui/resolve/resolve-primitive-fallback.rs b/src/test/ui/resolve/resolve-primitive-fallback.rs
index e5a3d68..992bcd7 100644
--- a/src/test/ui/resolve/resolve-primitive-fallback.rs
+++ b/src/test/ui/resolve/resolve-primitive-fallback.rs
@@ -2,7 +2,7 @@
     // Make sure primitive type fallback doesn't work in value namespace
     std::mem::size_of(u16);
     //~^ ERROR expected value, found builtin type `u16`
-    //~| ERROR this function takes 0 parameters but 1 parameter was supplied
+    //~| ERROR this function takes 0 arguments but 1 argument was supplied
 
     // Make sure primitive type fallback doesn't work with global paths
     let _: ::u8;
diff --git a/src/test/ui/resolve/resolve-primitive-fallback.stderr b/src/test/ui/resolve/resolve-primitive-fallback.stderr
index 92c2a03..6d61d2f 100644
--- a/src/test/ui/resolve/resolve-primitive-fallback.stderr
+++ b/src/test/ui/resolve/resolve-primitive-fallback.stderr
@@ -10,11 +10,13 @@
 LL |     let _: ::u8;
    |              ^^ not found in the crate root
 
-error[E0061]: this function takes 0 parameters but 1 parameter was supplied
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/resolve-primitive-fallback.rs:3:5
    |
 LL |     std::mem::size_of(u16);
-   |     ^^^^^^^^^^^^^^^^^^^^^^ expected 0 parameters
+   |     ^^^^^^^^^^^^^^^^^ --- supplied 1 argument
+   |     |
+   |     expected 0 arguments
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
index b049d8a..c3cfc5a 100644
--- a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
+++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
@@ -2,7 +2,7 @@
   --> $DIR/dont-infer-static.rs:8:5
    |
 LL | struct Foo<U> {
-   |            - help: consider adding an explicit lifetime bound `U: 'static`...
+   |            - help: consider adding an explicit lifetime bound...: `U: 'static`
 LL |     bar: Bar<U>
    |     ^^^^^^^^^^^
    |
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
index 8701408..297fcb0 100644
--- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
@@ -2,7 +2,7 @@
   --> $DIR/regions-enum-not-wf.rs:18:18
    |
 LL | enum Ref1<'a, T> {
-   |               - help: consider adding an explicit lifetime bound `T: 'a`...
+   |               - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     Ref1Variant1(RequireOutlives<'a, T>)
    |                  ^^^^^^^^^^^^^^^^^^^^^^
    |
@@ -16,7 +16,7 @@
   --> $DIR/regions-enum-not-wf.rs:23:25
    |
 LL | enum Ref2<'a, T> {
-   |               - help: consider adding an explicit lifetime bound `T: 'a`...
+   |               - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     Ref2Variant1,
 LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
    |                         ^^^^^^^^^^^^^^^^^^^^^^
@@ -31,7 +31,7 @@
   --> $DIR/regions-enum-not-wf.rs:35:1
    |
 LL |   enum RefDouble<'a, 'b, T> {
-   |   ^                      - help: consider adding an explicit lifetime bound `T: 'b`...
+   |   ^                      - help: consider adding an explicit lifetime bound...: `T: 'b`
    |  _|
    | |
 LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
@@ -52,7 +52,7 @@
   --> $DIR/regions-enum-not-wf.rs:36:23
    |
 LL | enum RefDouble<'a, 'b, T> {
-   |                        - help: consider adding an explicit lifetime bound `T: 'b`...
+   |                        - help: consider adding an explicit lifetime bound...: `T: 'b`
 LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
index 825c101..f665889 100644
--- a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
@@ -2,7 +2,7 @@
   --> $DIR/regions-struct-not-wf.rs:13:5
    |
 LL | impl<'a, T> Trait<'a, T> for usize {
-   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Out = &'a T;
    |     ^^^^^^^^^^^^^^^^^
    |
@@ -16,7 +16,7 @@
   --> $DIR/regions-struct-not-wf.rs:21:5
    |
 LL | impl<'a, T> Trait<'a, T> for u32 {
-   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Out = RefOk<'a, T>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
diff --git a/src/test/ui/span/E0057.stderr b/src/test/ui/span/E0057.stderr
index 6b5890c..31579e2 100644
--- a/src/test/ui/span/E0057.stderr
+++ b/src/test/ui/span/E0057.stderr
@@ -1,14 +1,18 @@
-error[E0057]: this function takes 1 parameter but 0 parameters were supplied
+error[E0057]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/E0057.rs:3:13
    |
 LL |     let a = f();
-   |             ^^^ expected 1 parameter
+   |             ^-- supplied 0 arguments
+   |             |
+   |             expected 1 argument
 
-error[E0057]: this function takes 1 parameter but 2 parameters were supplied
+error[E0057]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/E0057.rs:5:13
    |
 LL |     let c = f(2, 3);
-   |             ^^^^^^^ expected 1 parameter
+   |             ^ -  - supplied 2 arguments
+   |             |
+   |             expected 1 argument
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr
index 80a237a..116f5dd 100644
--- a/src/test/ui/span/issue-34264.stderr
+++ b/src/test/ui/span/issue-34264.stderr
@@ -50,14 +50,16 @@
 LL | fn bar(_: x, y: usize) {}
    |        ^^^^
 
-error[E0061]: this function takes 2 parameters but 3 parameters were supplied
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:7:5
    |
 LL | fn foo(Option<i32>, String) {}
    | --------------------------- defined here
 ...
 LL |     foo(Some(42), 2, "");
-   |     ^^^^^^^^^^^^^^^^^^^^ expected 2 parameters
+   |     ^^^ --------  -  -- supplied 3 arguments
+   |     |
+   |     expected 2 arguments
 
 error[E0308]: mismatched types
   --> $DIR/issue-34264.rs:8:13
@@ -65,14 +67,16 @@
 LL |     bar("", "");
    |             ^^ expected `usize`, found `&str`
 
-error[E0061]: this function takes 2 parameters but 3 parameters were supplied
+error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:10:5
    |
 LL | fn bar(x, y: usize) {}
    | ------------------- defined here
 ...
 LL |     bar(1, 2, 3);
-   |     ^^^^^^^^^^^^ expected 2 parameters
+   |     ^^^ -  -  - supplied 3 arguments
+   |     |
+   |     expected 2 arguments
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr
index 90a96e3..f6344fb 100644
--- a/src/test/ui/span/missing-unit-argument.stderr
+++ b/src/test/ui/span/missing-unit-argument.stderr
@@ -1,68 +1,72 @@
-error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:11:33
    |
 LL |     let _: Result<(), String> = Ok();
-   |                                 ^^^^
+   |                                 ^^-- supplied 0 arguments
    |
 help: expected the unit value `()`; create it with empty parentheses
    |
 LL |     let _: Result<(), String> = Ok(());
    |                                    ^^
 
-error[E0061]: this function takes 2 parameters but 0 parameters were supplied
+error[E0061]: this function takes 2 arguments but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:12:5
    |
 LL | fn foo(():(), ():()) {}
    | -------------------- defined here
 ...
 LL |     foo();
-   |     ^^^^^ expected 2 parameters
+   |     ^^^-- supplied 0 arguments
+   |     |
+   |     expected 2 arguments
 
-error[E0061]: this function takes 2 parameters but 1 parameter was supplied
+error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> $DIR/missing-unit-argument.rs:13:5
    |
 LL | fn foo(():(), ():()) {}
    | -------------------- defined here
 ...
 LL |     foo(());
-   |     ^^^^^^^ expected 2 parameters
+   |     ^^^ -- supplied 1 argument
+   |     |
+   |     expected 2 arguments
 
-error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:14:5
    |
 LL | fn bar(():()) {}
    | ------------- defined here
 ...
 LL |     bar();
-   |     ^^^^^
+   |     ^^^-- supplied 0 arguments
    |
 help: expected the unit value `()`; create it with empty parentheses
    |
 LL |     bar(());
    |         ^^
 
-error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:15:7
    |
 LL |     fn baz(self, (): ()) { }
    |     -------------------- defined here
 ...
 LL |     S.baz();
-   |       ^^^
+   |       ^^^- supplied 0 arguments
    |
 help: expected the unit value `()`; create it with empty parentheses
    |
 LL |     S.baz(());
    |           ^^
 
-error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/missing-unit-argument.rs:16:7
    |
 LL |     fn generic<T>(self, _: T) { }
    |     ------------------------- defined here
 ...
 LL |     S.generic::<()>();
-   |       ^^^^^^^
+   |       ^^^^^^^------ supplied 0 arguments
    |
 help: expected the unit value `()`; create it with empty parentheses
    |
diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed
index 8592af1..589ee1a 100644
--- a/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed
+++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed
@@ -3,7 +3,7 @@
 use std::fmt::Debug;
 
 fn foo(d: impl Debug + 'static) {
-//~^ HELP consider adding an explicit lifetime bound  `'static` to `impl Debug`
+//~^ HELP consider adding an explicit lifetime bound...
     bar(d);
 //~^ ERROR the parameter type `impl Debug` may not live long enough
 //~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds
diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs
index c67d78e..9a87129 100644
--- a/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs
+++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs
@@ -3,7 +3,7 @@
 use std::fmt::Debug;
 
 fn foo(d: impl Debug) {
-//~^ HELP consider adding an explicit lifetime bound  `'static` to `impl Debug`
+//~^ HELP consider adding an explicit lifetime bound...
     bar(d);
 //~^ ERROR the parameter type `impl Debug` may not live long enough
 //~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds
diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr
index cba231d..b6e6c0b 100644
--- a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr
+++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr
@@ -1,6 +1,9 @@
 error[E0310]: the parameter type `impl Debug` may not live long enough
   --> $DIR/suggest-impl-trait-lifetime.rs:7:5
    |
+LL | fn foo(d: impl Debug) {
+   |           ---------- help: consider adding an explicit lifetime bound...: `impl Debug + 'static`
+LL |
 LL |     bar(d);
    |     ^^^
    |
@@ -9,10 +12,6 @@
    |
 LL |     bar(d);
    |     ^^^
-help: consider adding an explicit lifetime bound  `'static` to `impl Debug`...
-   |
-LL | fn foo(d: impl Debug + 'static) {
-   |           ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs
index fa3e1a3..d012687 100644
--- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs
@@ -18,6 +18,6 @@
 }
 
 fn main() {
-    <E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
+    <E>::V(); //~ ERROR this function takes 1 argument but 0 arguments were supplied
     let _: u8 = <E2>::V; //~ ERROR mismatched types
 }
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
index 95c3a08..46e7dd0 100644
--- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
@@ -1,11 +1,13 @@
-error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:21:5
    |
 LL |     V(u8)
    |     ----- defined here
 ...
 LL |     <E>::V();
-   |     ^^^^^^^^ expected 1 parameter
+   |     ^^^^^^-- supplied 0 arguments
+   |     |
+   |     expected 1 argument
 
 error[E0308]: mismatched types
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
index 5a7f9d7..22e2391 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
@@ -25,7 +25,7 @@
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ...
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
-   |                  - help: consider adding an explicit lifetime bound `T: 'static`...
+   |                  - help: consider adding an explicit lifetime bound...: `T: 'static`
    |
 note: ...so that the type `T` will meet its required lifetime bounds
   --> $DIR/generic_type_does_not_live_long_enough.rs:9:1
diff --git a/src/test/ui/type/type-ascription-instead-of-initializer.rs b/src/test/ui/type/type-ascription-instead-of-initializer.rs
index aef2525..9f9b6f0 100644
--- a/src/test/ui/type/type-ascription-instead-of-initializer.rs
+++ b/src/test/ui/type/type-ascription-instead-of-initializer.rs
@@ -1,4 +1,4 @@
 fn main() {
     let x: Vec::with_capacity(10, 20);  //~ ERROR expected type, found `10`
-    //~^ ERROR this function takes 1 parameter
+    //~^ ERROR this function takes 1 argument
 }
diff --git a/src/test/ui/type/type-ascription-instead-of-initializer.stderr b/src/test/ui/type/type-ascription-instead-of-initializer.stderr
index 3fe676d..530f77e 100644
--- a/src/test/ui/type/type-ascription-instead-of-initializer.stderr
+++ b/src/test/ui/type/type-ascription-instead-of-initializer.stderr
@@ -7,11 +7,13 @@
    |         |help: use `=` if you meant to assign
    |         while parsing the type for `x`
 
-error[E0061]: this function takes 1 parameter but 2 parameters were supplied
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
   --> $DIR/type-ascription-instead-of-initializer.rs:2:12
    |
 LL |     let x: Vec::with_capacity(10, 20);
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 parameter
+   |            ^^^^^^^^^^^^^^^^^^ --  -- supplied 2 arguments
+   |            |
+   |            expected 1 argument
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/wf/wf-impl-associated-type-region.stderr b/src/test/ui/wf/wf-impl-associated-type-region.stderr
index 9cc3602..9942c80 100644
--- a/src/test/ui/wf/wf-impl-associated-type-region.stderr
+++ b/src/test/ui/wf/wf-impl-associated-type-region.stderr
@@ -2,7 +2,7 @@
   --> $DIR/wf-impl-associated-type-region.rs:10:5
    |
 LL | impl<'a, T> Foo<'a> for T {
-   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Bar = &'a T;
    |     ^^^^^^^^^^^^^^^^^
    |
diff --git a/src/test/ui/wf/wf-in-fn-type-static.stderr b/src/test/ui/wf/wf-in-fn-type-static.stderr
index 8952c78..7dc8f5a 100644
--- a/src/test/ui/wf/wf-in-fn-type-static.stderr
+++ b/src/test/ui/wf/wf-in-fn-type-static.stderr
@@ -2,7 +2,7 @@
   --> $DIR/wf-in-fn-type-static.rs:13:5
    |
 LL | struct Foo<T> {
-   |            - help: consider adding an explicit lifetime bound `T: 'static`...
+   |            - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // needs T: 'static
 LL |     x: fn() -> &'static T
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@
   --> $DIR/wf-in-fn-type-static.rs:18:5
    |
 LL | struct Bar<T> {
-   |            - help: consider adding an explicit lifetime bound `T: 'static`...
+   |            - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // needs T: Copy
 LL |     x: fn(&'static T)
    |     ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/wf/wf-in-obj-type-static.stderr b/src/test/ui/wf/wf-in-obj-type-static.stderr
index c461da7..32c3198 100644
--- a/src/test/ui/wf/wf-in-obj-type-static.stderr
+++ b/src/test/ui/wf/wf-in-obj-type-static.stderr
@@ -2,7 +2,7 @@
   --> $DIR/wf-in-obj-type-static.rs:14:5
    |
 LL | struct Foo<T> {
-   |            - help: consider adding an explicit lifetime bound `T: 'static`...
+   |            - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // needs T: 'static
 LL |     x: dyn Object<&'static T>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr
index f1cf514..52786fb 100644
--- a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr
+++ b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr
@@ -2,7 +2,7 @@
   --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:5
    |
 LL | impl<'a, T> Trait<'a, T> for usize {
-   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Out = &'a fn(T);
    |     ^^^^^^^^^^^^^^^^^^^^^
    |
@@ -16,7 +16,7 @@
   --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:5
    |
 LL | impl<'a, T> Trait<'a, T> for u32 {
-   |          - help: consider adding an explicit lifetime bound `T: 'a`...
+   |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Out = &'a dyn Baz<T>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
diff --git a/src/tools/clippy b/src/tools/clippy
index 2855b21..8fbb23f 160000
--- a/src/tools/clippy
+++ b/src/tools/clippy
@@ -1 +1 @@
-Subproject commit 2855b2143972df7102333193aa3c83ddce227e36
+Subproject commit 8fbb23f2549e75b89967f09b9293607bd3bb96a6
diff --git a/src/tools/rls b/src/tools/rls
index 0100ac8..10bf331 160000
--- a/src/tools/rls
+++ b/src/tools/rls
@@ -1 +1 @@
-Subproject commit 0100ac87b4ce5bbed6e56a62f313fbc3ff037a89
+Subproject commit 10bf331d4d1280d773045e57d65031969c51dec6