diff --git a/config.toml.example b/config.toml.example
index be97702442609..e832570ed982e 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -258,10 +258,9 @@
 [rust]
 
 # Whether or not to optimize the compiler and standard library.
-#
-# Note: the slowness of the non optimized compiler compiling itself usually
-#       outweighs the time gains in not doing optimizations, therefore a
-#       full bootstrap takes much more time with `optimize` set to false.
+# WARNING: Building with optimize = false is NOT SUPPORTED. Due to bootstrapping,
+# building without optimizations takes much longer than optimizing. Further, some platforms
+# fail to build without this optimization (c.f. #65352).
 #optimize = true
 
 # Indicates that the build should be configured for debugging Rust. A
@@ -341,6 +340,9 @@
 # nightly features
 #channel = "dev"
 
+# The root location of the MUSL installation directory.
+#musl-root = "..."
+
 # By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix
 # platforms to ensure that the compiler is usable by default from the build
 # directory (as it links to a number of dynamic libraries). This may not be
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 441bb8d68faf9..d1bdfa0a76763 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -200,16 +200,15 @@ struct Build {
     target: Vec<String>,
     cargo: Option<String>,
     rustc: Option<String>,
-    low_priority: Option<bool>,
-    compiler_docs: Option<bool>,
     docs: Option<bool>,
+    compiler_docs: Option<bool>,
     submodules: Option<bool>,
     fast_submodules: Option<bool>,
     gdb: Option<String>,
-    locked_deps: Option<bool>,
-    vendor: Option<bool>,
     nodejs: Option<String>,
     python: Option<String>,
+    locked_deps: Option<bool>,
+    vendor: Option<bool>,
     full_bootstrap: Option<bool>,
     extended: Option<bool>,
     tools: Option<HashSet<String>>,
@@ -217,6 +216,7 @@ struct Build {
     sanitizers: Option<bool>,
     profiler: Option<bool>,
     cargo_native_static: Option<bool>,
+    low_priority: Option<bool>,
     configure_args: Option<Vec<String>>,
     local_rebuild: Option<bool>,
     print_step_timings: Option<bool>,
@@ -228,11 +228,11 @@ struct Build {
 struct Install {
     prefix: Option<String>,
     sysconfdir: Option<String>,
-    datadir: Option<String>,
     docdir: Option<String>,
     bindir: Option<String>,
     libdir: Option<String>,
     mandir: Option<String>,
+    datadir: Option<String>,
 
     // standard paths, currently unused
     infodir: Option<String>,
@@ -243,14 +243,14 @@ struct Install {
 #[derive(Deserialize, Default)]
 #[serde(deny_unknown_fields, rename_all = "kebab-case")]
 struct Llvm {
-    ccache: Option<StringOrBool>,
-    ninja: Option<bool>,
-    assertions: Option<bool>,
     optimize: Option<bool>,
     thin_lto: Option<bool>,
     release_debuginfo: Option<bool>,
+    assertions: Option<bool>,
+    ccache: Option<StringOrBool>,
     version_check: Option<bool>,
     static_libstdcpp: Option<bool>,
+    ninja: Option<bool>,
     targets: Option<String>,
     experimental_targets: Option<String>,
     link_jobs: Option<u32>,
@@ -293,6 +293,7 @@ impl Default for StringOrBool {
 #[serde(deny_unknown_fields, rename_all = "kebab-case")]
 struct Rust {
     optimize: Option<bool>,
+    debug: Option<bool>,
     codegen_units: Option<u32>,
     codegen_units_std: Option<u32>,
     debug_assertions: Option<bool>,
@@ -301,25 +302,24 @@ struct Rust {
     debuginfo_level_std: Option<u32>,
     debuginfo_level_tools: Option<u32>,
     debuginfo_level_tests: Option<u32>,
-    parallel_compiler: Option<bool>,
     backtrace: Option<bool>,
+    incremental: Option<bool>,
+    parallel_compiler: Option<bool>,
     default_linker: Option<String>,
     channel: Option<String>,
     musl_root: Option<String>,
     rpath: Option<bool>,
+    verbose_tests: Option<bool>,
     optimize_tests: Option<bool>,
     codegen_tests: Option<bool>,
     ignore_git: Option<bool>,
-    debug: Option<bool>,
     dist_src: Option<bool>,
-    verbose_tests: Option<bool>,
-    incremental: Option<bool>,
     save_toolstates: Option<String>,
     codegen_backends: Option<Vec<String>>,
     codegen_backends_dir: Option<String>,
     lld: Option<bool>,
-    lldb: Option<bool>,
     llvm_tools: Option<bool>,
+    lldb: Option<bool>,
     deny_warnings: Option<bool>,
     backtrace_on_ice: Option<bool>,
     verify_llvm_ir: Option<bool>,
@@ -333,13 +333,13 @@ struct Rust {
 #[derive(Deserialize, Default)]
 #[serde(deny_unknown_fields, rename_all = "kebab-case")]
 struct TomlTarget {
-    llvm_config: Option<String>,
-    llvm_filecheck: Option<String>,
     cc: Option<String>,
     cxx: Option<String>,
     ar: Option<String>,
     ranlib: Option<String>,
     linker: Option<String>,
+    llvm_config: Option<String>,
+    llvm_filecheck: Option<String>,
     android_ndk: Option<String>,
     crt_static: Option<bool>,
     musl_root: Option<String>,
diff --git a/src/libcore/array/iter.rs b/src/libcore/array/iter.rs
new file mode 100644
index 0000000000000..850a599c6599f
--- /dev/null
+++ b/src/libcore/array/iter.rs
@@ -0,0 +1,266 @@
+//! Defines the `IntoIter` owned iterator for arrays.
+
+use crate::{
+    fmt,
+    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
+    mem::{self, MaybeUninit},
+    ops::Range,
+    ptr,
+};
+use super::LengthAtMost32;
+
+
+/// A by-value [array] iterator.
+///
+/// [array]: ../../std/primitive.array.html
+#[unstable(feature = "array_value_iter", issue = "0")]
+pub struct IntoIter<T, const N: usize>
+where
+    [T; N]: LengthAtMost32,
+{
+    /// This is the array we are iterating over.
+    ///
+    /// Elements with index `i` where `alive.start <= i < alive.end` have not
+    /// been yielded yet and are valid array entries. Elements with indices `i
+    /// < alive.start` or `i >= alive.end` have been yielded already and must
+    /// not be accessed anymore! Those dead elements might even be in a
+    /// completely uninitialized state!
+    ///
+    /// So the invariants are:
+    /// - `data[alive]` is alive (i.e. contains valid elements)
+    /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
+    ///   elements were already read and must not be touched anymore!)
+    data: [MaybeUninit<T>; N],
+
+    /// The elements in `data` that have not been yielded yet.
+    ///
+    /// Invariants:
+    /// - `alive.start <= alive.end`
+    /// - `alive.end <= N`
+    alive: Range<usize>,
+}
+
+impl<T, const N: usize> IntoIter<T, {N}>
+where
+    [T; N]: LengthAtMost32,
+{
+    /// Creates a new iterator over the given `array`.
+    ///
+    /// *Note*: this method might never get stabilized and/or removed in the
+    /// future as there will likely be another, preferred way of obtaining this
+    /// iterator (either via `IntoIterator` for arrays or via another way).
+    #[unstable(feature = "array_value_iter", issue = "0")]
+    pub fn new(array: [T; N]) -> Self {
+        // The transmute here is actually safe. The docs of `MaybeUninit`
+        // promise:
+        //
+        // > `MaybeUninit<T>` is guaranteed to have the same size and alignment
+        // > as `T`.
+        //
+        // The docs even show a transmute from an array of `MaybeUninit<T>` to
+        // an array of `T`.
+        //
+        // With that, this initialization satisfies the invariants.
+
+        // FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
+        // works with const generics:
+        //     `mem::transmute::<[T; {N}], [MaybeUninit<T>; {N}]>(array)`
+        //
+        // Until then, we do it manually here. We first create a bitwise copy
+        // but cast the pointer so that it is treated as a different type. Then
+        // we forget `array` so that it is not dropped.
+        let data = unsafe {
+            let data = ptr::read(&array as *const [T; N] as *const [MaybeUninit<T>; N]);
+            mem::forget(array);
+            data
+        };
+
+        Self {
+            data,
+            alive: 0..N,
+        }
+    }
+
+    /// Returns an immutable slice of all elements that have not been yielded
+    /// yet.
+    fn as_slice(&self) -> &[T] {
+        // This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
+        // the size and alignment of `T`. Furthermore, we know that all
+        // elements within `alive` are properly initialized.
+        let slice = &self.data[self.alive.clone()];
+        unsafe {
+            mem::transmute::<&[MaybeUninit<T>], &[T]>(slice)
+        }
+    }
+}
+
+
+#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
+impl<T, const N: usize> Iterator for IntoIter<T, {N}>
+where
+    [T; N]: LengthAtMost32,
+{
+    type Item = T;
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.alive.start == self.alive.end {
+            return None;
+        }
+
+        // Bump start index.
+        //
+        // From the check above we know that `alive.start != alive.end`.
+        // Combine this with the invariant `alive.start <= alive.end`, we know
+        // that `alive.start < alive.end`. Increasing `alive.start` by 1
+        // maintains the invariant regarding `alive`. However, due to this
+        // change, for a short time, the alive zone is not `data[alive]`
+        // anymore, but `data[idx..alive.end]`.
+        let idx = self.alive.start;
+        self.alive.start += 1;
+
+        // Read the element from the array. This is safe: `idx` is an index
+        // into the "alive" region of the array. Reading this element means
+        // that `data[idx]` is regarded as dead now (i.e. do not touch). As
+        // `idx` was the start of the alive-zone, the alive zone is now
+        // `data[alive]` again, restoring all invariants.
+        let out = unsafe { self.data.get_unchecked(idx).read() };
+
+        Some(out)
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let len = self.len();
+        (len, Some(len))
+    }
+
+    fn count(self) -> usize {
+        self.len()
+    }
+
+    fn last(mut self) -> Option<Self::Item> {
+        self.next_back()
+    }
+}
+
+#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
+impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, {N}>
+where
+    [T; N]: LengthAtMost32,
+{
+    fn next_back(&mut self) -> Option<Self::Item> {
+        if self.alive.start == self.alive.end {
+            return None;
+        }
+
+        // Decrease end index.
+        //
+        // From the check above we know that `alive.start != alive.end`.
+        // Combine this with the invariant `alive.start <= alive.end`, we know
+        // that `alive.start < alive.end`. As `alive.start` cannot be negative,
+        // `alive.end` is at least 1, meaning that we can safely decrement it
+        // by one. This also maintains the invariant `alive.start <=
+        // alive.end`. However, due to this change, for a short time, the alive
+        // zone is not `data[alive]` anymore, but `data[alive.start..alive.end
+        // + 1]`.
+        self.alive.end -= 1;
+
+        // Read the element from the array. This is safe: `alive.end` is an
+        // index into the "alive" region of the array. Compare the previous
+        // comment that states that the alive region is
+        // `data[alive.start..alive.end + 1]`. Reading this element means that
+        // `data[alive.end]` is regarded as dead now (i.e. do not touch). As
+        // `alive.end` was the end of the alive-zone, the alive zone is now
+        // `data[alive]` again, restoring all invariants.
+        let out = unsafe { self.data.get_unchecked(self.alive.end).read() };
+
+        Some(out)
+    }
+}
+
+#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
+impl<T, const N: usize> Drop for IntoIter<T, {N}>
+where
+    [T; N]: LengthAtMost32,
+{
+    fn drop(&mut self) {
+        // We simply drop each element via `for_each`. This should not incur
+        // any significant runtime overhead and avoids adding another `unsafe`
+        // block.
+        self.by_ref().for_each(drop);
+    }
+}
+
+#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
+impl<T, const N: usize> ExactSizeIterator for IntoIter<T, {N}>
+where
+    [T; N]: LengthAtMost32,
+{
+    fn len(&self) -> usize {
+        // Will never underflow due to the invariant `alive.start <=
+        // alive.end`.
+        self.alive.end - self.alive.start
+    }
+    fn is_empty(&self) -> bool {
+        self.alive.is_empty()
+    }
+}
+
+#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
+impl<T, const N: usize> FusedIterator for IntoIter<T, {N}>
+where
+    [T; N]: LengthAtMost32,
+{}
+
+// The iterator indeed reports the correct length. The number of "alive"
+// elements (that will still be yielded) is the length of the range `alive`.
+// This range is decremented in length in either `next` or `next_back`. It is
+// always decremented by 1 in those methods, but only if `Some(_)` is returned.
+#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
+unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, {N}>
+where
+    [T; N]: LengthAtMost32,
+{}
+
+#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
+impl<T: Clone, const N: usize> Clone for IntoIter<T, {N}>
+where
+    [T; N]: LengthAtMost32,
+{
+    fn clone(&self) -> Self {
+        unsafe {
+            // This creates a new uninitialized array. Note that the `assume_init`
+            // refers to the array, not the individual elements. And it is Ok if
+            // the array is in an uninitialized state as all elements may be
+            // uninitialized (all bit patterns are valid). Compare the
+            // `MaybeUninit` docs for more information.
+            let mut new_data: [MaybeUninit<T>; N] = MaybeUninit::uninit().assume_init();
+
+            // Clone all alive elements.
+            for idx in self.alive.clone() {
+                // The element at `idx` in the old array is alive, so we can
+                // safely call `get_ref()`. We then clone it, and write the
+                // clone into the new array.
+                let clone = self.data.get_unchecked(idx).get_ref().clone();
+                new_data.get_unchecked_mut(idx).write(clone);
+            }
+
+            Self {
+                data: new_data,
+                alive: self.alive.clone(),
+            }
+        }
+    }
+}
+
+#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
+impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, {N}>
+where
+    [T; N]: LengthAtMost32,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // Only print the elements that were not yielded yet: we cannot
+        // access the yielded elements anymore.
+        f.debug_tuple("IntoIter")
+            .field(&self.as_slice())
+            .finish()
+    }
+}
diff --git a/src/libcore/array.rs b/src/libcore/array/mod.rs
similarity index 98%
rename from src/libcore/array.rs
rename to src/libcore/array/mod.rs
index b5614010e5c2f..120658e9a4343 100644
--- a/src/libcore/array.rs
+++ b/src/libcore/array/mod.rs
@@ -14,6 +14,13 @@ use crate::hash::{Hash, self};
 use crate::marker::Unsize;
 use crate::slice::{Iter, IterMut};
 
+#[cfg(not(bootstrap))]
+mod iter;
+
+#[cfg(not(bootstrap))]
+#[unstable(feature = "array_value_iter", issue = "0")]
+pub use iter::IntoIter;
+
 /// Utility trait implemented only on arrays of fixed size
 ///
 /// This trait can be used to implement other traits on fixed-size arrays
diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs
index 9e133ac568811..4f3b79c78b66c 100644
--- a/src/libcore/tests/array.rs
+++ b/src/libcore/tests/array.rs
@@ -1,4 +1,4 @@
-use core::array::FixedSizeArray;
+use core::array::{FixedSizeArray, IntoIter};
 use core::convert::TryFrom;
 
 #[test]
@@ -40,3 +40,208 @@ fn array_try_from() {
         30 31 32
     }
 }
+
+
+#[test]
+fn iterator_collect() {
+    let arr = [0, 1, 2, 5, 9];
+    let v: Vec<_> = IntoIter::new(arr.clone()).collect();
+    assert_eq!(&arr[..], &v[..]);
+}
+
+#[test]
+fn iterator_rev_collect() {
+    let arr = [0, 1, 2, 5, 9];
+    let v: Vec<_> = IntoIter::new(arr.clone()).rev().collect();
+    assert_eq!(&v[..], &[9, 5, 2, 1, 0]);
+}
+
+#[test]
+fn iterator_nth() {
+    let v = [0, 1, 2, 3, 4];
+    for i in 0..v.len() {
+        assert_eq!(IntoIter::new(v.clone()).nth(i).unwrap(), v[i]);
+    }
+    assert_eq!(IntoIter::new(v.clone()).nth(v.len()), None);
+
+    let mut iter = IntoIter::new(v);
+    assert_eq!(iter.nth(2).unwrap(), v[2]);
+    assert_eq!(iter.nth(1).unwrap(), v[4]);
+}
+
+#[test]
+fn iterator_last() {
+    let v = [0, 1, 2, 3, 4];
+    assert_eq!(IntoIter::new(v).last().unwrap(), 4);
+    assert_eq!(IntoIter::new([0]).last().unwrap(), 0);
+
+    let mut it = IntoIter::new([0, 9, 2, 4]);
+    assert_eq!(it.next_back(), Some(4));
+    assert_eq!(it.last(), Some(2));
+}
+
+#[test]
+fn iterator_clone() {
+    let mut it = IntoIter::new([0, 2, 4, 6, 8]);
+    assert_eq!(it.next(), Some(0));
+    assert_eq!(it.next_back(), Some(8));
+    let mut clone = it.clone();
+    assert_eq!(it.next_back(), Some(6));
+    assert_eq!(clone.next_back(), Some(6));
+    assert_eq!(it.next_back(), Some(4));
+    assert_eq!(clone.next_back(), Some(4));
+    assert_eq!(it.next(), Some(2));
+    assert_eq!(clone.next(), Some(2));
+}
+
+#[test]
+fn iterator_fused() {
+    let mut it = IntoIter::new([0, 9, 2]);
+    assert_eq!(it.next(), Some(0));
+    assert_eq!(it.next(), Some(9));
+    assert_eq!(it.next(), Some(2));
+    assert_eq!(it.next(), None);
+    assert_eq!(it.next(), None);
+    assert_eq!(it.next(), None);
+    assert_eq!(it.next(), None);
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn iterator_len() {
+    let mut it = IntoIter::new([0, 1, 2, 5, 9]);
+    assert_eq!(it.size_hint(), (5, Some(5)));
+    assert_eq!(it.len(), 5);
+    assert_eq!(it.is_empty(), false);
+
+    assert_eq!(it.next(), Some(0));
+    assert_eq!(it.size_hint(), (4, Some(4)));
+    assert_eq!(it.len(), 4);
+    assert_eq!(it.is_empty(), false);
+
+    assert_eq!(it.next_back(), Some(9));
+    assert_eq!(it.size_hint(), (3, Some(3)));
+    assert_eq!(it.len(), 3);
+    assert_eq!(it.is_empty(), false);
+
+    // Empty
+    let it = IntoIter::new([] as [String; 0]);
+    assert_eq!(it.size_hint(), (0, Some(0)));
+    assert_eq!(it.len(), 0);
+    assert_eq!(it.is_empty(), true);
+}
+
+#[test]
+fn iterator_count() {
+    let v = [0, 1, 2, 3, 4];
+    assert_eq!(IntoIter::new(v.clone()).count(), 5);
+
+    let mut iter2 = IntoIter::new(v);
+    iter2.next();
+    iter2.next();
+    assert_eq!(iter2.count(), 3);
+}
+
+#[test]
+fn iterator_flat_map() {
+    assert!((0..5).flat_map(|i| IntoIter::new([2 * i, 2 * i + 1])).eq(0..10));
+}
+
+#[test]
+fn iterator_debug() {
+    let arr = [0, 1, 2, 5, 9];
+    assert_eq!(
+        format!("{:?}", IntoIter::new(arr)),
+        "IntoIter([0, 1, 2, 5, 9])",
+    );
+}
+
+#[test]
+fn iterator_drops() {
+    use core::cell::Cell;
+
+    // This test makes sure the correct number of elements are dropped. The `R`
+    // type is just a reference to a `Cell` that is incremented when an `R` is
+    // dropped.
+
+    #[derive(Clone)]
+    struct Foo<'a>(&'a Cell<usize>);
+
+    impl Drop for Foo<'_> {
+       fn drop(&mut self) {
+            self.0.set(self.0.get() + 1);
+        }
+    }
+
+    fn five(i: &Cell<usize>) -> [Foo<'_>; 5] {
+        // This is somewhat verbose because `Foo` does not implement `Copy`
+        // since it implements `Drop`. Consequently, we cannot write
+        // `[Foo(i); 5]`.
+        [Foo(i), Foo(i), Foo(i), Foo(i), Foo(i)]
+    }
+
+    // Simple: drop new iterator.
+    let i = Cell::new(0);
+    {
+        IntoIter::new(five(&i));
+    }
+    assert_eq!(i.get(), 5);
+
+    // Call `next()` once.
+    let i = Cell::new(0);
+    {
+        let mut iter = IntoIter::new(five(&i));
+        let _x = iter.next();
+        assert_eq!(i.get(), 0);
+        assert_eq!(iter.count(), 4);
+        assert_eq!(i.get(), 4);
+    }
+    assert_eq!(i.get(), 5);
+
+    // Check `clone` and calling `next`/`next_back`.
+    let i = Cell::new(0);
+    {
+        let mut iter = IntoIter::new(five(&i));
+        iter.next();
+        assert_eq!(i.get(), 1);
+        iter.next_back();
+        assert_eq!(i.get(), 2);
+
+        let mut clone = iter.clone();
+        assert_eq!(i.get(), 2);
+
+        iter.next();
+        assert_eq!(i.get(), 3);
+
+        clone.next();
+        assert_eq!(i.get(), 4);
+
+        assert_eq!(clone.count(), 2);
+        assert_eq!(i.get(), 6);
+    }
+    assert_eq!(i.get(), 8);
+
+    // Check via `nth`.
+    let i = Cell::new(0);
+    {
+        let mut iter = IntoIter::new(five(&i));
+        let _x = iter.nth(2);
+        assert_eq!(i.get(), 2);
+        let _y = iter.last();
+        assert_eq!(i.get(), 3);
+    }
+    assert_eq!(i.get(), 5);
+
+    // Check every element.
+    let i = Cell::new(0);
+    for (index, _x) in IntoIter::new(five(&i)).enumerate() {
+        assert_eq!(i.get(), index);
+    }
+    assert_eq!(i.get(), 5);
+
+    let i = Cell::new(0);
+    for (index, _x) in IntoIter::new(five(&i)).rev().enumerate() {
+        assert_eq!(i.get(), index);
+    }
+    assert_eq!(i.get(), 5);
+}
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 35661356028cb..b28ed2eaa0876 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -31,6 +31,7 @@
 #![feature(slice_partition_dedup)]
 #![feature(int_error_matching)]
 #![feature(const_fn)]
+#![feature(array_value_iter)]
 #![feature(iter_partition_in_place)]
 #![feature(iter_is_partitioned)]
 #![feature(iter_order_by)]
diff --git a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
index c88f1cac35040..34ac96beb5ca3 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
@@ -178,6 +178,9 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'
         a: ty::Region<'tcx>,
         b: ty::Region<'tcx>,
     ) {
+        if let ty::ReEmpty = a {
+            return;
+        }
         let b = self.to_region_vid(b);
         let a = self.to_region_vid(a);
         self.add_outlives(b, a);
@@ -190,6 +193,9 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'
         a: ty::Region<'tcx>,
         bound: VerifyBound<'tcx>,
     ) {
+        if let ty::ReEmpty = a {
+            return;
+        }
         let type_test = self.verify_to_type_test(kind, a, bound);
         self.add_type_test(type_test);
     }
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index dc6d4b27886e4..907c84b6f8cf0 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -394,16 +394,6 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
         }
     }
 
-    fn is_non_exhaustive_variant<'p>(&self, pattern: &'p Pat<'tcx>) -> bool {
-        match *pattern.kind {
-            PatKind::Variant { adt_def, variant_index, .. } => {
-                let ref variant = adt_def.variants[variant_index];
-                variant.is_field_list_non_exhaustive()
-            }
-            _ => false,
-        }
-    }
-
     fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
         match ty.kind {
             ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(),
@@ -1252,19 +1242,12 @@ pub fn is_useful<'p, 'a, 'tcx>(
     debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v[0]);
 
     if let Some(constructors) = pat_constructors(cx, v[0], pcx) {
-        let is_declared_nonexhaustive = cx.is_non_exhaustive_variant(v[0]) && !cx.is_local(pcx.ty);
-        debug!("is_useful - expanding constructors: {:#?}, is_declared_nonexhaustive: {:?}",
-               constructors, is_declared_nonexhaustive);
-
-        if is_declared_nonexhaustive {
-            Useful
-        } else {
-            split_grouped_constructors(
-                cx.tcx, cx.param_env, constructors, matrix, pcx.ty, pcx.span, Some(hir_id),
-            ).into_iter().map(|c|
-                is_useful_specialized(cx, matrix, v, c, pcx.ty, witness, hir_id)
-            ).find(|result| result.is_useful()).unwrap_or(NotUseful)
-        }
+        debug!("is_useful - expanding constructors: {:#?}", constructors);
+        split_grouped_constructors(
+            cx.tcx, cx.param_env, constructors, matrix, pcx.ty, pcx.span, Some(hir_id),
+        ).into_iter().map(|c|
+            is_useful_specialized(cx, matrix, v, c, pcx.ty, witness, hir_id)
+        ).find(|result| result.is_useful()).unwrap_or(NotUseful)
     } else {
         debug!("is_useful - expanding wildcard");
 
@@ -1548,27 +1531,30 @@ fn constructor_sub_pattern_tys<'a, 'tcx>(
                 // Use T as the sub pattern type of Box<T>.
                 vec![substs.type_at(0)]
             } else {
-                adt.variants[ctor.variant_index_for_adt(cx, adt)].fields.iter().map(|field| {
+                let variant = &adt.variants[ctor.variant_index_for_adt(cx, adt)];
+                let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !cx.is_local(ty);
+                variant.fields.iter().map(|field| {
                     let is_visible = adt.is_enum()
                         || field.vis.is_accessible_from(cx.module, cx.tcx);
-                    if is_visible {
-                        let ty = field.ty(cx.tcx, substs);
-                        match ty.kind {
-                            // If the field type returned is an array of an unknown
-                            // size return an TyErr.
-                            ty::Array(_, len)
-                                if len.try_eval_usize(cx.tcx, cx.param_env).is_none() =>
-                                cx.tcx.types.err,
-                            _ => ty,
-                        }
-                    } else {
-                        // Treat all non-visible fields as TyErr. They
-                        // can't appear in any other pattern from
-                        // this match (because they are private),
-                        // so their type does not matter - but
-                        // we don't want to know they are
-                        // uninhabited.
-                        cx.tcx.types.err
+                    let is_uninhabited = cx.is_uninhabited(field.ty(cx.tcx, substs));
+                    match (is_visible, is_non_exhaustive, is_uninhabited) {
+                        // Treat all uninhabited types in non-exhaustive variants as `TyErr`.
+                        (_, true, true) => cx.tcx.types.err,
+                        // Treat all non-visible fields as `TyErr`. They can't appear in any
+                        // other pattern from this match (because they are private), so their
+                        // type does not matter - but we don't want to know they are uninhabited.
+                        (false, ..) => cx.tcx.types.err,
+                        (true, ..) => {
+                            let ty = field.ty(cx.tcx, substs);
+                            match ty.kind {
+                                // If the field type returned is an array of an unknown
+                                // size return an TyErr.
+                                ty::Array(_, len)
+                                    if len.try_eval_usize(cx.tcx, cx.param_env).is_none() =>
+                                    cx.tcx.types.err,
+                                _ => ty,
+                            }
+                        },
                     }
                 }).collect()
             }
@@ -1874,15 +1860,18 @@ fn constructor_covered_by_range<'tcx>(
     }
 }
 
-fn patterns_for_variant<'p, 'tcx>(
+fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
+    cx: &mut MatchCheckCtxt<'a, 'tcx>,
     subpatterns: &'p [FieldPat<'tcx>],
-    wild_patterns: &[&'p Pat<'tcx>])
-    -> SmallVec<[&'p Pat<'tcx>; 2]>
-{
+    wild_patterns: &[&'p Pat<'tcx>],
+    is_non_exhaustive: bool,
+) -> SmallVec<[&'p Pat<'tcx>; 2]> {
     let mut result = SmallVec::from_slice(wild_patterns);
 
     for subpat in subpatterns {
-        result[subpat.field.index()] = &subpat.pattern;
+        if !is_non_exhaustive || !cx.is_uninhabited(subpat.pattern.ty) {
+            result[subpat.field.index()] = &subpat.pattern;
+        }
     }
 
     debug!("patterns_for_variant({:#?}, {:#?}) = {:#?}", subpatterns, wild_patterns, result);
@@ -1916,13 +1905,14 @@ fn specialize<'p, 'a: 'p, 'tcx>(
 
         PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
             let ref variant = adt_def.variants[variant_index];
+            let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !cx.is_local(pat.ty);
             Some(Variant(variant.def_id))
                 .filter(|variant_constructor| variant_constructor == constructor)
-                .map(|_| patterns_for_variant(subpatterns, wild_patterns))
+                .map(|_| patterns_for_variant(cx, subpatterns, wild_patterns, is_non_exhaustive))
         }
 
         PatKind::Leaf { ref subpatterns } => {
-            Some(patterns_for_variant(subpatterns, wild_patterns))
+            Some(patterns_for_variant(cx, subpatterns, wild_patterns, false))
         }
 
         PatKind::Deref { ref subpattern } => {
diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs
index 9883a64a1e896..be2e9f505aa6f 100644
--- a/src/librustc_resolve/error_codes.rs
+++ b/src/librustc_resolve/error_codes.rs
@@ -1797,6 +1797,31 @@ let _: <u8 as Age>::Empire; // ok!
 ```
 "##,
 
+E0576: r##"
+An associated item wasn't found in the given type.
+
+Erroneous code example:
+
+```compile_fail,E0576
+trait Hello {
+    type Who;
+
+    fn hello() -> <Self as Hello>::You; // error!
+}
+```
+
+In this example, we tried to use the non-existent associated type `You` of the
+`Hello` trait. To fix this error, use an existing associated type:
+
+```
+trait Hello {
+    type Who;
+
+    fn hello() -> <Self as Hello>::Who; // ok!
+}
+```
+"##,
+
 E0603: r##"
 A private item was used outside its scope.
 
@@ -1925,7 +1950,6 @@ struct Foo<X = Box<Self>> {
 //  E0427, merged into 530
 //  E0467, removed
 //  E0470, removed
-    E0576,
     E0577,
     E0578,
 }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 79dc4f7e13613..aa05a08686a99 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -215,7 +215,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// Report error if there is an explicit type parameter when using `impl Trait`.
     fn check_impl_trait(
         tcx: TyCtxt<'_>,
-        span: Span,
         seg: &hir::PathSegment,
         generics: &ty::Generics,
     ) -> bool {
@@ -228,14 +227,28 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         });
 
         if explicit && impl_trait {
+            let spans =
+                seg.generic_args().args
+                    .iter()
+                    .filter_map(|arg|
+                        match arg {
+                            GenericArg::Type(_) => Some(arg.span()),
+                            _ => None
+                        })
+                    .collect::<Vec<_>>();
+
             let mut err = struct_span_err! {
                 tcx.sess,
-                span,
+                spans.clone(),
                 E0632,
                 "cannot provide explicit generic arguments when `impl Trait` is \
-                 used in argument position"
+                used in argument position"
             };
 
+            for span in spans {
+                err.span_label(span, "explicit generic argument not allowed");
+            }
+
             err.emit();
         }
 
@@ -254,7 +267,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let empty_args = P(hir::GenericArgs {
             args: HirVec::new(), bindings: HirVec::new(), parenthesized: false,
         });
-        let suppress_mismatch = Self::check_impl_trait(tcx, span, seg, &def);
+        let suppress_mismatch = Self::check_impl_trait(tcx, seg, &def);
         Self::check_generic_arg_count(
             tcx,
             span,
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index d0cb0104f6cba..2894cd1c1f685 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -220,7 +220,7 @@
 
 #![cfg_attr(test, feature(print_internals, set_stdio, update_panic_count))]
 #![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"),
-            feature(slice_index_methods, decl_macro, coerce_unsized,
+            feature(slice_index_methods, coerce_unsized,
                     sgx_platform, ptr_wrapping_offset_from))]
 #![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"),
             feature(fixed_size_array, maybe_uninit_extra))]
@@ -251,6 +251,7 @@
 #![feature(container_error_extra)]
 #![feature(core_intrinsics)]
 #![feature(custom_test_frameworks)]
+#![feature(decl_macro)]
 #![feature(doc_alias)]
 #![feature(doc_cfg)]
 #![feature(doc_keyword)]
diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs
index 1386eac48dae2..4f92401d2bc57 100644
--- a/src/libsyntax/feature_gate/active.rs
+++ b/src/libsyntax/feature_gate/active.rs
@@ -330,8 +330,13 @@ declare_features! (
     /// Allows exhaustive pattern matching on types that contain uninhabited types.
     (active, exhaustive_patterns, "1.13.0", Some(51085), None),
 
-    /// Allows untagged unions `union U { ... }`.
-    (active, untagged_unions, "1.13.0", Some(32836), None),
+    /// Allows `union`s to implement `Drop`. Moreover, `union`s may now include fields
+    /// that don't implement `Copy` as long as they don't have any drop glue.
+    /// This is checked recursively. On encountering type variable where no progress can be made,
+    /// `T: Copy` is used as a substitute for "no drop glue".
+    ///
+    /// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0.
+    (active, untagged_unions, "1.13.0", Some(55149), None),
 
     /// Allows `#[link(..., cfg(..))]`.
     (active, link_cfg, "1.14.0", Some(37406), None),
@@ -522,13 +527,16 @@ declare_features! (
     /// Allows the definition of `const extern fn` and `const unsafe extern fn`.
     (active, const_extern_fn, "1.40.0", Some(64926), None),
 
-    // Allows the use of raw-dylibs (RFC 2627).
+    /// Allows the use of raw-dylibs (RFC 2627).
     (active, raw_dylib, "1.40.0", Some(58713), None),
 
-    /// Enable accurate caller location reporting during panic (RFC 2091).
+    /// Allows `#[track_caller]` to be used which provides
+    /// accurate caller location reporting during panic (RFC 2091).
     (active, track_caller, "1.40.0", Some(47809), None),
 
-    /// Non-object safe trait objects safe to use but cannot be created in safe rust
+    /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe.
+    /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
+    /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
     (active, object_safe_for_dispatch, "1.40.0", Some(43561), None),
 
     // -------------------------------------------------------------------------
diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs
index 172511f0f099b..502b1c0f74371 100644
--- a/src/libsyntax/feature_gate/check.rs
+++ b/src/libsyntax/feature_gate/check.rs
@@ -3,12 +3,8 @@ use super::accepted::ACCEPTED_FEATURES;
 use super::removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES};
 use super::builtin_attrs::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
 
-use crate::ast::{
-    self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind,
-    PatKind, RangeEnd, VariantData,
-};
+use crate::ast::{self, NodeId, PatKind, VariantData};
 use crate::attr::{self, check_builtin_attribute};
-use crate::source_map::Spanned;
 use crate::edition::{ALL_EDITIONS, Edition};
 use crate::visit::{self, FnKind, Visitor};
 use crate::parse::token;
@@ -157,9 +153,6 @@ fn leveled_feature_err<'a, S: Into<MultiSpan>>(
 
 }
 
-const EXPLAIN_BOX_SYNTAX: &str =
-    "box expression syntax is experimental; you can call `Box::new` instead";
-
 pub const EXPLAIN_STMT_ATTR_SYNTAX: &str =
     "attributes on expressions are experimental";
 
@@ -291,6 +284,25 @@ impl<'a> PostExpansionVisitor<'a> {
             err.emit();
         }
     }
+
+    fn check_gat(&self, generics: &ast::Generics, span: Span) {
+        if !generics.params.is_empty() {
+            gate_feature_post!(
+                &self,
+                generic_associated_types,
+                span,
+                "generic associated types are unstable"
+            );
+        }
+        if !generics.where_clause.predicates.is_empty() {
+            gate_feature_post!(
+                &self,
+                generic_associated_types,
+                span,
+                "where clauses on associated types are unstable"
+            );
+        }
+    }
 }
 
 impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
@@ -423,20 +435,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                    "auto traits are experimental and possibly buggy");
             }
 
