Rollup merge of #74064 - RalfJung:variant-count-bootstrap, r=kennytm

variant_count: avoid incorrect dummy implementation

This also avoids a stage 0 doctest failure.
diff --git a/src/doc/unstable-book/src/language-features/rustc-attrs.md b/src/doc/unstable-book/src/language-features/rustc-attrs.md
new file mode 100644
index 0000000..2967200
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/rustc-attrs.md
@@ -0,0 +1,53 @@
+# `rustc_attrs`
+
+This feature has no tracking issue, and is therefore internal to
+the compiler, not being intended for general use.
+
+Note: `rustc_attrs` enables many rustc-internal attributes and this page
+only discuss a few of them.
+
+------------------------
+
+The `rustc_attrs` feature allows debugging rustc type layouts by using
+`#[rustc_layout(...)]` to debug layout at compile time (it even works
+with `cargo check`) as an alternative to `rustc -Z print-type-sizes`
+that is way more verbose.
+
+Options provided by `#[rustc_layout(...)]` are `debug`, `size`, `abi`.
+Note that it only work best with sized type without generics.
+
+## Examples
+
+```rust,ignore
+#![feature(rustc_attrs)]
+
+#[rustc_layout(abi, size)]
+pub enum X {
+    Y(u8, u8, u8),
+    Z(isize),
+}
+```
+
+When that is compiled, the compiler will error with something like
+
+```text
+error: abi: Aggregate { sized: true }
+ --> src/lib.rs:4:1
+  |
+4 | / pub enum T {
+5 | |     Y(u8, u8, u8),
+6 | |     Z(isize),
+7 | | }
+  | |_^
+
+error: size: Size { raw: 16 }
+ --> src/lib.rs:4:1
+  |
+4 | / pub enum T {
+5 | |     Y(u8, u8, u8),
+6 | |     Z(isize),
+7 | | }
+  | |_^
+
+error: aborting due to 2 previous errors
+```
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index 13ef94d..5b671b4 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -1774,6 +1774,15 @@
     }
 }
 
+#[stable(feature = "box_str2", since = "1.45.0")]
+impl FromIterator<Box<str>> for String {
+    fn from_iter<I: IntoIterator<Item = Box<str>>>(iter: I) -> String {
+        let mut buf = String::new();
+        buf.extend(iter);
+        buf
+    }
+}
+
 #[stable(feature = "herd_cows", since = "1.19.0")]
 impl<'a> FromIterator<Cow<'a, str>> for String {
     fn from_iter<I: IntoIterator<Item = Cow<'a, str>>>(iter: I) -> String {
@@ -1842,6 +1851,13 @@
     }
 }
 
+#[stable(feature = "box_str2", since = "1.45.0")]
+impl Extend<Box<str>> for String {
+    fn extend<I: IntoIterator<Item = Box<str>>>(&mut self, iter: I) {
+        iter.into_iter().for_each(move |s| self.push_str(&s));
+    }
+}
+
 #[stable(feature = "extend_string", since = "1.4.0")]
 impl Extend<String> for String {
     fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index ac3ce225..2d6a391 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -419,8 +419,7 @@
     #[inline]
     #[stable(feature = "arc_unique", since = "1.4.0")]
     pub fn try_unwrap(this: Self) -> Result<T, Self> {
-        // See `drop` for why all these atomics are like this
-        if this.inner().strong.compare_exchange(1, 0, Release, Relaxed).is_err() {
+        if this.inner().strong.compare_exchange(1, 0, Relaxed, Relaxed).is_err() {
             return Err(this);
         }
 
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index 530cf88..ce4be97 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -1521,7 +1521,7 @@
     ///
     /// let iter = a.iter();
     ///
-    /// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i );
+    /// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i);
     ///
     /// assert_eq!(sum, 6);
     ///
@@ -1535,7 +1535,7 @@
     /// let mut iter = a.iter();
     ///
     /// // instead, we add in a .by_ref()
-    /// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i );
+    /// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i);
     ///
     /// assert_eq!(sum, 3);
     ///
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 313744e..32481bf 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -570,6 +570,9 @@
     /// Allows capturing variables in scope using format_args!
     (active, format_args_capture, "1.46.0", Some(67984), None),
 
+    /// Lazily evaluate constants. This allows constants to depend on type parameters.
+    (active, lazy_normalization_consts, "1.46.0", Some(72219), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
@@ -586,5 +589,6 @@
     sym::raw_dylib,
     sym::const_trait_impl,
     sym::const_trait_bound_opt_out,
+    sym::lazy_normalization_consts,
     sym::specialization,
 ];
diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs
index c8d4e9f..3b564e0 100644
--- a/src/librustc_infer/infer/combine.rs
+++ b/src/librustc_infer/infer/combine.rs
@@ -112,7 +112,7 @@
 
             // All other cases of inference are errors
             (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
-                Err(TypeError::Sorts(ty::relate::expected_found(relation, &a, &b)))
+                Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
             }
 
             _ => ty::relate::super_relate_tys(relation, a, b),
@@ -701,7 +701,7 @@
     a_is_expected: bool,
     (a, b): (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>),
 ) -> TypeError<'tcx> {
-    TypeError::ConstMismatch(ty::relate::expected_found_bool(a_is_expected, &a, &b))
+    TypeError::ConstMismatch(ty::relate::expected_found_bool(a_is_expected, a, b))
 }
 
 fn int_unification_error<'tcx>(
@@ -709,7 +709,7 @@
     v: (ty::IntVarValue, ty::IntVarValue),
 ) -> TypeError<'tcx> {
     let (a, b) = v;
-    TypeError::IntMismatch(ty::relate::expected_found_bool(a_is_expected, &a, &b))
+    TypeError::IntMismatch(ty::relate::expected_found_bool(a_is_expected, a, b))
 }
 
 fn float_unification_error<'tcx>(
@@ -717,5 +717,5 @@
     v: (ty::FloatVarValue, ty::FloatVarValue),
 ) -> TypeError<'tcx> {
     let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v;
-    TypeError::FloatMismatch(ty::relate::expected_found_bool(a_is_expected, &a, &b))
+    TypeError::FloatMismatch(ty::relate::expected_found_bool(a_is_expected, a, b))
 }
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index d942c07..698bef4 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -1370,7 +1370,7 @@
     /// we still evaluate them eagerly.
     #[inline]
     pub fn lazy_normalization(self) -> bool {
-        self.features().const_generics
+        self.features().const_generics || self.features().lazy_normalization_consts
     }
 
     #[inline]
diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs
index 9fa1260..9dda208 100644
--- a/src/librustc_middle/ty/print/pretty.rs
+++ b/src/librustc_middle/ty/print/pretty.rs
@@ -282,26 +282,27 @@
             //    where there is no explicit `extern crate`, we just prepend
             //    the crate name.
             match self.tcx().extern_crate(def_id) {
-                Some(&ExternCrate {
-                    src: ExternCrateSource::Extern(def_id),
-                    dependency_of: LOCAL_CRATE,
-                    span,
-                    ..
-                }) => {
-                    debug!("try_print_visible_def_path: def_id={:?}", def_id);
-                    return Ok((
-                        if !span.is_dummy() {
-                            self.print_def_path(def_id, &[])?
-                        } else {
-                            self.path_crate(cnum)?
-                        },
-                        true,
-                    ));
-                }
+                Some(&ExternCrate { src, dependency_of, span, .. }) => match (src, dependency_of) {
+                    (ExternCrateSource::Extern(def_id), LOCAL_CRATE) => {
+                        debug!("try_print_visible_def_path: def_id={:?}", def_id);
+                        return Ok((
+                            if !span.is_dummy() {
+                                self.print_def_path(def_id, &[])?
+                            } else {
+                                self.path_crate(cnum)?
+                            },
+                            true,
+                        ));
+                    }
+                    (ExternCrateSource::Path, LOCAL_CRATE) => {
+                        debug!("try_print_visible_def_path: def_id={:?}", def_id);
+                        return Ok((self.path_crate(cnum)?, true));
+                    }
+                    _ => {}
+                },
                 None => {
                     return Ok((self.path_crate(cnum)?, true));
                 }
-                _ => {}
             }
         }
 
diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs
index cee04ce..7946a27 100644
--- a/src/librustc_middle/ty/relate.rs
+++ b/src/librustc_middle/ty/relate.rs
@@ -159,8 +159,8 @@
         if a.c_variadic != b.c_variadic {
             return Err(TypeError::VariadicMismatch(expected_found(
                 relation,
-                &a.c_variadic,
-                &b.c_variadic,
+                a.c_variadic,
+                b.c_variadic,
             )));
         }
         let unsafety = relation.relate(a.unsafety, b.unsafety)?;
@@ -200,7 +200,7 @@
         b: ast::Unsafety,
     ) -> RelateResult<'tcx, ast::Unsafety> {
         if a != b {
-            Err(TypeError::UnsafetyMismatch(expected_found(relation, &a, &b)))
+            Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b)))
         } else {
             Ok(a)
         }
@@ -213,7 +213,7 @@
         a: abi::Abi,
         b: abi::Abi,
     ) -> RelateResult<'tcx, abi::Abi> {
-        if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(relation, &a, &b))) }
+        if a == b { Ok(a) } else { Err(TypeError::AbiMismatch(expected_found(relation, a, b))) }
     }
 }
 
@@ -226,8 +226,8 @@
         if a.item_def_id != b.item_def_id {
             Err(TypeError::ProjectionMismatched(expected_found(
                 relation,
-                &a.item_def_id,
-                &b.item_def_id,
+                a.item_def_id,
+                b.item_def_id,
             )))
         } else {
             let substs = relation.relate(a.substs, b.substs)?;
@@ -245,8 +245,8 @@
         if a.item_def_id != b.item_def_id {
             Err(TypeError::ProjectionMismatched(expected_found(
                 relation,
-                &a.item_def_id,
-                &b.item_def_id,
+                a.item_def_id,
+                b.item_def_id,
             )))
         } else {
             let ty = relation.relate_with_variance(ty::Invariant, a.ty, b.ty)?;
@@ -264,7 +264,7 @@
     ) -> RelateResult<'tcx, ty::TraitRef<'tcx>> {
         // Different traits cannot be related.
         if a.def_id != b.def_id {
-            Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
+            Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
         } else {
             let substs = relate_substs(relation, None, a.substs, b.substs)?;
             Ok(ty::TraitRef { def_id: a.def_id, substs })
@@ -280,7 +280,7 @@
     ) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> {
         // Different traits cannot be related.
         if a.def_id != b.def_id {
-            Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
+            Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
         } else {
             let substs = relate_substs(relation, None, a.substs, b.substs)?;
             Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs })
@@ -305,6 +305,7 @@
 }
 
 impl<'tcx> Relate<'tcx> for Ty<'tcx> {
+    #[inline]
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
         a: Ty<'tcx>,
@@ -421,7 +422,7 @@
                     let sz_b = sz_b.try_eval_usize(tcx, relation.param_env());
                     match (sz_a, sz_b) {
                         (Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize(
-                            expected_found(relation, &sz_a_val, &sz_b_val),
+                            expected_found(relation, sz_a_val, sz_b_val),
                         )),
                         _ => Err(err),
                     }
@@ -440,9 +441,9 @@
                     as_.iter().zip(bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())),
                 )?)
             } else if !(as_.is_empty() || bs.is_empty()) {
-                Err(TypeError::TupleSize(expected_found(relation, &as_.len(), &bs.len())))
+                Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len())))
             } else {
-                Err(TypeError::Sorts(expected_found(relation, &a, &b)))
+                Err(TypeError::Sorts(expected_found(relation, a, b)))
             }
         }
 
@@ -471,7 +472,7 @@
             Ok(tcx.mk_opaque(a_def_id, substs))
         }
 
-        _ => Err(TypeError::Sorts(expected_found(relation, &a, &b))),
+        _ => Err(TypeError::Sorts(expected_found(relation, a, b))),
     }
 }
 
@@ -521,10 +522,10 @@
                         if a_instance == b_instance {
                             Ok(ConstValue::Scalar(a_val))
                         } else {
-                            Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
+                            Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
                         }
                     } else {
-                        Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
+                        Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
                     }
                 }
 
