about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--src/bootstrap/channel.rs2
-rw-r--r--src/liballoc/alloc.rs1
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/string.rs1
-rw-r--r--src/liballoc/vec.rs3
-rw-r--r--src/libcore/bool.rs1
-rw-r--r--src/libcore/clone.rs1
-rw-r--r--src/libcore/cmp.rs4
-rw-r--r--src/libcore/default.rs1
-rw-r--r--src/libcore/fmt/mod.rs4
-rw-r--r--src/libcore/hash/mod.rs1
-rw-r--r--src/libcore/intrinsics.rs22
-rw-r--r--src/libcore/lib.rs4
-rw-r--r--src/libcore/macros.rs6
-rw-r--r--src/libcore/marker.rs1
-rw-r--r--src/libcore/num/mod.rs77
-rw-r--r--src/libcore/panicking.rs1
-rw-r--r--src/libcore/slice/mod.rs4
-rw-r--r--src/libcore/str/mod.rs5
-rw-r--r--src/libproc_macro/lib.rs2
-rw-r--r--src/librustc/hir/intravisit.rs2
-rw-r--r--src/librustc/hir/lowering.rs35
-rw-r--r--src/librustc/hir/lowering/expr.rs51
-rw-r--r--src/librustc/hir/lowering/item.rs6
-rw-r--r--src/librustc/hir/map/hir_id_validator.rs2
-rw-r--r--src/librustc/hir/map/mod.rs4
-rw-r--r--src/librustc/hir/mod.rs88
-rw-r--r--src/librustc/hir/pat_util.rs115
-rw-r--r--src/librustc/hir/print.rs11
-rw-r--r--src/librustc/lint/context.rs2
-rw-r--r--src/librustc/middle/dead.rs20
-rw-r--r--src/librustc/middle/expr_use_visitor.rs8
-rw-r--r--src/librustc/middle/liveness.rs319
-rw-r--r--src/librustc/ty/context.rs2
-rw-r--r--src/librustc/ty/mod.rs2
-rw-r--r--src/librustc/ty/sty.rs2
-rw-r--r--src/librustc_ast_borrowck/cfg/construct.rs2
-rw-r--r--src/librustc_interface/passes.rs15
-rw-r--r--src/librustc_mir/build/matches/mod.rs6
-rw-r--r--src/librustc_mir/hair/cx/expr.rs4
-rw-r--r--src/librustc_mir/hair/mod.rs13
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs109
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs45
-rw-r--r--src/librustc_mir/interpret/operand.rs11
-rw-r--r--src/librustc_mir/interpret/terminator.rs3
-rw-r--r--src/librustc_mir/lib.rs1
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs2
-rw-r--r--src/librustc_passes/lib.rs1
-rw-r--r--src/librustc_passes/rvalue_promotion.rs10
-rw-r--r--src/librustc_typeck/check/_match.rs18
-rw-r--r--src/librustc_typeck/check/pat.rs21
-rw-r--r--src/librustc_typeck/check/regionck.rs8
-rw-r--r--src/librustc_typeck/impl_wf_check.rs2
-rw-r--r--src/librustc_typeck/lib.rs4
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libsyntax/ext/mbe/macro_parser.rs12
-rw-r--r--src/libsyntax/ext/mbe/macro_rules.rs23
-rw-r--r--src/libsyntax/ext/mbe/quoted.rs31
-rw-r--r--src/libsyntax/lib.rs1
-rw-r--r--src/libsyntax/visit.rs2
-rw-r--r--src/stage0.txt2
-rw-r--r--src/test/ui/consts/const-eval/simd/insert_extract.rs53
-rw-r--r--src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs3
-rw-r--r--src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr20
m---------src/tools/cargo0
m---------src/tools/clippy24
68 files changed, 580 insertions, 683 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 106792b941e..cbaf7d801ca 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -550,9 +550,9 @@ dependencies = [
 
 [[package]]
 name = "compiletest_rs"
-version = "0.3.22"
+version = "0.3.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f40ecc9332b68270998995c00f8051ee856121764a0d3230e64c9efd059d27b6"
+checksum = "eb783fe7afb90ec3d3e49ccaf9196d29ab63c6ed61d4b0695839daa580ae3a3d"
 dependencies = [
  "diff",
  "filetime",
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index caa4843da4d..ef1b6e217a2 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -13,7 +13,7 @@ use build_helper::output;
 use crate::Build;
 
 // The version number
-pub const CFG_RELEASE_NUM: &str = "1.39.0";
+pub const CFG_RELEASE_NUM: &str = "1.40.0";
 
 pub struct GitInfo {
     inner: Option<Info>,
diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs
index a39fcd5ad4c..9bc76f51570 100644
--- a/src/liballoc/alloc.rs
+++ b/src/liballoc/alloc.rs
@@ -240,7 +240,6 @@ pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
 #[stable(feature = "global_alloc", since = "1.28.0")]
 #[rustc_allocator_nounwind]
 pub fn handle_alloc_error(layout: Layout) -> ! {
-    #[cfg_attr(bootstrap, allow(improper_ctypes))]
     extern "Rust" {
         #[lang = "oom"]
         fn oom_impl(layout: Layout) -> !;
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 9e6ed92ffb5..247cd9a0201 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -117,7 +117,6 @@
 #![feature(allocator_internals)]
 #![feature(on_unimplemented)]
 #![feature(rustc_const_unstable)]
-#![cfg_attr(bootstrap, feature(const_vec_new))]
 #![feature(slice_partition_dedup)]
 #![feature(maybe_uninit_extra, maybe_uninit_slice)]
 #![feature(alloc_layout_extra)]
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index e5f96ada6d5..abe50fdb7a3 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -369,7 +369,6 @@ impl String {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_string_new"))]
     pub const fn new() -> String {
         String { vec: Vec::new() }
     }
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 405969a550b..e5672f8542f 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -291,7 +291,7 @@ use crate::raw_vec::RawVec;
 /// [`reserve`]: ../../std/vec/struct.Vec.html#method.reserve
 /// [owned slice]: ../../std/boxed/struct.Box.html
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(all(not(bootstrap), not(test)), rustc_diagnostic_item = "vec_type")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")]
 pub struct Vec<T> {
     buf: RawVec<T>,
     len: usize,
@@ -314,7 +314,6 @@ impl<T> Vec<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_vec_new"))]
     pub const fn new() -> Vec<T> {
         Vec {
             buf: RawVec::NEW,
diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs
index f751ccb4280..617bdd238f4 100644
--- a/src/libcore/bool.rs
+++ b/src/libcore/bool.rs
@@ -1,6 +1,5 @@
 //! impl bool {}
 
-#[cfg(not(bootstrap))]
 #[lang = "bool"]
 impl bool {
     /// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise.
diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index 6bdae1b557d..14d947ccf24 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -135,7 +135,6 @@ pub trait Clone : Sized {
 
 /// Derive macro generating an impl of the trait `Clone`.
 #[rustc_builtin_macro]
-#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
 pub macro Clone($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index fc7329f57d4..d0ea75c7623 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -210,7 +210,6 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
 
 /// Derive macro generating an impl of the trait `PartialEq`.
 #[rustc_builtin_macro]
-#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics)]
 pub macro PartialEq($item:item) { /* compiler built-in */ }
@@ -273,7 +272,6 @@ pub trait Eq: PartialEq<Self> {
 
 /// Derive macro generating an impl of the trait `Eq`.
 #[rustc_builtin_macro]
-#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics, derive_eq)]
 pub macro Eq($item:item) { /* compiler built-in */ }
@@ -624,7 +622,6 @@ pub trait Ord: Eq + PartialOrd<Self> {
 
 /// Derive macro generating an impl of the trait `Ord`.
 #[rustc_builtin_macro]
-#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics)]
 pub macro Ord($item:item) { /* compiler built-in */ }
@@ -873,7 +870,6 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
 
 /// Derive macro generating an impl of the trait `PartialOrd`.
 #[rustc_builtin_macro]
-#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics)]
 pub macro PartialOrd($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/default.rs b/src/libcore/default.rs
index 806d4783107..1aadc77cfb8 100644
--- a/src/libcore/default.rs
+++ b/src/libcore/default.rs
@@ -117,7 +117,6 @@ pub trait Default: Sized {
 
 /// Derive macro generating an impl of the trait `Default`.
 #[rustc_builtin_macro]
-#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics)]
 pub macro Default($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 65e2f8b9be6..aafa35873bb 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -518,8 +518,7 @@ impl Display for Arguments<'_> {
     label="`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`",
 )]
 #[doc(alias = "{:?}")]
-#[cfg_attr(bootstrap, lang = "debug_trait")]
-#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "debug_trait")]
+#[rustc_diagnostic_item = "debug_trait"]
 pub trait Debug {
     /// Formats the value using the given formatter.
     ///
@@ -550,7 +549,6 @@ pub trait Debug {
 pub(crate) mod macros {
     /// Derive macro generating an impl of the trait `Debug`.
     #[rustc_builtin_macro]
-    #[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")]
     #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
     #[allow_internal_unstable(core_intrinsics)]
     pub macro Debug($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index aaaa6f9c575..020e085abf8 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -202,7 +202,6 @@ pub trait Hash {
 pub(crate) mod macros {
     /// Derive macro generating an impl of the trait `Hash`.
     #[rustc_builtin_macro]
-    #[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")]
     #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
     #[allow_internal_unstable(core_intrinsics)]
     pub macro Hash($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 905375eb60f..b240d059114 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1299,38 +1299,16 @@ extern "rust-intrinsic" {
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_add` method. For example,
     /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
-    #[cfg(bootstrap)]
-    pub fn overflowing_add<T>(a: T, b: T) -> T;
-    /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `wrapping_sub` method. For example,
-    /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
-    #[cfg(bootstrap)]
-    pub fn overflowing_sub<T>(a: T, b: T) -> T;
-    /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `wrapping_mul` method. For example,
-    /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
-    #[cfg(bootstrap)]
-    pub fn overflowing_mul<T>(a: T, b: T) -> T;
-
-    /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `wrapping_add` method. For example,
-    /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
-    #[cfg(not(bootstrap))]
     pub fn wrapping_add<T>(a: T, b: T) -> T;
     /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_sub` method. For example,
     /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
-    #[cfg(not(bootstrap))]
     pub fn wrapping_sub<T>(a: T, b: T) -> T;
     /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_mul` method. For example,
     /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
-    #[cfg(not(bootstrap))]
     pub fn wrapping_mul<T>(a: T, b: T) -> T;
 
     /// Computes `a + b`, while saturating at numeric bounds.
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 8221df56a51..e8c76b49a8e 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -87,7 +87,6 @@
 #![feature(link_llvm_intrinsics)]
 #![feature(never_type)]
 #![feature(nll)]
-#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))]
 #![feature(exhaustive_patterns)]
 #![feature(no_core)]
 #![feature(on_unimplemented)]
@@ -120,9 +119,6 @@
 #![feature(rtm_target_feature)]
 #![feature(f16c_target_feature)]
 #![feature(hexagon_target_feature)]
-#![cfg_attr(bootstrap, feature(const_slice_len))]
-#![cfg_attr(bootstrap, feature(const_str_as_bytes))]
-#![cfg_attr(bootstrap, feature(const_str_len))]
 #![feature(const_int_conversion)]
 #![feature(const_transmute)]
 #![feature(non_exhaustive)]
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index c6f5fb0b163..ef91c3559d8 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -1236,10 +1236,8 @@ pub(crate) mod builtin {
     pub macro test($item:item) { /* compiler built-in */ }
 
     /// Attribute macro applied to a function to turn it into a benchmark test.
-    #[cfg_attr(not(bootstrap), unstable(soft, feature = "test", issue = "50297",
-               reason = "`bench` is a part of custom test frameworks which are unstable"))]
-    #[cfg_attr(bootstrap, unstable(feature = "test", issue = "50297",
-               reason = "`bench` is a part of custom test frameworks which are unstable"))]
+    #[unstable(soft, feature = "test", issue = "50297",
+               reason = "`bench` is a part of custom test frameworks which are unstable")]
     #[allow_internal_unstable(test, rustc_attrs)]
     #[rustc_builtin_macro]
     pub macro bench($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index a2cfb320e76..7f3d958f5dc 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -290,7 +290,6 @@ pub trait Copy : Clone {
 
 /// Derive macro generating an impl of the trait `Copy`.
 #[rustc_builtin_macro]
-#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
 pub macro Copy($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 5d99c10e738..933a2a12473 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -1112,13 +1112,7 @@ $EndFeature, "
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_add(self, rhs: Self) -> Self {
-                #[cfg(bootstrap)] {
-                    intrinsics::overflowing_add(self, rhs)
-                }
-
-                #[cfg(not(bootstrap))] {
-                    intrinsics::wrapping_add(self, rhs)
-                }
+                intrinsics::wrapping_add(self, rhs)
             }
         }
 
@@ -1141,13 +1135,7 @@ $EndFeature, "
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_sub(self, rhs: Self) -> Self {
-                #[cfg(bootstrap)] {
-                    intrinsics::overflowing_sub(self, rhs)
-                }
-
-                #[cfg(not(bootstrap))] {
-                    intrinsics::wrapping_sub(self, rhs)
-                }
+                intrinsics::wrapping_sub(self, rhs)
             }
         }
 
@@ -1169,13 +1157,7 @@ $EndFeature, "
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_mul(self, rhs: Self) -> Self {
-                #[cfg(bootstrap)] {
-                    intrinsics::overflowing_mul(self, rhs)
-                }
-
-                #[cfg(not(bootstrap))] {
-                    intrinsics::wrapping_mul(self, rhs)
-                }
+                intrinsics::wrapping_mul(self, rhs)
             }
         }
 
@@ -1402,7 +1384,16 @@ $EndFeature, "
             #[stable(feature = "no_panic_abs", since = "1.13.0")]
             #[inline]
             pub const fn wrapping_abs(self) -> Self {
-                (self ^ (self >> ($BITS - 1))).wrapping_sub(self >> ($BITS - 1))
+                // sign is -1 (all ones) for negative numbers, 0 otherwise.
+                let sign = self >> ($BITS - 1);
+                // For positive self, sign == 0 so the expression is simply
+                // (self ^ 0).wrapping_sub(0) == self == abs(self).
+                //
+                // For negative self, self ^ sign == self ^ all_ones.
+                // But all_ones ^ self == all_ones - self == -1 - self.
+                // So for negative numbers, (self ^ sign).wrapping_sub(sign) is
+                // (-1 - self).wrapping_sub(-1) == -self == abs(self).
+                (self ^ sign).wrapping_sub(sign)
             }
         }
 
@@ -1761,7 +1752,7 @@ $EndFeature, "
             #[stable(feature = "no_panic_abs", since = "1.13.0")]
             #[inline]
             pub const fn overflowing_abs(self) -> (Self, bool) {
-                (self ^ (self >> ($BITS - 1))).overflowing_sub(self >> ($BITS - 1))
+                (self.wrapping_abs(), self == Self::min_value())
             }
         }
 
@@ -1969,7 +1960,21 @@ $EndFeature, "
                 // Note that the #[inline] above means that the overflow
                 // semantics of the subtraction depend on the crate we're being
                 // inlined into.
-                (self ^ (self >> ($BITS - 1))) - (self >> ($BITS - 1))
+
+                // sign is -1 (all ones) for negative numbers, 0 otherwise.
+                let sign = self >> ($BITS - 1);
+                // For positive self, sign == 0 so the expression is simply
+                // (self ^ 0) - 0 == self == abs(self).
+                //
+                // For negative self, self ^ sign == self ^ all_ones.
+                // But all_ones ^ self == all_ones - self == -1 - self.
+                // So for negative numbers, (self ^ sign) - sign is
+                // (-1 - self) - -1 == -self == abs(self).
+                //
+                // The subtraction overflows when self is min_value(), because
+                // (-1 - min_value()) - -1 is max_value() - -1 which overflows.
+                // This is exactly when we want self.abs() to overflow.
+                (self ^ sign) - sign
             }
         }
 
@@ -3040,13 +3045,7 @@ $EndFeature, "
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_add(self, rhs: Self) -> Self {
-                #[cfg(bootstrap)] {
-                    intrinsics::overflowing_add(self, rhs)
-                }
-
-                #[cfg(not(bootstrap))] {
-                    intrinsics::wrapping_add(self, rhs)
-                }
+                intrinsics::wrapping_add(self, rhs)
             }
         }
 
@@ -3068,13 +3067,7 @@ $EndFeature, "
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_sub(self, rhs: Self) -> Self {
-                #[cfg(bootstrap)] {
-                    intrinsics::overflowing_sub(self, rhs)
-                }
-
-                #[cfg(not(bootstrap))] {
-                    intrinsics::wrapping_sub(self, rhs)
-                }
+                intrinsics::wrapping_sub(self, rhs)
             }
         }
 
@@ -3097,13 +3090,7 @@ $EndFeature, "
                           without modifying the original"]
         #[inline]
         pub const fn wrapping_mul(self, rhs: Self) -> Self {
-            #[cfg(bootstrap)] {
-                intrinsics::overflowing_mul(self, rhs)
-            }
-
-            #[cfg(not(bootstrap))] {
-                intrinsics::wrapping_mul(self, rhs)
-            }
+            intrinsics::wrapping_mul(self, rhs)
         }
 
         doc_comment! {
diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs
index 7b7253419b1..e8f0561604a 100644
--- a/src/libcore/panicking.rs
+++ b/src/libcore/panicking.rs
@@ -71,7 +71,6 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, file_line_col: &(&'static str, u32, u3
     }
 
     // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
-    #[cfg_attr(bootstrap, allow(improper_ctypes))]
     extern "Rust" {
         #[lang = "panic_impl"]
         fn panic_impl(pi: &PanicInfo<'_>) -> !;
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 0c2a4e08672..5ec21e6d928 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -62,9 +62,8 @@ impl<T> [T] {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_slice_len"))]
     // SAFETY: const sound because we transmute out the length field as a usize (which it must be)
-    #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_union))]
+    #[allow_internal_unstable(const_fn_union)]
     pub const fn len(&self) -> usize {
         unsafe {
             crate::ptr::Repr { rust: self }.raw.len
@@ -81,7 +80,6 @@ impl<T> [T] {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_slice_len"))]
     pub const fn is_empty(&self) -> bool {
         self.len() == 0
     }
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index a6ec757faf1..ece61dde490 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -2090,7 +2090,6 @@ impl str {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_len"))]
     pub const fn len(&self) -> usize {
         self.as_bytes().len()
     }
@@ -2110,7 +2109,6 @@ impl str {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_len"))]
     pub const fn is_empty(&self) -> bool {
         self.len() == 0
     }
@@ -2168,9 +2166,8 @@ impl str {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline(always)]
-    #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_as_bytes"))]
     // SAFETY: const sound because we transmute two types with the same layout
-    #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_union))]
+    #[allow_internal_unstable(const_fn_union)]
     pub const fn as_bytes(&self) -> &[u8] {
         #[repr(C)]
         union Slices<'a> {
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index d408fef7515..d5cdc266acb 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -227,7 +227,7 @@ pub mod token_stream {
 /// To quote `$` itself, use `$$`.
 #[unstable(feature = "proc_macro_quote", issue = "54722")]
 #[allow_internal_unstable(proc_macro_def_site)]
-#[cfg_attr(not(bootstrap), rustc_builtin_macro)]
+#[rustc_builtin_macro]
 pub macro quote ($($t:tt)*) { /* compiler built-in */ }
 
 #[unstable(feature = "proc_macro_internals", issue = "27812")]
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 1f125de9672..91fc004b893 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -1103,7 +1103,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
 
 pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
     visitor.visit_id(arm.hir_id);
-    walk_list!(visitor, visit_pat, &arm.pats);
+    visitor.visit_pat(&arm.pat);
     if let Some(ref g) = arm.guard {
         match g {
             Guard::If(ref e) => visitor.visit_expr(e),
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 1e05018007a..f861499cfe4 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -97,7 +97,7 @@ pub struct LoweringContext<'a> {
 
     trait_impls: BTreeMap<DefId, Vec<hir::HirId>>,
 
-    modules: BTreeMap<NodeId, hir::ModuleItems>,
+    modules: BTreeMap<hir::HirId, hir::ModuleItems>,
 
     generator_kind: Option<hir::GeneratorKind>,
 
@@ -141,7 +141,7 @@ pub struct LoweringContext<'a> {
     /// vector.
     in_scope_lifetimes: Vec<ParamName>,
 
-    current_module: NodeId,
+    current_module: hir::HirId,
 
     type_def_lifetime_params: DefIdMap<usize>,
 
@@ -262,7 +262,7 @@ pub fn lower_crate(
         is_in_dyn_type: false,
         anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
         type_def_lifetime_params: Default::default(),
-        current_module: CRATE_NODE_ID,
+        current_module: hir::CRATE_HIR_ID,
         current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)],
         item_local_id_counters: Default::default(),
         node_id_to_hir_id: IndexVec::new(),
@@ -434,35 +434,6 @@ impl<'a> LoweringContext<'a> {
                 visit::walk_pat(self, p)
             }
 
-            // HACK(or_patterns; Centril | dlrobertson): Avoid creating
-            // HIR  nodes for `PatKind::Or` for the top level of a `ast::Arm`.
-            // This is a temporary hack that should go away once we push down
-            // `arm.pats: HirVec<P<Pat>>` -> `arm.pat: P<Pat>` to HIR. // Centril
-            fn visit_arm(&mut self, arm: &'tcx Arm) {
-                match &arm.pat.node {
-                    PatKind::Or(pats) => pats.iter().for_each(|p| self.visit_pat(p)),
-                    _ => self.visit_pat(&arm.pat),
-                }
-                walk_list!(self, visit_expr, &arm.guard);
-                self.visit_expr(&arm.body);
-                walk_list!(self, visit_attribute, &arm.attrs);
-            }
-
-            // HACK(or_patterns; Centril | dlrobertson): Same as above. // Centril
-            fn visit_expr(&mut self, e: &'tcx Expr) {
-                if let ExprKind::Let(pat, scrutinee) = &e.node {
-                    walk_list!(self, visit_attribute, e.attrs.iter());
-                    match &pat.node {
-                        PatKind::Or(pats) => pats.iter().for_each(|p| self.visit_pat(p)),
-                        _ => self.visit_pat(&pat),
-                    }
-                    self.visit_expr(scrutinee);
-                    self.visit_expr_post(e);
-                    return;
-                }
-                visit::walk_expr(self, e)
-            }
-
             fn visit_item(&mut self, item: &'tcx Item) {
                 let hir_id = self.lctx.allocate_hir_id_counter(item.id);
 
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs
index 990728fa0e6..90b6c9474ac 100644
--- a/src/librustc/hir/lowering/expr.rs
+++ b/src/librustc/hir/lowering/expr.rs
@@ -247,14 +247,14 @@ impl LoweringContext<'_> {
         // 4. The return type of the block is `bool` which seems like what the user wanted.
         let scrutinee = self.lower_expr(scrutinee);
         let then_arm = {
-            let pat = self.lower_pat_top_hack(pat);
+            let pat = self.lower_pat(pat);
             let expr = self.expr_bool(span, true);
             self.arm(pat, P(expr))
         };
         let else_arm = {
             let pat = self.pat_wild(span);
             let expr = self.expr_bool(span, false);
-            self.arm(hir_vec![pat], P(expr))
+            self.arm(pat, P(expr))
         };
         hir::ExprKind::Match(
             P(scrutinee),
@@ -278,7 +278,7 @@ impl LoweringContext<'_> {
             None => (self.expr_block_empty(span), false),
             Some(els) => (self.lower_expr(els), true),
         };
-        let else_arm = self.arm(hir_vec![else_pat], P(else_expr));
+        let else_arm = self.arm(else_pat, P(else_expr));
 
         // Handle then + scrutinee:
         let then_expr = self.lower_block_expr(then);
@@ -286,7 +286,7 @@ impl LoweringContext<'_> {
             // `<pat> => <then>`:
             ExprKind::Let(ref pat, ref scrutinee) => {
                 let scrutinee = self.lower_expr(scrutinee);
-                let pat = self.lower_pat_top_hack(pat);
+                let pat = self.lower_pat(pat);
                 (pat, scrutinee, hir::MatchSource::IfLetDesugar { contains_else_clause })
             }
             // `true => <then>`:
@@ -303,7 +303,7 @@ impl LoweringContext<'_> {
                 // let temporaries live outside of `cond`.
                 let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new());
                 let pat = self.pat_bool(span, true);
-                (hir_vec![pat], cond, hir::MatchSource::IfDesugar { contains_else_clause })
+                (pat, cond, hir::MatchSource::IfDesugar { contains_else_clause })
             }
         };
         let then_arm = self.arm(then_pat, P(then_expr));
@@ -327,7 +327,7 @@ impl LoweringContext<'_> {
         let else_arm = {
             let else_pat = self.pat_wild(span);
             let else_expr = self.expr_break(span, ThinVec::new());
-            self.arm(hir_vec![else_pat], else_expr)
+            self.arm(else_pat, else_expr)
         };
 
         // Handle then + scrutinee:
@@ -343,7 +343,7 @@ impl LoweringContext<'_> {
                 //     }
                 //   }
                 let scrutinee = self.with_loop_condition_scope(|t| t.lower_expr(scrutinee));
-                let pat = self.lower_pat_top_hack(pat);
+                let pat = self.lower_pat(pat);
                 (pat, scrutinee, hir::MatchSource::WhileLetDesugar, hir::LoopSource::WhileLet)
             }
             _ => {
@@ -371,7 +371,7 @@ impl LoweringContext<'_> {
                 let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new());
                 // `true => <then>`:
                 let pat = self.pat_bool(span, true);
-                (hir_vec![pat], cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While)
+                (pat, cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While)
             }
         };
         let then_arm = self.arm(then_pat, P(then_expr));
@@ -424,7 +424,7 @@ impl LoweringContext<'_> {
         hir::Arm {
             hir_id: self.next_id(),
             attrs: self.lower_attrs(&arm.attrs),
-            pats: self.lower_pat_top_hack(&arm.pat),
+            pat: self.lower_pat(&arm.pat),
             guard: match arm.guard {
                 Some(ref x) => Some(hir::Guard::If(P(self.lower_expr(x)))),
                 _ => None,
@@ -434,16 +434,6 @@ impl LoweringContext<'_> {
         }
     }
 
-    /// HACK(or_patterns; Centril | dlrobertson): For now we don't push down top level or-patterns
-    /// `p | q` into `hir::PatKind::Or(...)` as post-lowering bits of the compiler are not ready
-    /// to deal with it. This should by fixed by pushing it down to HIR and then HAIR.
-    fn lower_pat_top_hack(&mut self, pat: &Pat) -> HirVec<P<hir::Pat>> {
-        match pat.node {
-            PatKind::Or(ref ps) => ps.iter().map(|x| self.lower_pat(x)).collect(),
-            _ => hir_vec![self.lower_pat(pat)],
-        }
-    }
-
     pub(super) fn make_async_expr(
         &mut self,
         capture_clause: CaptureBy,
@@ -592,7 +582,7 @@ impl LoweringContext<'_> {
                 );
                 P(this.expr(await_span, expr_break, ThinVec::new()))
             });
-            self.arm(hir_vec![ready_pat], break_x)
+            self.arm(ready_pat, break_x)
         };
 
         // `::std::task::Poll::Pending => {}`
@@ -603,7 +593,7 @@ impl LoweringContext<'_> {
                 hir_vec![],
             );
             let empty_block = P(self.expr_block_empty(span));
-            self.arm(hir_vec![pending_pat], empty_block)
+            self.arm(pending_pat, empty_block)
         };
 
         let inner_match_stmt = {
@@ -645,7 +635,7 @@ impl LoweringContext<'_> {
         });
 
         // mut pinned => loop { ... }
-        let pinned_arm = self.arm(hir_vec![pinned_pat], loop_expr);
+        let pinned_arm = self.arm(pinned_pat, loop_expr);
 
         // match <expr> {
         //     mut pinned => loop { .. }
@@ -1079,7 +1069,7 @@ impl LoweringContext<'_> {
                 ThinVec::new(),
             ));
             let some_pat = self.pat_some(pat.span, val_pat);
-            self.arm(hir_vec![some_pat], assign)
+            self.arm(some_pat, assign)
         };
 
         // `::std::option::Option::None => break`
@@ -1087,7 +1077,7 @@ impl LoweringContext<'_> {
             let break_expr =
                 self.with_loop_scope(e.id, |this| this.expr_break(e.span, ThinVec::new()));
             let pat = self.pat_none(e.span);
-            self.arm(hir_vec![pat], break_expr)
+            self.arm(pat, break_expr)
         };
 
         // `mut iter`
@@ -1158,7 +1148,7 @@ impl LoweringContext<'_> {
         });
 
         // `mut iter => { ... }`
-        let iter_arm = self.arm(hir_vec![iter_pat], loop_expr);
+        let iter_arm = self.arm(iter_pat, loop_expr);
 
         // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
         let into_iter_expr = {
@@ -1244,7 +1234,7 @@ impl LoweringContext<'_> {
                 ThinVec::from(attrs.clone()),
             ));
             let ok_pat = self.pat_ok(span, val_pat);
-            self.arm(hir_vec![ok_pat], val_expr)
+            self.arm(ok_pat, val_expr)
         };
 
         // `Err(err) => #[allow(unreachable_code)]
@@ -1279,7 +1269,7 @@ impl LoweringContext<'_> {
             };
 
             let err_pat = self.pat_err(try_span, err_local);
-            self.arm(hir_vec![err_pat], ret_expr)
+            self.arm(err_pat, ret_expr)
         };
 
         hir::ExprKind::Match(
@@ -1474,14 +1464,11 @@ impl LoweringContext<'_> {
         }
     }
 
-    /// HACK(or_patterns; Centril | dlrobertson): For now we don't push down top level or-patterns
-    /// `p | q` into `hir::PatKind::Or(...)` as post-lowering bits of the compiler are not ready
-    /// to deal with it. This should by fixed by pushing it down to HIR and then HAIR.
-    fn arm(&mut self, pats: HirVec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
+    fn arm(&mut self, pat: P<hir::Pat>, expr: P<hir::Expr>) -> hir::Arm {
         hir::Arm {
             hir_id: self.next_id(),
             attrs: hir_vec![],
-            pats,
+            pat,
             guard: None,
             span: expr.span,
             body: expr,
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
index 61be40a6b90..5a8d5daaf09 100644
--- a/src/librustc/hir/lowering/item.rs
+++ b/src/librustc/hir/lowering/item.rs
@@ -45,14 +45,16 @@ impl<'tcx, 'interner> ItemLowerer<'tcx, 'interner> {
 
 impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> {
     fn visit_mod(&mut self, m: &'tcx Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
-        self.lctx.modules.insert(n, hir::ModuleItems {
+        let hir_id = self.lctx.lower_node_id(n);
+
+        self.lctx.modules.insert(hir_id, hir::ModuleItems {
             items: BTreeSet::new(),
             trait_items: BTreeSet::new(),
             impl_items: BTreeSet::new(),
         });
 
         let old = self.lctx.current_module;
-        self.lctx.current_module = n;
+        self.lctx.current_module = hir_id;
         visit::walk_mod(self, m);
         self.lctx.current_module = old;
     }
diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs
index 889659382d0..b66c2ce1178 100644
--- a/src/librustc/hir/map/hir_id_validator.rs
+++ b/src/librustc/hir/map/hir_id_validator.rs
@@ -10,7 +10,7 @@ pub fn check_crate(hir_map: &hir::map::Map<'_>) {
     let errors = Lock::new(Vec::new());
 
     par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| {
-        let local_def_id = hir_map.local_def_id_from_node_id(*module_id);
+        let local_def_id = hir_map.local_def_id(*module_id);
         hir_map.visit_item_likes_in_module(local_def_id, &mut OuterVisitor {
             hir_map,
             errors: &errors,
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 5cec8a593f1..956cb36c6b1 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -536,9 +536,7 @@ impl<'hir> Map<'hir> {
         // in the expect_* calls the loops below
         self.read(hir_id);
 
-        let node_id = self.hir_to_node_id[&hir_id];
-
-        let module = &self.forest.krate.modules[&node_id];
+        let module = &self.forest.krate.modules[&hir_id];
 
         for id in &module.items {
             visitor.visit_item(self.expect_item(*id));
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 92a8c008047..6fdc126e216 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -766,7 +766,7 @@ pub struct Crate {
 
     /// A list of modules written out in the order in which they
     /// appear in the crate. This includes the main crate module.
-    pub modules: BTreeMap<NodeId, ModuleItems>,
+    pub modules: BTreeMap<HirId, ModuleItems>,
 }
 
 impl Crate {
@@ -882,44 +882,61 @@ impl fmt::Debug for Pat {
 
 impl Pat {
     // FIXME(#19596) this is a workaround, but there should be a better way
-    fn walk_<G>(&self, it: &mut G) -> bool
-        where G: FnMut(&Pat) -> bool
-    {
+    fn walk_short_(&self, it: &mut impl FnMut(&Pat) -> bool) -> bool {
         if !it(self) {
             return false;
         }
 
-        match self.node {
-            PatKind::Binding(.., Some(ref p)) => p.walk_(it),
-            PatKind::Struct(_, ref fields, _) => {
-                fields.iter().all(|field| field.pat.walk_(it))
-            }
-            PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => {
-                s.iter().all(|p| p.walk_(it))
-            }
-            PatKind::Or(ref pats) => pats.iter().all(|p| p.walk_(it)),
-            PatKind::Box(ref s) | PatKind::Ref(ref s, _) => {
-                s.walk_(it)
-            }
-            PatKind::Slice(ref before, ref slice, ref after) => {
+        use PatKind::*;
+        match &self.node {
+            Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true,
+            Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
+            Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
+            TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
+            Slice(before, slice, after) => {
                 before.iter()
                       .chain(slice.iter())
                       .chain(after.iter())
-                      .all(|p| p.walk_(it))
+                      .all(|p| p.walk_short_(it))
             }
-            PatKind::Wild |
-            PatKind::Lit(_) |
-            PatKind::Range(..) |
-            PatKind::Binding(..) |
-            PatKind::Path(_) => {
-                true
+        }
+    }
+
+    /// Walk the pattern in left-to-right order,
+    /// short circuiting (with `.all(..)`) if `false` is returned.
+    ///
+    /// Note that when visiting e.g. `Tuple(ps)`,
+    /// if visiting `ps[0]` returns `false`,
+    /// then `ps[1]` will not be visited.
+    pub fn walk_short(&self, mut it: impl FnMut(&Pat) -> bool) -> bool {
+        self.walk_short_(&mut it)
+    }
+
+    // FIXME(#19596) this is a workaround, but there should be a better way
+    fn walk_(&self, it: &mut impl FnMut(&Pat) -> bool) {
+        if !it(self) {
+            return;
+        }
+
+        use PatKind::*;
+        match &self.node {
+            Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {},
+            Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it),
+            Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
+            TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
+            Slice(before, slice, after) => {
+                before.iter()
+                      .chain(slice.iter())
+                      .chain(after.iter())
+                      .for_each(|p| p.walk_(it))
             }
         }
     }
 
-    pub fn walk<F>(&self, mut it: F) -> bool
-        where F: FnMut(&Pat) -> bool
-    {
+    /// Walk the pattern in left-to-right order.
+    ///
+    /// If `it(pat)` returns `false`, the children are not visited.
+    pub fn walk(&self, mut it: impl FnMut(&Pat) -> bool) {
         self.walk_(&mut it)
     }
 }
@@ -1259,21 +1276,32 @@ pub struct Local {
 }
 
 /// Represents a single arm of a `match` expression, e.g.
-/// `<pats> (if <guard>) => <body>`.
+/// `<pat> (if <guard>) => <body>`.
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct Arm {
     #[stable_hasher(ignore)]
     pub hir_id: HirId,
     pub span: Span,
     pub attrs: HirVec<Attribute>,
-    /// Multiple patterns can be combined with `|`
-    pub pats: HirVec<P<Pat>>,
+    /// If this pattern and the optional guard matches, then `body` is evaluated.
+    pub pat: P<Pat>,
     /// Optional guard clause.
     pub guard: Option<Guard>,
     /// The expression the arm evaluates to if this arm matches.
     pub body: P<Expr>,
 }
 
+impl Arm {
+    // HACK(or_patterns; Centril | dlrobertson): Remove this and
+    // correctly handle each case in which this method is used.
+    pub fn top_pats_hack(&self) -> &[P<Pat>] {
+        match &self.pat.node {
+            PatKind::Or(pats) => pats,
+            _ => std::slice::from_ref(&self.pat),
+        }
+    }
+}
+
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum Guard {
     If(P<Expr>),
diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs
index 0d2c7d393bb..118e168f877 100644
--- a/src/librustc/hir/pat_util.rs
+++ b/src/librustc/hir/pat_util.rs
@@ -66,9 +66,7 @@ impl hir::Pat {
 
     /// Call `f` on every "binding" in a pattern, e.g., on `a` in
     /// `match foo() { Some(a) => (), None => () }`
-    pub fn each_binding<F>(&self, mut f: F)
-        where F: FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident),
-    {
+    pub fn each_binding(&self, mut f: impl FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident)) {
         self.walk(|p| {
             if let PatKind::Binding(binding_mode, _, ident, _) = p.node {
                 f(binding_mode, p.hir_id, p.span, ident);
@@ -77,35 +75,57 @@ impl hir::Pat {
         });
     }
 
+    /// Call `f` on every "binding" in a pattern, e.g., on `a` in
+    /// `match foo() { Some(a) => (), None => () }`.
+    ///
+    /// When encountering an or-pattern `p_0 | ... | p_n` only `p_0` will be visited.
+    pub fn each_binding_or_first(
+        &self,
+        f: &mut impl FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident),
+    ) {
+        self.walk(|p| match &p.node {
+            PatKind::Or(ps) => {
+                ps[0].each_binding_or_first(f);
+                false
+            },
+            PatKind::Binding(bm,  _, ident, _) => {
+                f(*bm, p.hir_id, p.span, *ident);
+                true
+            }
+            _ => true,
+        })
+    }
+
     /// Checks if the pattern contains any patterns that bind something to
     /// an ident, e.g., `foo`, or `Foo(foo)` or `foo @ Bar(..)`.
     pub fn contains_bindings(&self) -> bool {
-        let mut contains_bindings = false;
-        self.walk(|p| {
-            if let PatKind::Binding(..) = p.node {
-                contains_bindings = true;
-                false // there's at least one binding, can short circuit now.
-            } else {
-                true
-            }
-        });
-        contains_bindings
+        self.satisfies(|p| match p.node {
+            PatKind::Binding(..) => true,
+            _ => false,
+        })
     }
 
     /// Checks if the pattern contains any patterns that bind something to
     /// an ident or wildcard, e.g., `foo`, or `Foo(_)`, `foo @ Bar(..)`,
     pub fn contains_bindings_or_wild(&self) -> bool {
-        let mut contains_bindings = false;
-        self.walk(|p| {
-            match p.node {
-                PatKind::Binding(..) | PatKind::Wild => {
-                    contains_bindings = true;
-                    false // there's at least one binding/wildcard, can short circuit now.
-                }
-                _ => true
+        self.satisfies(|p| match p.node {
+            PatKind::Binding(..) | PatKind::Wild => true,
+            _ => false,
+        })
+    }
+
+    /// Checks if the pattern satisfies the given predicate on some sub-pattern.
+    fn satisfies(&self, pred: impl Fn(&Self) -> bool) -> bool {
+        let mut satisfies = false;
+        self.walk_short(|p| {
+            if pred(p) {
+                satisfies = true;
+                false // Found one, can short circuit now.
+            } else {
+                true
             }
         });
-        contains_bindings
+        satisfies
     }
 
     pub fn simple_ident(&self) -> Option<ast::Ident> {
@@ -119,20 +139,20 @@ impl hir::Pat {
     /// Returns variants that are necessary to exist for the pattern to match.
     pub fn necessary_variants(&self) -> Vec<DefId> {
         let mut variants = vec![];
-        self.walk(|p| {
-            match p.node {
-                PatKind::Path(hir::QPath::Resolved(_, ref path)) |
-                PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
-                PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
-                    match path.res {
-                        Res::Def(DefKind::Variant, id) => variants.push(id),
-                        Res::Def(DefKind::Ctor(CtorOf::Variant, ..), id) => variants.push(id),
-                        _ => ()
-                    }
+        self.walk(|p| match &p.node {
+            PatKind::Or(_) => false,
+            PatKind::Path(hir::QPath::Resolved(_, path)) |
+            PatKind::TupleStruct(hir::QPath::Resolved(_, path), ..) |
+            PatKind::Struct(hir::QPath::Resolved(_, path), ..) => {
+                if let Res::Def(DefKind::Variant, id)
+                    | Res::Def(DefKind::Ctor(CtorOf::Variant, ..), id)
+                    = path.res
+                {
+                    variants.push(id);
                 }
-                _ => ()
+                true
             }
-            true
+            _ => true,
         });
         variants.sort();
         variants.dedup();
@@ -148,33 +168,14 @@ impl hir::Pat {
         let mut result = None;
         self.each_binding(|annotation, _, _, _| {
             match annotation {
-                hir::BindingAnnotation::Ref => {
-                    match result {
-                        None | Some(hir::MutImmutable) => result = Some(hir::MutImmutable),
-                        _ => (),
-                    }
+                hir::BindingAnnotation::Ref => match result {
+                    None | Some(hir::MutImmutable) => result = Some(hir::MutImmutable),
+                    _ => {}
                 }
                 hir::BindingAnnotation::RefMut => result = Some(hir::MutMutable),
-                _ => (),
+                _ => {}
             }
         });
         result
     }
 }
-
-impl hir::Arm {
-    /// Checks if the patterns for this arm contain any `ref` or `ref mut`
-    /// bindings, and if yes whether its containing mutable ones or just immutables ones.
-    pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> {
-        // FIXME(tschottdorf): contains_explicit_ref_binding() must be removed
-        // for #42640 (default match binding modes).
-        //
-        // See #44848.
-        self.pats.iter()
-                 .filter_map(|pat| pat.contains_explicit_ref_binding())
-                 .max_by_key(|m| match *m {
-                    hir::MutMutable => 1,
-                    hir::MutImmutable => 0,
-                 })
-    }
-}
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index cfbfb5eceb5..3cbc9ebec0a 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1790,16 +1790,7 @@ impl<'a> State<'a> {
         self.ann.pre(self, AnnNode::Arm(arm));
         self.ibox(0);
         self.print_outer_attributes(&arm.attrs);
-        let mut first = true;
-        for p in &arm.pats {
-            if first {
-                first = false;
-            } else {
-                self.s.space();
-                self.word_space("|");
-            }
-            self.print_pat(&p);
-        }
+        self.print_pat(&arm.pat);
         self.s.space();
         if let Some(ref g) = arm.guard {
             match g {
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 7508dbe6c8a..e2582346de8 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -1510,7 +1510,7 @@ pub fn check_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
         time(tcx.sess, "module lints", || {
             // Run per-module lints
             par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
-                tcx.ensure().lint_mod(tcx.hir().local_def_id_from_node_id(module));
+                tcx.ensure().lint_mod(tcx.hir().local_def_id(module));
             });
         });
     });
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 1debf0e2b73..821ede37229 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -259,19 +259,13 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
     }
 
     fn visit_arm(&mut self, arm: &'tcx hir::Arm) {
-        if arm.pats.len() == 1 {
-            let variants = arm.pats[0].necessary_variants();
-
-            // Inside the body, ignore constructions of variants
-            // necessary for the pattern to match. Those construction sites
-            // can't be reached unless the variant is constructed elsewhere.
-            let len = self.ignore_variant_stack.len();
-            self.ignore_variant_stack.extend_from_slice(&variants);
-            intravisit::walk_arm(self, arm);
-            self.ignore_variant_stack.truncate(len);
-        } else {
-            intravisit::walk_arm(self, arm);
-        }
+        // Inside the body, ignore constructions of variants
+        // necessary for the pattern to match. Those construction sites
+        // can't be reached unless the variant is constructed elsewhere.
+        let len = self.ignore_variant_stack.len();
+        self.ignore_variant_stack.extend(arm.pat.necessary_variants());
+        intravisit::walk_arm(self, arm);
+        self.ignore_variant_stack.truncate(len);
     }
 
     fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index b0a9af6af0f..1b1491a8feb 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -779,16 +779,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
 
     fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm) -> TrackMatchMode {
         let mut mode = Unknown;
-        for pat in &arm.pats {
-            self.determine_pat_move_mode(discr_cmt.clone(), &pat, &mut mode);
-        }
+        self.determine_pat_move_mode(discr_cmt.clone(), &arm.pat, &mut mode);
         mode
     }
 
     fn walk_arm(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm, mode: MatchMode) {
-        for pat in &arm.pats {
-            self.walk_pat(discr_cmt.clone(), &pat, mode);
-        }
+        self.walk_pat(discr_cmt.clone(), &arm.pat, mode);
 
         if let Some(hir::Guard::If(ref e)) = arm.guard {
             self.consume_expr(e)
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 00013bfc574..9f6611712a8 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -96,7 +96,11 @@
 use self::LiveNodeKind::*;
 use self::VarKind::*;
 
+use crate::hir;
+use crate::hir::{Expr, HirId};
 use crate::hir::def::*;
+use crate::hir::def_id::DefId;
+use crate::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
 use crate::hir::Node;
 use crate::hir::ptr::P;
 use crate::ty::{self, TyCtxt};
@@ -105,20 +109,16 @@ use crate::lint;
 use crate::util::nodemap::{HirIdMap, HirIdSet};
 
 use errors::Applicability;
-use std::collections::{BTreeMap, VecDeque};
+use rustc_data_structures::fx::FxIndexMap;
+use std::collections::VecDeque;
 use std::{fmt, u32};
 use std::io::prelude::*;
 use std::io;
 use std::rc::Rc;
 use syntax::ast;
-use syntax::symbol::{kw, sym};
+use syntax::symbol::sym;
 use syntax_pos::Span;
 
-use crate::hir;
-use crate::hir::{Expr, HirId};
-use crate::hir::def_id::DefId;
-use crate::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
-
 #[derive(Copy, Clone, PartialEq)]
 struct Variable(u32);
 
@@ -404,7 +404,7 @@ fn visit_fn<'tcx>(
     lsets.warn_about_unused_args(body, entry_ln);
 }
 
-fn add_from_pat<'tcx>(ir: &mut IrMaps<'tcx>, pat: &P<hir::Pat>) {
+fn add_from_pat(ir: &mut IrMaps<'_>, pat: &P<hir::Pat>) {
     // For struct patterns, take note of which fields used shorthand
     // (`x` rather than `x: x`).
     let mut shorthand_field_ids = HirIdSet::default();
@@ -412,26 +412,21 @@ fn add_from_pat<'tcx>(ir: &mut IrMaps<'tcx>, pat: &P<hir::Pat>) {
     pats.push_back(pat);
     while let Some(pat) = pats.pop_front() {
         use crate::hir::PatKind::*;
-        match pat.node {
-            Binding(_, _, _, ref inner_pat) => {
+        match &pat.node {
+            Binding(.., inner_pat) => {
                 pats.extend(inner_pat.iter());
             }
-            Struct(_, ref fields, _) => {
-                for field in fields {
-                    if field.is_shorthand {
-                        shorthand_field_ids.insert(field.pat.hir_id);
-                    }
-                }
+            Struct(_, fields, _) => {
+                let ids = fields.iter().filter(|f| f.is_shorthand).map(|f| f.pat.hir_id);
+                shorthand_field_ids.extend(ids);
             }
-            Ref(ref inner_pat, _) |
-            Box(ref inner_pat) => {
+            Ref(inner_pat, _) | Box(inner_pat) => {
                 pats.push_back(inner_pat);
             }
-            TupleStruct(_, ref inner_pats, _) |
-            Tuple(ref inner_pats, _) => {
+            TupleStruct(_, inner_pats, _) | Tuple(inner_pats, _) | Or(inner_pats) => {
                 pats.extend(inner_pats.iter());
             }
-            Slice(ref pre_pats, ref inner_pat, ref post_pats) => {
+            Slice(pre_pats, inner_pat, post_pats) => {
                 pats.extend(pre_pats.iter());
                 pats.extend(inner_pat.iter());
                 pats.extend(post_pats.iter());
@@ -440,7 +435,7 @@ fn add_from_pat<'tcx>(ir: &mut IrMaps<'tcx>, pat: &P<hir::Pat>) {
         }
     }
 
-    pat.each_binding(|_bm, hir_id, _sp, ident| {
+    pat.each_binding(|_, hir_id, _, ident| {
         ir.add_live_node_for_node(hir_id, VarDefNode(ident.span));
         ir.add_variable(Local(LocalInfo {
             id: hir_id,
@@ -456,9 +451,7 @@ fn visit_local<'tcx>(ir: &mut IrMaps<'tcx>, local: &'tcx hir::Local) {
 }
 
 fn visit_arm<'tcx>(ir: &mut IrMaps<'tcx>, arm: &'tcx hir::Arm) {
-    for pat in &arm.pats {
-        add_from_pat(ir, pat);
-    }
+    add_from_pat(ir, &arm.pat);
     intravisit::walk_arm(ir, arm);
 }
 
@@ -734,35 +727,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         self.ir.variable(hir_id, span)
     }
 
-    fn pat_bindings<F>(&mut self, pat: &hir::Pat, mut f: F) where
-        F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, HirId),
-    {
-        pat.each_binding(|_bm, hir_id, sp, n| {
-            let ln = self.live_node(hir_id, sp);
-            let var = self.variable(hir_id, n.span);
-            f(self, ln, var, n.span, hir_id);
-        })
-    }
-
-    fn arm_pats_bindings<F>(&mut self, pat: Option<&hir::Pat>, f: F) where
-        F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, HirId),
-    {
-        if let Some(pat) = pat {
-            self.pat_bindings(pat, f);
-        }
-    }
-
-    fn define_bindings_in_pat(&mut self, pat: &hir::Pat, succ: LiveNode)
-                              -> LiveNode {
-        self.define_bindings_in_arm_pats(Some(pat), succ)
-    }
-
-    fn define_bindings_in_arm_pats(&mut self, pat: Option<&hir::Pat>, succ: LiveNode)
-                                   -> LiveNode {
-        let mut succ = succ;
-        self.arm_pats_bindings(pat, |this, ln, var, _sp, _id| {
-            this.init_from_succ(ln, succ);
-            this.define(ln, var);
+    fn define_bindings_in_pat(&mut self, pat: &hir::Pat, mut succ: LiveNode) -> LiveNode {
+        // In an or-pattern, only consider the first pattern; any later patterns
+        // must have the same bindings, and we also consider the first pattern
+        // to be the "authoritative" set of ids.
+        pat.each_binding_or_first(&mut |_, hir_id, pat_sp, ident| {
+            let ln = self.live_node(hir_id, pat_sp);
+            let var = self.variable(hir_id, ident.span);
+            self.init_from_succ(ln, succ);
+            self.define(ln, var);
             succ = ln;
         });
         succ
@@ -1076,12 +1049,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                         arm.guard.as_ref().map(|hir::Guard::If(e)| &**e),
                         body_succ
                     );
-                    // only consider the first pattern; any later patterns must have
-                    // the same bindings, and we also consider the first pattern to be
-                    // the "authoritative" set of ids
-                    let arm_succ =
-                        self.define_bindings_in_arm_pats(arm.pats.first().map(|p| &**p),
-                                                         guard_succ);
+                    let arm_succ = self.define_bindings_in_pat(&arm.pat, guard_succ);
                     self.merge_from_succ(ln, arm_succ, first_merge);
                     first_merge = false;
                 };
@@ -1388,74 +1356,36 @@ impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
         NestedVisitorMap::None
     }
 
-    fn visit_local(&mut self, l: &'tcx hir::Local) {
-        check_local(self, l);
-    }
-    fn visit_expr(&mut self, ex: &'tcx Expr) {
-        check_expr(self, ex);
-    }
-    fn visit_arm(&mut self, a: &'tcx hir::Arm) {
-        check_arm(self, a);
-    }
-}
+    fn visit_local(&mut self, local: &'tcx hir::Local) {
+        self.check_unused_vars_in_pat(&local.pat, None, |spans, hir_id, ln, var| {
+            if local.init.is_some() {
+                self.warn_about_dead_assign(spans, hir_id, ln, var);
+            }
+        });
 
-fn check_local<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, local: &'tcx hir::Local) {
-    match local.init {
-        Some(_) => {
-            this.warn_about_unused_or_dead_vars_in_pat(&local.pat);
-        },
-        None => {
-            this.pat_bindings(&local.pat, |this, ln, var, sp, id| {
-                let span = local.pat.simple_ident().map_or(sp, |ident| ident.span);
-                this.warn_about_unused(vec![span], id, ln, var);
-            })
-        }
+        intravisit::walk_local(self, local);
     }
 
-    intravisit::walk_local(this, local);
-}
-
-fn check_arm<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, arm: &'tcx hir::Arm) {
-    // Only consider the variable from the first pattern; any later patterns must have
-    // the same bindings, and we also consider the first pattern to be the "authoritative" set of
-    // ids. However, we should take the spans of variables with the same name from the later
-    // patterns so the suggestions to prefix with underscores will apply to those too.
-    let mut vars: BTreeMap<String, (LiveNode, Variable, HirId, Vec<Span>)> = Default::default();
-
-    for pat in &arm.pats {
-        this.arm_pats_bindings(Some(&*pat), |this, ln, var, sp, id| {
-            let name = this.ir.variable_name(var);
-            vars.entry(name)
-                .and_modify(|(.., spans)| {
-                    spans.push(sp);
-                })
-                .or_insert_with(|| {
-                    (ln, var, id, vec![sp])
-                });
-        });
+    fn visit_expr(&mut self, ex: &'tcx Expr) {
+        check_expr(self, ex);
     }
 
-    for (_, (ln, var, id, spans)) in vars {
-        this.warn_about_unused(spans, id, ln, var);
+    fn visit_arm(&mut self, arm: &'tcx hir::Arm) {
+        self.check_unused_vars_in_pat(&arm.pat, None, |_, _, _, _| {});
+        intravisit::walk_arm(self, arm);
     }
-
-    intravisit::walk_arm(this, arm);
 }
 
-fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
+fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr) {
     match expr.node {
         hir::ExprKind::Assign(ref l, _) => {
             this.check_place(&l);
-
-            intravisit::walk_expr(this, expr);
         }
 
         hir::ExprKind::AssignOp(_, ref l, _) => {
             if !this.tables.is_method_call(expr) {
                 this.check_place(&l);
             }
-
-            intravisit::walk_expr(this, expr);
         }
 
         hir::ExprKind::InlineAsm(ref ia, ref outputs, ref inputs) => {
@@ -1470,8 +1400,6 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
                 }
                 this.visit_expr(output);
             }
-
-            intravisit::walk_expr(this, expr);
         }
 
         // no correctness conditions related to liveness
@@ -1484,13 +1412,13 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
         hir::ExprKind::Lit(_) | hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) |
         hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) |
         hir::ExprKind::Closure(..) | hir::ExprKind::Path(_) | hir::ExprKind::Yield(..) |
-        hir::ExprKind::Box(..) | hir::ExprKind::Type(..) | hir::ExprKind::Err => {
-            intravisit::walk_expr(this, expr);
-        }
+        hir::ExprKind::Box(..) | hir::ExprKind::Type(..) | hir::ExprKind::Err => {}
     }
+
+    intravisit::walk_expr(this, expr);
 }
 
-impl<'a, 'tcx> Liveness<'a, 'tcx> {
+impl<'tcx> Liveness<'_, 'tcx> {
     fn check_place(&mut self, expr: &'tcx Expr) {
         match expr.node {
             hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
@@ -1503,7 +1431,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                         // as being used.
                         let ln = self.live_node(expr.hir_id, expr.span);
                         let var = self.variable(var_hid, expr.span);
-                        self.warn_about_dead_assign(expr.span, expr.hir_id, ln, var);
+                        self.warn_about_dead_assign(vec![expr.span], expr.hir_id, ln, var);
                     }
                 }
             }
@@ -1525,109 +1453,112 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     }
 
     fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) {
-        for param in &body.params {
-            param.pat.each_binding(|_bm, hir_id, _, ident| {
-                let sp = ident.span;
-                let var = self.variable(hir_id, sp);
-                // Ignore unused self.
-                if ident.name != kw::SelfLower {
-                    if !self.warn_about_unused(vec![sp], hir_id, entry_ln, var) {
-                        if self.live_on_entry(entry_ln, var).is_none() {
-                            self.report_dead_assign(hir_id, sp, var, true);
-                        }
-                    }
+        for p in &body.params {
+            self.check_unused_vars_in_pat(&p.pat, Some(entry_ln), |spans, hir_id, ln, var| {
+                if self.live_on_entry(ln, var).is_none() {
+                    self.report_dead_assign(hir_id, spans, var, true);
                 }
-            })
+            });
         }
     }
 
-    fn warn_about_unused_or_dead_vars_in_pat(&mut self, pat: &hir::Pat) {
-        self.pat_bindings(pat, |this, ln, var, sp, id| {
-            if !this.warn_about_unused(vec![sp], id, ln, var) {
-                this.warn_about_dead_assign(sp, id, ln, var);
+    fn check_unused_vars_in_pat(
+        &self,
+        pat: &hir::Pat,
+        entry_ln: Option<LiveNode>,
+        on_used_on_entry: impl Fn(Vec<Span>, HirId, LiveNode, Variable),
+    ) {
+        // In an or-pattern, only consider the variable; any later patterns must have the same
+        // bindings, and we also consider the first pattern to be the "authoritative" set of ids.
+        // However, we should take the spans of variables with the same name from the later
+        // patterns so the suggestions to prefix with underscores will apply to those too.
+        let mut vars: FxIndexMap<String, (LiveNode, Variable, HirId, Vec<Span>)> = <_>::default();
+
+        pat.each_binding(|_, hir_id, pat_sp, ident| {
+            let ln = entry_ln.unwrap_or_else(|| self.live_node(hir_id, pat_sp));
+            let var = self.variable(hir_id, ident.span);
+            vars.entry(self.ir.variable_name(var))
+                .and_modify(|(.., spans)| spans.push(ident.span))
+                .or_insert_with(|| (ln, var, hir_id, vec![ident.span]));
+        });
+
+        for (_, (ln, var, id, spans)) in vars {
+            if self.used_on_entry(ln, var) {
+                on_used_on_entry(spans, id, ln, var);
+            } else {
+                self.report_unused(spans, id, ln, var);
             }
-        })
+        }
     }
 
-    fn warn_about_unused(&self,
-                         spans: Vec<Span>,
-                         hir_id: HirId,
-                         ln: LiveNode,
-                         var: Variable)
-                         -> bool {
-        if !self.used_on_entry(ln, var) {
-            let r = self.should_warn(var);
-            if let Some(name) = r {
-                // annoying: for parameters in funcs like `fn(x: i32)
-                // {ret}`, there is only one node, so asking about
-                // assigned_on_exit() is not meaningful.
-                let is_assigned = if ln == self.s.exit_ln {
-                    false
-                } else {
-                    self.assigned_on_exit(ln, var).is_some()
-                };
+    fn report_unused(&self, spans: Vec<Span>, hir_id: HirId, ln: LiveNode, var: Variable) {
+        if let Some(name) = self.should_warn(var).filter(|name| name != "self") {
+            // annoying: for parameters in funcs like `fn(x: i32)
+            // {ret}`, there is only one node, so asking about
+            // assigned_on_exit() is not meaningful.
+            let is_assigned = if ln == self.s.exit_ln {
+                false
+            } else {
+                self.assigned_on_exit(ln, var).is_some()
+            };
 
-                if is_assigned {
-                    self.ir.tcx.lint_hir_note(
-                        lint::builtin::UNUSED_VARIABLES,
-                        hir_id,
-                        spans,
-                        &format!("variable `{}` is assigned to, but never used", name),
-                        &format!("consider using `_{}` instead", name),
-                    );
-                } else if name != "self" {
-                    let mut err = self.ir.tcx.struct_span_lint_hir(
-                        lint::builtin::UNUSED_VARIABLES,
-                        hir_id,
-                        spans.clone(),
-                        &format!("unused variable: `{}`", name),
-                    );
+            if is_assigned {
+                self.ir.tcx.lint_hir_note(
+                    lint::builtin::UNUSED_VARIABLES,
+                    hir_id,
+                    spans,
+                    &format!("variable `{}` is assigned to, but never used", name),
+                    &format!("consider using `_{}` instead", name),
+                );
+            } else {
+                let mut err = self.ir.tcx.struct_span_lint_hir(
+                    lint::builtin::UNUSED_VARIABLES,
+                    hir_id,
+                    spans.clone(),
+                    &format!("unused variable: `{}`", name),
+                );
+
+                if self.ir.variable_is_shorthand(var) {
+                    if let Node::Binding(pat) = self.ir.tcx.hir().get(hir_id) {
+                        // Handle `ref` and `ref mut`.
+                        let spans = spans.iter()
+                            .map(|_span| (pat.span, format!("{}: _", name)))
+                            .collect();
 
-                    if self.ir.variable_is_shorthand(var) {
-                        if let Node::Binding(pat) = self.ir.tcx.hir().get(hir_id) {
-                            // Handle `ref` and `ref mut`.
-                            let spans = spans.iter()
-                                .map(|_span| (pat.span, format!("{}: _", name)))
-                                .collect();
-
-                            err.multipart_suggestion(
-                                "try ignoring the field",
-                                spans,
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                    } else {
                         err.multipart_suggestion(
-                            "consider prefixing with an underscore",
-                            spans.iter().map(|span| (*span, format!("_{}", name))).collect(),
+                            "try ignoring the field",
+                            spans,
                             Applicability::MachineApplicable,
                         );
                     }
-
-                    err.emit()
+                } else {
+                    err.multipart_suggestion(
+                        "consider prefixing with an underscore",
+                        spans.iter().map(|span| (*span, format!("_{}", name))).collect(),
+                        Applicability::MachineApplicable,
+                    );
                 }
+
+                err.emit()
             }
-            true
-        } else {
-            false
         }
     }
 
-    fn warn_about_dead_assign(&self, sp: Span, hir_id: HirId, ln: LiveNode, var: Variable) {
+    fn warn_about_dead_assign(&self, spans: Vec<Span>, hir_id: HirId, ln: LiveNode, var: Variable) {
         if self.live_on_exit(ln, var).is_none() {
-            self.report_dead_assign(hir_id, sp, var, false);
+            self.report_dead_assign(hir_id, spans, var, false);
         }
     }
 
-    fn report_dead_assign(&self, hir_id: HirId, sp: Span, var: Variable, is_argument: bool) {
+    fn report_dead_assign(&self, hir_id: HirId, spans: Vec<Span>, var: Variable, is_param: bool) {
         if let Some(name) = self.should_warn(var) {
-            if is_argument {
-                self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
+            if is_param {
+                self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, spans,
                 &format!("value passed to `{}` is never read", name))
                 .help("maybe it is overwritten before being read?")
                 .emit();
             } else {
-                self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp,
+                self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, spans,
                 &format!("value assigned to `{}` is never read", name))
                 .help("maybe it is overwritten before being read?")
                 .emit();
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index c08f250f3dc..8a466567319 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -974,7 +974,7 @@ pub struct FreeRegionInfo {
 ///
 /// [rustc guide]: https://rust-lang.github.io/rustc-guide/ty.html
 #[derive(Copy, Clone)]
-#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyCtxt")]
+#[rustc_diagnostic_item = "TyCtxt"]
 pub struct TyCtxt<'tcx> {
     gcx: &'tcx GlobalCtxt<'tcx>,
 }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 0c1b2a23d44..3d1ae838d81 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -581,7 +581,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::TyS<'tcx> {
     }
 }
 
-#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "Ty")]
+#[rustc_diagnostic_item = "Ty"]
 pub type Ty<'tcx> = &'tcx TyS<'tcx>;
 
 impl<'tcx> rustc_serialize::UseSpecializedEncodable for Ty<'tcx> {}
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index e5eca752135..6510aea8c25 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -86,7 +86,7 @@ impl BoundRegion {
 /// AST structure in `libsyntax/ast.rs` as well.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
          RustcEncodable, RustcDecodable, HashStable, Debug)]
-#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyKind")]
+#[rustc_diagnostic_item = "TyKind"]
 pub enum TyKind<'tcx> {
     /// The primitive boolean type. Written as `bool`.
     Bool,
diff --git a/src/librustc_ast_borrowck/cfg/construct.rs b/src/librustc_ast_borrowck/cfg/construct.rs
index 0dc999083a9..e2c5de648a2 100644
--- a/src/librustc_ast_borrowck/cfg/construct.rs
+++ b/src/librustc_ast_borrowck/cfg/construct.rs
@@ -390,7 +390,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
             // patterns and the guard (if there is one) in the arm.
             let bindings_exit = self.add_dummy_node(&[]);
 
-            for pat in &arm.pats {
+            for pat in arm.top_pats_hack() {
                 // Visit the pattern, coming from the discriminant exit
                 let mut pat_exit = self.pat(&pat, discr_exit);
 
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 56db695f254..37b33466d70 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -905,10 +905,10 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
             });
         }, {
             par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
-                tcx.ensure().check_mod_loops(tcx.hir().local_def_id_from_node_id(module));
-                tcx.ensure().check_mod_attrs(tcx.hir().local_def_id_from_node_id(module));
-                tcx.ensure().check_mod_unstable_api_usage(
-                    tcx.hir().local_def_id_from_node_id(module));
+                let local_def_id = tcx.hir().local_def_id(module);
+                tcx.ensure().check_mod_loops(local_def_id);
+                tcx.ensure().check_mod_attrs(local_def_id);
+                tcx.ensure().check_mod_unstable_api_usage(local_def_id);
             });
         });
     });
@@ -931,9 +931,10 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
                     // "not all control paths return a value" is reported here.
                     //
                     // maybe move the check to a MIR pass?
-                    tcx.ensure().check_mod_liveness(tcx.hir().local_def_id_from_node_id(module));
+                    let local_def_id = tcx.hir().local_def_id(module);
 
-                    tcx.ensure().check_mod_intrinsics(tcx.hir().local_def_id_from_node_id(module));
+                    tcx.ensure().check_mod_liveness(local_def_id);
+                    tcx.ensure().check_mod_intrinsics(local_def_id);
                 });
             });
         });
@@ -993,7 +994,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
         }, {
             time(sess, "privacy checking modules", || {
                 par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
-                    tcx.ensure().check_mod_privacy(tcx.hir().local_def_id_from_node_id(module));
+                    tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module));
                 });
             });
         });
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 2b0237c7c08..5f1bd3e9115 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -142,7 +142,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // Step 2. Create the otherwise and prebinding blocks.
 
         // create binding start block for link them by false edges
-        let candidate_count = arms.iter().map(|c| c.patterns.len()).sum::<usize>();
+        let candidate_count = arms.iter().map(|c| c.top_pats_hack().len()).sum::<usize>();
         let pre_binding_blocks: Vec<_> = (0..candidate_count)
             .map(|_| self.cfg.start_new_block())
             .collect();
@@ -159,7 +159,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             .map(|arm| {
                 let arm_has_guard = arm.guard.is_some();
                 match_has_guard |= arm_has_guard;
-                let arm_candidates: Vec<_> = arm.patterns
+                let arm_candidates: Vec<_> = arm.top_pats_hack()
                     .iter()
                     .zip(candidate_pre_binding_blocks.by_ref())
                     .map(
@@ -238,7 +238,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let scope = this.declare_bindings(
                     None,
                     arm.span,
-                    &arm.patterns[0],
+                    &arm.top_pats_hack()[0],
                     ArmHasGuard(arm.guard.is_some()),
                     Some((Some(&scrutinee_place), scrutinee_span)),
                 );
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index d57b68c48ee..a24b14598eb 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -860,9 +860,9 @@ impl ToBorrowKind for hir::Mutability {
     }
 }
 
-fn convert_arm<'a, 'tcx>(cx: &mut Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
+fn convert_arm<'tcx>(cx: &mut Cx<'_, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
     Arm {
-        patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(),
+        pattern: cx.pattern_from_hir(&arm.pat),
         guard: match arm.guard {
                 Some(hir::Guard::If(ref e)) => Some(Guard::If(e.to_ref())),
                 _ => None,
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 0638cb462f7..63a9a83154b 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -293,7 +293,7 @@ pub struct FruInfo<'tcx> {
 
 #[derive(Clone, Debug)]
 pub struct Arm<'tcx> {
-    pub patterns: Vec<Pattern<'tcx>>,
+    pub pattern: Pattern<'tcx>,
     pub guard: Option<Guard<'tcx>>,
     pub body: ExprRef<'tcx>,
     pub lint_level: LintLevel,
@@ -301,6 +301,17 @@ pub struct Arm<'tcx> {
     pub span: Span,
 }
 
+impl Arm<'tcx> {
+    // HACK(or_patterns; Centril | dlrobertson): Remove this and
+    // correctly handle each case in which this method is used.
+    pub fn top_pats_hack(&self) -> &[Pattern<'tcx>] {
+        match &*self.pattern.kind {
+            PatternKind::Or { pats } => pats,
+            _ => std::slice::from_ref(&self.pattern),
+        }
+    }
+}
+
 #[derive(Clone, Debug)]
 pub enum Guard<'tcx> {
     If(ExprRef<'tcx>),
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 57e0a48ca89..3791ae1c41e 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -14,7 +14,6 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc::hir::def::*;
 use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
-use rustc::hir::ptr::P;
 use rustc::hir::{self, Pat, PatKind};
 
 use smallvec::smallvec;
@@ -76,7 +75,7 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
         });
 
         // Check legality of move bindings and `@` patterns.
-        self.check_patterns(false, slice::from_ref(&loc.pat));
+        self.check_patterns(false, &loc.pat);
     }
 
     fn visit_body(&mut self, body: &'tcx hir::Body) {
@@ -84,7 +83,7 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
 
         for param in &body.params {
             self.check_irrefutable(&param.pat, "function argument");
-            self.check_patterns(false, slice::from_ref(&param.pat));
+            self.check_patterns(false, &param.pat);
         }
     }
 }
@@ -122,11 +121,9 @@ impl PatternContext<'_, '_> {
 }
 
 impl<'tcx> MatchVisitor<'_, 'tcx> {
-    fn check_patterns(&mut self, has_guard: bool, pats: &[P<Pat>]) {
-        check_legality_of_move_bindings(self, has_guard, pats);
-        for pat in pats {
-            check_legality_of_bindings_in_at_patterns(self, pat);
-        }
+    fn check_patterns(&mut self, has_guard: bool, pat: &Pat) {
+        check_legality_of_move_bindings(self, has_guard, pat);
+        check_legality_of_bindings_in_at_patterns(self, pat);
     }
 
     fn check_match(
@@ -137,7 +134,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
     ) {
         for arm in arms {
             // First, check legality of move bindings.
-            self.check_patterns(arm.guard.is_some(), &arm.pats);
+            self.check_patterns(arm.guard.is_some(), &arm.pat);
 
             // Second, if there is a guard on each arm, make sure it isn't
             // assigning or borrowing anything mutably.
@@ -146,9 +143,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
             }
 
             // Third, perform some lints.
-            for pat in &arm.pats {
-                check_for_bindings_named_same_as_variants(self, pat);
-            }
+            check_for_bindings_named_same_as_variants(self, &arm.pat);
         }
 
         let module = self.tcx.hir().get_module_parent(scrut.hir_id);
@@ -156,7 +151,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
             let mut have_errors = false;
 
             let inlined_arms : Vec<(Vec<_>, _)> = arms.iter().map(|arm| (
-                arm.pats.iter().map(|pat| {
+                arm.top_pats_hack().iter().map(|pat| {
                     let mut patcx = PatternContext::new(self.tcx,
                                                         self.param_env.and(self.identity_substs),
                                                         self.tables);
@@ -545,78 +540,60 @@ fn maybe_point_at_variant(ty: Ty<'_>, patterns: &[Pattern<'_>]) -> Vec<Span> {
     covered
 }
 
-// Legality of move bindings checking
-fn check_legality_of_move_bindings(
-    cx: &mut MatchVisitor<'_, '_>,
-    has_guard: bool,
-    pats: &[P<Pat>],
-) {
+// Check the legality of legality of by-move bindings.
+fn check_legality_of_move_bindings(cx: &mut MatchVisitor<'_, '_>, has_guard: bool, pat: &Pat) {
     let mut by_ref_span = None;
-    for pat in pats {
-        pat.each_binding(|_, hir_id, span, _path| {
-            if let Some(&bm) = cx.tables.pat_binding_modes().get(hir_id) {
-                if let ty::BindByReference(..) = bm {
-                    by_ref_span = Some(span);
-                }
-            } else {
-                cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode");
+    pat.each_binding(|_, hir_id, span, _| {
+        if let Some(&bm) = cx.tables.pat_binding_modes().get(hir_id) {
+            if let ty::BindByReference(..) = bm {
+                by_ref_span = Some(span);
             }
-        })
-    }
+        } else {
+            cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode");
+        }
+    });
+
     let span_vec = &mut Vec::new();
-    let check_move = |
-        cx: &mut MatchVisitor<'_, '_>,
-        p: &Pat,
-        sub: Option<&Pat>,
-        span_vec: &mut Vec<Span>,
-    | {
-        // check legality of moving out of the enum
-
-        // x @ Foo(..) is legal, but x @ Foo(y) isn't.
+    let mut check_move = |p: &Pat, sub: Option<&Pat>| {
+        // Check legality of moving out of the enum.
+        //
+        // `x @ Foo(..)` is legal, but `x @ Foo(y)` isn't.
         if sub.map_or(false, |p| p.contains_bindings()) {
-            struct_span_err!(cx.tcx.sess, p.span, E0007,
-                             "cannot bind by-move with sub-bindings")
+            struct_span_err!(cx.tcx.sess, p.span, E0007, "cannot bind by-move with sub-bindings")
                 .span_label(p.span, "binds an already bound by-move value by moving it")
                 .emit();
-        } else if !has_guard {
-            if let Some(_by_ref_span) = by_ref_span {
-                span_vec.push(p.span);
-            }
+        } else if !has_guard && by_ref_span.is_some() {
+            span_vec.push(p.span);
         }
     };
 
-    for pat in pats {
-        pat.walk(|p| {
-            if let PatKind::Binding(_, _, _, ref sub) = p.node {
-                if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) {
-                    match bm {
-                        ty::BindByValue(..) => {
-                            let pat_ty = cx.tables.node_type(p.hir_id);
-                            if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) {
-                                check_move(cx, p, sub.as_ref().map(|p| &**p), span_vec);
-                            }
-                        }
-                        _ => {}
+    pat.walk(|p| {
+        if let PatKind::Binding(.., sub) = &p.node {
+            if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) {
+                if let ty::BindByValue(..) = bm {
+                    let pat_ty = cx.tables.node_type(p.hir_id);
+                    if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) {
+                        check_move(p, sub.as_deref());
                     }
-                } else {
-                    cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode");
                 }
+            } else {
+                cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode");
             }
-            true
-        });
-    }
-    if !span_vec.is_empty(){
-        let span = MultiSpan::from_spans(span_vec.clone());
+        }
+        true
+    });
+
+    if !span_vec.is_empty() {
         let mut err = struct_span_err!(
             cx.tcx.sess,
-            span,
+            MultiSpan::from_spans(span_vec.clone()),
             E0009,
             "cannot bind by-move and by-ref in the same pattern",
         );
         if let Some(by_ref_span) = by_ref_span {
             err.span_label(by_ref_span, "both by-ref and by-move used");
         }
-        for span in span_vec.iter(){
+        for span in span_vec.iter() {
             err.span_label(*span, "by-move pattern here");
         }
         err.emit();
@@ -627,7 +604,7 @@ fn check_legality_of_move_bindings(
 /// because of the way rvalues are handled in the borrow check. (See issue
 /// #14587.)
 fn check_legality_of_bindings_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pat) {
-    AtBindingPatternVisitor { cx: cx, bindings_allowed: true }.visit_pat(pat);
+    AtBindingPatternVisitor { cx, bindings_allowed: true }.visit_pat(pat);
 }
 
 struct AtBindingPatternVisitor<'a, 'b, 'tcx> {
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index ec09e69ec85..5fc23b4a69e 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -239,7 +239,52 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             "transmute" => {
                 self.copy_op_transmute(args[0], dest)?;
             }
+            "simd_insert" => {
+                let index = self.read_scalar(args[1])?.to_u32()? as u64;
+                let scalar = args[2];
+                let input = args[0];
+                let (len, e_ty) = self.read_vector_ty(input);
+                assert!(
+                    index < len,
+                    "Index `{}` must be in bounds of vector type `{}`: `[0, {})`",
+                    index, e_ty, len
+                );
+                assert_eq!(
+                    input.layout, dest.layout,
+                    "Return type `{}` must match vector type `{}`",
+                    dest.layout.ty, input.layout.ty
+                );
+                assert_eq!(
+                    scalar.layout.ty, e_ty,
+                    "Scalar type `{}` must match vector element type `{}`",
+                    scalar.layout.ty, e_ty
+                );
 
+                for i in 0..len {
+                    let place = self.place_field(dest, i)?;
+                    let value = if i == index {
+                        scalar
+                    } else {
+                        self.operand_field(input, i)?
+                    };
+                    self.copy_op(value, place)?;
+                }
+            }
+            "simd_extract" => {
+                let index = self.read_scalar(args[1])?.to_u32()? as _;
+                let (len, e_ty) = self.read_vector_ty(args[0]);
+                assert!(
+                    index < len,
+                    "index `{}` is out-of-bounds of vector type `{}` with length `{}`",
+                    index, e_ty, len
+                );
+                assert_eq!(
+                    e_ty, dest.layout.ty,
+                    "Return type `{}` must match vector element type `{}`",
+                    dest.layout.ty, e_ty
+                );
+                self.copy_op(self.operand_field(args[0], index)?, dest)?;
+            }
             _ => return Ok(false),
         }
 
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index ba35623ab12..f5d1ec3eb75 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -335,6 +335,17 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         }
     }
 
+    /// Read vector length and element type
+    pub fn read_vector_ty(
+        &self, op: OpTy<'tcx, M::PointerTag>
+    ) -> (u64, &rustc::ty::TyS<'tcx>) {
+        if let layout::Abi::Vector { .. } = op.layout.abi {
+            (op.layout.ty.simd_size(*self.tcx) as _, op.layout.ty.simd_type(*self.tcx))
+        } else {
+            bug!("Type `{}` is not a SIMD vector type", op.layout.ty)
+        }
+    }
+
     /// Read a scalar from a place
     pub fn read_scalar(
         &self,
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index e6598bc0ffb..ef6b7d626e7 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -249,9 +249,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
         match instance.def {
             ty::InstanceDef::Intrinsic(..) => {
-                if caller_abi != Abi::RustIntrinsic {
-                    throw_unsup!(FunctionAbiMismatch(caller_abi, Abi::RustIntrinsic))
-                }
                 // The intrinsic itself cannot diverge, so if we got here without a return
                 // place... (can happen e.g., for transmute returning `!`)
                 let dest = match dest {
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 9a03719ab61..938dab57181 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -6,6 +6,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 
 #![feature(nll)]
 #![feature(in_band_lifetimes)]
+#![feature(inner_deref)]
 #![feature(slice_patterns)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index c1639b9b5bb..abe2d2f4a54 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -557,6 +557,8 @@ impl Qualif for IsNotPromotable {
                             | "saturating_add"
                             | "saturating_sub"
                             | "transmute"
+                            | "simd_insert"
+                            | "simd_extract"
                             => return true,
 
                             _ => {}
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index a5a8315a1e7..4e29706714f 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -8,7 +8,6 @@
 
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))]
 
 #![recursion_limit="256"]
 
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index 38b4fa354c1..d4c3dc917e5 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -499,19 +499,15 @@ fn check_expr_kind<'a, 'tcx>(
         }
 
         // Conditional control flow (possible to implement).
-        hir::ExprKind::Match(ref expr, ref hirvec_arm, ref _match_source) => {
+        hir::ExprKind::Match(ref expr, ref arms, ref _match_source) => {
             // Compute the most demanding borrow from all the arms'
             // patterns and set that on the discriminator.
-            let mut mut_borrow = false;
-            for pat in hirvec_arm.iter().flat_map(|arm| &arm.pats) {
-                mut_borrow = v.remove_mut_rvalue_borrow(pat);
-            }
-            if mut_borrow {
+            if arms.iter().fold(false, |_, arm| v.remove_mut_rvalue_borrow(&arm.pat)) {
                 v.mut_rvalue_borrows.insert(expr.hir_id);
             }
 
             let _ = v.check_expr(expr);
-            for index in hirvec_arm.iter() {
+            for index in arms.iter() {
                 let _ = v.check_expr(&*index.body);
                 if let Some(hir::Guard::If(ref expr)) = index.guard {
                     let _ = v.check_expr(&expr);
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 50fd72f0613..14a07c8c9c7 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -58,11 +58,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // collection into `Vec`), so we get types for all bindings.
         let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
             let mut all_pats_diverge = Diverges::WarnedAlways;
-            for p in &arm.pats {
-                self.diverges.set(Diverges::Maybe);
-                self.check_pat_top(&p, discrim_ty, Some(discrim.span));
-                all_pats_diverge &= self.diverges.get();
-            }
+            self.diverges.set(Diverges::Maybe);
+            self.check_pat_top(&arm.pat, discrim_ty, Some(discrim.span));
+            all_pats_diverge &= self.diverges.get();
 
             // As discussed with @eddyb, this is for disabling unreachable_code
             // warnings on patterns (they're now subsumed by unreachable_patterns
@@ -428,11 +426,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         //
         // See #44848.
         let contains_ref_bindings = arms.iter()
-                                        .filter_map(|a| a.contains_explicit_ref_binding())
-                                        .max_by_key(|m| match *m {
-                                            hir::MutMutable => 1,
-                                            hir::MutImmutable => 0,
-                                        });
+            .filter_map(|a| a.pat.contains_explicit_ref_binding())
+            .max_by_key(|m| match *m {
+                hir::MutMutable => 1,
+                hir::MutImmutable => 0,
+            });
 
         if let Some(m) = contains_ref_bindings {
             self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m))
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 550ea0bf2da..af3259b987a 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -97,11 +97,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.check_pat_struct(pat, qpath, fields, *etc, expected, def_bm, discrim_span)
             }
             PatKind::Or(pats) => {
-                let expected_ty = self.structurally_resolved_type(pat.span, expected);
                 for pat in pats {
                     self.check_pat(pat, expected, def_bm, discrim_span);
                 }
-                expected_ty
+                expected
             }
             PatKind::Tuple(elements, ddpos) => {
                 self.check_pat_tuple(pat.span, elements, *ddpos, expected, def_bm, discrim_span)
@@ -208,7 +207,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match pat.node {
             PatKind::Struct(..) |
             PatKind::TupleStruct(..) |
-            PatKind::Or(_) |
             PatKind::Tuple(..) |
             PatKind::Box(_) |
             PatKind::Range(..) |
@@ -226,6 +224,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     _ => true,
                 }
             }
+            // FIXME(or_patterns; Centril | dlrobertson): To keep things compiling
+            // for or-patterns at the top level, we need to make `p_0 | ... | p_n`
+            // a "non reference pattern". For example the following currently compiles:
+            // ```
+            // match &1 {
+            //     e @ &(1...2) | e @ &(3...4) => {}
+            //     _ => {}
+            // }
+            // ```
+            //
+            // We should consider whether we should do something special in nested or-patterns.
+            PatKind::Or(_) |
             PatKind::Wild |
             PatKind::Binding(..) |
             PatKind::Ref(..) => false,
@@ -426,12 +436,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // If the binding is like `ref x | ref const x | ref mut x`
                 // then `x` is assigned a value of type `&M T` where M is the
                 // mutability and T is the expected type.
-                let region_ty = self.new_ref_ty(pat.span, mutbl, expected);
-
+                //
                 // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)`
                 // is required. However, we use equality, which is stronger.
                 // See (note_1) for an explanation.
-                region_ty
+                self.new_ref_ty(pat.span, mutbl, expected)
             }
             // Otherwise, the type of x is the expected type `T`.
             ty::BindByValue(_) => {
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 9ca2a275fce..ac9f9f1ea25 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -488,9 +488,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> {
 
     fn visit_arm(&mut self, arm: &'tcx hir::Arm) {
         // see above
-        for p in &arm.pats {
-            self.constrain_bindings_in_pat(p);
-        }
+        self.constrain_bindings_in_pat(&arm.pat);
         intravisit::walk_arm(self, arm);
     }
 
@@ -1069,9 +1067,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
         let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(discr))));
         debug!("discr_cmt={:?}", discr_cmt);
         for arm in arms {
-            for root_pat in &arm.pats {
-                self.link_pattern(discr_cmt.clone(), &root_pat);
-            }
+            self.link_pattern(discr_cmt.clone(), &arm.pat);
         }
     }
 
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index bc0f17c3bf0..854549bb66b 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -54,7 +54,7 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) {
     // but it's one that we must perform earlier than the rest of
     // WfCheck.
     for &module in tcx.hir().krate().modules.keys() {
-        tcx.ensure().check_mod_impl_wf(tcx.hir().local_def_id_from_node_id(module));
+        tcx.ensure().check_mod_impl_wf(tcx.hir().local_def_id(module));
     }
 }
 
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 2450c807d54..dbff1e91617 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -303,7 +303,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
     tcx.sess.track_errors(|| {
         time(tcx.sess, "type collecting", || {
             for &module in tcx.hir().krate().modules.keys() {
-                tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id_from_node_id(module));
+                tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
             }
         });
     })?;
@@ -338,7 +338,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
 
     time(tcx.sess, "item-types checking", || {
         for &module in tcx.hir().krate().modules.keys() {
-            tcx.ensure().check_mod_item_types(tcx.hir().local_def_id_from_node_id(module));
+            tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
         }
     });
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 0b9e717221f..2985e7f70b5 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -1,7 +1,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/")]
 
-#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))]
 #![feature(rustc_private)]
 #![feature(arbitrary_self_types)]
 #![feature(box_patterns)]
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 21aeb9c26f8..5d9683f8ded 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -238,7 +238,6 @@
 #![feature(array_error_internals)]
 #![feature(asm)]
 #![feature(associated_type_bounds)]
-#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))]
 #![feature(box_syntax)]
 #![feature(c_variadic)]
 #![feature(cfg_target_has_atomic)]
diff --git a/src/libsyntax/ext/mbe/macro_parser.rs b/src/libsyntax/ext/mbe/macro_parser.rs
index b51384d3b15..8f49ba9572d 100644
--- a/src/libsyntax/ext/mbe/macro_parser.rs
+++ b/src/libsyntax/ext/mbe/macro_parser.rs
@@ -413,18 +413,6 @@ fn nameize<I: Iterator<Item = NamedMatch>>(
     Success(ret_val)
 }
 
-/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For
-/// other tokens, this is "unexpected token...".
-crate fn parse_failure_msg(tok: &Token) -> String {
-    match tok.kind {
-        token::Eof => "unexpected end of macro invocation".to_string(),
-        _ => format!(
-            "no rules expected the token `{}`",
-            pprust::token_to_string(tok)
-        ),
-    }
-}
-
 /// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison)
 fn token_name_eq(t1: &Token, t2: &Token) -> bool {
     if let (Some((ident1, is_raw1)), Some((ident2, is_raw2))) = (t1.ident(), t2.ident()) {
diff --git a/src/libsyntax/ext/mbe/macro_rules.rs b/src/libsyntax/ext/mbe/macro_rules.rs
index 816baadb12f..c24f6a66603 100644
--- a/src/libsyntax/ext/mbe/macro_rules.rs
+++ b/src/libsyntax/ext/mbe/macro_rules.rs
@@ -6,7 +6,7 @@ use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind};
 use crate::ext::expand::{AstFragment, AstFragmentKind};
 use crate::ext::mbe;
 use crate::ext::mbe::macro_check;
-use crate::ext::mbe::macro_parser::{parse, parse_failure_msg};
+use crate::ext::mbe::macro_parser::parse;
 use crate::ext::mbe::macro_parser::{Error, Failure, Success};
 use crate::ext::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedParseResult};
 use crate::ext::mbe::transcribe::transcribe;
@@ -15,6 +15,7 @@ use crate::parse::parser::Parser;
 use crate::parse::token::TokenKind::*;
 use crate::parse::token::{self, NtTT, Token};
 use crate::parse::{Directory, ParseSess};
+use crate::print::pprust;
 use crate::symbol::{kw, sym, Symbol};
 use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};
 
@@ -371,10 +372,6 @@ pub fn compile_declarative_macro(
                             tt.clone().into(),
                             true,
                             sess,
-                            features,
-                            &def.attrs,
-                            edition,
-                            def.id,
                         )
                         .pop()
                         .unwrap();
@@ -398,10 +395,6 @@ pub fn compile_declarative_macro(
                             tt.clone().into(),
                             false,
                             sess,
-                            features,
-                            &def.attrs,
-                            edition,
-                            def.id,
                         )
                         .pop()
                         .unwrap();
@@ -1184,3 +1177,15 @@ impl TokenTree {
         parse(cx.parse_sess(), tts, mtch, Some(directory), true)
     }
 }
+
+/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For
+/// other tokens, this is "unexpected token...".
+fn parse_failure_msg(tok: &Token) -> String {
+    match tok.kind {
+        token::Eof => "unexpected end of macro invocation".to_string(),
+        _ => format!(
+            "no rules expected the token `{}`",
+            pprust::token_to_string(tok),
+        ),
+    }
+}
diff --git a/src/libsyntax/ext/mbe/quoted.rs b/src/libsyntax/ext/mbe/quoted.rs
index 3952e29a5f0..8cb85bdef76 100644
--- a/src/libsyntax/ext/mbe/quoted.rs
+++ b/src/libsyntax/ext/mbe/quoted.rs
@@ -1,18 +1,15 @@
 use crate::ast;
-use crate::ast::NodeId;
 use crate::ext::mbe::macro_parser;
 use crate::ext::mbe::{TokenTree, KleeneOp, KleeneToken, SequenceRepetition, Delimited};
-use crate::feature_gate::Features;
 use crate::parse::token::{self, Token};
 use crate::parse::ParseSess;
 use crate::print::pprust;
 use crate::symbol::kw;
 use crate::tokenstream;
 
-use syntax_pos::{edition::Edition, Span};
+use syntax_pos::Span;
 
 use rustc_data_structures::sync::Lrc;
-use std::iter::Peekable;
 
 /// Takes a `tokenstream::TokenStream` and returns a `Vec<self::TokenTree>`. Specifically, this
 /// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a
@@ -39,17 +36,13 @@ pub(super) fn parse(
     input: tokenstream::TokenStream,
     expect_matchers: bool,
     sess: &ParseSess,
-    features: &Features,
-    attrs: &[ast::Attribute],
-    edition: Edition,
-    macro_node_id: NodeId,
 ) -> Vec<TokenTree> {
     // Will contain the final collection of `self::TokenTree`
     let mut result = Vec::new();
 
     // For each token tree in `input`, parse the token into a `self::TokenTree`, consuming
     // additional trees if need be.
-    let mut trees = input.trees().peekable();
+    let mut trees = input.trees();
     while let Some(tree) = trees.next() {
         // Given the parsed tree, if there is a metavar and we are expecting matchers, actually
         // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`).
@@ -58,10 +51,6 @@ pub(super) fn parse(
             &mut trees,
             expect_matchers,
             sess,
-            features,
-            attrs,
-            edition,
-            macro_node_id,
         );
         match tree {
             TokenTree::MetaVar(start_sp, ident) if expect_matchers => {
@@ -109,13 +98,9 @@ pub(super) fn parse(
 ///   unstable features or not.
 fn parse_tree(
     tree: tokenstream::TokenTree,
-    trees: &mut Peekable<impl Iterator<Item = tokenstream::TokenTree>>,
+    trees: &mut impl Iterator<Item = tokenstream::TokenTree>,
     expect_matchers: bool,
     sess: &ParseSess,
-    features: &Features,
-    attrs: &[ast::Attribute],
-    edition: Edition,
-    macro_node_id: NodeId,
 ) -> TokenTree {
     // Depending on what `tree` is, we could be parsing different parts of a macro
     match tree {
@@ -135,10 +120,6 @@ fn parse_tree(
                     tts.into(),
                     expect_matchers,
                     sess,
-                    features,
-                    attrs,
-                    edition,
-                    macro_node_id,
                 );
                 // Get the Kleene operator and optional separator
                 let (separator, kleene) = parse_sep_and_kleene_op(trees, span.entire(), sess);
@@ -192,10 +173,6 @@ fn parse_tree(
                     tts.into(),
                     expect_matchers,
                     sess,
-                    features,
-                    attrs,
-                    edition,
-                    macro_node_id,
                 ),
             }),
         ),
@@ -244,7 +221,7 @@ fn parse_kleene_op(
 /// operator and separator, then a tuple with `(separator, KleeneOp)` is returned. Otherwise, an
 /// error with the appropriate span is emitted to `sess` and a dummy value is returned.
 fn parse_sep_and_kleene_op(
-    input: &mut Peekable<impl Iterator<Item = tokenstream::TokenTree>>,
+    input: &mut impl Iterator<Item = tokenstream::TokenTree>,
     span: Span,
     sess: &ParseSess,
 ) -> (Option<Token>, KleeneToken) {
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index b0833010fe0..2c10220c766 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -7,7 +7,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        test(attr(deny(warnings))))]
 
-#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))]
 #![feature(box_syntax)]
 #![feature(const_fn)]
 #![feature(const_transmute)]
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index d7c537be896..4fc29d70540 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -834,8 +834,6 @@ pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) {
 
 pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
     visitor.visit_pat(&arm.pat);
-    // NOTE(or_patterns; Centril | dlrobertson):
-    // If you change this, also change the hack in `lowering.rs`.
     walk_list!(visitor, visit_expr, &arm.guard);
     visitor.visit_expr(&arm.body);
     walk_list!(visitor, visit_attribute, &arm.attrs);
diff --git a/src/stage0.txt b/src/stage0.txt
index 1a9e64a1862..9509d3e9961 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2019-08-13
+date: 2019-09-25
 rustc: beta
 cargo: beta
 
diff --git a/src/test/ui/consts/const-eval/simd/insert_extract.rs b/src/test/ui/consts/const-eval/simd/insert_extract.rs
new file mode 100644
index 00000000000..d3462d802ea
--- /dev/null
+++ b/src/test/ui/consts/const-eval/simd/insert_extract.rs
@@ -0,0 +1,53 @@
+// run-pass
+#![feature(const_fn)]
+#![feature(repr_simd)]
+#![feature(platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)] struct i8x1(i8);
+#[repr(simd)] struct u16x2(u16, u16);
+#[repr(simd)] struct f32x3(f32, f32, f32);
+
+extern "platform-intrinsic" {
+    fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
+    fn simd_extract<T, U>(x: T, idx: u32) -> U;
+}
+
+fn main() {
+    {
+        const U: i8x1 = i8x1(13);
+        const V: i8x1 = unsafe { simd_insert(U, 0_u32, 42_i8) };
+        const X0: i8 = V.0;
+        const Y0: i8 = unsafe { simd_extract(V, 0) };
+        assert_eq!(X0, 42);
+        assert_eq!(Y0, 42);
+    }
+    {
+        const U: u16x2 = u16x2(13, 14);
+        const V: u16x2 = unsafe { simd_insert(U, 1_u32, 42_u16) };
+        const X0: u16 = V.0;
+        const X1: u16 = V.1;
+        const Y0: u16 = unsafe { simd_extract(V, 0) };
+        const Y1: u16 = unsafe { simd_extract(V, 1) };
+        assert_eq!(X0, 13);
+        assert_eq!(X1, 42);
+        assert_eq!(Y0, 13);
+        assert_eq!(Y1, 42);
+    }
+    {
+        const U: f32x3 = f32x3(13., 14., 15.);
+        const V: f32x3 = unsafe { simd_insert(U, 1_u32, 42_f32) };
+        const X0: f32 = V.0;
+        const X1: f32 = V.1;
+        const X2: f32 = V.2;
+        const Y0: f32 = unsafe { simd_extract(V, 0) };
+        const Y1: f32 = unsafe { simd_extract(V, 1) };
+        const Y2: f32 = unsafe { simd_extract(V, 2) };
+        assert_eq!(X0, 13.);
+        assert_eq!(X1, 42.);
+        assert_eq!(X2, 15.);
+        assert_eq!(Y0, 13.);
+        assert_eq!(Y1, 42.);
+        assert_eq!(Y2, 15.);
+    }
+}
diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
index 4cb35e907c8..7870d394c8b 100644
--- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
+++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
@@ -33,6 +33,9 @@ fn main() {
     let mut mut_unused_var = 1;
 
     let (mut var, unused_var) = (1, 2);
+    // NOTE: `var` comes after `unused_var` lexicographically yet the warning
+    // for `var` will be emitted before the one for `unused_var`. We use an
+    // `IndexMap` to ensure this is the case instead of a `BTreeMap`.
 
     if let SoulHistory { corridors_of_light,
                          mut hours_are_suns,
diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
index a0b34d220c8..74bbef8adad 100644
--- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
+++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr
@@ -30,13 +30,13 @@ LL |     let (mut var, unused_var) = (1, 2);
    |                   ^^^^^^^^^^ help: consider prefixing with an underscore: `_unused_var`
 
 warning: unused variable: `corridors_of_light`
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:26
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:40:26
    |
 LL |     if let SoulHistory { corridors_of_light,
    |                          ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _`
 
 warning: variable `hours_are_suns` is assigned to, but never used
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:30
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:41:30
    |
 LL |                          mut hours_are_suns,
    |                              ^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL |                          mut hours_are_suns,
    = note: consider using `_hours_are_suns` instead
 
 warning: value assigned to `hours_are_suns` is never read
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:40:9
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:43:9
    |
 LL |         hours_are_suns = false;
    |         ^^^^^^^^^^^^^^
@@ -58,43 +58,43 @@ LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
    = help: maybe it is overwritten before being read?
 
 warning: unused variable: `fire`
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:44:32
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:47:32
    |
 LL |     let LovelyAmbition { lips, fire } = the_spirit;
    |                                ^^^^ help: try ignoring the field: `fire: _`
 
 warning: unused variable: `case`
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:53:23
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:56:23
    |
 LL |         Large::Suit { case } => {}
    |                       ^^^^ help: try ignoring the field: `case: _`
 
 warning: unused variable: `case`
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:58:24
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:61:24
    |
 LL |         &Large::Suit { case } => {}
    |                        ^^^^ help: try ignoring the field: `case: _`
 
 warning: unused variable: `case`
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:63:27
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:66:27
    |
 LL |         box Large::Suit { case } => {}
    |                           ^^^^ help: try ignoring the field: `case: _`
 
 warning: unused variable: `case`
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:68:24
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:71:24
    |
 LL |         (Large::Suit { case },) => {}
    |                        ^^^^ help: try ignoring the field: `case: _`
 
 warning: unused variable: `case`
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:73:24
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:76:24
    |
 LL |         [Large::Suit { case }] => {}
    |                        ^^^^ help: try ignoring the field: `case: _`
 
 warning: unused variable: `case`
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:78:29
+  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:81:29
    |
 LL |         Tuple(Large::Suit { case }, ()) => {}
    |                             ^^^^ help: try ignoring the field: `case: _`
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject aa6b7e01abce30091cc594cb23a15c46cead6e2
+Subproject ab6fa8908c9b6c8f7e2249231c395eebfbc4989
diff --git a/src/tools/clippy b/src/tools/clippy
-Subproject 157edad6205fdd6a4f5932fba2675c619074635
+Subproject d5570e44e8c6cfe9a5633f9a53c7749bd3bacc4