-            ast::ItemKind::TraitAlias(..) => {
-                gate_feature_post!(
-                    &self,
-                    trait_alias,
-                    i.span,
-                    "trait aliases are experimental"
-                );
-            }
-
-            ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
-                let msg = "`macro` is experimental";
-                gate_feature_post!(&self, decl_macro, i.span, msg);
-            }
-
             ast::ItemKind::OpaqueTy(..) => {
                 gate_feature_post!(
                     &self,
@@ -500,37 +498,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         }
     }
 
-    fn visit_expr(&mut self, e: &'a ast::Expr) {
-        match e.kind {
-            ast::ExprKind::Box(_) => {
-                gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
-            }
-            ast::ExprKind::Type(..) => {
-                // To avoid noise about type ascription in common syntax errors, only emit if it
-                // is the *only* error.
-                if self.parse_sess.span_diagnostic.err_count() == 0 {
-                    gate_feature_post!(&self, type_ascription, e.span,
-                                       "type ascription is experimental");
-                }
-            }
-            ast::ExprKind::TryBlock(_) => {
-                gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
-            }
-            ast::ExprKind::Block(_, opt_label) => {
-                if let Some(label) = opt_label {
-                    gate_feature_post!(&self, label_break_value, label.ident.span,
-                                    "labels on blocks are unstable");
-                }
-            }
-            _ => {}
-        }
-        visit::walk_expr(self, e)
-    }
-
-    fn visit_arm(&mut self, arm: &'a ast::Arm) {
-        visit::walk_arm(self, arm)
-    }
-
     fn visit_pat(&mut self, pattern: &'a ast::Pat) {
         match &pattern.kind {
             PatKind::Slice(pats) => {
@@ -550,25 +517,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                     }
                 }
             }