@@ -534,7 +535,7 @@
                     if a_bytes == b_bytes {
                         Ok(a_val)
                     } else {
-                        Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
+                        Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
                     }
                 }
 
@@ -554,7 +555,7 @@
 
                                 Ok(a_val)
                             } else {
-                                Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
+                                Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
                             }
                         }
                         // FIXME(const_generics): There are probably some `TyKind`s
@@ -564,12 +565,12 @@
                                 DUMMY_SP,
                                 &format!("unexpected consts: a: {:?}, b: {:?}", a, b),
                             );
-                            Err(TypeError::ConstMismatch(expected_found(relation, &a, &b)))
+                            Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
                         }
                     }
                 }
 
-                _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
+                _ => Err(TypeError::ConstMismatch(expected_found(relation, a, b))),
             };
 
             new_val.map(ty::ConstKind::Value)
@@ -584,7 +585,7 @@
                 relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?;
             Ok(ty::ConstKind::Unevaluated(a_def_id, substs, a_promoted))
         }
-        _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))),
+        _ => Err(TypeError::ConstMismatch(expected_found(relation, a, b))),
     };
     new_const_val.map(|val| tcx.mk_const(ty::Const { val, ty: a.ty }))
 }
@@ -607,7 +608,7 @@
         b_v.sort_by(|a, b| a.stable_cmp(tcx, b));
         b_v.dedup();
         if a_v.len() != b_v.len() {
-            return Err(TypeError::ExistentialMismatch(expected_found(relation, &a, &b)));
+            return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
         }
 
         let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| {
@@ -616,7 +617,7 @@
                 (Trait(a), Trait(b)) => Ok(Trait(relation.relate(a, b)?)),
                 (Projection(a), Projection(b)) => Ok(Projection(relation.relate(a, b)?)),
                 (AutoTrait(a), AutoTrait(b)) if a == b => Ok(AutoTrait(a)),
-                _ => Err(TypeError::ExistentialMismatch(expected_found(relation, &a, &b))),
+                _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))),
             }
         });
         Ok(tcx.mk_existential_predicates(v)?)
@@ -740,20 +741,14 @@
 ///////////////////////////////////////////////////////////////////////////
 // Error handling
 
-pub fn expected_found<R, T>(relation: &mut R, a: &T, b: &T) -> ExpectedFound<T>
+pub fn expected_found<R, T>(relation: &mut R, a: T, b: T) -> ExpectedFound<T>
 where
     R: TypeRelation<'tcx>,
-    T: Clone,
 {
     expected_found_bool(relation.a_is_expected(), a, b)
 }
 
-pub fn expected_found_bool<T>(a_is_expected: bool, a: &T, b: &T) -> ExpectedFound<T>
-where
-    T: Clone,
-{
-    let a = a.clone();
-    let b = b.clone();
+pub fn expected_found_bool<T>(a_is_expected: bool, a: T, b: T) -> ExpectedFound<T> {
     if a_is_expected {
         ExpectedFound { expected: a, found: b }
     } else {
diff --git a/src/librustc_mir/borrow_check/type_check/input_output.rs b/src/librustc_mir/borrow_check/type_check/input_output.rs
index edd2dc3..8cebd36 100644
--- a/src/librustc_mir/borrow_check/type_check/input_output.rs
+++ b/src/librustc_mir/borrow_check/type_check/input_output.rs
@@ -122,7 +122,7 @@
         if let Err(terr) = self.eq_opaque_type_and_type(
             mir_output_ty,
             normalized_output_ty,
-            self.mir_def_id.to_def_id(),
+            self.mir_def_id,
             Locations::All(output_span),
             ConstraintCategory::BoringNoLocation,
         ) {
@@ -145,7 +145,7 @@
             if let Err(err) = self.eq_opaque_type_and_type(
                 mir_output_ty,
                 user_provided_output_ty,
-                self.mir_def_id.to_def_id(),
+                self.mir_def_id,
                 Locations::All(output_span),
                 ConstraintCategory::BoringNoLocation,
             ) {
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index 0e35caf..3532b6d 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -1144,7 +1144,8 @@
                 // When you have `let x: impl Foo = ...` in a closure,
                 // the resulting inferend values are stored with the
                 // def-id of the base function.
-                let parent_def_id = self.tcx().closure_base_def_id(self.mir_def_id.to_def_id());
+                let parent_def_id =
+                    self.tcx().closure_base_def_id(self.mir_def_id.to_def_id()).expect_local();
                 return self.eq_opaque_type_and_type(sub, sup, parent_def_id, locations, category);
             } else {
                 return Err(terr);
@@ -1208,7 +1209,7 @@
         &mut self,
         revealed_ty: Ty<'tcx>,
         anon_ty: Ty<'tcx>,
-        anon_owner_def_id: DefId,
+        anon_owner_def_id: LocalDefId,
         locations: Locations,
         category: ConstraintCategory,
     ) -> Fallible<()> {
@@ -1238,8 +1239,7 @@
         let tcx = infcx.tcx;
         let param_env = self.param_env;
         let body = self.body;
-        let concrete_opaque_types =
-            &tcx.typeck_tables_of(anon_owner_def_id.expect_local()).concrete_opaque_types;
+        let concrete_opaque_types = &tcx.typeck_tables_of(anon_owner_def_id).concrete_opaque_types;
         let mut opaque_type_values = Vec::new();
 
         debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id);
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index d62300b..75067ff 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -334,9 +334,9 @@
                 }
 
                 v
-            } else if def_id.is_local() {
+            } else if let Some(def_id) = def_id.as_local() {
                 // constant defined in this crate, we can figure out a lint level!
-                match tcx.def_kind(def_id) {
+                match tcx.def_kind(def_id.to_def_id()) {
                     // constants never produce a hard error at the definition site. Anything else is
                     // a backwards compatibility hazard (and will break old versions of winapi for
                     // sure)
@@ -346,7 +346,7 @@
                     // validation thus preventing such a hard error from being a backwards
                     // compatibility hazard
                     DefKind::Const | DefKind::AssocConst => {
-                        let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+                        let hir_id = tcx.hir().as_local_hir_id(def_id);
                         err.report_as_lint(
                             tcx.at(tcx.def_span(def_id)),
                             "any use of this value will cause an error",
@@ -369,7 +369,7 @@
                                 err.report_as_lint(
                                     tcx.at(span),
                                     "reaching this expression at runtime will panic or abort",
-                                    tcx.hir().as_local_hir_id(def_id.expect_local()),
+                                    tcx.hir().as_local_hir_id(def_id),
                                     Some(err.span),
                                 )
                             }
diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs
index 6dd0674..707e136 100644
--- a/src/librustc_mir/dataflow/drop_flag_effects.rs
+++ b/src/librustc_mir/dataflow/drop_flag_effects.rs
@@ -1,6 +1,7 @@
 use crate::util::elaborate_drops::DropFlagState;
 use rustc_middle::mir::{self, Body, Location};
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_target::abi::VariantIdx;
 
 use super::indexes::MovePathIndex;
 use super::move_paths::{InitKind, LookupResult, MoveData};
@@ -228,3 +229,42 @@
         }
     }
 }
+
+/// Calls `handle_inactive_variant` for each descendant move path of `enum_place` that contains a
+/// `Downcast` to a variant besides the `active_variant`.
+///
+/// NOTE: If there are no move paths corresponding to an inactive variant,
+/// `handle_inactive_variant` will not be called for that variant.
+pub(crate) fn on_all_inactive_variants<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    body: &mir::Body<'tcx>,
+    move_data: &MoveData<'tcx>,
+    enum_place: mir::Place<'tcx>,
+    active_variant: VariantIdx,
+    mut handle_inactive_variant: impl FnMut(MovePathIndex),
+) {
+    let enum_mpi = match move_data.rev_lookup.find(enum_place.as_ref()) {
+        LookupResult::Exact(mpi) => mpi,
+        LookupResult::Parent(_) => return,
+    };
+
+    let enum_path = &move_data.move_paths[enum_mpi];
+    for (variant_mpi, variant_path) in enum_path.children(&move_data.move_paths) {
+        // Because of the way we build the `MoveData` tree, each child should have exactly one more
+        // projection than `enum_place`. This additional projection must be a downcast since the
+        // base is an enum.
+        let (downcast, base_proj) = variant_path.place.projection.split_last().unwrap();
+        assert_eq!(enum_place.projection.len(), base_proj.len());
+
+        let variant_idx = match *downcast {
+            mir::ProjectionElem::Downcast(_, idx) => idx,
+            _ => unreachable!(),
+        };
+
+        if variant_idx != active_variant {
+            on_all_children_bits(tcx, body, move_data, variant_mpi, |mpi| {
+                handle_inactive_variant(mpi)
+            });
+        }
+    }
+}
diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs
index d5def03..8975fae 100644
--- a/src/librustc_mir/dataflow/impls/mod.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -12,7 +12,7 @@
 
 use crate::util::elaborate_drops::DropFlagState;
 
-use super::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
+use super::move_paths::{HasMoveData, InitIndex, InitKind, MoveData, MovePathIndex};
 use super::{AnalysisDomain, BottomValue, GenKill, GenKillAnalysis};
 
 use super::drop_flag_effects_for_function_entry;
@@ -124,11 +124,23 @@
     tcx: TyCtxt<'tcx>,
     body: &'a Body<'tcx>,
     mdpe: &'a MoveDataParamEnv<'tcx>,
+
+    mark_inactive_variants_as_uninit: bool,
 }
 
 impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
     pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
-        MaybeUninitializedPlaces { tcx, body, mdpe }
+        MaybeUninitializedPlaces { tcx, body, mdpe, mark_inactive_variants_as_uninit: false }
+    }
+
+    /// Causes inactive enum variants to be marked as "maybe uninitialized" after a switch on an
+    /// enum discriminant.
+    ///
+    /// This is correct in a vacuum but is not the default because it causes problems in the borrow
+    /// checker, where this information gets propagated along `FakeEdge`s.
+    pub fn mark_inactive_variants_as_uninit(mut self) -> Self {
+        self.mark_inactive_variants_as_uninit = true;
+        self
     }
 }
 
@@ -350,27 +362,16 @@
         _adt: &ty::AdtDef,
         variant: VariantIdx,
     ) {
-        let enum_mpi = match self.move_data().rev_lookup.find(enum_place.as_ref()) {
-            LookupResult::Exact(mpi) => mpi,
-            LookupResult::Parent(_) => return,
-        };
-
-        // Kill all move paths that correspond to variants other than this one
-        let move_paths = &self.move_data().move_paths;
-        let enum_path = &move_paths[enum_mpi];
-        for (mpi, variant_path) in enum_path.children(move_paths) {
-            trans.kill(mpi);
-            match variant_path.place.projection.last().unwrap() {
-                mir::ProjectionElem::Downcast(_, idx) if *idx == variant => continue,
-                _ => drop_flag_effects::on_all_children_bits(
-                    self.tcx,
-                    self.body,
-                    self.move_data(),
-                    mpi,
-                    |mpi| trans.kill(mpi),
-                ),
-            }
-        }
+        // Kill all move paths that correspond to variants we know to be inactive along this
+        // particular outgoing edge of a `SwitchInt`.
+        drop_flag_effects::on_all_inactive_variants(
+            self.tcx,
+            self.body,
+            self.move_data(),
+            enum_place,
+            variant,
+            |mpi| trans.kill(mpi),
+        );
     }
 }
 
@@ -443,6 +444,30 @@
             },
         );
     }
+
+    fn discriminant_switch_effect(
+        &self,
+        trans: &mut impl GenKill<Self::Idx>,
+        _block: mir::BasicBlock,
+        enum_place: mir::Place<'tcx>,
+        _adt: &ty::AdtDef,
+        variant: VariantIdx,
+    ) {
+        if !self.mark_inactive_variants_as_uninit {
+            return;
+        }
+
+        // Mark all move paths that correspond to variants other than this one as maybe
+        // uninitialized (in reality, they are *definitely* uninitialized).
+        drop_flag_effects::on_all_inactive_variants(
+            self.tcx,
+            self.body,
+            self.move_data(),
+            enum_place,
+            variant,
+            |mpi| trans.gen(mpi),
+        );
+    }
 }
 
 impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