-            PatKind::Box(..) => {
-                gate_feature_post!(&self, box_patterns,
-                                  pattern.span,
-                                  "box pattern syntax is experimental");
-            }
-            PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => {
-                gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
-                                   "exclusive range pattern syntax is experimental");
-            }
             _ => {}
         }
         visit::walk_pat(self, pattern)
     }
 
-    fn visit_fn(&mut self,
-                fn_kind: FnKind<'a>,
-                fn_decl: &'a ast::FnDecl,
-                span: Span,
-                _node_id: NodeId) {
+    fn visit_fn(&mut self, fn_kind: FnKind<'a>, fn_decl: &'a ast::FnDecl, span: Span, _: NodeId) {
         if let Some(header) = fn_kind.header() {
             // Stability of const fn methods are covered in
             // `visit_trait_item` and `visit_impl_item` below; this is
@@ -583,26 +537,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         visit::walk_fn(self, fn_kind, fn_decl, span)
     }
 
-    fn visit_generic_param(&mut self, param: &'a GenericParam) {
-        match param.kind {
-            GenericParamKind::Const { .. } =>
-                gate_feature_post!(&self, const_generics, param.ident.span,
-                    "const generics are unstable"),
-            _ => {}
-        }
-        visit::walk_generic_param(self, param)
-    }
-
-    fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) {
-        match constraint.kind {
-            AssocTyConstraintKind::Bound { .. } =>
-                gate_feature_post!(&self, associated_type_bounds, constraint.span,
-                    "associated type bounds are unstable"),
-            _ => {}
-        }
-        visit::walk_assoc_ty_constraint(self, constraint)
-    }
-
     fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
         match ti.kind {
             ast::TraitItemKind::Method(ref sig, ref block) => {
@@ -624,14 +558,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                     gate_feature_post!(&self, associated_type_defaults, ti.span,
                                        "associated type defaults are unstable");
                 }
-                if !ti.generics.params.is_empty() {
-                    gate_feature_post!(&self, generic_associated_types, ti.span,
-                                       "generic associated types are unstable");
-                }
-                if !ti.generics.where_clause.predicates.is_empty() {
-                    gate_feature_post!(&self, generic_associated_types, ti.span,
-                                       "where clauses on associated types are unstable");
-                }
+                self.check_gat(&ti.generics, ti.span);
             }
             _ => {}
         }
@@ -661,27 +588,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 );
             }
             ast::ImplItemKind::TyAlias(_) => {
-                if !ii.generics.params.is_empty() {
-                    gate_feature_post!(&self, generic_associated_types, ii.span,
-                                       "generic associated types are unstable");
-                }
-                if !ii.generics.where_clause.predicates.is_empty() {
-                    gate_feature_post!(&self, generic_associated_types, ii.span,
-                                       "where clauses on associated types are unstable");
-                }
+                self.check_gat(&ii.generics, ii.span);
             }
             _ => {}
         }
         visit::walk_impl_item(self, ii)
     }
-
-    fn visit_vis(&mut self, vis: &'a ast::Visibility) {
-        if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node {
-            gate_feature_post!(&self, crate_visibility_modifier, vis.span,
-                               "`crate` visibility modifier is experimental");
-        }
-        visit::walk_vis(self, vis)
-    }
 }
 
 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
@@ -867,6 +779,22 @@ pub fn check_crate(krate: &ast::Crate,
     gate_all!(yields, generators, "yield syntax is experimental");
     gate_all!(or_patterns, "or-patterns syntax is experimental");
     gate_all!(const_extern_fn, "`const extern fn` definitions are unstable");
+    gate_all!(trait_alias, "trait aliases are experimental");
+    gate_all!(associated_type_bounds, "associated type bounds are unstable");
+    gate_all!(crate_visibility_modifier, "`crate` visibility modifier is experimental");
+    gate_all!(const_generics, "const generics are unstable");
+    gate_all!(decl_macro, "`macro` is experimental");
+    gate_all!(box_patterns, "box pattern syntax is experimental");
+    gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental");
+    gate_all!(try_blocks, "`try` blocks are unstable");
+    gate_all!(label_break_value, "labels on blocks are unstable");
+    gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead");
+
+    // To avoid noise about type ascription in common syntax errors,
+    // only emit if it is the *only* error. (Also check it last.)
+    if parse_sess.span_diagnostic.err_count() == 0 {
+        gate_all!(type_ascription, "type ascription is experimental");
+    }
 
     visit::walk_crate(&mut visitor, krate);
 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2ce0046ca276c..f25224d1e36f5 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1122,6 +1122,7 @@ impl<'a> Parser<'a> {
         self.expected_tokens.push(TokenType::Keyword(kw::Crate));
         if self.is_crate_vis() {
             self.bump(); // `crate`
+            self.sess.gated_spans.crate_visibility_modifier.borrow_mut().push(self.prev_span);
             return Ok(respan(self.prev_span, VisibilityKind::Crate(CrateSugar::JustCrate)));
         }
 
diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs
index 67a530ec6831b..97b1092452aaf 100644
--- a/src/libsyntax/parse/parser/expr.rs
+++ b/src/libsyntax/parse/parser/expr.rs
@@ -252,6 +252,7 @@ impl<'a> Parser<'a> {
                 self.last_type_ascription = Some((self.prev_span, maybe_path));
 
                 lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?;
+                self.sess.gated_spans.type_ascription.borrow_mut().push(lhs.span);
                 continue
             } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
                 // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to
@@ -453,7 +454,9 @@ impl<'a> Parser<'a> {
                 self.bump();
                 let e = self.parse_prefix_expr(None);
                 let (span, e) = self.interpolated_or_expr_span(e)?;
-                (lo.to(span), ExprKind::Box(e))
+                let span = lo.to(span);
+                self.sess.gated_spans.box_syntax.borrow_mut().push(span);
+                (span, ExprKind::Box(e))
             }
             token::Ident(..) if self.token.is_ident_named(sym::not) => {
                 // `not` is just an ordinary identifier in Rust-the-language,
@@ -1260,6 +1263,10 @@ impl<'a> Parser<'a> {
         blk_mode: BlockCheckMode,
         outer_attrs: ThinVec<Attribute>,
     ) -> PResult<'a, P<Expr>> {
+        if let Some(label) = opt_label {
+            self.sess.gated_spans.label_break_value.borrow_mut().push(label.ident.span);
+        }
+
         self.expect(&token::OpenDelim(token::Brace))?;
 
         let mut attrs = outer_attrs;
@@ -1646,7 +1653,9 @@ impl<'a> Parser<'a> {
             error.emit();
             Err(error)
         } else {
-            Ok(self.mk_expr(span_lo.to(body.span), ExprKind::TryBlock(body), attrs))
+            let span = span_lo.to(body.span);
+            self.sess.gated_spans.try_blocks.borrow_mut().push(span);
+            Ok(self.mk_expr(span, ExprKind::TryBlock(body), attrs))
         }
     }
 
diff --git a/src/libsyntax/parse/parser/generics.rs b/src/libsyntax/parse/parser/generics.rs
index bfcb0042a75a3..51caae69c86a4 100644
--- a/src/libsyntax/parse/parser/generics.rs
+++ b/src/libsyntax/parse/parser/generics.rs
@@ -55,11 +55,15 @@ impl<'a> Parser<'a> {
     }
 
     fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> {
+        let lo = self.token.span;
+
         self.expect_keyword(kw::Const)?;
         let ident = self.parse_ident()?;
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
 
+        self.sess.gated_spans.const_generics.borrow_mut().push(lo.to(self.prev_span));
+
         Ok(GenericParam {
             ident,
             id: ast::DUMMY_NODE_ID,
diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index 73bd80e2a21f7..95bddb5afdd08 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -211,7 +211,7 @@ impl<'a> Parser<'a> {
         {
             // UNSAFE TRAIT ITEM
             self.bump(); // `unsafe`
-            let info = self.parse_item_trait(Unsafety::Unsafe)?;
+            let info = self.parse_item_trait(lo, Unsafety::Unsafe)?;
             return self.mk_item_with_info(attrs, lo, vis, info);
         }
 
@@ -289,7 +289,7 @@ impl<'a> Parser<'a> {
                 && self.is_keyword_ahead(1, &[kw::Trait]))
         {
             // TRAIT ITEM
-            let info = self.parse_item_trait(Unsafety::Normal)?;
+            let info = self.parse_item_trait(lo, Unsafety::Normal)?;
             return self.mk_item_with_info(attrs, lo, vis, info);
         }
 
@@ -780,7 +780,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`.
-    fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
+    fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
         // Parse optional `auto` prefix.
         let is_auto = if self.eat_keyword(kw::Auto) {
             IsAuto::Yes
@@ -793,29 +793,43 @@ impl<'a> Parser<'a> {
         let mut tps = self.parse_generics()?;
 
         // Parse optional colon and supertrait bounds.
-        let bounds = if self.eat(&token::Colon) {
+        let had_colon = self.eat(&token::Colon);
+        let span_at_colon = self.prev_span;
+        let bounds = if had_colon {
             self.parse_generic_bounds(Some(self.prev_span))?
         } else {
             Vec::new()
         };
 
+        let span_before_eq = self.prev_span;
         if self.eat(&token::Eq) {
             // It's a trait alias.
+            if had_colon {
+                let span = span_at_colon.to(span_before_eq);
+                self.struct_span_err(span, "bounds are not allowed on trait aliases")
+                    .emit();
+            }
+
             let bounds = self.parse_generic_bounds(None)?;
             tps.where_clause = self.parse_where_clause()?;
             self.expect(&token::Semi)?;
+
+            let whole_span = lo.to(self.prev_span);
             if is_auto == IsAuto::Yes {
                 let msg = "trait aliases cannot be `auto`";
-                self.struct_span_err(self.prev_span, msg)
-                    .span_label(self.prev_span, msg)
+                self.struct_span_err(whole_span, msg)
+                    .span_label(whole_span, msg)
                     .emit();
             }
             if unsafety != Unsafety::Normal {
                 let msg = "trait aliases cannot be `unsafe`";
-                self.struct_span_err(self.prev_span, msg)
-                    .span_label(self.prev_span, msg)
+                self.struct_span_err(whole_span, msg)
+                    .span_label(whole_span, msg)
                     .emit();
             }
+
+            self.sess.gated_spans.trait_alias.borrow_mut().push(whole_span);
+
             Ok((ident, ItemKind::TraitAlias(tps, bounds), None))
         } else {
             // It's a normal trait.
@@ -1692,6 +1706,11 @@ impl<'a> Parser<'a> {
         };
 
         let span = lo.to(self.prev_span);
+
+        if !def.legacy {
+            self.sess.gated_spans.decl_macro.borrow_mut().push(span);
+        }
+
         Ok(Some(self.mk_item(span, ident, ItemKind::MacroDef(def), vis.clone(), attrs.to_vec())))
     }
 
diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs
index af795e51792ff..969d5dd837480 100644
--- a/src/libsyntax/parse/parser/pat.rs
+++ b/src/libsyntax/parse/parser/pat.rs
@@ -324,7 +324,9 @@ impl<'a> Parser<'a> {
                 self.parse_pat_ident(BindingMode::ByRef(mutbl))?
             } else if self.eat_keyword(kw::Box) {
                 // Parse `box pat`
-                PatKind::Box(self.parse_pat_with_range_pat(false, None)?)
+                let pat = self.parse_pat_with_range_pat(false, None)?;
+                self.sess.gated_spans.box_patterns.borrow_mut().push(lo.to(self.prev_span));
+                PatKind::Box(pat)
             } else if self.can_be_ident_pat() {
                 // Parse `ident @ pat`
                 // This can give false positives and parse nullary enums,
@@ -609,6 +611,11 @@ impl<'a> Parser<'a> {
         Ok(PatKind::Mac(mac))
     }
 
+    fn excluded_range_end(&self, span: Span) -> RangeEnd {
+        self.sess.gated_spans.exclusive_range_pattern.borrow_mut().push(span);
+        RangeEnd::Excluded
+    }
+
     /// Parse a range pattern `$path $form $end?` where `$form = ".." | "..." | "..=" ;`.
     /// The `$path` has already been parsed and the next token is the `$form`.
     fn parse_pat_range_starting_with_path(
@@ -618,7 +625,7 @@ impl<'a> Parser<'a> {
         path: Path
     ) -> PResult<'a, PatKind> {
         let (end_kind, form) = match self.token.kind {
-            token::DotDot => (RangeEnd::Excluded, ".."),
+            token::DotDot => (self.excluded_range_end(self.token.span), ".."),
             token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."),
             token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="),
             _ => panic!("can only parse `..`/`...`/`..=` for ranges (checked above)"),
@@ -641,7 +648,7 @@ impl<'a> Parser<'a> {
         } else if self.eat(&token::DotDotEq) {
             (RangeEnd::Included(RangeSyntax::DotDotEq), "..=")
         } else if self.eat(&token::DotDot) {
-            (RangeEnd::Excluded, "..")
+            (self.excluded_range_end(op_span), "..")
         } else {
             panic!("impossible case: we already matched on a range-operator token")
         };
diff --git a/src/libsyntax/parse/parser/path.rs b/src/libsyntax/parse/parser/path.rs
index 639d61a2b5cd4..77709a2295339 100644
--- a/src/libsyntax/parse/parser/path.rs
+++ b/src/libsyntax/parse/parser/path.rs
@@ -404,8 +404,9 @@ impl<'a> Parser<'a> {
                 // Parse lifetime argument.
                 args.push(GenericArg::Lifetime(self.expect_lifetime()));
                 misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints);
-            } else if self.check_ident() && self.look_ahead(1,
-                    |t| t == &token::Eq || t == &token::Colon) {
+            } else if self.check_ident()
+                && self.look_ahead(1, |t| t == &token::Eq || t == &token::Colon)
+            {
                 // Parse associated type constraint.
                 let lo = self.token.span;
                 let ident = self.parse_ident()?;
@@ -420,7 +421,14 @@ impl<'a> Parser<'a> {
                 } else {
                     unreachable!();
                 };
+
                 let span = lo.to(self.prev_span);
+
+                // Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
+                if let AssocTyConstraintKind::Bound { .. } = kind {
+                    self.sess.gated_spans.associated_type_bounds.borrow_mut().push(span);
+                }
+
                 constraints.push(AssocTyConstraint {
                     id: ast::DUMMY_NODE_ID,
                     ident,
diff --git a/src/libsyntax/sess.rs b/src/libsyntax/sess.rs
index e49d3954f8e69..28a0868d5dd1e 100644
--- a/src/libsyntax/sess.rs
+++ b/src/libsyntax/sess.rs
@@ -30,6 +30,28 @@ crate struct GatedSpans {
     crate or_patterns: Lock<Vec<Span>>,
     /// Spans collected for gating `const_extern_fn`, e.g. `const extern fn foo`.
     crate const_extern_fn: Lock<Vec<Span>>,
+    /// Spans collected for gating `trait_alias`, e.g. `trait Foo = Ord + Eq;`.
+    pub trait_alias: Lock<Vec<Span>>,
+    /// Spans collected for gating `associated_type_bounds`, e.g. `Iterator<Item: Ord>`.
+    pub associated_type_bounds: Lock<Vec<Span>>,
+    /// Spans collected for gating `crate_visibility_modifier`, e.g. `crate fn`.
+    pub crate_visibility_modifier: Lock<Vec<Span>>,
+    /// Spans collected for gating `const_generics`, e.g. `const N: usize`.
+    pub const_generics: Lock<Vec<Span>>,
+    /// Spans collected for gating `decl_macro`, e.g. `macro m() {}`.
+    pub decl_macro: Lock<Vec<Span>>,
+    /// Spans collected for gating `box_patterns`, e.g. `box 0`.
+    pub box_patterns: Lock<Vec<Span>>,
+    /// Spans collected for gating `exclusive_range_pattern`, e.g. `0..2`.
+    pub exclusive_range_pattern: Lock<Vec<Span>>,
+    /// Spans collected for gating `try_blocks`, e.g. `try { a? + b? }`.
+    pub try_blocks: Lock<Vec<Span>>,
+    /// Spans collected for gating `label_break_value`, e.g. `'label: { ... }`.
+    pub label_break_value: Lock<Vec<Span>>,
+    /// Spans collected for gating `box_syntax`, e.g. `box $expr`.
+    pub box_syntax: Lock<Vec<Span>>,
+    /// Spans collected for gating `type_ascription`, e.g. `42: usize`.
+    pub type_ascription: Lock<Vec<Span>>,
 }
 
 /// Info about a parsing session.
diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs
index 96d0c3fcab1c5..c874f1ffb1175 100644
--- a/src/libsyntax_ext/proc_macro_harness.rs
+++ b/src/libsyntax_ext/proc_macro_harness.rs
@@ -337,6 +337,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
 //          use proc_macro::bridge::client::ProcMacro;
 //
 //          #[rustc_proc_macro_decls]
+//          #[allow(deprecated)]
 //          static DECLS: &[ProcMacro] = &[
 //              ProcMacro::custom_derive($name_trait1, &[], ::$name1);
 //              ProcMacro::custom_derive($name_trait2, &["attribute_name"], ::$name2);
@@ -416,6 +417,16 @@ fn mk_decls(
     ).map(|mut i| {
         let attr = cx.meta_word(span, sym::rustc_proc_macro_decls);
         i.attrs.push(cx.attribute(attr));
+
+        let deprecated_attr = attr::mk_nested_word_item(
+            Ident::new(sym::deprecated, span)
+        );
+        let allow_deprecated_attr = attr::mk_list_item(
+            Ident::new(sym::allow, span),
+            vec![deprecated_attr]
+        );
+        i.attrs.push(cx.attribute(allow_deprecated_attr));
+
         i
     });
 
diff --git a/src/test/ui/const-generics/array-impls/into-iter-impls-length-32.rs b/src/test/ui/const-generics/array-impls/into-iter-impls-length-32.rs
new file mode 100644
index 0000000000000..0aeba8607e818
--- /dev/null
+++ b/src/test/ui/const-generics/array-impls/into-iter-impls-length-32.rs
@@ -0,0 +1,41 @@
+// check-pass
+
+#![feature(array_value_iter)]
+#![feature(trusted_len)]
+
+use std::{
+    array::IntoIter,
+    fmt::Debug,
+    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
+};
+
+pub fn yes_iterator() -> impl Iterator<Item = i32> {
+    IntoIter::new([0i32; 32])
+}
+
+pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator {
+    IntoIter::new([0i32; 32])
+}
+
+pub fn yes_exact_size_iterator() -> impl ExactSizeIterator {
+    IntoIter::new([0i32; 32])
+}
+
+pub fn yes_fused_iterator() -> impl FusedIterator {
+    IntoIter::new([0i32; 32])
+}
+
+pub fn yes_trusted_len() -> impl TrustedLen {
+    IntoIter::new([0i32; 32])
+}
+
+pub fn yes_clone() -> impl Clone {
+    IntoIter::new([0i32; 32])
+}
+
+pub fn yes_debug() -> impl Debug {
+    IntoIter::new([0i32; 32])
+}
+
+
+fn main() {}
diff --git a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.rs
new file mode 100644
index 0000000000000..a0bbd2ce64add
--- /dev/null
+++ b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.rs
@@ -0,0 +1,53 @@
+#![feature(array_value_iter)]
+#![feature(trusted_len)]
+
+use std::{
+    array::IntoIter,
+    fmt::Debug,
+    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
+};
+
+pub fn no_iterator() -> impl Iterator<Item = i32> {
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+    IntoIter::new([0i32; 33])
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+}
+
+pub fn no_double_ended_iterator() -> impl DoubleEndedIterator {
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+    IntoIter::new([0i32; 33])
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+}
+
+pub fn no_exact_size_iterator() -> impl ExactSizeIterator {
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+    IntoIter::new([0i32; 33])
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+}
+
+pub fn no_fused_iterator() -> impl FusedIterator {
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+    IntoIter::new([0i32; 33])
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+}
+
+pub fn no_trusted_len() -> impl TrustedLen {
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+    IntoIter::new([0i32; 33])
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+}
+
+pub fn no_clone() -> impl Clone {
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+    IntoIter::new([0i32; 33])
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+}
+
+pub fn no_debug() -> impl Debug {
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+    IntoIter::new([0i32; 33])
+    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
+}
+
+
+fn main() {}
diff --git a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr
new file mode 100644
index 0000000000000..bfdff8e3bbe61
--- /dev/null
+++ b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr
@@ -0,0 +1,122 @@
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:12:5
+   |
+LL |     IntoIter::new([0i32; 33])
+   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required by `std::array::IntoIter::<T, N>::new`
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:10:25
+   |
+LL | pub fn no_iterator() -> impl Iterator<Item = i32> {
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::array::IntoIter<i32, 33usize>`
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:18:5
+   |
+LL |     IntoIter::new([0i32; 33])
+   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required by `std::array::IntoIter::<T, N>::new`
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:16:38
+   |
+LL | pub fn no_double_ended_iterator() -> impl DoubleEndedIterator {
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::array::IntoIter<i32, 33usize>`
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:24:5
+   |
+LL |     IntoIter::new([0i32; 33])
+   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required by `std::array::IntoIter::<T, N>::new`
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:22:36
+   |
+LL | pub fn no_exact_size_iterator() -> impl ExactSizeIterator {
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required because of the requirements on the impl of `std::iter::ExactSizeIterator` for `std::array::IntoIter<i32, 33usize>`
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:30:5
+   |
+LL |     IntoIter::new([0i32; 33])
+   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required by `std::array::IntoIter::<T, N>::new`
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:28:31
+   |
+LL | pub fn no_fused_iterator() -> impl FusedIterator {
+   |                               ^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required because of the requirements on the impl of `std::iter::FusedIterator` for `std::array::IntoIter<i32, 33usize>`
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:36:5
+   |
+LL |     IntoIter::new([0i32; 33])
+   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required by `std::array::IntoIter::<T, N>::new`
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:34:28
+   |
+LL | pub fn no_trusted_len() -> impl TrustedLen {
+   |                            ^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required because of the requirements on the impl of `std::iter::TrustedLen` for `std::array::IntoIter<i32, 33usize>`
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:42:5
+   |
+LL |     IntoIter::new([0i32; 33])
+   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required by `std::array::IntoIter::<T, N>::new`
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:40:22
+   |
+LL | pub fn no_clone() -> impl Clone {
+   |                      ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required because of the requirements on the impl of `std::clone::Clone` for `std::array::IntoIter<i32, 33usize>`
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:48:5
+   |
+LL |     IntoIter::new([0i32; 33])
+   |     ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required by `std::array::IntoIter::<T, N>::new`
+
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/into-iter-no-impls-length-33.rs:46:22
+   |
+LL | pub fn no_debug() -> impl Debug {
+   |                      ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+   |
+   = note: required because of the requirements on the impl of `std::fmt::Debug` for `std::array::IntoIter<i32, 33usize>`
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/const-param-in-trait-ungated.stderr b/src/test/ui/const-generics/const-param-in-trait-ungated.stderr
index cfb1f8b581c85..330c93e83b5e7 100644
--- a/src/test/ui/const-generics/const-param-in-trait-ungated.stderr
+++ b/src/test/ui/const-generics/const-param-in-trait-ungated.stderr
@@ -1,8 +1,8 @@
 error[E0658]: const generics are unstable
-  --> $DIR/const-param-in-trait-ungated.rs:1:19
+  --> $DIR/const-param-in-trait-ungated.rs:1:13
    |
 LL | trait Trait<const T: ()> {}
-   |                   ^
+   |             ^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
index a2872ab982da4..e34a2da24cecc 100644
--- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
@@ -1,8 +1,8 @@
 error[E0658]: const generics are unstable
-  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19
+  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:13
    |
 LL | struct B<T, const N: T>(PhantomData<[T; N]>);
-   |                   ^
+   |             ^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
diff --git a/src/test/ui/const-generics/issues/issue-60263.stderr b/src/test/ui/const-generics/issues/issue-60263.stderr
index fe7b6fdb1904d..5223c8c5137ae 100644
--- a/src/test/ui/const-generics/issues/issue-60263.stderr
+++ b/src/test/ui/const-generics/issues/issue-60263.stderr
@@ -1,8 +1,8 @@
 error[E0658]: const generics are unstable
-  --> $DIR/issue-60263.rs:1:16
+  --> $DIR/issue-60263.rs:1:10
    |
 LL | struct B<const I: u8>;
-   |                ^
+   |          ^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs
index 0faa9090f4ebc..00737d8428b3d 100644
--- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs
+++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.rs
@@ -70,3 +70,7 @@ fn main() {
     // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed.
     // let _: &dyn Tr1<As1: Copy> = &S1;
 }
+
+macro_rules! accept_path { ($p:path) => {} }
+accept_path!(Iterator<Item: Ord>);
+//~^ ERROR associated type bounds are unstable
diff --git a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr
index 84af2a0163ae4..a7ab7614d7b78 100644
--- a/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr
+++ b/src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr
@@ -115,6 +115,15 @@ LL |     let _: impl Tr1<As1: Copy> = S1;
    = note: for more information, see https://github.com/rust-lang/rust/issues/52662
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
+error[E0658]: associated type bounds are unstable
+  --> $DIR/feature-gate-associated_type_bounds.rs:75:23
+   |
+LL | accept_path!(Iterator<Item: Ord>);
+   |                       ^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/52662
+   = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
+
 error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
   --> $DIR/feature-gate-associated_type_bounds.rs:54:14
    |
@@ -139,7 +148,7 @@ LL |     let _: impl Tr1<As1: Copy> = S1;
    |
    = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
 
-error: aborting due to 16 previous errors
+error: aborting due to 17 previous errors
 
 Some errors have detailed explanations: E0562, E0658.
 For more information about an error, try `rustc --explain E0562`.
diff --git a/src/test/ui/feature-gates/feature-gate-box_patterns.rs b/src/test/ui/feature-gates/feature-gate-box_patterns.rs
index 8bec16a974e80..c5b926d5af28c 100644
--- a/src/test/ui/feature-gates/feature-gate-box_patterns.rs
+++ b/src/test/ui/feature-gates/feature-gate-box_patterns.rs
@@ -2,3 +2,6 @@ fn main() {
     let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental
     println!("x: {}", x);
 }
+
+macro_rules! accept_pat { ($p:pat) => {} }
+accept_pat!(box 0); //~ ERROR box pattern syntax is experimental
diff --git a/src/test/ui/feature-gates/feature-gate-box_patterns.stderr b/src/test/ui/feature-gates/feature-gate-box_patterns.stderr
index d2dafe93a862f..1e47bd41e8870 100644
--- a/src/test/ui/feature-gates/feature-gate-box_patterns.stderr
+++ b/src/test/ui/feature-gates/feature-gate-box_patterns.stderr
@@ -7,6 +7,15 @@ LL |     let box x = Box::new('c');
    = note: for more information, see https://github.com/rust-lang/rust/issues/29641
    = help: add `#![feature(box_patterns)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: box pattern syntax is experimental
+  --> $DIR/feature-gate-box_patterns.rs:7:13
+   |
+LL | accept_pat!(box 0);
+   |             ^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29641
+   = help: add `#![feature(box_patterns)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-box_syntax.rs b/src/test/ui/feature-gates/feature-gate-box_syntax.rs
index 778660cc0b549..c23953a9e099e 100644
--- a/src/test/ui/feature-gates/feature-gate-box_syntax.rs
+++ b/src/test/ui/feature-gates/feature-gate-box_syntax.rs
@@ -1,6 +1,9 @@
 // Test that the use of the box syntax is gated by `box_syntax` feature gate.
 
-fn main() {
+#[cfg(FALSE)]
+fn foo() {
     let x = box 3;
     //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead
 }
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-box_syntax.stderr b/src/test/ui/feature-gates/feature-gate-box_syntax.stderr
index 61b0534d2dc3e..cbafa50257706 100644
--- a/src/test/ui/feature-gates/feature-gate-box_syntax.stderr
+++ b/src/test/ui/feature-gates/feature-gate-box_syntax.stderr
@@ -1,5 +1,5 @@
 error[E0658]: box expression syntax is experimental; you can call `Box::new` instead
-  --> $DIR/feature-gate-box_syntax.rs:4:13
+  --> $DIR/feature-gate-box_syntax.rs:5:13
    |
 LL |     let x = box 3;
    |             ^^^^^
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr
index 935f84b9163d3..790bc33e2683e 100644
--- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr
@@ -1,17 +1,17 @@
 error[E0658]: const generics are unstable
-  --> $DIR/feature-gate-const_generics-ptr.rs:1:22
+  --> $DIR/feature-gate-const_generics-ptr.rs:1:16
    |
 LL | struct ConstFn<const F: fn()>;
-   |                      ^
+   |                ^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
 
 error[E0658]: const generics are unstable
-  --> $DIR/feature-gate-const_generics-ptr.rs:5:23
+  --> $DIR/feature-gate-const_generics-ptr.rs:5:17
    |
 LL | struct ConstPtr<const P: *const u32>;
-   |                       ^
+   |                 ^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.rs b/src/test/ui/feature-gates/feature-gate-const_generics.rs
index fe1ded1c4bbc4..0adc9902a6937 100644
--- a/src/test/ui/feature-gates/feature-gate-const_generics.rs
+++ b/src/test/ui/feature-gates/feature-gate-const_generics.rs
@@ -2,4 +2,9 @@ fn foo<const X: ()>() {} //~ ERROR const generics are unstable
 
 struct Foo<const X: usize>([(); X]); //~ ERROR const generics are unstable
 
+macro_rules! accept_item { ($i:item) => {} }
+accept_item! {
+    impl<const X: ()> A {} //~ ERROR const generics are unstable
+}
+
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.stderr b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
index 468e9c31d37e2..f0154ed289f14 100644
--- a/src/test/ui/feature-gates/feature-gate-const_generics.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
@@ -1,21 +1,30 @@
 error[E0658]: const generics are unstable
-  --> $DIR/feature-gate-const_generics.rs:1:14
+  --> $DIR/feature-gate-const_generics.rs:1:8
    |
 LL | fn foo<const X: ()>() {}
-   |              ^
+   |        ^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
 
 error[E0658]: const generics are unstable
-  --> $DIR/feature-gate-const_generics.rs:3:18
+  --> $DIR/feature-gate-const_generics.rs:3:12
    |
 LL | struct Foo<const X: usize>([(); X]);
-   |                  ^
+   |            ^^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/44580
    = help: add `#![feature(const_generics)]` to the crate attributes to enable
 
-error: aborting due to 2 previous errors
+error[E0658]: const generics are unstable
+  --> $DIR/feature-gate-const_generics.rs:7:10
+   |
+LL |     impl<const X: ()> A {}
+   |          ^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/44580
+   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.rs b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.rs
index 0e3f6b168be6b..7517fb280ea78 100644
--- a/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.rs
+++ b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.rs
@@ -5,4 +5,7 @@ crate struct Bender { //~ ERROR `crate` visibility modifier is experimental
     water: bool,
 }
 
+macro_rules! accept_vis { ($v:vis) => {} }
+accept_vis!(crate);  //~ ERROR `crate` visibility modifier is experimental
+
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr
index 1e061eced3660..b317872cea817 100644
--- a/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr
+++ b/src/test/ui/feature-gates/feature-gate-crate_visibility_modifier.stderr
@@ -7,6 +7,15 @@ LL | crate struct Bender {
    = note: for more information, see https://github.com/rust-lang/rust/issues/53120
    = help: add `#![feature(crate_visibility_modifier)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: `crate` visibility modifier is experimental
+  --> $DIR/feature-gate-crate_visibility_modifier.rs:9:13
+   |
+LL | accept_vis!(crate);
+   |             ^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/53120
+   = help: add `#![feature(crate_visibility_modifier)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-decl_macro.rs b/src/test/ui/feature-gates/feature-gate-decl_macro.rs
index d002c5dbbd2db..b208a047481a4 100644
--- a/src/test/ui/feature-gates/feature-gate-decl_macro.rs
+++ b/src/test/ui/feature-gates/feature-gate-decl_macro.rs
@@ -2,4 +2,8 @@
 
 macro m() {} //~ ERROR `macro` is experimental
 
+macro_rules! accept_item { ($i:item) => {} }
+accept_item! {
+    macro m() {} //~ ERROR `macro` is experimental
+}
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-decl_macro.stderr b/src/test/ui/feature-gates/feature-gate-decl_macro.stderr
index 905a1b1531044..c6690ebd4d917 100644
--- a/src/test/ui/feature-gates/feature-gate-decl_macro.stderr
+++ b/src/test/ui/feature-gates/feature-gate-decl_macro.stderr
@@ -7,6 +7,15 @@ LL | macro m() {}
    = note: for more information, see https://github.com/rust-lang/rust/issues/39412
    = help: add `#![feature(decl_macro)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: `macro` is experimental
+  --> $DIR/feature-gate-decl_macro.rs:7:5
+   |
+LL |     macro m() {}
+   |     ^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/39412
+   = help: add `#![feature(decl_macro)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.rs b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.rs
index ded08b93fe81c..594ec73fe26f7 100644
--- a/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.rs
+++ b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.rs
@@ -1,6 +1,10 @@
-pub fn main() {
+#[cfg(FALSE)]
+fn foo() {
     match 22 {
         0 .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental
+        PATH .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental
         _ => {}
     }
 }
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
index ee20408d1781f..075fdbed90d6c 100644
--- a/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
+++ b/src/test/ui/feature-gates/feature-gate-exclusive-range-pattern.stderr
@@ -1,12 +1,21 @@
 error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/feature-gate-exclusive-range-pattern.rs:3:9
+  --> $DIR/feature-gate-exclusive-range-pattern.rs:4:11
    |
 LL |         0 .. 3 => {}
-   |         ^^^^^^
+   |           ^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/37854
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/feature-gate-exclusive-range-pattern.rs:5:14
+   |
+LL |         PATH .. 3 => {}
+   |              ^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/37854
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-label_break_value.rs b/src/test/ui/feature-gates/feature-gate-label_break_value.rs
index 6fc38f45517ef..8d7ecd27b450f 100644
--- a/src/test/ui/feature-gates/feature-gate-label_break_value.rs
+++ b/src/test/ui/feature-gates/feature-gate-label_break_value.rs
@@ -1,5 +1,8 @@
-pub fn main() {
+#[cfg(FALSE)]
+pub fn foo() {
     'a: { //~ ERROR labels on blocks are unstable
         break 'a;
     }
 }
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-label_break_value.stderr b/src/test/ui/feature-gates/feature-gate-label_break_value.stderr
index a417e0eec22f2..6a861d3e04f92 100644
--- a/src/test/ui/feature-gates/feature-gate-label_break_value.stderr
+++ b/src/test/ui/feature-gates/feature-gate-label_break_value.stderr
@@ -1,5 +1,5 @@
 error[E0658]: labels on blocks are unstable
-  --> $DIR/feature-gate-label_break_value.rs:2:5
+  --> $DIR/feature-gate-label_break_value.rs:3:5
    |
 LL |     'a: {
    |     ^^
diff --git a/src/test/ui/feature-gates/feature-gate-trait-alias.rs b/src/test/ui/feature-gates/feature-gate-trait-alias.rs
index 819085adddade..4b94d7d6d3bda 100644
--- a/src/test/ui/feature-gates/feature-gate-trait-alias.rs
+++ b/src/test/ui/feature-gates/feature-gate-trait-alias.rs
@@ -1,4 +1,13 @@
 trait Foo = Default;
 //~^ ERROR trait aliases are experimental
 
+macro_rules! accept_item {
+    ($i:item) => {}
+}
+
+accept_item! {
+    trait Foo = Ord + Eq;
+    //~^ ERROR trait aliases are experimental
+}
+
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-trait-alias.stderr b/src/test/ui/feature-gates/feature-gate-trait-alias.stderr
index 9250e27d15807..b1bf6ad349129 100644
--- a/src/test/ui/feature-gates/feature-gate-trait-alias.stderr
+++ b/src/test/ui/feature-gates/feature-gate-trait-alias.stderr
@@ -7,6 +7,15 @@ LL | trait Foo = Default;
    = note: for more information, see https://github.com/rust-lang/rust/issues/41517
    = help: add `#![feature(trait_alias)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: trait aliases are experimental
+  --> $DIR/feature-gate-trait-alias.rs:9:5
+   |
+LL |     trait Foo = Ord + Eq;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/41517
+   = help: add `#![feature(trait_alias)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-try_blocks.rs b/src/test/ui/feature-gates/feature-gate-try_blocks.rs
index 06cadd82c0731..b451ba84a1565 100644
--- a/src/test/ui/feature-gates/feature-gate-try_blocks.rs
+++ b/src/test/ui/feature-gates/feature-gate-try_blocks.rs
@@ -1,9 +1,12 @@
 // compile-flags: --edition 2018
 
-pub fn main() {
-    let try_result: Option<_> = try { //~ ERROR `try` expression is experimental
+#[cfg(FALSE)]
+fn foo() {
+    let try_result: Option<_> = try { //~ ERROR `try` blocks are unstable
         let x = 5;
         x
     };
     assert_eq!(try_result, Some(5));
 }
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-try_blocks.stderr b/src/test/ui/feature-gates/feature-gate-try_blocks.stderr
index 565f3610a2e21..44a7d9b9043fd 100644
--- a/src/test/ui/feature-gates/feature-gate-try_blocks.stderr
+++ b/src/test/ui/feature-gates/feature-gate-try_blocks.stderr
@@ -1,5 +1,5 @@
-error[E0658]: `try` expression is experimental
-  --> $DIR/feature-gate-try_blocks.rs:4:33
+error[E0658]: `try` blocks are unstable
+  --> $DIR/feature-gate-try_blocks.rs:5:33
    |
 LL |       let try_result: Option<_> = try {
    |  _________________________________^
diff --git a/src/test/ui/feature-gates/feature-gate-type_ascription.rs b/src/test/ui/feature-gates/feature-gate-type_ascription.rs
index 7a597157300ed..655891d802c1c 100644
--- a/src/test/ui/feature-gates/feature-gate-type_ascription.rs
+++ b/src/test/ui/feature-gates/feature-gate-type_ascription.rs
@@ -1,5 +1,8 @@
 // Type ascription is unstable
 
-fn main() {
+#[cfg(FALSE)]
+fn foo() {
     let a = 10: u8; //~ ERROR type ascription is experimental
 }
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-type_ascription.stderr b/src/test/ui/feature-gates/feature-gate-type_ascription.stderr
index 83f95529f0d9d..d63d624c6c112 100644
--- a/src/test/ui/feature-gates/feature-gate-type_ascription.stderr
+++ b/src/test/ui/feature-gates/feature-gate-type_ascription.stderr
@@ -1,5 +1,5 @@
 error[E0658]: type ascription is experimental
-  --> $DIR/feature-gate-type_ascription.rs:4:13
+  --> $DIR/feature-gate-type_ascription.rs:5:13
    |
 LL |     let a = 10: u8;
    |             ^^^^^^
diff --git a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr
index 1885518a4585c..2182b3a313efb 100644
--- a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr
+++ b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr
@@ -6,7 +6,7 @@ LL | |     a: String,
 LL | | }
    | |_^
    |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/32836
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55149
    = help: add `#![feature(untagged_unions)]` to the crate attributes to enable
 
 error[E0658]: unions with non-`Copy` fields are unstable
@@ -17,7 +17,7 @@ LL | |     a: T,
 LL | | }
    | |_^
    |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/32836
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55149
    = help: add `#![feature(untagged_unions)]` to the crate attributes to enable
 
 error[E0658]: unions with `Drop` implementations are unstable
@@ -28,7 +28,7 @@ LL | |     a: u8,
 LL | | }
    | |_^
    |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/32836
+   = note: for more information, see https://github.com/rust-lang/rust/issues/55149
    = help: add `#![feature(untagged_unions)]` to the crate attributes to enable
 
 error[E0740]: unions may not contain fields that need dropping
diff --git a/src/test/ui/impl-trait/issues/universal-issue-48703.stderr b/src/test/ui/impl-trait/issues/universal-issue-48703.stderr
index a51302dce2966..8f05ab3c4940c 100644
--- a/src/test/ui/impl-trait/issues/universal-issue-48703.stderr
+++ b/src/test/ui/impl-trait/issues/universal-issue-48703.stderr
@@ -1,8 +1,8 @@
 error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
-  --> $DIR/universal-issue-48703.rs:8:5
+  --> $DIR/universal-issue-48703.rs:8:11
    |
 LL |     foo::<String>('a');
-   |     ^^^^^^^^^^^^^
+   |           ^^^^^^ explicit generic argument not allowed
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr
index f09aa166ef508..c980e9463e48a 100644
--- a/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr
+++ b/src/test/ui/impl-trait/issues/universal-turbofish-in-method-issue-50950.stderr
@@ -1,8 +1,10 @@
 error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
-  --> $DIR/universal-turbofish-in-method-issue-50950.rs:14:9
+  --> $DIR/universal-turbofish-in-method-issue-50950.rs:14:24
    |
 LL |     evt.handle_event::<TestEvent, fn(TestEvent)>(|_evt| {
-   |         ^^^^^^^^^^^^
+   |                        ^^^^^^^^^  ^^^^^^^^^^^^^ explicit generic argument not allowed
+   |                        |
+   |                        explicit generic argument not allowed
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-19883.stderr b/src/test/ui/issues/issue-19883.stderr
index 738add1684004..e370b2ec1cb42 100644
--- a/src/test/ui/issues/issue-19883.stderr
+++ b/src/test/ui/issues/issue-19883.stderr
@@ -6,3 +6,4 @@ LL |         <Dst as From<Self>>::Dst
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0576`.
diff --git a/src/test/ui/issues/issue-22037.stderr b/src/test/ui/issues/issue-22037.stderr
index 40d4a5e3bc0c5..615628558f08b 100644
--- a/src/test/ui/issues/issue-22037.stderr
+++ b/src/test/ui/issues/issue-22037.stderr
@@ -6,3 +6,4 @@ LL |     fn a(&self) -> <Self as A>::X;
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0576`.
diff --git a/src/test/ui/issues/issue-22384.stderr b/src/test/ui/issues/issue-22384.stderr
index 130c3124b6f82..1f767a443d0f0 100644
--- a/src/test/ui/issues/issue-22384.stderr
+++ b/src/test/ui/issues/issue-22384.stderr
@@ -6,3 +6,4 @@ LL |     <<i32 as Copy>::foobar as Trait>::foo();
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0576`.
diff --git a/src/test/ui/nll/empty-type-predicate-2.rs b/src/test/ui/nll/empty-type-predicate-2.rs
new file mode 100644
index 0000000000000..20d6e47f75300
--- /dev/null
+++ b/src/test/ui/nll/empty-type-predicate-2.rs
@@ -0,0 +1,18 @@
+// Regression test for #65553
+//
+// `D::Error:` is lowered to `D::Error: ReEmpty` - check that we don't ICE in
+// NLL for the unexpected region.
+
+// check-pass
+
+trait Deserializer {
+    type Error;
+}
+
+fn d1<D: Deserializer>() where D::Error: {}
+
+fn d2<D: Deserializer>() {
+    d1::<D>();
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/empty-type-predicate.rs b/src/test/ui/nll/empty-type-predicate.rs
index 48073f8749e75..d126a455daeb2 100644
--- a/src/test/ui/nll/empty-type-predicate.rs
+++ b/src/test/ui/nll/empty-type-predicate.rs
@@ -3,9 +3,9 @@
 // `dyn T:` is lowered to `dyn T: ReEmpty` - check that we don't ICE in NLL for
 // the unexpected region.
 
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
 
 trait T {}
 fn f() where dyn T: {}
 
-fn main() {}
+fn main() { f(); }
diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs
index 5fe72caf9c1ff..9667711242ce6 100644
--- a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs
+++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs
@@ -4,6 +4,7 @@
 // check-pass
 
 #![feature(or_patterns)]
+#![feature(box_patterns)]
 
 fn main() {}
 
diff --git a/src/test/ui/parser/pat-tuple-4.rs b/src/test/ui/parser/pat-tuple-4.rs
index 2f03160430a22..6b8c146949aec 100644
--- a/src/test/ui/parser/pat-tuple-4.rs
+++ b/src/test/ui/parser/pat-tuple-4.rs
@@ -4,7 +4,6 @@ fn main() {
     match 0 {
         (.. PAT) => {}
         //~^ ERROR `..X` range patterns are not supported
-        //~| ERROR exclusive range pattern syntax is experimental
     }
 }
 
diff --git a/src/test/ui/parser/pat-tuple-4.stderr b/src/test/ui/parser/pat-tuple-4.stderr
index af3ecce184649..1962dc4ff20a8 100644
--- a/src/test/ui/parser/pat-tuple-4.stderr
+++ b/src/test/ui/parser/pat-tuple-4.stderr
@@ -4,17 +4,8 @@ error: `..X` range patterns are not supported
 LL |         (.. PAT) => {}
    |          ^^^^^^ help: try using the minimum value for the type: `MIN..PAT`
 
-error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/pat-tuple-4.rs:5:10
-   |
-LL |         (.. PAT) => {}
-   |          ^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/37854
-   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
-
 error[E0308]: mismatched types
-  --> $DIR/pat-tuple-4.rs:11:30
+  --> $DIR/pat-tuple-4.rs:10:30
    |
 LL | const RECOVERY_WITNESS: () = 0;
    |                              ^ expected (), found integer
@@ -22,7 +13,6 @@ LL | const RECOVERY_WITNESS: () = 0;
    = note: expected type `()`
               found type `{integer}`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0308, E0658.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/pat-tuple-5.stderr b/src/test/ui/parser/pat-tuple-5.stderr
index 09ebdc29a2161..17155b4dd4954 100644
--- a/src/test/ui/parser/pat-tuple-5.stderr
+++ b/src/test/ui/parser/pat-tuple-5.stderr
@@ -5,10 +5,10 @@ LL |         (PAT ..) => {}
    |          ^^^^^^ help: try using the maximum value for the type: `PAT..MAX`
 
 error[E0658]: exclusive range pattern syntax is experimental
-  --> $DIR/pat-tuple-5.rs:5:10
+  --> $DIR/pat-tuple-5.rs:5:14
    |
 LL |         (PAT ..) => {}
-   |          ^^^^^^
+   |              ^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/37854
    = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
diff --git a/src/test/ui/pattern/rest-pat-syntactic.rs b/src/test/ui/pattern/rest-pat-syntactic.rs
index 9656a0b5de9ce..45b31f6125374 100644
--- a/src/test/ui/pattern/rest-pat-syntactic.rs
+++ b/src/test/ui/pattern/rest-pat-syntactic.rs
@@ -3,6 +3,8 @@
 
 // check-pass
 
+#![feature(box_patterns)]
+
 fn main() {}
 
 macro_rules! accept_pat {
diff --git a/src/test/ui/proc-macro/proc-macro-deprecated-attr.rs b/src/test/ui/proc-macro/proc-macro-deprecated-attr.rs
new file mode 100644
index 0000000000000..f1144a4a55b16
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-deprecated-attr.rs
@@ -0,0 +1,16 @@
+// check-pass
+// force-host
+// no-prefer-dynamic
+
+#![deny(deprecated)]
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+#[deprecated(since = "1.0.0", note = "test")]
+pub fn test_compile_without_warning_with_deprecated(_: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs
new file mode 100644
index 0000000000000..0096e2963007a
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs
@@ -0,0 +1,22 @@
+// aux-build:uninhabited.rs
+#![deny(unreachable_patterns)]
+#![feature(never_type)]
+#![feature(non_exhaustive)]
+
+extern crate uninhabited;
+
+use uninhabited::PartiallyInhabitedVariants;
+
+// This test checks a redundant/useless pattern of a non-exhaustive enum/variant is still
+// warned against.
+
+pub fn foo(x: PartiallyInhabitedVariants) {
+    match x {
+        PartiallyInhabitedVariants::Struct { .. } => {},
+        PartiallyInhabitedVariants::Struct { .. } => {},
+        //~^ ERROR unreachable pattern
+        _ => {},
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr
new file mode 100644
index 0000000000000..d46b1fd4c4202
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr
@@ -0,0 +1,14 @@
+error: unreachable pattern
+  --> $DIR/issue-65157-repeated-match-arm.rs:16:9
+   |
+LL |         PartiallyInhabitedVariants::Struct { .. } => {},
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-65157-repeated-match-arm.rs:2:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/synthetic-param.stderr b/src/test/ui/synthetic-param.stderr
index f8d14f26f32de..951d7edb7f523 100644
--- a/src/test/ui/synthetic-param.stderr
+++ b/src/test/ui/synthetic-param.stderr
@@ -1,20 +1,20 @@
 error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
-  --> $DIR/synthetic-param.rs:20:5
+  --> $DIR/synthetic-param.rs:20:12
    |
 LL |     func::<u8>(42);
-   |     ^^^^^^^^^^
+   |            ^^ explicit generic argument not allowed
 
 error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
-  --> $DIR/synthetic-param.rs:23:5
+  --> $DIR/synthetic-param.rs:23:17
    |
 LL |     Foo::func::<u8>(42);
-   |     ^^^^^^^^^^^^^^^
+   |                 ^^ explicit generic argument not allowed
 
 error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
-  --> $DIR/synthetic-param.rs:26:5
+  --> $DIR/synthetic-param.rs:26:23
    |
 LL |     Bar::<i8>::func::<u8>(42);
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^ explicit generic argument not allowed
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.rs b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.rs
index 5948d45b6987f..039bbce8c1ed0 100644
--- a/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.rs
+++ b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.rs
@@ -4,4 +4,7 @@ trait Foo {}
 auto trait A = Foo; //~ ERROR trait aliases cannot be `auto`
 unsafe trait B = Foo; //~ ERROR trait aliases cannot be `unsafe`
 
+trait C: Ord = Eq; //~ ERROR bounds are not allowed on trait aliases
+trait D: = Eq; //~ ERROR bounds are not allowed on trait aliases
+
 fn main() {}
diff --git a/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr
index f456a2d778c25..18c22133bc780 100644
--- a/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr
+++ b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr
@@ -1,14 +1,26 @@
 error: trait aliases cannot be `auto`
-  --> $DIR/trait-alias-syntax-fail.rs:4:19
+  --> $DIR/trait-alias-syntax-fail.rs:4:1
    |
 LL | auto trait A = Foo;
-   |                   ^ trait aliases cannot be `auto`
+   | ^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `auto`
 
 error: trait aliases cannot be `unsafe`
-  --> $DIR/trait-alias-syntax-fail.rs:5:21
+  --> $DIR/trait-alias-syntax-fail.rs:5:1
    |
 LL | unsafe trait B = Foo;
-   |                     ^ trait aliases cannot be `unsafe`
+   | ^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `unsafe`
 
-error: aborting due to 2 previous errors
+error: bounds are not allowed on trait aliases
+  --> $DIR/trait-alias-syntax-fail.rs:7:8
+   |
+LL | trait C: Ord = Eq;
+   |        ^^^^^
+
+error: bounds are not allowed on trait aliases
+  --> $DIR/trait-alias-syntax-fail.rs:8:8
+   |
+LL | trait D: = Eq;
+   |        ^
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/type/type-path-err-node-types.stderr b/src/test/ui/type/type-path-err-node-types.stderr
index cd93525c76219..ea9cca2bfaab0 100644
--- a/src/test/ui/type/type-path-err-node-types.stderr
+++ b/src/test/ui/type/type-path-err-node-types.stderr
@@ -30,5 +30,5 @@ LL |     let _ = |a, b: _| -> _ { 0 };
 
 error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0282, E0412, E0425, E0433.
+Some errors have detailed explanations: E0282, E0412, E0425, E0433, E0576.
 For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
index 39752f66b9d65..dee990ec3d1cb 100644
--- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr
@@ -200,5 +200,5 @@ LL |     <u8 as Dr>::X::N;
 
 error: aborting due to 32 previous errors
 
-Some errors have detailed explanations: E0223, E0433, E0575, E0599.
+Some errors have detailed explanations: E0223, E0433, E0575, E0576, E0599.
 For more information about an error, try `rustc --explain E0223`.