diff --git a/src/librustc_mir/transform/check_consts/mod.rs b/src/librustc_mir/transform/check_consts/mod.rs
index e4aa88e..81c1b0b 100644
--- a/src/librustc_mir/transform/check_consts/mod.rs
+++ b/src/librustc_mir/transform/check_consts/mod.rs
@@ -22,7 +22,7 @@
 pub struct ConstCx<'mir, 'tcx> {
     pub body: &'mir mir::Body<'tcx>,
     pub tcx: TyCtxt<'tcx>,
-    pub def_id: DefId,
+    pub def_id: LocalDefId,
     pub param_env: ty::ParamEnv<'tcx>,
     pub const_kind: Option<hir::ConstContext>,
 }
@@ -40,7 +40,7 @@
         param_env: ty::ParamEnv<'tcx>,
     ) -> Self {
         let const_kind = tcx.hir().body_const_context(def_id);
-        ConstCx { body, tcx, def_id: def_id.to_def_id(), param_env, const_kind }
+        ConstCx { body, tcx, def_id: def_id, param_env, const_kind }
     }
 
     /// Returns the kind of const context this `Item` represents (`const`, `static`, etc.).
diff --git a/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs b/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs
index 1fd907f..55075b3 100644
--- a/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs
+++ b/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs
@@ -29,13 +29,7 @@
         return;
     }
 
-    let ccx = ConstCx {
-        body,
-        tcx,
-        def_id: def_id.to_def_id(),
-        const_kind,
-        param_env: tcx.param_env(def_id),
-    };
+    let ccx = ConstCx { body, tcx, def_id, const_kind, param_env: tcx.param_env(def_id) };
 
     let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() };
 
diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs
index e2893e8..3dddd9c 100644
--- a/src/librustc_mir/transform/check_consts/qualifs.rs
+++ b/src/librustc_mir/transform/check_consts/qualifs.rs
@@ -126,7 +126,7 @@
         // because that component may be part of an enum variant (e.g.,
         // `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be
         // structural-match (`Option::None`).
-        let id = cx.tcx.hir().local_def_id_to_hir_id(cx.def_id.as_local().unwrap());
+        let id = cx.tcx.hir().local_def_id_to_hir_id(cx.def_id);
         traits::search_for_structural_match_violation(id, cx.body.span, cx.tcx, ty).is_some()
     }
 
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index f00fc96..5cb161e 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -56,7 +56,7 @@
             // without breaking stable code?
             MaybeMutBorrowedLocals::mut_borrows_only(tcx, &body, param_env)
                 .unsound_ignore_borrow_on_drop()
-                .into_engine(tcx, &body, def_id)
+                .into_engine(tcx, &body, def_id.to_def_id())
                 .iterate_to_fixpoint()
                 .into_results_cursor(&body)
         });
@@ -83,7 +83,7 @@
             let ConstCx { tcx, body, def_id, .. } = *ccx;
 
             FlowSensitiveAnalysis::new(NeedsDrop, ccx)
-                .into_engine(tcx, &body, def_id)
+                .into_engine(tcx, &body, def_id.to_def_id())
                 .iterate_to_fixpoint()
                 .into_results_cursor(&body)
         });
@@ -110,7 +110,7 @@
             let ConstCx { tcx, body, def_id, .. } = *ccx;
 
             FlowSensitiveAnalysis::new(HasMutInterior, ccx)
-                .into_engine(tcx, &body, def_id)
+                .into_engine(tcx, &body, def_id.to_def_id())
                 .iterate_to_fixpoint()
                 .into_results_cursor(&body)
         });
@@ -153,7 +153,7 @@
 
             hir::ConstContext::Const | hir::ConstContext::Static(_) => {
                 let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx)
-                    .into_engine(ccx.tcx, &ccx.body, ccx.def_id)
+                    .into_engine(ccx.tcx, &ccx.body, ccx.def_id.to_def_id())
                     .iterate_to_fixpoint()
                     .into_results_cursor(&ccx.body);
 
@@ -195,13 +195,13 @@
         let ConstCx { tcx, body, def_id, const_kind, .. } = *self.ccx;
 
         let use_min_const_fn_checks = (const_kind == Some(hir::ConstContext::ConstFn)
-            && crate::const_eval::is_min_const_fn(tcx, def_id))
+            && crate::const_eval::is_min_const_fn(tcx, def_id.to_def_id()))
             && !tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you;
 
         if use_min_const_fn_checks {
             // Enforce `min_const_fn` for stable `const fn`s.
             use crate::transform::qualify_min_const_fn::is_min_const_fn;
-            if let Err((span, err)) = is_min_const_fn(tcx, def_id, &body) {
+            if let Err((span, err)) = is_min_const_fn(tcx, def_id.to_def_id(), &body) {
                 error_min_const_fn_violation(tcx, span, err);
                 return;
             }
@@ -212,10 +212,10 @@
         // Ensure that the end result is `Sync` in a non-thread local `static`.
         let should_check_for_sync = const_kind
             == Some(hir::ConstContext::Static(hir::Mutability::Not))
-            && !tcx.is_thread_local_static(def_id);
+            && !tcx.is_thread_local_static(def_id.to_def_id());
 
         if should_check_for_sync {
-            let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+            let hir_id = tcx.hir().as_local_hir_id(def_id);
             check_return_ty_is_sync(tcx, &body, hir_id);
         }
     }
@@ -535,7 +535,7 @@
                     // `#[allow_internal_unstable]`.
                     use crate::transform::qualify_min_const_fn::lib_feature_allowed;
                     if !self.span.allows_unstable(feature)
-                        && !lib_feature_allowed(self.tcx, self.def_id, feature)
+                        && !lib_feature_allowed(self.tcx, self.def_id.to_def_id(), feature)
                     {
                         self.check_op(ops::FnCallUnstable(def_id, feature));
                     }
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 1704d8b..d3bfd87 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -48,6 +48,7 @@
                 .into_results_cursor(body);
 
             let uninits = MaybeUninitializedPlaces::new(tcx, body, &env)
+                .mark_inactive_variants_as_uninit()
                 .into_engine(tcx, body, def_id)
                 .dead_unwinds(&dead_unwinds)
                 .iterate_to_fixpoint()
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 8ca240d..14c3093 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -203,7 +203,8 @@
 }
 
 fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs {
-    let const_kind = tcx.hir().body_const_context(def_id.expect_local());
+    let def_id = def_id.expect_local();
+    let const_kind = tcx.hir().body_const_context(def_id);
 
     // No need to const-check a non-const `fn`.
     if const_kind.is_none() {
@@ -214,7 +215,7 @@
     // cannot yet be stolen), because `mir_validated()`, which steals
     // from `mir_const(), forces this query to execute before
     // performing the steal.
-    let body = &tcx.mir_const(def_id).borrow();
+    let body = &tcx.mir_const(def_id.to_def_id()).borrow();
 
     if body.return_ty().references_error() {
         tcx.sess.delay_span_bug(body.span, "mir_const_qualif: MIR had errors");
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index bd7ebaa..5aa6722 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -60,15 +60,16 @@
             return;
         }
 
-        let def_id = src.def_id();
+        let def_id = src.def_id().expect_local();
 
         let mut rpo = traversal::reverse_postorder(body);
-        let ccx = ConstCx::new(tcx, def_id.expect_local(), body);
+        let ccx = ConstCx::new(tcx, def_id, body);
         let (temps, all_candidates) = collect_temps_and_candidates(&ccx, &mut rpo);
 
         let promotable_candidates = validate_candidates(&ccx, &temps, &all_candidates);
 
-        let promoted = promote_candidates(def_id, body, tcx, temps, promotable_candidates);
+        let promoted =
+            promote_candidates(def_id.to_def_id(), body, tcx, temps, promotable_candidates);
         self.promoted_fragments.set(promoted);
     }
 }
@@ -724,7 +725,7 @@
             ty::FnDef(def_id, _) => {
                 is_const_fn(self.tcx, def_id)
                     || is_unstable_const_fn(self.tcx, def_id).is_some()
-                    || is_lang_panic_fn(self.tcx, self.def_id)
+                    || is_lang_panic_fn(self.tcx, self.def_id.to_def_id())
             }
             _ => false,
         };
diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs
index 18b92bf..372cb78 100644
--- a/src/librustc_mir_build/hair/pattern/_match.rs
+++ b/src/librustc_mir_build/hair/pattern/_match.rs
@@ -276,6 +276,7 @@
 use self::WitnessPreference::*;
 
 use rustc_data_structures::captures::Captures;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_index::vec::Idx;
 
 use super::{compare_const_vals, PatternFoldable, PatternFolder};
@@ -1246,15 +1247,15 @@
 }
 
 #[derive(Clone, Debug)]
-crate enum Usefulness<'tcx, 'p> {
+crate enum Usefulness<'tcx> {
     /// Carries a list of unreachable subpatterns. Used only in the presence of or-patterns.
-    Useful(Vec<&'p Pat<'tcx>>),
+    Useful(Vec<Span>),
     /// Carries a list of witnesses of non-exhaustiveness.
     UsefulWithWitness(Vec<Witness<'tcx>>),
     NotUseful,
 }
 
-impl<'tcx, 'p> Usefulness<'tcx, 'p> {
+impl<'tcx> Usefulness<'tcx> {
     fn new_useful(preference: WitnessPreference) -> Self {
         match preference {
             ConstructWitness => UsefulWithWitness(vec![Witness(vec![])]),
@@ -1269,7 +1270,7 @@
         }
     }
 
-    fn apply_constructor(
+    fn apply_constructor<'p>(
         self,
         cx: &MatchCheckCtxt<'p, 'tcx>,
         ctor: &Constructor<'tcx>,
@@ -1828,7 +1829,7 @@
     hir_id: HirId,
     is_under_guard: bool,
     is_top_level: bool,
-) -> Usefulness<'tcx, 'p> {
+) -> Usefulness<'tcx> {
     let &Matrix(ref rows) = matrix;
     debug!("is_useful({:#?}, {:#?})", matrix, v);
 
@@ -1852,16 +1853,35 @@
         // We need to push the already-seen patterns into the matrix in order to detect redundant
         // branches like `Some(_) | Some(0)`. We also keep track of the unreachable subpatterns.
         let mut matrix = matrix.clone();
-        let mut unreachable_pats = Vec::new();
+        // `Vec` of all the unreachable branches of the current or-pattern.
+        let mut unreachable_branches = Vec::new();
+        // Subpatterns that are unreachable from all branches. E.g. in the following case, the last
+        // `true` is unreachable only from one branch, so it is overall reachable.
+        // ```
+        // match (true, true) {
+        //     (true, true) => {}
+        //     (false | true, false | true) => {}
+        // }
+        // ```
+        let mut unreachable_subpats = FxHashSet::default();
+        // Whether any branch at all is useful.
         let mut any_is_useful = false;
+
         for v in vs {
             let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false);
             match res {
                 Useful(pats) => {
-                    any_is_useful = true;
-                    unreachable_pats.extend(pats);
+                    if !any_is_useful {
+                        any_is_useful = true;
+                        // Initialize with the first set of unreachable subpatterns encountered.
+                        unreachable_subpats = pats.into_iter().collect();
+                    } else {
+                        // Keep the patterns unreachable from both this and previous branches.
+                        unreachable_subpats =
+                            pats.into_iter().filter(|p| unreachable_subpats.contains(p)).collect();
+                    }
                 }
-                NotUseful => unreachable_pats.push(v.head()),
+                NotUseful => unreachable_branches.push(v.head().span),
                 UsefulWithWitness(_) => {
                     bug!("Encountered or-pat in `v` during exhaustiveness checking")
                 }
@@ -1871,7 +1891,13 @@
                 matrix.push(v);
             }
         }
-        return if any_is_useful { Useful(unreachable_pats) } else { NotUseful };
+        if any_is_useful {
+            // Collect all the unreachable patterns.
+            unreachable_branches.extend(unreachable_subpats);
+            return Useful(unreachable_branches);
+        } else {
+            return NotUseful;
+        }
     }
 
     // FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
@@ -2014,7 +2040,7 @@
     witness_preference: WitnessPreference,
     hir_id: HirId,
     is_under_guard: bool,
-) -> Usefulness<'tcx, 'p> {
+) -> Usefulness<'tcx> {
     debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, ty);
 
     // We cache the result of `Fields::wildcards` because it is used a lot.
diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs
index 6fc447a..2ae20f5 100644
--- a/src/librustc_mir_build/hair/pattern/check_match.rs
+++ b/src/librustc_mir_build/hair/pattern/check_match.rs
@@ -12,6 +12,7 @@
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{HirId, Pat};
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::config::nightly_options;
 use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME;
 use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
 use rustc_session::parse::feature_err;
@@ -392,8 +393,8 @@
                 }
             }
             Useful(unreachable_subpatterns) => {
-                for pat in unreachable_subpatterns {
-                    unreachable_pattern(cx.tcx, pat.span, id, None);
+                for span in unreachable_subpatterns {
+                    unreachable_pattern(cx.tcx, span, id, None);
                 }
             }
             UsefulWithWitness(_) => bug!(),
@@ -487,9 +488,27 @@
     adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
     err.help(
         "ensure that all possible cases are being handled, \
-         possibly by adding wildcards or more match arms",
+              possibly by adding wildcards or more match arms",
     );
     err.note(&format!("the matched value is of type `{}`", scrut_ty));
+    if (scrut_ty == cx.tcx.types.usize || scrut_ty == cx.tcx.types.isize)
+        && !is_empty_match
+        && witnesses.len() == 1
+        && witnesses[0].is_wildcard()
+    {
+        err.note(&format!(
+            "`{}` does not have a fixed maximum value, \
+                so a wildcard `_` is necessary to match exhaustively",
+            scrut_ty,
+        ));
+        if nightly_options::is_nightly_build() {
+            err.help(&format!(
+                "add `#![feature(precise_pointer_size_matching)]` \
+                    to the crate attributes to enable precise `{}` matching",
+                scrut_ty,
+            ));
+        }
+    }
     err.emit();
 }
 
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index acc2a50..92afb7d 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -152,10 +152,14 @@
         arm_target_feature,
         asm,
         assert,
+        assert_inhabited,
+        assert_uninit_valid,
+        assert_zero_valid,
         associated_consts,
         associated_type_bounds,
         associated_type_defaults,
         associated_types,
+        assume,
         assume_init,
         async_await,
         async_closure,
@@ -181,11 +185,14 @@
         box_patterns,
         box_syntax,
         braced_empty_structs,
+        breakpoint,
         bswap,
         bitreverse,
         C,
         caller_location,
         cdylib,
+        ceilf32,
+        ceilf64,
         cfg,
         cfg_accessible,
         cfg_attr,
@@ -239,8 +246,14 @@
         convert,
         Copy,
         copy_closures,
+        copy,
+        copy_nonoverlapping,
+        copysignf32,
+        copysignf64,
         core,
         core_intrinsics,
+        cosf32,
+        cosf64,
         count_code_region,
         coverage_counter_add,
         coverage_counter_subtract,
@@ -299,6 +312,7 @@
         dropck_eyepatch,
         dropck_parametricity,
         drop_types_in_const,
+        drop_in_place,
         dylib,
         dyn_trait,
         eh_personality,
@@ -311,11 +325,16 @@
         Eq,
         Equal,
         enclosing_scope,
+        exact_div,
         except,
         exclusive_range_pattern,
         exhaustive_integer_patterns,
         exhaustive_patterns,
         existential_type,
+        expf32,
+        expf64,
+        exp2f32,
+        exp2f64,
         expected,
         export_name,
         expr,
@@ -329,6 +348,10 @@
         f16c_target_feature,
         f32,
         f64,
+        fadd_fast,
+        fabsf32,
+        fabsf64,
+        fdiv_fast,
         feature,
         ffi_const,
         ffi_pure,
@@ -336,13 +359,21 @@
         field,
         field_init_shorthand,
         file,
+        float_to_int_unchecked,
+        floorf64,
+        floorf32,
+        fmaf32,
+        fmaf64,
         fmt,
         fmt_internals,
+        fmul_fast,
         fn_must_use,
         forbid,
+        forget,
         format_args,
         format_args_nl,
         format_args_capture,
+        frem_fast,
         from,
         From,
         from_desugaring,
@@ -352,6 +383,7 @@
         from_ok,
         from_usize,
         from_trait,
+        fsub_fast,
         fundamental,
         future,
         Future,
@@ -427,6 +459,7 @@
         label_break_value,
         lang,
         lang_items,
+        lazy_normalization_consts,
         lateout,
         let_chains,
         lhs,
@@ -448,6 +481,12 @@
         llvm_asm,
         local_inner_macros,
         log_syntax,
+        logf32,
+        logf64,
+        log10f32,
+        log10f64,
+        log2f32,
+        log2f64,
         loop_break_value,
         macro_at_most_once_rep,
         macro_escape,
@@ -475,10 +514,16 @@
         message,
         meta,
         min_align_of,
+        min_align_of_val,
         min_const_fn,
         min_const_unsafe_fn,
         min_specialization,
+        minnumf32,
+        minnumf64,
+        maxnumf32,
+        maxnumf64,
         mips_target_feature,
+        miri_start_panic,
         mmx_target_feature,
         module,
         module_path,
@@ -491,6 +536,8 @@
         naked,
         naked_functions,
         name,
+        nearbyintf32,
+        nearbyintf64,
         needs_allocator,
         needs_drop,
         needs_panic_runtime,
@@ -518,6 +565,7 @@
         None,
         non_exhaustive,
         non_modrs_mods,
+        nontemporal_store,
         nontrapping_fptoint: "nontrapping-fptoint",
         noreturn,
         no_niche,
@@ -577,8 +625,16 @@
         poll,
         Poll,
         powerpc_target_feature,
+        powf32,
+        powf64,
+        powif32,
+        powif64,
         precise_pointer_size_matching,
         pref_align_of,
+        prefetch_read_data,
+        prefetch_read_instruction,
+        prefetch_write_data,
+        prefetch_write_instruction,
         prelude,
         prelude_import,
         preserves_flags,
@@ -640,10 +696,14 @@
         Result,
         Return,
         rhs,
+        rintf32,
+        rintf64,
         riscv_target_feature,
         rlib,
         rotate_left,
         rotate_right,
+        roundf32,
+        roundf64,
         rt,
         rtm_target_feature,
         rust,
@@ -726,14 +786,19 @@
         simd_ffi,
         simd_insert,
         since,
+        sinf32,
+        sinf64,
         size,
         size_of,
+        size_of_val,
         slice_patterns,
         slicing_syntax,
         soft,
         Some,
         specialization,
         speed,
+        sqrtf32,
+        sqrtf64,
         sse4a_target_feature,
         stable,
         staged_api,
@@ -787,6 +852,8 @@
         transparent_enums,
         transparent_unions,
         trivial_bounds,
+        truncf32,
+        truncf64,
         Try,
         try_blocks,
         try_trait,
@@ -809,6 +876,8 @@
         u32,
         u64,
         u8,
+        unaligned_volatile_load,
+        unaligned_volatile_store,
         unboxed_closures,
         unchecked_add,
         unchecked_div,
@@ -824,6 +893,7 @@
         universal_impl_trait,
         unlikely,
         unmarked_api,
+        unreachable,
         unreachable_code,
         unrestricted_attribute_tokens,
         unsafe_block_in_unsafe_fn,
@@ -843,12 +913,21 @@
         val,
         var,
         variant_count,
+        va_arg,
+        va_copy,
+        va_end,
+        va_start,
         vec,
         Vec,
         version,
         vis,
         visible_private_types,
         volatile,
+        volatile_copy_memory,
+        volatile_copy_nonoverlapping_memory,
+        volatile_load,
+        volatile_set_memory,
+        volatile_store,
         warn,
         wasm_import_module,
         wasm_target_feature,
@@ -858,6 +937,7 @@
         wrapping_add,
         wrapping_sub,
         wrapping_mul,
+        write_bytes,
         Yield,
     }
 }
diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs
index ce478de..b605318 100644
--- a/src/librustc_trait_selection/opaque_types.rs
+++ b/src/librustc_trait_selection/opaque_types.rs
@@ -108,7 +108,7 @@
 pub trait InferCtxtExt<'tcx> {
     fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
         &self,
-        parent_def_id: DefId,
+        parent_def_id: LocalDefId,
         body_id: hir::HirId,
         param_env: ty::ParamEnv<'tcx>,
         value: &T,
@@ -184,7 +184,7 @@
     /// - `value_span` -- the span where the value came from, used in error reporting
     fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
         &self,
-        parent_def_id: DefId,
+        parent_def_id: LocalDefId,
         body_id: hir::HirId,
         param_env: ty::ParamEnv<'tcx>,
         value: &T,
@@ -986,7 +986,7 @@
 
 struct Instantiator<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
-    parent_def_id: DefId,
+    parent_def_id: LocalDefId,
     body_id: hir::HirId,
     param_env: ty::ParamEnv<'tcx>,
     value_span: Span,
@@ -1043,8 +1043,7 @@
                         let parent_def_id = self.parent_def_id;
                         let def_scope_default = || {
                             let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
-                            parent_def_id
-                                == tcx.hir().local_def_id(opaque_parent_hir_id).to_def_id()
+                            parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
                         };
                         let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) {
                             Some(Node::Item(item)) => match item.kind {
@@ -1053,18 +1052,14 @@
                                     impl_trait_fn: Some(parent),
                                     origin,
                                     ..
-                                }) => (parent == self.parent_def_id, origin),
+                                }) => (parent == self.parent_def_id.to_def_id(), origin),
                                 // Named `type Foo = impl Bar;`
                                 hir::ItemKind::OpaqueTy(hir::OpaqueTy {
                                     impl_trait_fn: None,
                                     origin,
                                     ..
                                 }) => (
-                                    may_define_opaque_type(
-                                        tcx,
-                                        self.parent_def_id.expect_local(),
-                                        opaque_hir_id,
-                                    ),
+                                    may_define_opaque_type(tcx, self.parent_def_id, opaque_hir_id),
                                     origin,
                                 ),
                                 _ => (def_scope_default(), hir::OpaqueTyOrigin::Misc),
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 6205088..9b3b4a6 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -5,10 +5,11 @@
 
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_target::spec::abi::Abi;
 
 use std::iter;
@@ -16,14 +17,13 @@
 fn equate_intrinsic_type<'tcx>(
     tcx: TyCtxt<'tcx>,
     it: &hir::ForeignItem<'_>,
+    def_id: DefId,
     n_tps: usize,
     abi: Abi,
     safety: hir::Unsafety,
     inputs: Vec<Ty<'tcx>>,
     output: Ty<'tcx>,
 ) {
-    let def_id = tcx.hir().local_def_id(it.hir_id);
-
     match it.kind {
         hir::ForeignItemKind::Fn(..) => {}
         _ => {
@@ -67,15 +67,43 @@
 }
 
 /// Returns `true` if the given intrinsic is unsafe to call or not.
-pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
+pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
     match intrinsic {
-        "abort" | "size_of" | "min_align_of" | "needs_drop" | "caller_location" | "size_of_val"
-        | "min_align_of_val" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow"
-        | "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add"
-        | "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz"
-        | "bswap" | "bitreverse" | "discriminant_value" | "type_id" | "likely" | "unlikely"
-        | "ptr_guaranteed_eq" | "ptr_guaranteed_ne" | "minnumf32" | "minnumf64" | "maxnumf32"
-        | "maxnumf64" | "type_name" | "variant_count" => hir::Unsafety::Normal,
+        sym::abort
+        | sym::size_of
+        | sym::min_align_of
+        | sym::needs_drop
+        | sym::caller_location
+        | sym::size_of_val
+        | sym::min_align_of_val
+        | sym::add_with_overflow
+        | sym::sub_with_overflow
+        | sym::mul_with_overflow
+        | sym::wrapping_add
+        | sym::wrapping_sub
+        | sym::wrapping_mul
+        | sym::saturating_add
+        | sym::saturating_sub
+        | sym::rotate_left
+        | sym::rotate_right
+        | sym::ctpop
+        | sym::ctlz
+        | sym::cttz
+        | sym::bswap
+        | sym::bitreverse
+        | sym::discriminant_value
+        | sym::type_id
+        | sym::likely
+        | sym::unlikely
+        | sym::ptr_guaranteed_eq
+        | sym::ptr_guaranteed_ne
+        | sym::minnumf32
+        | sym::minnumf64
+        | sym::maxnumf32
+        | sym::rustc_peek
+        | sym::maxnumf64
+        | sym::type_name
+        | sym::variant_count => hir::Unsafety::Normal,
         _ => hir::Unsafety::Unsafe,
     }
 }
@@ -84,7 +112,9 @@
 /// and in libcore/intrinsics.rs
 pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
     let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
-    let name = it.ident.as_str();
+    let def_id = tcx.hir().local_def_id(it.hir_id).to_def_id();
+    let intrinsic_name = tcx.item_name(def_id);
+    let name_str = intrinsic_name.as_str();
 
     let mk_va_list_ty = |mutbl| {
         tcx.lang_items().va_list().map(|did| {
@@ -98,8 +128,8 @@
         })
     };
 
-    let (n_tps, inputs, output, unsafety) = if name.starts_with("atomic_") {
-        let split: Vec<&str> = name.split('_').collect();
+    let (n_tps, inputs, output, unsafety) = if name_str.starts_with("atomic_") {
+        let split: Vec<&str> = name_str.split('_').collect();
         assert!(split.len() >= 2, "Atomic intrinsic in an incorrect format");
 
         //We only care about the operation here
@@ -129,32 +159,30 @@
             }
         };
         (n_tps, inputs, output, hir::Unsafety::Unsafe)
-    } else if &name[..] == "abort" {
-        (0, Vec::new(), tcx.types.never, hir::Unsafety::Normal)
-    } else if &name[..] == "unreachable" {
-        (0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe)
     } else {
-        let unsafety = intrinsic_operation_unsafety(&name[..]);
-        let (n_tps, inputs, output) = match &name[..] {
-            "breakpoint" => (0, Vec::new(), tcx.mk_unit()),
-            "size_of" | "pref_align_of" | "min_align_of" | "variant_count" => {
+        let unsafety = intrinsic_operation_unsafety(intrinsic_name);
+        let (n_tps, inputs, output) = match intrinsic_name {
+            sym::abort => (0, Vec::new(), tcx.types.never),
+            sym::unreachable => (0, Vec::new(), tcx.types.never),
+            sym::breakpoint => (0, Vec::new(), tcx.mk_unit()),
+            sym::size_of | sym::pref_align_of | sym::min_align_of | sym::variant_count => {
                 (1, Vec::new(), tcx.types.usize)
             }
-            "size_of_val" | "min_align_of_val" => {
+            sym::size_of_val | sym::min_align_of_val => {
                 (1, vec![tcx.mk_imm_ptr(param(0))], tcx.types.usize)
             }
-            "rustc_peek" => (1, vec![param(0)], param(0)),
-            "caller_location" => (0, vec![], tcx.caller_location_ty()),
-            "assert_inhabited" | "assert_zero_valid" | "assert_uninit_valid" => {
+            sym::rustc_peek => (1, vec![param(0)], param(0)),
+            sym::caller_location => (0, vec![], tcx.caller_location_ty()),
+            sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => {
                 (1, Vec::new(), tcx.mk_unit())
             }
-            "forget" => (1, vec![param(0)], tcx.mk_unit()),
-            "transmute" => (2, vec![param(0)], param(1)),
-            "move_val_init" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
-            "prefetch_read_data"
-            | "prefetch_write_data"
-            | "prefetch_read_instruction"
-            | "prefetch_write_instruction" => (
+            sym::forget => (1, vec![param(0)], tcx.mk_unit()),
+            sym::transmute => (2, vec![param(0)], param(1)),
+            sym::move_val_init => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
+            sym::prefetch_read_data
+            | sym::prefetch_write_data
+            | sym::prefetch_read_instruction
+            | sym::prefetch_write_instruction => (
                 1,
                 vec![
                     tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
@@ -162,12 +190,12 @@
                 ],
                 tcx.mk_unit(),
             ),
-            "drop_in_place" => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()),
-            "needs_drop" => (1, Vec::new(), tcx.types.bool),
+            sym::drop_in_place => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()),
+            sym::needs_drop => (1, Vec::new(), tcx.types.bool),
 
-            "type_name" => (1, Vec::new(), tcx.mk_static_str()),
-            "type_id" => (1, Vec::new(), tcx.types.u64),
-            "offset" | "arith_offset" => (
+            sym::type_name => (1, Vec::new(), tcx.mk_static_str()),
+            sym::type_id => (1, Vec::new(), tcx.types.u64),
+            sym::offset | sym::arith_offset => (
                 1,
                 vec![
                     tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
@@ -175,7 +203,7 @@
                 ],
                 tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
             ),
-            "copy" | "copy_nonoverlapping" => (
+            sym::copy | sym::copy_nonoverlapping => (
                 1,
                 vec![
                     tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
@@ -184,7 +212,7 @@
                 ],
                 tcx.mk_unit(),
             ),
-            "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => (
+            sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => (
                 1,
                 vec![
                     tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
@@ -193,7 +221,7 @@
                 ],
                 tcx.mk_unit(),
             ),
-            "write_bytes" | "volatile_set_memory" => (
+            sym::write_bytes | sym::volatile_set_memory => (
                 1,
                 vec![
                     tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
@@ -202,93 +230,98 @@
                 ],
                 tcx.mk_unit(),
             ),
-            "sqrtf32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "sqrtf64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "powif32" => (0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32),
-            "powif64" => (0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64),
-            "sinf32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "sinf64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "cosf32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "cosf64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "powf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
-            "powf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
-            "expf32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "expf64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "exp2f32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "exp2f64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "logf32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "logf64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "log10f32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "log10f64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "log2f32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "log2f64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "fmaf32" => (0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32),
-            "fmaf64" => (0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64),
-            "fabsf32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "fabsf64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "minnumf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
-            "minnumf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
-            "maxnumf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
-            "maxnumf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
-            "copysignf32" => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
-            "copysignf64" => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
-            "floorf32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "floorf64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "ceilf32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "ceilf64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "truncf32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "truncf64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "rintf32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "rintf64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "nearbyintf32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "nearbyintf64" => (0, vec![tcx.types.f64], tcx.types.f64),
-            "roundf32" => (0, vec![tcx.types.f32], tcx.types.f32),
-            "roundf64" => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::sqrtf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::sqrtf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::powif32 => (0, vec![tcx.types.f32, tcx.types.i32], tcx.types.f32),
+            sym::powif64 => (0, vec![tcx.types.f64, tcx.types.i32], tcx.types.f64),
+            sym::sinf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::sinf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::cosf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::cosf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::powf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
+            sym::powf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
+            sym::expf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::expf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::exp2f32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::exp2f64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::logf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::logf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::log10f32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::log10f64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::log2f32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::log2f64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::fmaf32 => (0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32),
+            sym::fmaf64 => (0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64),
+            sym::fabsf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::fabsf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::minnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
+            sym::minnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
+            sym::maxnumf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
+            sym::maxnumf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
+            sym::copysignf32 => (0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
+            sym::copysignf64 => (0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
+            sym::floorf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::floorf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::ceilf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::ceilf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::truncf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::truncf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::rintf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::rintf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::nearbyintf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::nearbyintf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+            sym::roundf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+            sym::roundf64 => (0, vec![tcx.types.f64], tcx.types.f64),
 
-            "volatile_load" | "unaligned_volatile_load" => {
+            sym::volatile_load | sym::unaligned_volatile_load => {
                 (1, vec![tcx.mk_imm_ptr(param(0))], param(0))
             }
-            "volatile_store" | "unaligned_volatile_store" => {
+            sym::volatile_store | sym::unaligned_volatile_store => {
                 (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit())
             }
 
-            "ctpop" | "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "bswap"
-            | "bitreverse" => (1, vec![param(0)], param(0)),
+            sym::ctpop
+            | sym::ctlz
+            | sym::ctlz_nonzero
+            | sym::cttz
+            | sym::cttz_nonzero
+            | sym::bswap
+            | sym::bitreverse => (1, vec![param(0)], param(0)),
 
-            "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => {
+            sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
                 (1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool]))
             }
 
-            "ptr_guaranteed_eq" | "ptr_guaranteed_ne" => {
+            sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
                 (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.bool)
             }
 
-            "ptr_offset_from" => {
+            sym::ptr_offset_from => {
                 (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize)
             }
-            "unchecked_div" | "unchecked_rem" | "exact_div" => {
+            sym::unchecked_div | sym::unchecked_rem | sym::exact_div => {
                 (1, vec![param(0), param(0)], param(0))
             }
-            "unchecked_shl" | "unchecked_shr" | "rotate_left" | "rotate_right" => {
+            sym::unchecked_shl | sym::unchecked_shr | sym::rotate_left | sym::rotate_right => {
                 (1, vec![param(0), param(0)], param(0))
             }
-            "unchecked_add" | "unchecked_sub" | "unchecked_mul" => {
+            sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => {
                 (1, vec![param(0), param(0)], param(0))
             }
-            "wrapping_add" | "wrapping_sub" | "wrapping_mul" => {
+            sym::wrapping_add | sym::wrapping_sub | sym::wrapping_mul => {
                 (1, vec![param(0), param(0)], param(0))
             }
-            "saturating_add" | "saturating_sub" => (1, vec![param(0), param(0)], param(0)),
-            "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
+            sym::saturating_add | sym::saturating_sub => (1, vec![param(0), param(0)], param(0)),
+            sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => {
                 (1, vec![param(0), param(0)], param(0))
             }
-            "float_to_int_unchecked" => (2, vec![param(0)], param(1)),
+            sym::float_to_int_unchecked => (2, vec![param(0)], param(1)),
 
-            "assume" => (0, vec![tcx.types.bool], tcx.mk_unit()),
-            "likely" => (0, vec![tcx.types.bool], tcx.types.bool),
-            "unlikely" => (0, vec![tcx.types.bool], tcx.types.bool),
+            sym::assume => (0, vec![tcx.types.bool], tcx.mk_unit()),
+            sym::likely => (0, vec![tcx.types.bool], tcx.types.bool),
+            sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool),
 
-            "discriminant_value" => {
+            sym::discriminant_value => {
                 let assoc_items =
                     tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap());
                 let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id;
@@ -303,7 +336,7 @@
                 )
             }
 
-            "try" => {
+            kw::Try => {
                 let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
                 let try_fn_ty = ty::Binder::bind(tcx.mk_fn_sig(
                     iter::once(mut_u8),
@@ -326,12 +359,12 @@
                 )
             }
 
-            "va_start" | "va_end" => match mk_va_list_ty(hir::Mutability::Mut) {
+            sym::va_start | sym::va_end => match mk_va_list_ty(hir::Mutability::Mut) {
                 Some((va_list_ref_ty, _)) => (0, vec![va_list_ref_ty], tcx.mk_unit()),
                 None => bug!("`va_list` language item needed for C-variadic intrinsics"),
             },
 
-            "va_copy" => match mk_va_list_ty(hir::Mutability::Not) {
+            sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) {
                 Some((va_list_ref_ty, va_list_ty)) => {
                     let va_list_ptr_ty = tcx.mk_mut_ptr(va_list_ty);
                     (0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.mk_unit())
@@ -339,38 +372,38 @@
                 None => bug!("`va_list` language item needed for C-variadic intrinsics"),
             },
 
-            "va_arg" => match mk_va_list_ty(hir::Mutability::Mut) {
+            sym::va_arg => match mk_va_list_ty(hir::Mutability::Mut) {
                 Some((va_list_ref_ty, _)) => (1, vec![va_list_ref_ty], param(0)),
                 None => bug!("`va_list` language item needed for C-variadic intrinsics"),
             },
 
-            "nontemporal_store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
+            sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
 
-            "miri_start_panic" => {
+            sym::miri_start_panic => {
                 // FIXME - the relevant types aren't lang items,
                 // so it's not trivial to check this
                 return;
             }
 
-            "count_code_region" => {
+            sym::count_code_region => {
                 (0, vec![tcx.types.u32, tcx.types.u32, tcx.types.u32], tcx.mk_unit())
             }
 
-            "coverage_counter_add" | "coverage_counter_subtract" => (
+            sym::coverage_counter_add | sym::coverage_counter_subtract => (
                 0,
                 vec![tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32, tcx.types.u32],
                 tcx.mk_unit(),
             ),
 
-            "coverage_unreachable" => (0, vec![tcx.types.u32, tcx.types.u32], tcx.mk_unit()),
+            sym::coverage_unreachable => (0, vec![tcx.types.u32, tcx.types.u32], tcx.mk_unit()),
 
-            ref other => {
+            other => {
                 struct_span_err!(
                     tcx.sess,
                     it.span,
                     E0093,
                     "unrecognized intrinsic function: `{}`",
-                    *other
+                    other,
                 )
                 .span_label(it.span, "unrecognized intrinsic")
                 .emit();
@@ -379,7 +412,7 @@
         };
         (n_tps, inputs, output, unsafety)
     };
-    equate_intrinsic_type(tcx, it, n_tps, Abi::RustIntrinsic, unsafety, inputs, output)
+    equate_intrinsic_type(tcx, it, def_id, n_tps, Abi::RustIntrinsic, unsafety, inputs, output)
 }
 
 /// Type-check `extern "platform-intrinsic" { ... }` functions.
@@ -389,6 +422,7 @@
         tcx.mk_ty_param(n, name)
     };
 
+    let def_id = tcx.hir().local_def_id(it.hir_id).to_def_id();
     let name = it.ident.as_str();
 
     let (n_tps, inputs, output) = match &*name {
@@ -463,6 +497,7 @@
     equate_intrinsic_type(
         tcx,
         it,
+        def_id,
         n_tps,
         Abi::PlatformIntrinsic,
         hir::Unsafety::Unsafe,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 58fd0f9..e564b01 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1321,8 +1321,8 @@
         fcx.resume_yield_tys = Some((resume_ty, yield_ty));
     }
 
-    let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id).to_def_id());
-    let outer_hir_id = hir.as_local_hir_id(outer_def_id.expect_local());
+    let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id).to_def_id()).expect_local();
+    let outer_hir_id = hir.as_local_hir_id(outer_def_id);
     GatherLocalsVisitor { fcx: &fcx, parent_id: outer_hir_id }.visit_body(body);
 
     // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
@@ -3427,7 +3427,7 @@
 
         let (value, opaque_type_map) =
             self.register_infer_ok_obligations(self.instantiate_opaque_types(
-                parent_def_id.to_def_id(),
+                parent_def_id,
                 self.body_id,
                 self.param_env,
                 value,
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 8920203e..cc491c5 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -2063,7 +2063,7 @@
     ident: Ident,
 ) -> ty::PolyFnSig<'tcx> {
     let unsafety = if abi == abi::Abi::RustIntrinsic {
-        intrinsic_operation_unsafety(&tcx.item_name(def_id).as_str())
+        intrinsic_operation_unsafety(tcx.item_name(def_id))
     } else {
         hir::Unsafety::Unsafe
     };
diff --git a/src/test/mir-opt/no-drop-for-inactive-variant/rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/no-drop-for-inactive-variant/rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir
index ce987a5..2e8cfae 100644
--- a/src/test/mir-opt/no-drop-for-inactive-variant/rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/no-drop-for-inactive-variant/rustc.unwrap.SimplifyCfg-elaborate-drops.after.mir
@@ -8,22 +8,19 @@
     let mut _4: !;                       // in scope 0 at $SRC_DIR/libstd/macros.rs:LL:COL
     let mut _5: isize;                   // in scope 0 at $DIR/no-drop-for-inactive-variant.rs:12:1: 12:2
     let mut _6: isize;                   // in scope 0 at $DIR/no-drop-for-inactive-variant.rs:12:1: 12:2
+    let mut _7: isize;                   // in scope 0 at $DIR/no-drop-for-inactive-variant.rs:12:1: 12:2
     scope 1 {
         debug x => _3;                   // in scope 1 at $DIR/no-drop-for-inactive-variant.rs:9:14: 9:15
     }
 
     bb0: {
         _2 = discriminant(_1);           // scope 0 at $DIR/no-drop-for-inactive-variant.rs:9:9: 9:16
-        switchInt(move _2) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/no-drop-for-inactive-variant.rs:9:9: 9:16
+        switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/no-drop-for-inactive-variant.rs:9:9: 9:16
     }
 
-    bb1 (cleanup): {
-        resume;                          // scope 0 at $DIR/no-drop-for-inactive-variant.rs:7:1: 12:2
-    }
-
-    bb2: {
+    bb1: {
         StorageLive(_4);                 // scope 0 at $SRC_DIR/libstd/macros.rs:LL:COL
-        const std::rt::begin_panic::<&str>(const "explicit panic") -> bb5; // scope 0 at $SRC_DIR/libstd/macros.rs:LL:COL
+        const std::rt::begin_panic::<&str>(const "explicit panic") -> bb4; // scope 0 at $SRC_DIR/libstd/macros.rs:LL:COL
                                          // ty::Const
                                          // + ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}
                                          // + val: Value(Scalar(<ZST>))
@@ -38,20 +35,21 @@
                                          // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, size: Size { raw: 14 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) }
     }
 
-    bb3: {
+    bb2: {
         unreachable;                     // scope 0 at $DIR/no-drop-for-inactive-variant.rs:8:11: 8:14
     }
 
-    bb4: {
+    bb3: {
         StorageLive(_3);                 // scope 0 at $DIR/no-drop-for-inactive-variant.rs:9:14: 9:15
         _3 = move ((_1 as Some).0: T);   // scope 0 at $DIR/no-drop-for-inactive-variant.rs:9:14: 9:15
         _0 = move _3;                    // scope 1 at $DIR/no-drop-for-inactive-variant.rs:9:20: 9:21
         StorageDead(_3);                 // scope 0 at $DIR/no-drop-for-inactive-variant.rs:9:21: 9:22
-        _5 = discriminant(_1);           // scope 0 at $DIR/no-drop-for-inactive-variant.rs:12:1: 12:2
+        _6 = discriminant(_1);           // scope 0 at $DIR/no-drop-for-inactive-variant.rs:12:1: 12:2
         return;                          // scope 0 at $DIR/no-drop-for-inactive-variant.rs:12:2: 12:2
     }
 
-    bb5 (cleanup): {
-        drop(_1) -> bb1;                 // scope 0 at $DIR/no-drop-for-inactive-variant.rs:12:1: 12:2
+    bb4 (cleanup): {
+        _5 = discriminant(_1);           // scope 0 at $DIR/no-drop-for-inactive-variant.rs:12:1: 12:2
+        resume;                          // scope 0 at $DIR/no-drop-for-inactive-variant.rs:7:1: 12:2
     }
 }
diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/32bit/rustc.map.SimplifyLocals.diff b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/32bit/rustc.map.SimplifyLocals.diff
index 551f6db..440c5f8 100644
--- a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/32bit/rustc.map.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/32bit/rustc.map.SimplifyLocals.diff
@@ -7,13 +7,28 @@
       let mut _2: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
 -     let _3: std::boxed::Box<()>;         // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15
 -     let mut _4: std::boxed::Box<()>;     // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:25: 4:26
--     let mut _5: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
+-     let mut _5: bool;                    // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
 -     let mut _6: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
+-     let mut _7: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
       scope 1 {
           debug x => ((_0 as Some).0: std::boxed::Box<()>); // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15
       }
   
       bb0: {
+-         _5 = const false;                // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
+-                                          // ty::Const
+-                                          // + ty: bool
+-                                          // + val: Value(Scalar(0x00))
+-                                          // mir::Constant
+-                                          // + span: $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
+-                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+-         _5 = const true;                 // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
+-                                          // ty::Const
+-                                          // + ty: bool
+-                                          // + val: Value(Scalar(0x01))
+-                                          // mir::Constant
+-                                          // + span: $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
+-                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
           _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
           switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
       }
@@ -35,7 +50,7 @@
       }
   
       bb3: {
--         _5 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
+-         _6 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
           return;                          // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:2: 6:2
       }
   }
diff --git a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/64bit/rustc.map.SimplifyLocals.diff b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/64bit/rustc.map.SimplifyLocals.diff
index 388b382..c12d171 100644
--- a/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/64bit/rustc.map.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify-locals-removes-unused-discriminant-reads/64bit/rustc.map.SimplifyLocals.diff
@@ -7,13 +7,28 @@
       let mut _2: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
 -     let _3: std::boxed::Box<()>;         // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15
 -     let mut _4: std::boxed::Box<()>;     // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:25: 4:26
--     let mut _5: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
+-     let mut _5: bool;                    // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
 -     let mut _6: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
+-     let mut _7: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
       scope 1 {
           debug x => ((_0 as Some).0: std::boxed::Box<()>); // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15
       }
   
       bb0: {
+-         _5 = const false;                // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
+-                                          // ty::Const
+-                                          // + ty: bool
+-                                          // + val: Value(Scalar(0x00))
+-                                          // mir::Constant
+-                                          // + span: $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
+-                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+-         _5 = const true;                 // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
+-                                          // ty::Const
+-                                          // + ty: bool
+-                                          // + val: Value(Scalar(0x01))
+-                                          // mir::Constant
+-                                          // + span: $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
+-                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
           _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
           switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13
       }
@@ -35,7 +50,7 @@
       }
   
       bb3: {
--         _5 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
+-         _6 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2
           return;                          // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:2: 6:2
       }
   }
diff --git a/src/test/ui/const-generics/lazy-normalization/issue-71986.rs b/src/test/ui/const-generics/issue-71986.rs
similarity index 100%
rename from src/test/ui/const-generics/lazy-normalization/issue-71986.rs
rename to src/test/ui/const-generics/issue-71986.rs
diff --git a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
index 6c5d009..c7a63e5 100644
--- a/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
+++ b/src/test/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
@@ -6,6 +6,8 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `usize`
+   = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
 
 error[E0004]: non-exhaustive patterns: `_` not covered
   --> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11
@@ -15,6 +17,8 @@
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `isize`
+   = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/auxiliary/reexported-trait.rs b/src/test/ui/issues/auxiliary/reexported-trait.rs
new file mode 100644
index 0000000..51a991b
--- /dev/null
+++ b/src/test/ui/issues/auxiliary/reexported-trait.rs
@@ -0,0 +1,17 @@
+mod private {
+    pub trait Trait {
+        fn trait_method(&self) {
+        }
+    }
+    pub trait TraitB {
+        fn trait_method_b(&self) {
+        }
+    }
+}
+
+pub struct FooStruct;
+pub use crate::private::Trait;
+impl crate::private::Trait for FooStruct {}
+
+pub use crate::private::TraitB as TraitBRename;
+impl crate::private::TraitB for FooStruct {}
diff --git a/src/test/ui/issues/issue-56175.rs b/src/test/ui/issues/issue-56175.rs
new file mode 100644
index 0000000..ca1d0d4
--- /dev/null
+++ b/src/test/ui/issues/issue-56175.rs
@@ -0,0 +1,9 @@
+// edition:2018
+// aux-crate:reexported_trait=reexported-trait.rs
+
+fn main() {
+    reexported_trait::FooStruct.trait_method();
+    //~^ ERROR
+    reexported_trait::FooStruct.trait_method_b();
+    //~^ ERROR
+}
diff --git a/src/test/ui/issues/issue-56175.stderr b/src/test/ui/issues/issue-56175.stderr
new file mode 100644
index 0000000..c0799db
--- /dev/null
+++ b/src/test/ui/issues/issue-56175.stderr
@@ -0,0 +1,27 @@
+error[E0599]: no method named `trait_method` found for struct `reexported_trait::FooStruct` in the current scope
+  --> $DIR/issue-56175.rs:5:33
+   |
+LL |     reexported_trait::FooStruct.trait_method();
+   |                                 ^^^^^^^^^^^^ method not found in `reexported_trait::FooStruct`
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL | use reexported_trait::Trait;
+   |
+
+error[E0599]: no method named `trait_method_b` found for struct `reexported_trait::FooStruct` in the current scope
+  --> $DIR/issue-56175.rs:7:33
+   |
+LL |     reexported_trait::FooStruct.trait_method_b();
+   |                                 ^^^^^^^^^^^^^^ method not found in `reexported_trait::FooStruct`
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL | use reexported_trait::TraitBRename;
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs
new file mode 100644
index 0000000..44cb748
--- /dev/null
+++ b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs
@@ -0,0 +1,10 @@
+pub const fn sof<T>() -> usize {
+    10
+}
+
+fn test<T>() {
+    let _: [u8; sof::<T>()];
+    //~^ ERROR the size for values of type `T`
+}
+
+fn main() {}
diff --git a/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr
new file mode 100644
index 0000000..6e19251
--- /dev/null
+++ b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/feature-gate-lazy_normalization_consts.rs:6:23
+   |
+LL | pub const fn sof<T>() -> usize {
+   |                  - required by this bound in `sof`
+...
+LL | fn test<T>() {
+   |         - this type parameter needs to be `std::marker::Sized`
+LL |     let _: [u8; sof::<T>()];
+   |                       ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | pub const fn sof<T: ?Sized>() -> usize {
+   |                   ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/lazy_normalization_consts/issue-47814.rs b/src/test/ui/lazy_normalization_consts/issue-47814.rs
new file mode 100644
index 0000000..1fd0c45
--- /dev/null
+++ b/src/test/ui/lazy_normalization_consts/issue-47814.rs
@@ -0,0 +1,16 @@
+// check-pass
+#![feature(lazy_normalization_consts)]
+#![allow(incomplete_features)]
+pub struct ArpIPv4<'a> {
+    _s: &'a u8
+}
+
+impl<'a> ArpIPv4<'a> {
+    const LENGTH: usize = 20;
+
+    pub fn to_buffer() -> [u8; Self::LENGTH] {
+        unimplemented!()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lazy_normalization_consts/issue-57739.rs b/src/test/ui/lazy_normalization_consts/issue-57739.rs
new file mode 100644
index 0000000..4607f3e
--- /dev/null
+++ b/src/test/ui/lazy_normalization_consts/issue-57739.rs
@@ -0,0 +1,17 @@
+#![feature(lazy_normalization_consts)]
+//~^ WARN the feature `lazy_normalization_consts` is incomplete
+trait ArraySizeTrait {
+    const SIZE: usize = 0;
+}
+
+impl<T: ?Sized> ArraySizeTrait for T {
+    const SIZE: usize = 1;
+}
+
+struct SomeArray<T: ArraySizeTrait> {
+    array: [u8; T::SIZE],
+    //~^ ERROR constant expression depends on a generic parameter
+    phantom: std::marker::PhantomData<T>,
+}
+
+fn main() {}
diff --git a/src/test/ui/lazy_normalization_consts/issue-57739.stderr b/src/test/ui/lazy_normalization_consts/issue-57739.stderr
new file mode 100644
index 0000000..1987f58
--- /dev/null
+++ b/src/test/ui/lazy_normalization_consts/issue-57739.stderr
@@ -0,0 +1,19 @@
+warning: the feature `lazy_normalization_consts` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-57739.rs:1:12
+   |
+LL | #![feature(lazy_normalization_consts)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #72219 <https://github.com/rust-lang/rust/issues/72219> for more information
+
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-57739.rs:12:5
+   |
+LL |     array: [u8; T::SIZE],
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/src/test/ui/lazy_normalization_consts/issue-73980.rs b/src/test/ui/lazy_normalization_consts/issue-73980.rs
new file mode 100644
index 0000000..339b22c
--- /dev/null
+++ b/src/test/ui/lazy_normalization_consts/issue-73980.rs
@@ -0,0 +1,14 @@
+// check-pass
+#![feature(lazy_normalization_consts)]
+#![allow(incomplete_features)]
+
+pub struct X<P, Q>(P, Q);
+pub struct L<T: ?Sized>(T);
+
+impl<T: ?Sized> L<T> {
+    const S: usize = 1;
+}
+
+impl<T> X<T, [u8; L::<T>::S]> {}
+
+fn main() {}
diff --git a/src/test/ui/mir-dataflow/def-inits-1.rs b/src/test/ui/mir-dataflow/def-inits-1.rs
index 91d41e9..3046082 100644
--- a/src/test/ui/mir-dataflow/def-inits-1.rs
+++ b/src/test/ui/mir-dataflow/def-inits-1.rs
@@ -11,13 +11,13 @@
 fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
     let ret;
     // `ret` starts off uninitialized
-    unsafe { rustc_peek(&ret); }  //~ ERROR rustc_peek: bit not set
+    rustc_peek(&ret);  //~ ERROR rustc_peek: bit not set
 
     // All function formal parameters start off initialized.
 
-    unsafe { rustc_peek(&x) };
-    unsafe { rustc_peek(&y) };
-    unsafe { rustc_peek(&z) };
+    rustc_peek(&x);
+    rustc_peek(&y);
+    rustc_peek(&z);
 
     ret = if test {
         ::std::mem::replace(x, y)
@@ -27,21 +27,21 @@
     };
 
     // `z` may be uninitialized here.
-    unsafe { rustc_peek(&z); } //~ ERROR rustc_peek: bit not set
+    rustc_peek(&z); //~ ERROR rustc_peek: bit not set
 
     // `y` is definitely uninitialized here.
-    unsafe { rustc_peek(&y); } //~ ERROR rustc_peek: bit not set
+    rustc_peek(&y); //~ ERROR rustc_peek: bit not set
 
     // `x` is still (definitely) initialized (replace above is a reborrow).
-    unsafe { rustc_peek(&x); }
+    rustc_peek(&x);
 
     ::std::mem::drop(x);
 
     // `x` is *definitely* uninitialized here
-    unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set
+    rustc_peek(&x); //~ ERROR rustc_peek: bit not set
 
     // `ret` is now definitely initialized (via `if` above).
-    unsafe { rustc_peek(&ret); }
+    rustc_peek(&ret);
 
     ret
 }
diff --git a/src/test/ui/mir-dataflow/def-inits-1.stderr b/src/test/ui/mir-dataflow/def-inits-1.stderr
index 48d8450..e2bddb5 100644
--- a/src/test/ui/mir-dataflow/def-inits-1.stderr
+++ b/src/test/ui/mir-dataflow/def-inits-1.stderr
@@ -1,26 +1,26 @@
 error: rustc_peek: bit not set
-  --> $DIR/def-inits-1.rs:14:14
+  --> $DIR/def-inits-1.rs:14:5
    |
-LL |     unsafe { rustc_peek(&ret); }
-   |              ^^^^^^^^^^^^^^^^
+LL |     rustc_peek(&ret);
+   |     ^^^^^^^^^^^^^^^^
 
 error: rustc_peek: bit not set
-  --> $DIR/def-inits-1.rs:30:14
+  --> $DIR/def-inits-1.rs:30:5
    |
-LL |     unsafe { rustc_peek(&z); }
-   |              ^^^^^^^^^^^^^^
+LL |     rustc_peek(&z);
+   |     ^^^^^^^^^^^^^^
 
 error: rustc_peek: bit not set
-  --> $DIR/def-inits-1.rs:33:14
+  --> $DIR/def-inits-1.rs:33:5
    |
-LL |     unsafe { rustc_peek(&y); }
-   |              ^^^^^^^^^^^^^^
+LL |     rustc_peek(&y);
+   |     ^^^^^^^^^^^^^^
 
 error: rustc_peek: bit not set
-  --> $DIR/def-inits-1.rs:41:14
+  --> $DIR/def-inits-1.rs:41:5
    |
-LL |     unsafe { rustc_peek(&x); }
-   |              ^^^^^^^^^^^^^^
+LL |     rustc_peek(&x);
+   |     ^^^^^^^^^^^^^^
 
 error: stop_after_dataflow ended compilation
 
diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs b/src/test/ui/mir-dataflow/indirect-mutation-offset.rs
index caa307e..374a9f7 100644
--- a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs
+++ b/src/test/ui/mir-dataflow/indirect-mutation-offset.rs
@@ -38,7 +38,7 @@
 
     *rmut_cell = 42;  // Mutates `x` indirectly even though `x` is not marked indirectly mutable!!!
     let val = *rmut_cell;
-    unsafe { rustc_peek(x) }; //~ ERROR rustc_peek: bit not set
+    rustc_peek(x); //~ ERROR rustc_peek: bit not set
 
     val
 };
diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr b/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr
index 8d3548ec..1d5287c 100644
--- a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr
+++ b/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr
@@ -1,8 +1,8 @@
 error: rustc_peek: bit not set
-  --> $DIR/indirect-mutation-offset.rs:41:14
+  --> $DIR/indirect-mutation-offset.rs:41:5
    |
-LL |     unsafe { rustc_peek(x) };
-   |              ^^^^^^^^^^^^^
+LL |     rustc_peek(x);
+   |     ^^^^^^^^^^^^^
 
 error: stop_after_dataflow ended compilation
 
diff --git a/src/test/ui/mir-dataflow/inits-1.rs b/src/test/ui/mir-dataflow/inits-1.rs
index 4a4786a..8fb1d4b 100644
--- a/src/test/ui/mir-dataflow/inits-1.rs
+++ b/src/test/ui/mir-dataflow/inits-1.rs
@@ -11,13 +11,13 @@
 fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
     let ret;
     // `ret` starts off uninitialized, so we get an error report here.
-    unsafe { rustc_peek(&ret); }  //~ ERROR rustc_peek: bit not set
+    rustc_peek(&ret);  //~ ERROR rustc_peek: bit not set
 
     // All function formal parameters start off initialized.
 
-    unsafe { rustc_peek(&x) };
-    unsafe { rustc_peek(&y) };
-    unsafe { rustc_peek(&z) };
+    rustc_peek(&x);
+    rustc_peek(&y);
+    rustc_peek(&z);
 
     ret = if test {
         ::std::mem::replace(x, y)
@@ -28,21 +28,21 @@
 
 
     // `z` may be initialized here.
-    unsafe { rustc_peek(&z); }
+    rustc_peek(&z);
 
     // `y` is definitely uninitialized here.
-    unsafe { rustc_peek(&y); }  //~ ERROR rustc_peek: bit not set
+    rustc_peek(&y);  //~ ERROR rustc_peek: bit not set
 
     // `x` is still (definitely) initialized (replace above is a reborrow).
-    unsafe { rustc_peek(&x); }
+    rustc_peek(&x);
 
     ::std::mem::drop(x);
 
     // `x` is *definitely* uninitialized here
-    unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set
+    rustc_peek(&x); //~ ERROR rustc_peek: bit not set
 
     // `ret` is now definitely initialized (via `if` above).
-    unsafe { rustc_peek(&ret); }
+    rustc_peek(&ret);
 
     ret
 }
diff --git a/src/test/ui/mir-dataflow/inits-1.stderr b/src/test/ui/mir-dataflow/inits-1.stderr
index 23d0679..7a00a70 100644
--- a/src/test/ui/mir-dataflow/inits-1.stderr
+++ b/src/test/ui/mir-dataflow/inits-1.stderr
@@ -1,20 +1,20 @@
 error: rustc_peek: bit not set
-  --> $DIR/inits-1.rs:14:14
+  --> $DIR/inits-1.rs:14:5
    |
-LL |     unsafe { rustc_peek(&ret); }
-   |              ^^^^^^^^^^^^^^^^
+LL |     rustc_peek(&ret);
+   |     ^^^^^^^^^^^^^^^^
 
 error: rustc_peek: bit not set
-  --> $DIR/inits-1.rs:34:14
+  --> $DIR/inits-1.rs:34:5
    |
-LL |     unsafe { rustc_peek(&y); }
-   |              ^^^^^^^^^^^^^^
+LL |     rustc_peek(&y);
+   |     ^^^^^^^^^^^^^^
 
 error: rustc_peek: bit not set
-  --> $DIR/inits-1.rs:42:14
+  --> $DIR/inits-1.rs:42:5
    |
-LL |     unsafe { rustc_peek(&x); }
-   |              ^^^^^^^^^^^^^^
+LL |     rustc_peek(&x);
+   |     ^^^^^^^^^^^^^^
 
 error: stop_after_dataflow ended compilation
 
diff --git a/src/test/ui/mir-dataflow/liveness-ptr.rs b/src/test/ui/mir-dataflow/liveness-ptr.rs
index 34097d7..786da52 100644
--- a/src/test/ui/mir-dataflow/liveness-ptr.rs
+++ b/src/test/ui/mir-dataflow/liveness-ptr.rs
@@ -10,17 +10,17 @@
     x = 0;
 
     // `x` is live here since it is used in the next statement...
-    unsafe { rustc_peek(x); }
+    rustc_peek(x);
 
     p = &x;
 
     // ... but not here, even while it can be accessed through `p`.
-    unsafe { rustc_peek(x); } //~ ERROR rustc_peek: bit not set
+    rustc_peek(x); //~ ERROR rustc_peek: bit not set
     let tmp = unsafe { *p };
 
     x = tmp + 1;
 
-    unsafe { rustc_peek(x); }
+    rustc_peek(x);
 
     x
 }
diff --git a/src/test/ui/mir-dataflow/liveness-ptr.stderr b/src/test/ui/mir-dataflow/liveness-ptr.stderr
index 3397d0c..858cdba 100644
--- a/src/test/ui/mir-dataflow/liveness-ptr.stderr
+++ b/src/test/ui/mir-dataflow/liveness-ptr.stderr
@@ -1,8 +1,8 @@
 error: rustc_peek: bit not set
-  --> $DIR/liveness-ptr.rs:18:14
+  --> $DIR/liveness-ptr.rs:18:5
    |
-LL |     unsafe { rustc_peek(x); }
-   |              ^^^^^^^^^^^^^
+LL |     rustc_peek(x);
+   |     ^^^^^^^^^^^^^
 
 error: stop_after_dataflow ended compilation
 
diff --git a/src/test/ui/mir-dataflow/uninits-1.rs b/src/test/ui/mir-dataflow/uninits-1.rs
index 66b3f45..c2b4284 100644
--- a/src/test/ui/mir-dataflow/uninits-1.rs
+++ b/src/test/ui/mir-dataflow/uninits-1.rs
@@ -11,13 +11,13 @@
 fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S {
     let ret;
     // `ret` starts off uninitialized
-    unsafe { rustc_peek(&ret); }
+    rustc_peek(&ret);
 
     // All function formal parameters start off initialized.
 
-    unsafe { rustc_peek(&x) }; //~ ERROR rustc_peek: bit not set
-    unsafe { rustc_peek(&y) }; //~ ERROR rustc_peek: bit not set
-    unsafe { rustc_peek(&z) }; //~ ERROR rustc_peek: bit not set
+    rustc_peek(&x); //~ ERROR rustc_peek: bit not set
+    rustc_peek(&y); //~ ERROR rustc_peek: bit not set
+    rustc_peek(&z); //~ ERROR rustc_peek: bit not set
 
     ret = if test {
         ::std::mem::replace(x, y)
@@ -27,21 +27,21 @@
     };
 
     // `z` may be uninitialized here.
-    unsafe { rustc_peek(&z); }
+    rustc_peek(&z);
 
     // `y` is definitely uninitialized here.
-    unsafe { rustc_peek(&y); }
+    rustc_peek(&y);
 
     // `x` is still (definitely) initialized (replace above is a reborrow).
-    unsafe { rustc_peek(&x); } //~ ERROR rustc_peek: bit not set
+    rustc_peek(&x); //~ ERROR rustc_peek: bit not set
 
     ::std::mem::drop(x);
 
     // `x` is *definitely* uninitialized here
-    unsafe { rustc_peek(&x); }
+    rustc_peek(&x);
 
     // `ret` is now definitely initialized (via `if` above).
-    unsafe { rustc_peek(&ret); } //~ ERROR rustc_peek: bit not set
+    rustc_peek(&ret); //~ ERROR rustc_peek: bit not set
 
     ret
 }
diff --git a/src/test/ui/mir-dataflow/uninits-1.stderr b/src/test/ui/mir-dataflow/uninits-1.stderr
index 5f6dbde..c52f5ac 100644
--- a/src/test/ui/mir-dataflow/uninits-1.stderr
+++ b/src/test/ui/mir-dataflow/uninits-1.stderr
@@ -1,32 +1,32 @@
 error: rustc_peek: bit not set
-  --> $DIR/uninits-1.rs:18:14
+  --> $DIR/uninits-1.rs:18:5
    |
-LL |     unsafe { rustc_peek(&x) };
-   |              ^^^^^^^^^^^^^^
+LL |     rustc_peek(&x);
+   |     ^^^^^^^^^^^^^^
 
 error: rustc_peek: bit not set
-  --> $DIR/uninits-1.rs:19:14
+  --> $DIR/uninits-1.rs:19:5
    |
-LL |     unsafe { rustc_peek(&y) };
-   |              ^^^^^^^^^^^^^^
+LL |     rustc_peek(&y);
+   |     ^^^^^^^^^^^^^^
 
 error: rustc_peek: bit not set
-  --> $DIR/uninits-1.rs:20:14
+  --> $DIR/uninits-1.rs:20:5
    |
-LL |     unsafe { rustc_peek(&z) };
-   |              ^^^^^^^^^^^^^^
+LL |     rustc_peek(&z);
+   |     ^^^^^^^^^^^^^^
 
 error: rustc_peek: bit not set
-  --> $DIR/uninits-1.rs:36:14
+  --> $DIR/uninits-1.rs:36:5
    |
-LL |     unsafe { rustc_peek(&x); }
-   |              ^^^^^^^^^^^^^^
+LL |     rustc_peek(&x);
+   |     ^^^^^^^^^^^^^^
 
 error: rustc_peek: bit not set
-  --> $DIR/uninits-1.rs:44:14
+  --> $DIR/uninits-1.rs:44:5
    |
-LL |     unsafe { rustc_peek(&ret); }
-   |              ^^^^^^^^^^^^^^^^
+LL |     rustc_peek(&ret);
+   |     ^^^^^^^^^^^^^^^^
 
 error: stop_after_dataflow ended compilation
 
diff --git a/src/test/ui/mir-dataflow/uninits-2.rs b/src/test/ui/mir-dataflow/uninits-2.rs
index 2ccf1c7..c584ee7 100644
--- a/src/test/ui/mir-dataflow/uninits-2.rs
+++ b/src/test/ui/mir-dataflow/uninits-2.rs
@@ -11,12 +11,12 @@
 fn foo(x: &mut S) {
     // `x` is initialized here, so maybe-uninit bit is 0.
 
-    unsafe { rustc_peek(&x) }; //~ ERROR rustc_peek: bit not set
+    rustc_peek(&x); //~ ERROR rustc_peek: bit not set
 
     ::std::mem::drop(x);
 
     // `x` definitely uninitialized here, so maybe-uninit bit is 1.
-    unsafe { rustc_peek(&x) };
+    rustc_peek(&x);
 }
 fn main() {
     foo(&mut S(13));
diff --git a/src/test/ui/mir-dataflow/uninits-2.stderr b/src/test/ui/mir-dataflow/uninits-2.stderr
index dcb6137..0ef954e 100644
--- a/src/test/ui/mir-dataflow/uninits-2.stderr
+++ b/src/test/ui/mir-dataflow/uninits-2.stderr
@@ -1,8 +1,8 @@
 error: rustc_peek: bit not set
-  --> $DIR/uninits-2.rs:14:14
+  --> $DIR/uninits-2.rs:14:5
    |
-LL |     unsafe { rustc_peek(&x) };
-   |              ^^^^^^^^^^^^^^
+LL |     rustc_peek(&x);
+   |     ^^^^^^^^^^^^^^
 
 error: stop_after_dataflow ended compilation
 
diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
index 44bae28..a1147cb 100644
--- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
+++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
@@ -29,6 +29,9 @@
         (1, 4 | 5) => {} //~ ERROR unreachable pattern
         _ => {}
     }
+    match (true, true) {
+        (false | true, false | true) => (),
+    }
     match (Some(0u8),) {
         (None | Some(1 | 2),) => {}
         (Some(1),) => {} //~ ERROR unreachable pattern
@@ -67,4 +70,29 @@
              | 1) => {}
         _ => {}
     }
+
+    // A subpattern that is only unreachable in one branch is overall reachable.
+    match (true, true) {
+        (true, true) => {}
+        (false | true, false | true) => {}
+    }
+    match (true, true) {
+        (true, false) => {}
+        (false, true) => {}
+        (false | true, false | true) => {}
+    }
+    // A subpattern that is unreachable in all branches is overall unreachable.
+    match (true, true) {
+        (false, true) => {}
+        (true, true) => {}
+        (false | true, false
+            | true) => {} //~ ERROR unreachable
+    }
+    match (true, true) {
+        (true, false) => {}
+        (true, true) => {}
+        (false
+            | true, //~ ERROR unreachable
+            false | true) => {}
+    }
 }
diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
index bef6f82..d92b545a 100644
--- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
+++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr
@@ -53,52 +53,64 @@
    |         ^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:34:9
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:37:9
    |
 LL |         (Some(1),) => {}
    |         ^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:35:9
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:38:9
    |
 LL |         (None,) => {}
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:40:9
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:43:9
    |
 LL |         ((1..=4,),) => {}
    |         ^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:45:14
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:48:14
    |
 LL |         (1 | 1,) => {}
    |              ^
 
 error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:52:15
-   |
-LL |             | 0] => {}
-   |               ^
-
-error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:50:15
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:53:15
    |
 LL |             | 0
    |               ^
 
 error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:60:10
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:55:15
+   |
+LL |             | 0] => {}
+   |               ^
+
+error: unreachable pattern
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:63:10
    |
 LL |         [1
    |          ^
 
 error: unreachable pattern
-  --> $DIR/exhaustiveness-unreachable-pattern.rs:66:14
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:69:14
    |
 LL |         Some(0
    |              ^
 
-error: aborting due to 16 previous errors
+error: unreachable pattern
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:89:15
+   |
+LL |             | true) => {}
+   |               ^^^^
+
+error: unreachable pattern
+  --> $DIR/exhaustiveness-unreachable-pattern.rs:95:15
+   |
+LL |             | true,
+   |               ^^^^
+
+error: aborting due to 18 previous errors
 
diff --git a/src/test/ui/or-patterns/search-via-bindings.rs b/src/test/ui/or-patterns/search-via-bindings.rs
index eb127b8..067e617 100644
--- a/src/test/ui/or-patterns/search-via-bindings.rs
+++ b/src/test/ui/or-patterns/search-via-bindings.rs
@@ -3,7 +3,6 @@
 // run-pass
 
 #![feature(or_patterns)]
-#![allow(unreachable_patterns)] // FIXME(or-patterns) this shouldn't trigger
 
 fn search(target: (bool, bool, bool)) -> u32 {
     let x = ((false, true), (false, true), (false, true));
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs
new file mode 100644
index 0000000..0c52876
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.rs
@@ -0,0 +1,23 @@
+use std::{usize, isize};
+
+fn main() {
+    match 0usize {
+        //~^ ERROR non-exhaustive patterns
+        //~| NOTE pattern `_` not covered
+        //~| NOTE the matched value is of type `usize`
+        //~| NOTE `usize` does not have a fixed maximum value
+        0 ..= usize::MAX => {}
+    }
+
+    match 0isize {
+        //~^ ERROR non-exhaustive patterns
+        //~| NOTE pattern `_` not covered
+        //~| NOTE the matched value is of type `isize`
+        //~| NOTE `isize` does not have a fixed maximum value
+        isize::MIN ..= isize::MAX => {}
+    }
+
+    match 7usize {}
+    //~^ ERROR non-exhaustive patterns
+    //~| NOTE the matched value is of type `usize`
+}
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr
new file mode 100644
index 0000000..d0aa452
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-pointer-size-int.stderr
@@ -0,0 +1,34 @@
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:4:11
+   |
+LL |     match 0usize {
+   |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `usize`
+   = note: `usize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:12:11
+   |
+LL |     match 0isize {
+   |           ^^^^^^ pattern `_` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `isize`
+   = note: `isize` does not have a fixed maximum value, so a wildcard `_` is necessary to match exhaustively
+   = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
+
+error[E0004]: non-exhaustive patterns: type `usize` is non-empty
+  --> $DIR/non-exhaustive-pattern-pointer-size-int.rs:20:11
+   |
+LL |     match 7usize {}
+   |           ^^^^^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `usize`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0004`.