From f8376b59d1391a5191a561c44067355f1a99c7c0 Mon Sep 17 00:00:00 2001
From: David Wood <david@davidtw.co>
Date: Sun, 9 Aug 2020 20:08:45 +0100
Subject: [PATCH 01/40] shim: monomorphic `FnPtrShim`s during construction

This commit adjusts MIR shim construction so that substitutions are
applied to function pointer shims during construction, rather than
during codegen (as determined by `substs_for_mir_body`) - as
substitutions will no longer occur during codegen, function pointer
shims can now be polymorphic without incurring double substitutions.

Signed-off-by: David Wood <david@davidtw.co>
---
 compiler/rustc_middle/src/ty/instance.rs      | 53 ++++++++--------
 compiler/rustc_mir/src/shim.rs                | 60 ++++++++++---------
 ...-Fn-call.AddMovesForPackedDrops.before.mir |  4 +-
 3 files changed, 58 insertions(+), 59 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index c8b6705b35f36..a6b62097d5b18 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -62,10 +62,6 @@ pub enum InstanceDef<'tcx> {
     /// `<fn() as FnTrait>::call_*` (generated `FnTrait` implementation for `fn()` pointers).
     ///
     /// `DefId` is `FnTrait::call_*`.
-    ///
-    /// NB: the (`fn` pointer) type must currently be monomorphic to avoid double substitution
-    /// problems with the MIR shim bodies. `Instance::resolve` enforces this.
-    // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
     FnPtrShim(DefId, Ty<'tcx>),
 
     /// Dynamic dispatch to `<dyn Trait as Trait>::fn`.
@@ -87,10 +83,6 @@ pub enum InstanceDef<'tcx> {
     /// The `DefId` is for `core::ptr::drop_in_place`.
     /// The `Option<Ty<'tcx>>` is either `Some(T)`, or `None` for empty drop
     /// glue.
-    ///
-    /// NB: the type must currently be monomorphic to avoid double substitution
-    /// problems with the MIR shim bodies. `Instance::resolve` enforces this.
-    // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
     DropGlue(DefId, Option<Ty<'tcx>>),
 
     /// Compiler-generated `<T as Clone>::clone` implementation.
@@ -99,10 +91,6 @@ pub enum InstanceDef<'tcx> {
     /// Additionally, arrays, tuples, and closures get a `Clone` shim even if they aren't `Copy`.
     ///
     /// The `DefId` is for `Clone::clone`, the `Ty` is the type `T` with the builtin `Clone` impl.
-    ///
-    /// NB: the type must currently be monomorphic to avoid double substitution
-    /// problems with the MIR shim bodies. `Instance::resolve` enforces this.
-    // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
     CloneShim(DefId, Ty<'tcx>),
 }
 
@@ -243,6 +231,27 @@ impl<'tcx> InstanceDef<'tcx> {
             _ => false,
         }
     }
+
+    /// Returns `true` when the MIR body associated with this instance should be monomorphized
+    /// by its users (e.g. codegen or miri) by substituting the `substs` from `Instance` (see
+    /// `Instance::substs_for_mir_body`).
+    ///
+    /// Otherwise, returns `false` only for some kinds of shims where the construction of the MIR
+    /// body should perform necessary substitutions.
+    pub fn has_polymorphic_mir_body(&self) -> bool {
+        match *self {
+            InstanceDef::CloneShim(..)
+            | InstanceDef::FnPtrShim(..)
+            | InstanceDef::DropGlue(_, Some(_)) => false,
+            InstanceDef::ClosureOnceShim { .. }
+            | InstanceDef::DropGlue(..)
+            | InstanceDef::Item(_)
+            | InstanceDef::Intrinsic(..)
+            | InstanceDef::ReifyShim(..)
+            | InstanceDef::Virtual(..)
+            | InstanceDef::VtableShim(..) => true,
+        }
+    }
 }
 
 impl<'tcx> fmt::Display for Instance<'tcx> {
@@ -440,30 +449,18 @@ impl<'tcx> Instance<'tcx> {
         Instance { def, substs }
     }
 
-    /// FIXME(#69925) Depending on the kind of `InstanceDef`, the MIR body associated with an
+    /// Depending on the kind of `InstanceDef`, the MIR body associated with an
     /// instance is expressed in terms of the generic parameters of `self.def_id()`, and in other
     /// cases the MIR body is expressed in terms of the types found in the substitution array.
     /// In the former case, we want to substitute those generic types and replace them with the
     /// values from the substs when monomorphizing the function body. But in the latter case, we
     /// don't want to do that substitution, since it has already been done effectively.
     ///
-    /// This function returns `Some(substs)` in the former case and None otherwise -- i.e., if
+    /// This function returns `Some(substs)` in the former case and `None` otherwise -- i.e., if
     /// this function returns `None`, then the MIR body does not require substitution during
-    /// monomorphization.
+    /// codegen.
     pub fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> {
-        match self.def {
-            InstanceDef::CloneShim(..)
-            | InstanceDef::DropGlue(_, Some(_)) => None,
-            InstanceDef::ClosureOnceShim { .. }
-            | InstanceDef::DropGlue(..)
-            // FIXME(#69925): `FnPtrShim` should be in the other branch.
-            | InstanceDef::FnPtrShim(..)
-            | InstanceDef::Item(_)
-            | InstanceDef::Intrinsic(..)
-            | InstanceDef::ReifyShim(..)
-            | InstanceDef::Virtual(..)
-            | InstanceDef::VtableShim(..) => Some(self.substs),
-        }
+        if self.def.has_polymorphic_mir_body() { Some(self.substs) } else { None }
     }
 
     /// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by
diff --git a/compiler/rustc_mir/src/shim.rs b/compiler/rustc_mir/src/shim.rs
index 479b6c2a6ca9f..a99302e952155 100644
--- a/compiler/rustc_mir/src/shim.rs
+++ b/compiler/rustc_mir/src/shim.rs
@@ -33,7 +33,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
     let mut result = match instance {
         ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance),
         ty::InstanceDef::VtableShim(def_id) => {
-            build_call_shim(tcx, instance, Some(Adjustment::Deref), CallKind::Direct(def_id), None)
+            build_call_shim(tcx, instance, Some(Adjustment::Deref), CallKind::Direct(def_id))
         }
         ty::InstanceDef::FnPtrShim(def_id, ty) => {
             let trait_ = tcx.trait_of_item(def_id).unwrap();
@@ -42,16 +42,8 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
                 Some(ty::ClosureKind::FnMut | ty::ClosureKind::Fn) => Adjustment::Deref,
                 None => bug!("fn pointer {:?} is not an fn", ty),
             };
-            // HACK: we need the "real" argument types for the MIR,
-            // but because our substs are (Self, Args), where Args
-            // is a tuple, we must include the *concrete* argument
-            // types in the MIR. They will be substituted again with
-            // the param-substs, but because they are concrete, this
-            // will not do any harm.
-            let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx));
-            let arg_tys = sig.inputs();
-
-            build_call_shim(tcx, instance, Some(adjustment), CallKind::Indirect(ty), Some(arg_tys))
+
+            build_call_shim(tcx, instance, Some(adjustment), CallKind::Indirect(ty))
         }
         // We are generating a call back to our def-id, which the
         // codegen backend knows to turn to an actual call, be it
@@ -59,7 +51,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
         // indirect calls must be codegen'd differently than direct ones
         // (such as `#[track_caller]`).
         ty::InstanceDef::ReifyShim(def_id) => {
-            build_call_shim(tcx, instance, None, CallKind::Direct(def_id), None)
+            build_call_shim(tcx, instance, None, CallKind::Direct(def_id))
         }
         ty::InstanceDef::ClosureOnceShim { call_once: _ } => {
             let fn_mut = tcx.require_lang_item(LangItem::FnMut, None);
@@ -70,13 +62,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
                 .unwrap()
                 .def_id;
 
-            build_call_shim(
-                tcx,
-                instance,
-                Some(Adjustment::RefMut),
-                CallKind::Direct(call_mut),
-                None,
-            )
+            build_call_shim(tcx, instance, Some(Adjustment::RefMut), CallKind::Direct(call_mut))
         }
         ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty),
         ty::InstanceDef::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty),
@@ -641,29 +627,45 @@ impl CloneShimBuilder<'tcx> {
     }
 }
 
-/// Builds a "call" shim for `instance`. The shim calls the
-/// function specified by `call_kind`, first adjusting its first
-/// argument according to `rcvr_adjustment`.
-///
-/// If `untuple_args` is a vec of types, the second argument of the
-/// function will be untupled as these types.
+/// Builds a "call" shim for `instance`. The shim calls the function specified by `call_kind`,
+/// first adjusting its first argument according to `rcvr_adjustment`.
 fn build_call_shim<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: ty::InstanceDef<'tcx>,
     rcvr_adjustment: Option<Adjustment>,
     call_kind: CallKind<'tcx>,
-    untuple_args: Option<&[Ty<'tcx>]>,
 ) -> Body<'tcx> {
     debug!(
-        "build_call_shim(instance={:?}, rcvr_adjustment={:?}, \
-            call_kind={:?}, untuple_args={:?})",
-        instance, rcvr_adjustment, call_kind, untuple_args
+        "build_call_shim(instance={:?}, rcvr_adjustment={:?}, call_kind={:?})",
+        instance, rcvr_adjustment, call_kind
     );
 
+    // `FnPtrShim` contains the fn pointer type that a call shim is being built for - this is used
+    // to substitute into the signature of the shim. It is not necessary for users of this
+    // MIR body to perform further substitutions (see `InstanceDef::has_polymorphic_mir_body`).
+    let (sig_substs, untuple_args) = if let ty::InstanceDef::FnPtrShim(_, ty) = instance {
+        let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx));
+
+        let untuple_args = sig.inputs();
+
+        // Create substitutions for the `Self` and `Args` generic parameters of the shim body.
+        let arg_tup = tcx.mk_tup(untuple_args.iter());
+        let sig_substs = tcx.mk_substs_trait(ty, &[ty::subst::GenericArg::from(arg_tup)]);
+
+        (Some(sig_substs), Some(untuple_args))
+    } else {
+        (None, None)
+    };
+
     let def_id = instance.def_id();
     let sig = tcx.fn_sig(def_id);
     let mut sig = tcx.erase_late_bound_regions(&sig);
 
+    assert_eq!(sig_substs.is_some(), !instance.has_polymorphic_mir_body());
+    if let Some(sig_substs) = sig_substs {
+        sig = sig.subst(tcx, sig_substs);
+    }
+
     if let CallKind::Indirect(fnty) = call_kind {
         // `sig` determines our local decls, and thus the callee type in the `Call` terminator. This
         // can only be an `FnDef` or `FnPtr`, but currently will be `Self` since the types come from
diff --git a/src/test/mir-opt/fn_ptr_shim.core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir b/src/test/mir-opt/fn_ptr_shim.core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir
index d3f92d389f5b2..bcc6042f2fb62 100644
--- a/src/test/mir-opt/fn_ptr_shim.core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir
+++ b/src/test/mir-opt/fn_ptr_shim.core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir
@@ -1,7 +1,7 @@
 // MIR for `std::ops::Fn::call` before AddMovesForPackedDrops
 
-fn std::ops::Fn::call(_1: *const fn(), _2: Args) -> <Self as FnOnce<Args>>::Output {
-    let mut _0: <Self as std::ops::FnOnce<Args>>::Output; // return place in scope 0 at $SRC_DIR/core/src/ops/function.rs:LL:COL
+fn std::ops::Fn::call(_1: *const fn(), _2: ()) -> <fn() as FnOnce<()>>::Output {
+    let mut _0: <fn() as std::ops::FnOnce<()>>::Output; // return place in scope 0 at $SRC_DIR/core/src/ops/function.rs:LL:COL
 
     bb0: {
         _0 = move (*_1)() -> bb1;        // scope 0 at $SRC_DIR/core/src/ops/function.rs:LL:COL

From 8f27e3cb1b4140d9124d60df0850ef734e73b884 Mon Sep 17 00:00:00 2001
From: Christiaan Dirkx <christiaan@dirkx.email>
Date: Sun, 13 Sep 2020 01:55:34 +0200
Subject: [PATCH 02/40] Make some methods of `Pin` unstable const

Make the following methods unstable const under the `const_pin` feature:
- `new`
- `new_unchecked`
- `into_inner`
- `into_inner_unchecked`
- `get_ref`
- `into_ref`

Also adds tests for these methods in a const context.

Tracking issue: #76654
---
 library/core/src/lib.rs   |  1 +
 library/core/src/pin.rs   | 27 ++++++++++++++++-----------
 library/core/tests/lib.rs |  2 ++
 library/core/tests/pin.rs | 21 +++++++++++++++++++++
 4 files changed, 40 insertions(+), 11 deletions(-)
 create mode 100644 library/core/tests/pin.rs

diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index c3cadcbb01e31..696b6a64a9fec 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -80,6 +80,7 @@
 #![feature(const_int_pow)]
 #![feature(constctlz)]
 #![feature(const_panic)]
+#![feature(const_pin)]
 #![feature(const_fn_union)]
 #![feature(const_generics)]
 #![feature(const_option)]
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 1cc1dfb014335..fa5b37edc36e6 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -471,9 +471,10 @@ impl<P: Deref<Target: Unpin>> Pin<P> {
     ///
     /// Unlike `Pin::new_unchecked`, this method is safe because the pointer
     /// `P` dereferences to an [`Unpin`] type, which cancels the pinning guarantees.
-    #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn new(pointer: P) -> Pin<P> {
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    #[stable(feature = "pin", since = "1.33.0")]
+    pub const fn new(pointer: P) -> Pin<P> {
         // SAFETY: the value pointed to is `Unpin`, and so has no requirements
         // around pinning.
         unsafe { Pin::new_unchecked(pointer) }
@@ -483,9 +484,10 @@ impl<P: Deref<Target: Unpin>> Pin<P> {
     ///
     /// This requires that the data inside this `Pin` is [`Unpin`] so that we
     /// can ignore the pinning invariants when unwrapping it.
-    #[stable(feature = "pin_into_inner", since = "1.39.0")]
     #[inline(always)]
-    pub fn into_inner(pin: Pin<P>) -> P {
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    #[stable(feature = "pin_into_inner", since = "1.39.0")]
+    pub const fn into_inner(pin: Pin<P>) -> P {
         pin.pointer
     }
 }
@@ -556,9 +558,10 @@ impl<P: Deref> Pin<P> {
     ///
     /// [`mem::swap`]: crate::mem::swap
     #[lang = "new_unchecked"]
-    #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub unsafe fn new_unchecked(pointer: P) -> Pin<P> {
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    #[stable(feature = "pin", since = "1.33.0")]
+    pub const unsafe fn new_unchecked(pointer: P) -> Pin<P> {
         Pin { pointer }
     }
 
@@ -589,9 +592,10 @@ impl<P: Deref> Pin<P> {
     ///
     /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used
     /// instead.
-    #[stable(feature = "pin_into_inner", since = "1.39.0")]
     #[inline(always)]
-    pub unsafe fn into_inner_unchecked(pin: Pin<P>) -> P {
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    #[stable(feature = "pin_into_inner", since = "1.39.0")]
+    pub const unsafe fn into_inner_unchecked(pin: Pin<P>) -> P {
         pin.pointer
     }
 }
@@ -693,17 +697,18 @@ impl<'a, T: ?Sized> Pin<&'a T> {
     /// with the same lifetime as the original `Pin`.
     ///
     /// ["pinning projections"]: self#projections-and-structural-pinning
-    #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn get_ref(self) -> &'a T {
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    #[stable(feature = "pin", since = "1.33.0")]
+    pub const fn get_ref(self) -> &'a T {
         self.pointer
     }
 }
 
 impl<'a, T: ?Sized> Pin<&'a mut T> {
     /// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime.
-    #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
+    #[stable(feature = "pin", since = "1.33.0")]
     pub fn into_ref(self) -> Pin<&'a T> {
         Pin { pointer: self.pointer }
     }
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index a2e294ace1860..b8d67d7266543 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -39,6 +39,7 @@
 #![feature(iter_order_by)]
 #![feature(cmp_min_max_by)]
 #![feature(iter_map_while)]
+#![feature(const_pin)]
 #![feature(const_slice_from_raw_parts)]
 #![feature(const_raw_ptr_deref)]
 #![feature(never_type)]
@@ -74,6 +75,7 @@ mod num;
 mod ops;
 mod option;
 mod pattern;
+mod pin;
 mod ptr;
 mod result;
 mod slice;
diff --git a/library/core/tests/pin.rs b/library/core/tests/pin.rs
new file mode 100644
index 0000000000000..1363353163829
--- /dev/null
+++ b/library/core/tests/pin.rs
@@ -0,0 +1,21 @@
+use core::pin::Pin;
+
+#[test]
+fn pin_const() {
+    // test that the methods of `Pin` are usable in a const context
+
+    const POINTER: &'static usize = &2;
+
+    const PINNED: Pin<&'static usize> = Pin::new(POINTER);
+    const PINNED_UNCHECKED: Pin<&'static usize> = unsafe { Pin::new_unchecked(POINTER) };
+    assert_eq!(PINNED_UNCHECKED, PINNED);
+
+    const INNER: &'static usize = Pin::into_inner(PINNED);
+    assert_eq!(INNER, POINTER);
+
+    const INNER_UNCHECKED: &'static usize = unsafe { Pin::into_inner_unchecked(PINNED) };
+    assert_eq!(INNER_UNCHECKED, POINTER);
+
+    const REF: &'static usize = PINNED.get_ref();
+    assert_eq!(REF, POINTER)
+}

From 176956c115c2b797471a3f59eef3e17789229007 Mon Sep 17 00:00:00 2001
From: Stein Somers <git@steinsomers.be>
Date: Tue, 15 Sep 2020 00:02:48 +0200
Subject: [PATCH 03/40] Test and fix Sync & Send traits of BTreeMap artefacts

---
 library/alloc/src/collections/btree/borrow.rs |   3 +
 .../alloc/src/collections/btree/map/tests.rs  | 140 ++++++++++++++++++
 2 files changed, 143 insertions(+)

diff --git a/library/alloc/src/collections/btree/borrow.rs b/library/alloc/src/collections/btree/borrow.rs
index 5c95acfbe9c20..016f139a501a0 100644
--- a/library/alloc/src/collections/btree/borrow.rs
+++ b/library/alloc/src/collections/btree/borrow.rs
@@ -16,6 +16,9 @@ pub struct DormantMutRef<'a, T> {
     _marker: PhantomData<&'a mut T>,
 }
 
+unsafe impl<'a, T> Sync for DormantMutRef<'a, T> where &'a mut T: Sync {}
+unsafe impl<'a, T> Send for DormantMutRef<'a, T> where &'a mut T: Send {}
+
 impl<'a, T> DormantMutRef<'a, T> {
     /// Capture a unique borrow, and immediately reborrow it. For the compiler,
     /// the lifetime of the new reference is the same as the lifetime of the
diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs
index af5cf7d7d875c..d2cd6b8e5241a 100644
--- a/library/alloc/src/collections/btree/map/tests.rs
+++ b/library/alloc/src/collections/btree/map/tests.rs
@@ -1418,6 +1418,146 @@ fn test_variance() {
     }
 }
 
+#[test]
+#[allow(dead_code)]
+fn test_sync() {
+    fn map<T: Sync>(v: &BTreeMap<T, T>) -> impl Sync + '_ {
+        v
+    }
+
+    fn into_iter<T: Sync>(v: BTreeMap<T, T>) -> impl Sync {
+        v.into_iter()
+    }
+
+    fn into_keys<T: Sync + Ord>(v: BTreeMap<T, T>) -> impl Sync {
+        v.into_keys()
+    }
+
+    fn into_values<T: Sync + Ord>(v: BTreeMap<T, T>) -> impl Sync {
+        v.into_values()
+    }
+
+    fn drain_filter<T: Sync + Ord>(v: &mut BTreeMap<T, T>) -> impl Sync + '_ {
+        v.drain_filter(|_, _| false)
+    }
+
+    fn iter<T: Sync>(v: &BTreeMap<T, T>) -> impl Sync + '_ {
+        v.iter()
+    }
+
+    fn iter_mut<T: Sync>(v: &mut BTreeMap<T, T>) -> impl Sync + '_ {
+        v.iter_mut()
+    }
+
+    fn keys<T: Sync>(v: &BTreeMap<T, T>) -> impl Sync + '_ {
+        v.keys()
+    }
+
+    fn values<T: Sync>(v: &BTreeMap<T, T>) -> impl Sync + '_ {
+        v.values()
+    }
+
+    fn values_mut<T: Sync>(v: &mut BTreeMap<T, T>) -> impl Sync + '_ {
+        v.values_mut()
+    }
+
+    fn range<T: Sync + Ord>(v: &BTreeMap<T, T>) -> impl Sync + '_ {
+        v.range(..)
+    }
+
+    fn range_mut<T: Sync + Ord>(v: &mut BTreeMap<T, T>) -> impl Sync + '_ {
+        v.range_mut(..)
+    }
+
+    fn entry<T: Sync + Ord + Default>(v: &mut BTreeMap<T, T>) -> impl Sync + '_ {
+        v.entry(Default::default())
+    }
+
+    fn occupied_entry<T: Sync + Ord + Default>(v: &mut BTreeMap<T, T>) -> impl Sync + '_ {
+        match v.entry(Default::default()) {
+            Occupied(entry) => entry,
+            _ => unreachable!(),
+        }
+    }
+
+    fn vacant_entry<T: Sync + Ord + Default>(v: &mut BTreeMap<T, T>) -> impl Sync + '_ {
+        match v.entry(Default::default()) {
+            Vacant(entry) => entry,
+            _ => unreachable!(),
+        }
+    }
+}
+
+#[test]
+#[allow(dead_code)]
+fn test_send() {
+    fn map<T: Send>(v: BTreeMap<T, T>) -> impl Send {
+        v
+    }
+
+    fn into_iter<T: Send>(v: BTreeMap<T, T>) -> impl Send {
+        v.into_iter()
+    }
+
+    fn into_keys<T: Send + Ord>(v: BTreeMap<T, T>) -> impl Send {
+        v.into_keys()
+    }
+
+    fn into_values<T: Send + Ord>(v: BTreeMap<T, T>) -> impl Send {
+        v.into_values()
+    }
+
+    fn drain_filter<T: Send + Ord>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
+        v.drain_filter(|_, _| false)
+    }
+
+    fn iter<T: Send + Sync>(v: &BTreeMap<T, T>) -> impl Send + '_ {
+        v.iter()
+    }
+
+    fn iter_mut<T: Send + Sync>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
+        v.iter_mut()
+    }
+
+    fn keys<T: Send + Sync>(v: &BTreeMap<T, T>) -> impl Send + '_ {
+        v.keys()
+    }
+
+    fn values<T: Send + Sync>(v: &BTreeMap<T, T>) -> impl Send + '_ {
+        v.values()
+    }
+
+    fn values_mut<T: Send + Sync>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
+        v.values_mut()
+    }
+
+    fn range<T: Send + Sync + Ord>(v: &BTreeMap<T, T>) -> impl Send + '_ {
+        v.range(..)
+    }
+
+    fn range_mut<T: Send + Sync + Ord>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
+        v.range_mut(..)
+    }
+
+    fn entry<T: Send + Ord + Default>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
+        v.entry(Default::default())
+    }
+
+    fn occupied_entry<T: Send + Ord + Default>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
+        match v.entry(Default::default()) {
+            Occupied(entry) => entry,
+            _ => unreachable!(),
+        }
+    }
+
+    fn vacant_entry<T: Send + Ord + Default>(v: &mut BTreeMap<T, T>) -> impl Send + '_ {
+        match v.entry(Default::default()) {
+            Vacant(entry) => entry,
+            _ => unreachable!(),
+        }
+    }
+}
+
 #[test]
 fn test_occupied_entry_key() {
     let mut a = BTreeMap::new();

From eede953c283c7bbe903a0e8abb44c923baf5cfac Mon Sep 17 00:00:00 2001
From: Lzu Tao <taolzu@gmail.com>
Date: Thu, 10 Sep 2020 03:10:36 +0000
Subject: [PATCH 04/40] Only get ImplKind::Impl once

---
 src/librustdoc/clean/inline.rs | 41 ++++++++++++++++++----------------
 1 file changed, 22 insertions(+), 19 deletions(-)

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index f8987c6beca33..931355b82f503 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -350,14 +350,22 @@ pub fn build_impl(
         }
     }
 
-    let for_ = if let Some(did) = did.as_local() {
-        let hir_id = tcx.hir().local_def_id_to_hir_id(did);
-        match tcx.hir().expect_item(hir_id).kind {
-            hir::ItemKind::Impl { self_ty, .. } => self_ty.clean(cx),
-            _ => panic!("did given to build_impl was not an impl"),
+    let impl_item = match did.as_local() {
+        Some(did) => {
+            let hir_id = tcx.hir().local_def_id_to_hir_id(did);
+            match tcx.hir().expect_item(hir_id).kind {
+                hir::ItemKind::Impl { self_ty, ref generics, ref items, .. } => {
+                    Some((self_ty, generics, items))
+                }
+                _ => panic!("`DefID` passed to `build_impl` is not an `impl"),
+            }
         }
-    } else {
-        tcx.type_of(did).clean(cx)
+        None => None,
+    };
+
+    let for_ = match impl_item {
+        Some((self_ty, _, _)) => self_ty.clean(cx),
+        None => tcx.type_of(did).clean(cx),
     };
 
     // Only inline impl if the implementing type is
@@ -377,17 +385,12 @@ pub fn build_impl(
     }
 
     let predicates = tcx.explicit_predicates_of(did);
-    let (trait_items, generics) = if let Some(did) = did.as_local() {
-        let hir_id = tcx.hir().local_def_id_to_hir_id(did);
-        match tcx.hir().expect_item(hir_id).kind {
-            hir::ItemKind::Impl { ref generics, ref items, .. } => (
-                items.iter().map(|item| tcx.hir().impl_item(item.id).clean(cx)).collect::<Vec<_>>(),
-                generics.clean(cx),
-            ),
-            _ => panic!("did given to build_impl was not an impl"),
-        }
-    } else {
-        (
+    let (trait_items, generics) = match impl_item {
+        Some((_, generics, items)) => (
+            items.iter().map(|item| tcx.hir().impl_item(item.id).clean(cx)).collect::<Vec<_>>(),
+            generics.clean(cx),
+        ),
+        None => (
             tcx.associated_items(did)
                 .in_definition_order()
                 .filter_map(|item| {
@@ -399,7 +402,7 @@ pub fn build_impl(
                 })
                 .collect::<Vec<_>>(),
             clean::enter_impl_trait(cx, || (tcx.generics_of(did), predicates).clean(cx)),
-        )
+        ),
     };
     let polarity = tcx.impl_polarity(did);
     let trait_ = associated_trait.clean(cx).map(|bound| match bound {

From 94dae6004035c356b00dac8764c1b4808d740928 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Wed, 16 Sep 2020 23:09:57 +0200
Subject: [PATCH 05/40] simplfy condition in ItemLowerer::with_trait_impl_ref()

---
 compiler/rustc_ast_lowering/src/item.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 6d41b7836b121..617cacee0e7f1 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -27,7 +27,7 @@ pub(super) struct ItemLowerer<'a, 'lowering, 'hir> {
 impl ItemLowerer<'_, '_, '_> {
     fn with_trait_impl_ref(&mut self, impl_ref: &Option<TraitRef>, f: impl FnOnce(&mut Self)) {
         let old = self.lctx.is_in_trait_impl;
-        self.lctx.is_in_trait_impl = if let &None = impl_ref { false } else { true };
+        self.lctx.is_in_trait_impl = impl_ref.is_some();
         f(self);
         self.lctx.is_in_trait_impl = old;
     }

From b7c8bea6cbf0aff4cbb36b127edc0bb4c66c4cf9 Mon Sep 17 00:00:00 2001
From: Ivan Tham <pickfire@riseup.net>
Date: Thu, 17 Sep 2020 09:07:19 +0800
Subject: [PATCH 06/40] Fix wording in mir doc

---
 compiler/rustc_middle/src/mir/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 29daf7e9309aa..467d0192a8144 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2285,7 +2285,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
 /// Constants
 ///
 /// Two constants are equal if they are the same constant. Note that
-/// this does not necessarily mean that they are `==` in Rust -- in
+/// this does not necessarily mean that they are `==` in Rust. In
 /// particular, one must be wary of `NaN`!
 
 #[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, HashStable)]

From f4a7149f499a4b91d296678002f0bce4ded85038 Mon Sep 17 00:00:00 2001
From: Hanif Bin Ariffin <hanif.ariffin.4326@gmail.com>
Date: Thu, 17 Sep 2020 10:56:08 +0800
Subject: [PATCH 07/40] Don't compile regex at every function call.

Use `SyncOnceCell` to only compile it once.
I believe this still adds some kind of locking mechanism?
---
 compiler/rustc_mir/src/dataflow/framework/graphviz.rs | 10 +++++++++-
 compiler/rustc_mir/src/lib.rs                         |  1 +
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_mir/src/dataflow/framework/graphviz.rs b/compiler/rustc_mir/src/dataflow/framework/graphviz.rs
index 94151fbd0903a..5d4c4251961d2 100644
--- a/compiler/rustc_mir/src/dataflow/framework/graphviz.rs
+++ b/compiler/rustc_mir/src/dataflow/framework/graphviz.rs
@@ -1,6 +1,7 @@
 //! A helpful diagram for debugging dataflow problems.
 
 use std::borrow::Cow;
+use std::lazy::SyncOnceCell;
 use std::{io, ops, str};
 
 use regex::Regex;
@@ -570,6 +571,13 @@ where
     }
 }
 
+macro_rules! regex {
+    ($re:literal $(,)?) => {{
+        static RE: SyncOnceCell<regex::Regex> = SyncOnceCell::new();
+        RE.get_or_init(|| Regex::new($re).unwrap())
+    }};
+}
+
 fn diff_pretty<T, C>(new: T, old: T, ctxt: &C) -> String
 where
     T: DebugWithContext<C>,
@@ -578,7 +586,7 @@ where
         return String::new();
     }
 
-    let re = Regex::new("\t?\u{001f}([+-])").unwrap();
+    let re = regex!("\t?\u{001f}([+-])");
 
     let raw_diff = format!("{:#?}", DebugDiffWithAdapter { new, old, ctxt });
 
diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs
index 42717f273843a..8d2253b4d826b 100644
--- a/compiler/rustc_mir/src/lib.rs
+++ b/compiler/rustc_mir/src/lib.rs
@@ -27,6 +27,7 @@ Rust MIR: a lowered representation of Rust.
 #![feature(trait_alias)]
 #![feature(option_expect_none)]
 #![feature(or_patterns)]
+#![feature(once_cell)]
 #![recursion_limit = "256"]
 
 #[macro_use]

From b47913962097874257ad10227b943ef7af85d49f Mon Sep 17 00:00:00 2001
From: est31 <MTest31@outlook.com>
Date: Thu, 17 Sep 2020 06:12:40 +0200
Subject: [PATCH 08/40] Remove intrinsics::arith_offset use from libarena

The use of arith_offset was added in 803e9ae67b770d8500c4ab5862e988d29118356a
before the stable wrapper of the intrinsic was available.

https://doc.rust-lang.org/stable/std/intrinsics/fn.arith_offset.html
---
 compiler/rustc_arena/src/lib.rs | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs
index 5e6a0340d12a0..16f735f055f92 100644
--- a/compiler/rustc_arena/src/lib.rs
+++ b/compiler/rustc_arena/src/lib.rs
@@ -11,7 +11,6 @@
     html_root_url = "https://doc.rust-lang.org/nightly/",
     test(no_crate_inject, attr(deny(warnings)))
 )]
-#![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
 #![feature(raw_vec_internals)]
 #![cfg_attr(test, feature(test))]
@@ -25,7 +24,6 @@ use smallvec::SmallVec;
 use std::alloc::Layout;
 use std::cell::{Cell, RefCell};
 use std::cmp;
-use std::intrinsics;
 use std::marker::{PhantomData, Send};
 use std::mem;
 use std::ptr;
@@ -130,7 +128,7 @@ impl<T> TypedArena<T> {
 
         unsafe {
             if mem::size_of::<T>() == 0 {
-                self.ptr.set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1) as *mut T);
+                self.ptr.set((self.ptr.get() as *mut u8).wrapping_offset(1) as *mut T);
                 let ptr = mem::align_of::<T>() as *mut T;
                 // Don't drop the object. This `write` is equivalent to `forget`.
                 ptr::write(ptr, object);

From 4fe6ca37898bcd65488764f2679e27c936879ade Mon Sep 17 00:00:00 2001
From: est31 <MTest31@outlook.com>
Date: Thu, 17 Sep 2020 07:08:34 +0200
Subject: [PATCH 09/40] Replace const_generics feature gate with
 min_const_generics

The latter is on the path to stabilization.
---
 compiler/rustc_data_structures/src/lib.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 88c160e93b66a..b339261189b9c 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -26,7 +26,7 @@
 #![feature(thread_id_value)]
 #![feature(extend_one)]
 #![feature(const_panic)]
-#![feature(const_generics)]
+#![feature(min_const_generics)]
 #![feature(once_cell)]
 #![allow(rustc::default_hash_types)]
 

From ebdea011436dfea810ff1bbd827636ac75f6f092 Mon Sep 17 00:00:00 2001
From: est31 <MTest31@outlook.com>
Date: Thu, 17 Sep 2020 07:46:35 +0200
Subject: [PATCH 10/40] Remove redundant #![feature(...)] 's from compiler/

---
 compiler/rustc_ast/src/lib.rs             | 4 ----
 compiler/rustc_codegen_ssa/src/lib.rs     | 2 --
 compiler/rustc_data_structures/src/lib.rs | 1 -
 compiler/rustc_expand/src/lib.rs          | 1 -
 compiler/rustc_infer/src/lib.rs           | 2 --
 compiler/rustc_middle/src/lib.rs          | 5 -----
 compiler/rustc_mir/src/lib.rs             | 3 ---
 compiler/rustc_parse/src/lib.rs           | 1 -
 compiler/rustc_parse_format/src/lib.rs    | 2 --
 compiler/rustc_privacy/src/lib.rs         | 1 -
 compiler/rustc_span/src/lib.rs            | 2 --
 compiler/rustc_traits/src/lib.rs          | 1 -
 compiler/rustc_ty/src/lib.rs              | 1 -
 13 files changed, 26 deletions(-)

diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index b556c1a446b7b..76b84d9da8334 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -5,17 +5,13 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
-#![feature(bool_to_option)]
 #![feature(box_syntax)]
 #![feature(const_fn)] // For the `transmute` in `P::new`
 #![feature(const_panic)]
-#![feature(const_fn_transmute)]
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
 #![feature(nll)]
 #![feature(or_patterns)]
-#![feature(try_trait)]
-#![feature(unicode_internals)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 73e3336917587..a87ce1446ba14 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -8,8 +8,6 @@
 #![feature(or_patterns)]
 #![feature(trusted_len)]
 #![feature(associated_type_bounds)]
-#![feature(const_fn)] // for rustc_index::newtype_index
-#![feature(const_panic)] // for rustc_index::newtype_index
 #![recursion_limit = "256"]
 
 //! This crate contains codegen code that is used by all codegen backends (LLVM and others).
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index b339261189b9c..e5dd7107ff3ad 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -11,7 +11,6 @@
 #![feature(control_flow_enum)]
 #![feature(in_band_lifetimes)]
 #![feature(unboxed_closures)]
-#![feature(generators)]
 #![feature(generator_trait)]
 #![feature(fn_traits)]
 #![feature(min_specialization)]
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index 5436b1ef737f5..47247294f5dc6 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -1,5 +1,4 @@
 #![feature(bool_to_option)]
-#![feature(cow_is_borrowed)]
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
 #![feature(or_patterns)]
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index e05041d88460e..504b66bae7329 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -13,7 +13,6 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![feature(bindings_after_at)]
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
@@ -23,7 +22,6 @@
 #![feature(never_type)]
 #![feature(or_patterns)]
 #![feature(in_band_lifetimes)]
-#![feature(crate_visibility_modifier)]
 #![recursion_limit = "512"] // For rustdoc
 
 #[macro_use]
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index a675aae5b17d4..6b411ef8f09ee 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -30,12 +30,9 @@
 #![feature(cmp_min_max_by)]
 #![feature(const_fn)]
 #![feature(const_panic)]
-#![feature(const_fn_transmute)]
 #![feature(core_intrinsics)]
 #![feature(discriminant_kind)]
-#![feature(drain_filter)]
 #![feature(never_type)]
-#![feature(exhaustive_patterns)]
 #![feature(extern_types)]
 #![feature(nll)]
 #![feature(once_cell)]
@@ -43,13 +40,11 @@
 #![feature(or_patterns)]
 #![feature(min_specialization)]
 #![feature(trusted_len)]
-#![feature(stmt_expr_attributes)]
 #![feature(test)]
 #![feature(in_band_lifetimes)]
 #![feature(crate_visibility_modifier)]
 #![feature(associated_type_bounds)]
 #![feature(rustc_attrs)]
-#![feature(hash_raw_entry)]
 #![feature(int_error_matching)]
 #![recursion_limit = "512"]
 
diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs
index 42717f273843a..fae4a261b3e32 100644
--- a/compiler/rustc_mir/src/lib.rs
+++ b/compiler/rustc_mir/src/lib.rs
@@ -13,15 +13,12 @@ Rust MIR: a lowered representation of Rust.
 #![feature(const_panic)]
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
-#![feature(drain_filter)]
 #![feature(exact_size_is_empty)]
 #![feature(exhaustive_patterns)]
-#![feature(iter_order_by)]
 #![feature(never_type)]
 #![feature(min_specialization)]
 #![feature(trusted_len)]
 #![feature(try_blocks)]
-#![feature(associated_type_bounds)]
 #![feature(associated_type_defaults)]
 #![feature(stmt_expr_attributes)]
 #![feature(trait_alias)]
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 0becdf24c532b..72a34b86ae20b 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -3,7 +3,6 @@
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
 #![feature(bindings_after_at)]
-#![feature(try_blocks)]
 #![feature(or_patterns)]
 
 use rustc_ast as ast;
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index e07b8b86aef8e..dde162681b773 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -11,8 +11,6 @@
 )]
 #![feature(nll)]
 #![feature(or_patterns)]
-#![feature(rustc_private)]
-#![feature(unicode_internals)]
 #![feature(bool_to_option)]
 
 pub use Alignment::*;
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 03cc718b8995d..d451a383b12a3 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1,7 +1,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(or_patterns)]
 #![recursion_limit = "256"]
 
 use rustc_attr as attr;
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index e38cd516b91ac..1d1013967b7db 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -10,10 +10,8 @@
 #![feature(const_panic)]
 #![feature(negative_impls)]
 #![feature(nll)]
-#![feature(optin_builtin_traits)]
 #![feature(min_specialization)]
 #![feature(option_expect_none)]
-#![feature(refcell_take)]
 
 #[macro_use]
 extern crate rustc_macros;
diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs
index 6fea4732dda3f..d0b05beb4e63c 100644
--- a/compiler/rustc_traits/src/lib.rs
+++ b/compiler/rustc_traits/src/lib.rs
@@ -4,7 +4,6 @@
 #![feature(crate_visibility_modifier)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(or_patterns)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_ty/src/lib.rs b/compiler/rustc_ty/src/lib.rs
index 6e9042d1ba7c8..8dd6aa3c7fcc1 100644
--- a/compiler/rustc_ty/src/lib.rs
+++ b/compiler/rustc_ty/src/lib.rs
@@ -5,7 +5,6 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
-#![feature(bool_to_option)]
 #![feature(nll)]
 #![recursion_limit = "256"]
 

From 1dd3df6738b5bbe676b6ae5b561c491ca483f017 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Thu, 17 Sep 2020 08:59:30 +0200
Subject: [PATCH 11/40] black_box: silence unused_mut warning when building
 with cfg(miri)

---
 library/core/src/hint.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 1192b9e164a14..fdf5bbf61441f 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -110,7 +110,7 @@ pub fn spin_loop() {
 /// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
 #[inline]
 #[unstable(feature = "test", issue = "50297")]
-#[allow(unreachable_code)] // this makes #[cfg] a bit easier below.
+#[cfg_attr(miri, allow(unused_mut))]
 pub fn black_box<T>(mut dummy: T) -> T {
     // We need to "use" the argument in some way LLVM can't introspect, and on
     // targets that support it we can typically leverage inline assembly to do

From 4382436cb4918857614a8a883e81be50900d145f Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 15 Sep 2020 20:34:50 +0100
Subject: [PATCH 12/40] Make invalid integer operation messages consistent

---
 compiler/rustc_middle/src/mir/mod.rs          | 56 ++++++++++---------
 src/test/ui/array_const_index-0.rs            |  2 +-
 src/test/ui/array_const_index-0.stderr        |  2 +-
 src/test/ui/array_const_index-1.rs            |  2 +-
 src/test/ui/array_const_index-1.stderr        |  2 +-
 .../defaults-not-assumed-fail.stderr          |  2 +-
 ...20-assoc-const-arith-overflow.noopt.stderr | 16 +++---
 ...9020-assoc-const-arith-overflow.opt.stderr | 16 +++---
 ...h-overflow.opt_with_overflow_checks.stderr | 16 +++---
 .../simple_fail.full.stderr                   |  2 +-
 .../ice-assert-fail-div-by-zero.stderr        |  2 +-
 .../ui/consts/array-literal-index-oob.stderr  |  2 +-
 .../ui/consts/assoc_const_generic_impl.stderr |  2 +-
 src/test/ui/consts/const-array-oob.rs         |  2 +-
 src/test/ui/consts/const-array-oob.stderr     |  2 +-
 src/test/ui/consts/const-err-early.stderr     | 10 ++--
 src/test/ui/consts/const-err-multi.stderr     |  2 +-
 src/test/ui/consts/const-err.stderr           |  2 +-
 src/test/ui/consts/const-err2.noopt.stderr    | 14 ++---
 src/test/ui/consts/const-err2.opt.stderr      | 14 ++---
 ...const-err2.opt_with_overflow_checks.stderr | 14 ++---
 .../conditional_array_execution.stderr        |  2 +-
 .../const-eval/const-eval-overflow-3.stderr   |  2 +-
 .../const-eval/const-eval-overflow-4.stderr   |  2 +-
 .../const-eval/const-eval-overflow2.stderr    | 16 +++---
 .../const-eval/const-eval-overflow2b.stderr   | 16 +++---
 .../const-eval/const-eval-overflow2c.stderr   | 16 +++---
 .../consts/const-eval/erroneous-const.stderr  |  4 +-
 .../index-out-of-bounds-never-type.stderr     |  2 +-
 .../const-eval/index_out_of_bounds.stderr     |  2 +-
 .../index_out_of_bounds_propagated.stderr     |  2 +-
 .../ui/consts/const-eval/issue-43197.stderr   |  4 +-
 .../ui/consts/const-eval/issue-50814-2.stderr |  2 +-
 .../ui/consts/const-eval/issue-50814.stderr   |  2 +-
 .../const-eval/promoted_errors.noopt.stderr   | 12 ++--
 .../const-eval/promoted_errors.opt.stderr     | 10 ++--
 ...ted_errors.opt_with_overflow_checks.stderr | 12 ++--
 .../ui/consts/const-eval/pub_const_err.stderr |  2 +-
 .../const-eval/pub_const_err_bin.stderr       |  2 +-
 .../consts/const-eval/shift_overflow.stderr   |  2 +-
 .../const-eval/unused-broken-const.stderr     |  2 +-
 .../const-external-macro-const-err.stderr     |  2 +-
 .../const-len-underflow-separate-spans.stderr |  2 +-
 .../ui/consts/const-len-underflow-subspans.rs |  2 +-
 .../const-len-underflow-subspans.stderr       |  2 +-
 src/test/ui/consts/const-prop-ice.stderr      |  2 +-
 src/test/ui/consts/const-prop-ice2.stderr     |  2 +-
 src/test/ui/consts/const-slice-oob.rs         |  2 +-
 src/test/ui/consts/const-slice-oob.stderr     |  2 +-
 src/test/ui/error-codes/E0080.rs              |  2 +-
 src/test/ui/error-codes/E0080.stderr          |  4 +-
 src/test/ui/eval-enum.rs                      |  4 +-
 src/test/ui/eval-enum.stderr                  |  4 +-
 src/test/ui/issues/issue-54348.stderr         |  4 +-
 .../ui/issues/issue-8460-const.noopt.stderr   | 48 ++++++++--------
 .../ui/issues/issue-8460-const.opt.stderr     | 48 ++++++++--------
 ...8460-const.opt_with_overflow_checks.stderr | 48 ++++++++--------
 .../lint-exceeding-bitshifts.noopt.stderr     | 48 ++++++++--------
 .../lint/lint-exceeding-bitshifts.opt.stderr  | 48 ++++++++--------
 ...-bitshifts.opt_with_overflow_checks.stderr | 48 ++++++++--------
 .../ui/mir/mir_detects_invalid_ops.stderr     |  4 +-
 .../overflowing-lsh-1.stderr                  |  2 +-
 .../overflowing-lsh-2.stderr                  |  2 +-
 .../overflowing-lsh-3.stderr                  |  2 +-
 .../overflowing-lsh-4.stderr                  |  2 +-
 .../overflowing-rsh-1.stderr                  |  2 +-
 .../overflowing-rsh-2.stderr                  |  2 +-
 .../overflowing-rsh-3.stderr                  |  2 +-
 .../overflowing-rsh-4.stderr                  |  2 +-
 .../overflowing-rsh-5.stderr                  |  2 +-
 .../overflowing-rsh-6.stderr                  |  2 +-
 71 files changed, 323 insertions(+), 319 deletions(-)

diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 29daf7e9309aa..67dceed7c0123 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1279,49 +1279,49 @@ impl<O> AssertKind<O> {
         match self {
             BoundsCheck { ref len, ref index } => write!(
                 f,
-                "\"index out of bounds: the len is {{}} but the index is {{}}\", {:?}, {:?}",
+                "\"index out of bounds: the length is {{}} but the index is {{}}\", {:?}, {:?}",
                 len, index
             ),
 
             OverflowNeg(op) => {
-                write!(f, "\"attempt to negate {{}} which would overflow\", {:?}", op)
+                write!(f, "\"attempt to negate `{{}}`, which would overflow\", {:?}", op)
             }
-            DivisionByZero(op) => write!(f, "\"attempt to divide {{}} by zero\", {:?}", op),
+            DivisionByZero(op) => write!(f, "\"attempt to divide `{{}}` by zero\", {:?}", op),
             RemainderByZero(op) => write!(
                 f,
-                "\"attempt to calculate the remainder of {{}} with a divisor of zero\", {:?}",
+                "\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {:?}",
                 op
             ),
             Overflow(BinOp::Add, l, r) => write!(
                 f,
-                "\"attempt to compute `{{}} + {{}}` which would overflow\", {:?}, {:?}",
+                "\"attempt to compute `{{}} + {{}}`, which would overflow\", {:?}, {:?}",
                 l, r
             ),
             Overflow(BinOp::Sub, l, r) => write!(
                 f,
-                "\"attempt to compute `{{}} - {{}}` which would overflow\", {:?}, {:?}",
+                "\"attempt to compute `{{}} - {{}}`, which would overflow\", {:?}, {:?}",
                 l, r
             ),
             Overflow(BinOp::Mul, l, r) => write!(
                 f,
-                "\"attempt to compute `{{}} * {{}}` which would overflow\", {:?}, {:?}",
+                "\"attempt to compute `{{}} * {{}}`, which would overflow\", {:?}, {:?}",
                 l, r
             ),
             Overflow(BinOp::Div, l, r) => write!(
                 f,
-                "\"attempt to compute `{{}} / {{}}` which would overflow\", {:?}, {:?}",
+                "\"attempt to compute `{{}} / {{}}`, which would overflow\", {:?}, {:?}",
                 l, r
             ),
             Overflow(BinOp::Rem, l, r) => write!(
                 f,
-                "\"attempt to compute the remainder of `{{}} % {{}}` which would overflow\", {:?}, {:?}",
+                "\"attempt to compute the remainder of `{{}} % {{}}`, which would overflow\", {:?}, {:?}",
                 l, r
             ),
             Overflow(BinOp::Shr, _, r) => {
-                write!(f, "\"attempt to shift right by {{}} which would overflow\", {:?}", r)
+                write!(f, "\"attempt to shift right by `{{}}`, which would overflow\", {:?}", r)
             }
             Overflow(BinOp::Shl, _, r) => {
-                write!(f, "\"attempt to shift left by {{}} which would overflow\", {:?}", r)
+                write!(f, "\"attempt to shift left by `{{}}`, which would overflow\", {:?}", r)
             }
             _ => write!(f, "\"{}\"", self.description()),
         }
@@ -1332,36 +1332,40 @@ impl<O: fmt::Debug> fmt::Debug for AssertKind<O> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         use AssertKind::*;
         match self {
-            BoundsCheck { ref len, ref index } => {
-                write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index)
-            }
-            OverflowNeg(op) => write!(f, "attempt to negate {:#?} which would overflow", op),
-            DivisionByZero(op) => write!(f, "attempt to divide {:#?} by zero", op),
-            RemainderByZero(op) => {
-                write!(f, "attempt to calculate the remainder of {:#?} with a divisor of zero", op)
-            }
+            BoundsCheck { ref len, ref index } => write!(
+                f,
+                "index out of bounds: the length is {:?} but the index is {:?}",
+                len, index
+            ),
+            OverflowNeg(op) => write!(f, "attempt to negate `{:#?}`, which would overflow", op),
+            DivisionByZero(op) => write!(f, "attempt to divide `{:#?}` by zero", op),
+            RemainderByZero(op) => write!(
+                f,
+                "attempt to calculate the remainder of `{:#?}` with a divisor of zero",
+                op
+            ),
             Overflow(BinOp::Add, l, r) => {
-                write!(f, "attempt to compute `{:#?} + {:#?}` which would overflow", l, r)
+                write!(f, "attempt to compute `{:#?} + {:#?}`, which would overflow", l, r)
             }
             Overflow(BinOp::Sub, l, r) => {
-                write!(f, "attempt to compute `{:#?} - {:#?}` which would overflow", l, r)
+                write!(f, "attempt to compute `{:#?} - {:#?}`, which would overflow", l, r)
             }
             Overflow(BinOp::Mul, l, r) => {
-                write!(f, "attempt to compute `{:#?} * {:#?}` which would overflow", l, r)
+                write!(f, "attempt to compute `{:#?} * {:#?}`, which would overflow", l, r)
             }
             Overflow(BinOp::Div, l, r) => {
-                write!(f, "attempt to compute `{:#?} / {:#?}` which would overflow", l, r)
+                write!(f, "attempt to compute `{:#?} / {:#?}`, which would overflow", l, r)
             }
             Overflow(BinOp::Rem, l, r) => write!(
                 f,
-                "attempt to compute the remainder of `{:#?} % {:#?}` which would overflow",
+                "attempt to compute the remainder of `{:#?} % {:#?}`, which would overflow",
                 l, r
             ),
             Overflow(BinOp::Shr, _, r) => {
-                write!(f, "attempt to shift right by {:#?} which would overflow", r)
+                write!(f, "attempt to shift right by `{:#?}`, which would overflow", r)
             }
             Overflow(BinOp::Shl, _, r) => {
-                write!(f, "attempt to shift left by {:#?} which would overflow", r)
+                write!(f, "attempt to shift left by `{:#?}`, which would overflow", r)
             }
             _ => write!(f, "{}", self.description()),
         }
diff --git a/src/test/ui/array_const_index-0.rs b/src/test/ui/array_const_index-0.rs
index 3422aeae8c5be..4021dfcc6eb7d 100644
--- a/src/test/ui/array_const_index-0.rs
+++ b/src/test/ui/array_const_index-0.rs
@@ -1,6 +1,6 @@
 const A: &'static [i32] = &[];
 const B: i32 = (&A)[1];
-//~^ index out of bounds: the len is 0 but the index is 1
+//~^ index out of bounds: the length is 0 but the index is 1
 //~| ERROR any use of this value will cause an error
 
 fn main() {
diff --git a/src/test/ui/array_const_index-0.stderr b/src/test/ui/array_const_index-0.stderr
index 16ebc4a5775a0..7ccc3aa087e1e 100644
--- a/src/test/ui/array_const_index-0.stderr
+++ b/src/test/ui/array_const_index-0.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | const B: i32 = (&A)[1];
    | ---------------^^^^^^^-
    |                |
-   |                index out of bounds: the len is 0 but the index is 1
+   |                index out of bounds: the length is 0 but the index is 1
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/array_const_index-1.rs b/src/test/ui/array_const_index-1.rs
index 1f77cb6a3923f..d0ee1796c0ffc 100644
--- a/src/test/ui/array_const_index-1.rs
+++ b/src/test/ui/array_const_index-1.rs
@@ -1,6 +1,6 @@
 const A: [i32; 0] = [];
 const B: i32 = A[1];
-//~^ index out of bounds: the len is 0 but the index is 1
+//~^ index out of bounds: the length is 0 but the index is 1
 //~| ERROR any use of this value will cause an error
 
 fn main() {
diff --git a/src/test/ui/array_const_index-1.stderr b/src/test/ui/array_const_index-1.stderr
index 98a64eaadcf57..37de61b9df01b 100644
--- a/src/test/ui/array_const_index-1.stderr
+++ b/src/test/ui/array_const_index-1.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | const B: i32 = A[1];
    | ---------------^^^^-
    |                |
-   |                index out of bounds: the len is 0 but the index is 1
+   |                index out of bounds: the length is 0 but the index is 1
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.stderr b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr
index c1b08010cd5b6..1497633c26af9 100644
--- a/src/test/ui/associated-const/defaults-not-assumed-fail.stderr
+++ b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL |     const B: u8 = Self::A + 1;
    |     --------------^^^^^^^^^^^-
    |                   |
-   |                   attempt to compute `u8::MAX + 1_u8` which would overflow
+   |                   attempt to compute `u8::MAX + 1_u8`, which would overflow
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/associated-const/issue-69020-assoc-const-arith-overflow.noopt.stderr b/src/test/ui/associated-const/issue-69020-assoc-const-arith-overflow.noopt.stderr
index 724823e36405e..f59287bce736b 100644
--- a/src/test/ui/associated-const/issue-69020-assoc-const-arith-overflow.noopt.stderr
+++ b/src/test/ui/associated-const/issue-69020-assoc-const-arith-overflow.noopt.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:29:22
    |
 LL |     const NEG: i32 = -i32::MIN + T::NEG;
-   |                      ^^^^^^^^^ attempt to negate i32::MIN which would overflow
+   |                      ^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow
    |
    = note: `#[deny(arithmetic_overflow)]` on by default
 
@@ -10,25 +10,25 @@ error: this arithmetic operation will overflow
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:31:35
    |
 LL |     const NEG_REV: i32 = T::NEG + (-i32::MIN);
-   |                                   ^^^^^^^^^^^ attempt to negate i32::MIN which would overflow
+   |                                   ^^^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:34:22
    |
 LL |     const ADD: i32 = (i32::MAX+1) + T::ADD;
-   |                      ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32` which would overflow
+   |                      ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:36:36
    |
 LL |     const ADD_REV: i32 =  T::ADD + (i32::MAX+1);
-   |                                    ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32` which would overflow
+   |                                    ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:39:22
    |
 LL |     const DIV: i32 = (1/0) + T::DIV;
-   |                      ^^^^^ attempt to divide 1_i32 by zero
+   |                      ^^^^^ attempt to divide `1_i32` by zero
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
@@ -36,19 +36,19 @@ error: this operation will panic at runtime
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:41:35
    |
 LL |     const DIV_REV: i32 = T::DIV + (1/0);
-   |                                   ^^^^^ attempt to divide 1_i32 by zero
+   |                                   ^^^^^ attempt to divide `1_i32` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:44:22
    |
 LL |     const OOB: i32 = [1][1] + T::OOB;
-   |                      ^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |                      ^^^^^^ index out of bounds: the length is 1 but the index is 1
 
 error: this operation will panic at runtime
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:46:35
    |
 LL |     const OOB_REV: i32 = T::OOB + [1][1];
-   |                                   ^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |                                   ^^^^^^ index out of bounds: the length is 1 but the index is 1
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/associated-const/issue-69020-assoc-const-arith-overflow.opt.stderr b/src/test/ui/associated-const/issue-69020-assoc-const-arith-overflow.opt.stderr
index 724823e36405e..f59287bce736b 100644
--- a/src/test/ui/associated-const/issue-69020-assoc-const-arith-overflow.opt.stderr
+++ b/src/test/ui/associated-const/issue-69020-assoc-const-arith-overflow.opt.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:29:22
    |
 LL |     const NEG: i32 = -i32::MIN + T::NEG;
-   |                      ^^^^^^^^^ attempt to negate i32::MIN which would overflow
+   |                      ^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow
    |
    = note: `#[deny(arithmetic_overflow)]` on by default
 
@@ -10,25 +10,25 @@ error: this arithmetic operation will overflow
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:31:35
    |
 LL |     const NEG_REV: i32 = T::NEG + (-i32::MIN);
-   |                                   ^^^^^^^^^^^ attempt to negate i32::MIN which would overflow
+   |                                   ^^^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:34:22
    |
 LL |     const ADD: i32 = (i32::MAX+1) + T::ADD;
-   |                      ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32` which would overflow
+   |                      ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:36:36
    |
 LL |     const ADD_REV: i32 =  T::ADD + (i32::MAX+1);
-   |                                    ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32` which would overflow
+   |                                    ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:39:22
    |
 LL |     const DIV: i32 = (1/0) + T::DIV;
-   |                      ^^^^^ attempt to divide 1_i32 by zero
+   |                      ^^^^^ attempt to divide `1_i32` by zero
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
@@ -36,19 +36,19 @@ error: this operation will panic at runtime
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:41:35
    |
 LL |     const DIV_REV: i32 = T::DIV + (1/0);
-   |                                   ^^^^^ attempt to divide 1_i32 by zero
+   |                                   ^^^^^ attempt to divide `1_i32` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:44:22
    |
 LL |     const OOB: i32 = [1][1] + T::OOB;
-   |                      ^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |                      ^^^^^^ index out of bounds: the length is 1 but the index is 1
 
 error: this operation will panic at runtime
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:46:35
    |
 LL |     const OOB_REV: i32 = T::OOB + [1][1];
-   |                                   ^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |                                   ^^^^^^ index out of bounds: the length is 1 but the index is 1
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/associated-const/issue-69020-assoc-const-arith-overflow.opt_with_overflow_checks.stderr b/src/test/ui/associated-const/issue-69020-assoc-const-arith-overflow.opt_with_overflow_checks.stderr
index 724823e36405e..f59287bce736b 100644
--- a/src/test/ui/associated-const/issue-69020-assoc-const-arith-overflow.opt_with_overflow_checks.stderr
+++ b/src/test/ui/associated-const/issue-69020-assoc-const-arith-overflow.opt_with_overflow_checks.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:29:22
    |
 LL |     const NEG: i32 = -i32::MIN + T::NEG;
-   |                      ^^^^^^^^^ attempt to negate i32::MIN which would overflow
+   |                      ^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow
    |
    = note: `#[deny(arithmetic_overflow)]` on by default
 
@@ -10,25 +10,25 @@ error: this arithmetic operation will overflow
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:31:35
    |
 LL |     const NEG_REV: i32 = T::NEG + (-i32::MIN);
-   |                                   ^^^^^^^^^^^ attempt to negate i32::MIN which would overflow
+   |                                   ^^^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:34:22
    |
 LL |     const ADD: i32 = (i32::MAX+1) + T::ADD;
-   |                      ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32` which would overflow
+   |                      ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:36:36
    |
 LL |     const ADD_REV: i32 =  T::ADD + (i32::MAX+1);
-   |                                    ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32` which would overflow
+   |                                    ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:39:22
    |
 LL |     const DIV: i32 = (1/0) + T::DIV;
-   |                      ^^^^^ attempt to divide 1_i32 by zero
+   |                      ^^^^^ attempt to divide `1_i32` by zero
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
@@ -36,19 +36,19 @@ error: this operation will panic at runtime
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:41:35
    |
 LL |     const DIV_REV: i32 = T::DIV + (1/0);
-   |                                   ^^^^^ attempt to divide 1_i32 by zero
+   |                                   ^^^^^ attempt to divide `1_i32` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:44:22
    |
 LL |     const OOB: i32 = [1][1] + T::OOB;
-   |                      ^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |                      ^^^^^^ index out of bounds: the length is 1 but the index is 1
 
 error: this operation will panic at runtime
   --> $DIR/issue-69020-assoc-const-arith-overflow.rs:46:35
    |
 LL |     const OOB_REV: i32 = T::OOB + [1][1];
-   |                                   ^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |                                   ^^^^^^ index out of bounds: the length is 1 but the index is 1
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr
index 104cab8667c70..f95d6d2d5709c 100644
--- a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr
+++ b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/simple_fail.rs:7:33
    |
 LL | type Arr<const N: usize> = [u8; N - 1];
-   |                                 ^^^^^ attempt to compute `0_usize - 1_usize` which would overflow
+   |                                 ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr
index e2a3e4db8abd1..276fb716d4255 100644
--- a/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr
+++ b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr
@@ -2,7 +2,7 @@ warning: this operation will panic at runtime
   --> $DIR/ice-assert-fail-div-by-zero.rs:11:5
    |
 LL |     f.0 / 0;
-   |     ^^^^^^^ attempt to divide _ by zero
+   |     ^^^^^^^ attempt to divide `_` by zero
    |
 note: the lint level is defined here
   --> $DIR/ice-assert-fail-div-by-zero.rs:5:9
diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr
index 08c0231536a7f..5916ea6d323e6 100644
--- a/src/test/ui/consts/array-literal-index-oob.stderr
+++ b/src/test/ui/consts/array-literal-index-oob.stderr
@@ -2,7 +2,7 @@ warning: this operation will panic at runtime
   --> $DIR/array-literal-index-oob.rs:7:8
    |
 LL |     &{ [1, 2, 3][4] };
-   |        ^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 4
+   |        ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
    |
 note: the lint level is defined here
   --> $DIR/array-literal-index-oob.rs:4:20
diff --git a/src/test/ui/consts/assoc_const_generic_impl.stderr b/src/test/ui/consts/assoc_const_generic_impl.stderr
index cd27331ad512d..db64ebe0c4ae0 100644
--- a/src/test/ui/consts/assoc_const_generic_impl.stderr
+++ b/src/test/ui/consts/assoc_const_generic_impl.stderr
@@ -4,7 +4,7 @@ warning: any use of this value will cause an error
 LL |     const I_AM_ZERO_SIZED: ()  = [()][std::mem::size_of::<Self>()];
    |     -----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
    |                                  |
-   |                                  index out of bounds: the len is 1 but the index is 4
+   |                                  index out of bounds: the length is 1 but the index is 4
    |
 note: the lint level is defined here
   --> $DIR/assoc_const_generic_impl.rs:3:9
diff --git a/src/test/ui/consts/const-array-oob.rs b/src/test/ui/consts/const-array-oob.rs
index 1174a76adabcb..eca2fe18ab96a 100644
--- a/src/test/ui/consts/const-array-oob.rs
+++ b/src/test/ui/consts/const-array-oob.rs
@@ -5,7 +5,7 @@ const BAR: usize = FOO[5]; // no error, because the error below occurs before re
 
 const BLUB: [u32; FOO[4]] = [5, 6];
 //~^ ERROR evaluation of constant value failed [E0080]
-//~| index out of bounds: the len is 3 but the index is 4
+//~| index out of bounds: the length is 3 but the index is 4
 
 fn main() {
     let _ = BAR;
diff --git a/src/test/ui/consts/const-array-oob.stderr b/src/test/ui/consts/const-array-oob.stderr
index f25cac5cddd47..1aa3e88e52097 100644
--- a/src/test/ui/consts/const-array-oob.stderr
+++ b/src/test/ui/consts/const-array-oob.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/const-array-oob.rs:6:19
    |
 LL | const BLUB: [u32; FOO[4]] = [5, 6];
-   |                   ^^^^^^ index out of bounds: the len is 3 but the index is 4
+   |                   ^^^^^^ index out of bounds: the length is 3 but the index is 4
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-err-early.stderr b/src/test/ui/consts/const-err-early.stderr
index 0cb7751819774..36b36db7c18bc 100644
--- a/src/test/ui/consts/const-err-early.stderr
+++ b/src/test/ui/consts/const-err-early.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | pub const A: i8 = -std::i8::MIN;
    | ------------------^^^^^^^^^^^^^-
    |                   |
-   |                   attempt to negate i8::MIN which would overflow
+   |                   attempt to negate `i8::MIN`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/const-err-early.rs:1:9
@@ -18,7 +18,7 @@ error: any use of this value will cause an error
 LL | pub const B: u8 = 200u8 + 200u8;
    | ------------------^^^^^^^^^^^^^-
    |                   |
-   |                   attempt to compute `200_u8 + 200_u8` which would overflow
+   |                   attempt to compute `200_u8 + 200_u8`, which would overflow
 
 error: any use of this value will cause an error
   --> $DIR/const-err-early.rs:5:19
@@ -26,7 +26,7 @@ error: any use of this value will cause an error
 LL | pub const C: u8 = 200u8 * 4;
    | ------------------^^^^^^^^^-
    |                   |
-   |                   attempt to compute `200_u8 * 4_u8` which would overflow
+   |                   attempt to compute `200_u8 * 4_u8`, which would overflow
 
 error: any use of this value will cause an error
   --> $DIR/const-err-early.rs:6:19
@@ -34,7 +34,7 @@ error: any use of this value will cause an error
 LL | pub const D: u8 = 42u8 - (42u8 + 1);
    | ------------------^^^^^^^^^^^^^^^^^-
    |                   |
-   |                   attempt to compute `42_u8 - 43_u8` which would overflow
+   |                   attempt to compute `42_u8 - 43_u8`, which would overflow
 
 error: any use of this value will cause an error
   --> $DIR/const-err-early.rs:7:19
@@ -42,7 +42,7 @@ error: any use of this value will cause an error
 LL | pub const E: u8 = [5u8][1];
    | ------------------^^^^^^^^-
    |                   |
-   |                   index out of bounds: the len is 1 but the index is 1
+   |                   index out of bounds: the length is 1 but the index is 1
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/consts/const-err-multi.stderr b/src/test/ui/consts/const-err-multi.stderr
index a0c91ff6b54f2..5b688d4c6d84c 100644
--- a/src/test/ui/consts/const-err-multi.stderr
+++ b/src/test/ui/consts/const-err-multi.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | pub const A: i8 = -std::i8::MIN;
    | ------------------^^^^^^^^^^^^^-
    |                   |
-   |                   attempt to negate i8::MIN which would overflow
+   |                   attempt to negate `i8::MIN`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/const-err-multi.rs:1:9
diff --git a/src/test/ui/consts/const-err.stderr b/src/test/ui/consts/const-err.stderr
index ea27aa8fc8da0..693b74c2c2f61 100644
--- a/src/test/ui/consts/const-err.stderr
+++ b/src/test/ui/consts/const-err.stderr
@@ -4,7 +4,7 @@ warning: any use of this value will cause an error
 LL | const FOO: u8 = [5u8][1];
    | ----------------^^^^^^^^-
    |                 |
-   |                 index out of bounds: the len is 1 but the index is 1
+   |                 index out of bounds: the length is 1 but the index is 1
    |
 note: the lint level is defined here
   --> $DIR/const-err.rs:5:9
diff --git a/src/test/ui/consts/const-err2.noopt.stderr b/src/test/ui/consts/const-err2.noopt.stderr
index 687ffc4c4bf95..2473632cbc804 100644
--- a/src/test/ui/consts/const-err2.noopt.stderr
+++ b/src/test/ui/consts/const-err2.noopt.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:19:13
    |
 LL |     let a = -std::i8::MIN;
-   |             ^^^^^^^^^^^^^ attempt to negate i8::MIN which would overflow
+   |             ^^^^^^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
    |
    = note: `#[deny(arithmetic_overflow)]` on by default
 
@@ -10,37 +10,37 @@ error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:21:18
    |
 LL |     let a_i128 = -std::i128::MIN;
-   |                  ^^^^^^^^^^^^^^^ attempt to negate i128::MIN which would overflow
+   |                  ^^^^^^^^^^^^^^^ attempt to negate `i128::MIN`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:23:13
    |
 LL |     let b = 200u8 + 200u8 + 200u8;
-   |             ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8` which would overflow
+   |             ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:25:18
    |
 LL |     let b_i128 = std::i128::MIN - std::i128::MAX;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX` which would overflow
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:27:13
    |
 LL |     let c = 200u8 * 4;
-   |             ^^^^^^^^^ attempt to compute `200_u8 * 4_u8` which would overflow
+   |             ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:29:13
    |
 LL |     let d = 42u8 - (42u8 + 1);
-   |             ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8` which would overflow
+   |             ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/const-err2.rs:31:14
    |
 LL |     let _e = [5u8][1];
-   |              ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |              ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
diff --git a/src/test/ui/consts/const-err2.opt.stderr b/src/test/ui/consts/const-err2.opt.stderr
index 687ffc4c4bf95..2473632cbc804 100644
--- a/src/test/ui/consts/const-err2.opt.stderr
+++ b/src/test/ui/consts/const-err2.opt.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:19:13
    |
 LL |     let a = -std::i8::MIN;
-   |             ^^^^^^^^^^^^^ attempt to negate i8::MIN which would overflow
+   |             ^^^^^^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
    |
    = note: `#[deny(arithmetic_overflow)]` on by default
 
@@ -10,37 +10,37 @@ error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:21:18
    |
 LL |     let a_i128 = -std::i128::MIN;
-   |                  ^^^^^^^^^^^^^^^ attempt to negate i128::MIN which would overflow
+   |                  ^^^^^^^^^^^^^^^ attempt to negate `i128::MIN`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:23:13
    |
 LL |     let b = 200u8 + 200u8 + 200u8;
-   |             ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8` which would overflow
+   |             ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:25:18
    |
 LL |     let b_i128 = std::i128::MIN - std::i128::MAX;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX` which would overflow
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:27:13
    |
 LL |     let c = 200u8 * 4;
-   |             ^^^^^^^^^ attempt to compute `200_u8 * 4_u8` which would overflow
+   |             ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:29:13
    |
 LL |     let d = 42u8 - (42u8 + 1);
-   |             ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8` which would overflow
+   |             ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/const-err2.rs:31:14
    |
 LL |     let _e = [5u8][1];
-   |              ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |              ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
diff --git a/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr b/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr
index 687ffc4c4bf95..2473632cbc804 100644
--- a/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr
+++ b/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:19:13
    |
 LL |     let a = -std::i8::MIN;
-   |             ^^^^^^^^^^^^^ attempt to negate i8::MIN which would overflow
+   |             ^^^^^^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
    |
    = note: `#[deny(arithmetic_overflow)]` on by default
 
@@ -10,37 +10,37 @@ error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:21:18
    |
 LL |     let a_i128 = -std::i128::MIN;
-   |                  ^^^^^^^^^^^^^^^ attempt to negate i128::MIN which would overflow
+   |                  ^^^^^^^^^^^^^^^ attempt to negate `i128::MIN`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:23:13
    |
 LL |     let b = 200u8 + 200u8 + 200u8;
-   |             ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8` which would overflow
+   |             ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:25:18
    |
 LL |     let b_i128 = std::i128::MIN - std::i128::MAX;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX` which would overflow
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:27:13
    |
 LL |     let c = 200u8 * 4;
-   |             ^^^^^^^^^ attempt to compute `200_u8 * 4_u8` which would overflow
+   |             ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/const-err2.rs:29:13
    |
 LL |     let d = 42u8 - (42u8 + 1);
-   |             ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8` which would overflow
+   |             ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/const-err2.rs:31:14
    |
 LL |     let _e = [5u8][1];
-   |              ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |              ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.stderr b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
index 62f339809e431..65dfbd8097e76 100644
--- a/src/test/ui/consts/const-eval/conditional_array_execution.stderr
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
@@ -4,7 +4,7 @@ warning: any use of this value will cause an error
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
    | ------------------^^^^^---------------------------
    |                   |
-   |                   attempt to compute `5_u32 - 6_u32` which would overflow
+   |                   attempt to compute `5_u32 - 6_u32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/conditional_array_execution.rs:3:9
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr
index dd79cbd7e5ff7..0ae51786b36a5 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/const-eval-overflow-3.rs:20:11
    |
 LL |     = [0; (i8::MAX + 1) as usize];
-   |           ^^^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8` which would overflow
+   |           ^^^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4.stderr
index 30c52a82ea364..e548fc266c212 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-4.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-4.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/const-eval-overflow-4.rs:13:13
    |
 LL |     : [u32; (i8::MAX as i8 + 1i8) as usize]
-   |             ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8` which would overflow
+   |             ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2.stderr
index 2ad557a71139e..51a810b8f3ba8 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow2.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | / const VALS_I8: (i8,) =
 LL | |     (
 LL | |      i8::MIN - 1,
-   | |      ^^^^^^^^^^^ attempt to compute `i8::MIN - 1_i8` which would overflow
+   | |      ^^^^^^^^^^^ attempt to compute `i8::MIN - 1_i8`, which would overflow
 LL | |      );
    | |_______-
    |
@@ -20,7 +20,7 @@ error: any use of this value will cause an error
 LL | / const VALS_I16: (i16,) =
 LL | |     (
 LL | |      i16::MIN - 1,
-   | |      ^^^^^^^^^^^^ attempt to compute `i16::MIN - 1_i16` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `i16::MIN - 1_i16`, which would overflow
 LL | |      );
    | |_______-
 
@@ -30,7 +30,7 @@ error: any use of this value will cause an error
 LL | / const VALS_I32: (i32,) =
 LL | |     (
 LL | |      i32::MIN - 1,
-   | |      ^^^^^^^^^^^^ attempt to compute `i32::MIN - 1_i32` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `i32::MIN - 1_i32`, which would overflow
 LL | |      );
    | |_______-
 
@@ -40,7 +40,7 @@ error: any use of this value will cause an error
 LL | / const VALS_I64: (i64,) =
 LL | |     (
 LL | |      i64::MIN - 1,
-   | |      ^^^^^^^^^^^^ attempt to compute `i64::MIN - 1_i64` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `i64::MIN - 1_i64`, which would overflow
 LL | |      );
    | |_______-
 
@@ -50,7 +50,7 @@ error: any use of this value will cause an error
 LL | / const VALS_U8: (u8,) =
 LL | |     (
 LL | |      u8::MIN - 1,
-   | |      ^^^^^^^^^^^ attempt to compute `0_u8 - 1_u8` which would overflow
+   | |      ^^^^^^^^^^^ attempt to compute `0_u8 - 1_u8`, which would overflow
 LL | |      );
    | |_______-
 
@@ -59,7 +59,7 @@ error: any use of this value will cause an error
    |
 LL | / const VALS_U16: (u16,) = (
 LL | |      u16::MIN - 1,
-   | |      ^^^^^^^^^^^^ attempt to compute `0_u16 - 1_u16` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `0_u16 - 1_u16`, which would overflow
 LL | |      );
    | |_______-
 
@@ -68,7 +68,7 @@ error: any use of this value will cause an error
    |
 LL | / const VALS_U32: (u32,) = (
 LL | |      u32::MIN - 1,
-   | |      ^^^^^^^^^^^^ attempt to compute `0_u32 - 1_u32` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
 LL | |      );
    | |_______-
 
@@ -78,7 +78,7 @@ error: any use of this value will cause an error
 LL | / const VALS_U64: (u64,) =
 LL | |     (
 LL | |      u64::MIN - 1,
-   | |      ^^^^^^^^^^^^ attempt to compute `0_u64 - 1_u64` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `0_u64 - 1_u64`, which would overflow
 LL | |      );
    | |_______-
 
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr
index fce616b296c29..eec440fcb76a5 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | / const VALS_I8: (i8,) =
 LL | |     (
 LL | |      i8::MAX + 1,
-   | |      ^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8` which would overflow
+   | |      ^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow
 LL | |      );
    | |_______-
    |
@@ -20,7 +20,7 @@ error: any use of this value will cause an error
 LL | / const VALS_I16: (i16,) =
 LL | |     (
 LL | |      i16::MAX + 1,
-   | |      ^^^^^^^^^^^^ attempt to compute `i16::MAX + 1_i16` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `i16::MAX + 1_i16`, which would overflow
 LL | |      );
    | |_______-
 
@@ -30,7 +30,7 @@ error: any use of this value will cause an error
 LL | / const VALS_I32: (i32,) =
 LL | |     (
 LL | |      i32::MAX + 1,
-   | |      ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow
 LL | |      );
    | |_______-
 
@@ -40,7 +40,7 @@ error: any use of this value will cause an error
 LL | / const VALS_I64: (i64,) =
 LL | |     (
 LL | |      i64::MAX + 1,
-   | |      ^^^^^^^^^^^^ attempt to compute `i64::MAX + 1_i64` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `i64::MAX + 1_i64`, which would overflow
 LL | |      );
    | |_______-
 
@@ -50,7 +50,7 @@ error: any use of this value will cause an error
 LL | / const VALS_U8: (u8,) =
 LL | |     (
 LL | |      u8::MAX + 1,
-   | |      ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8` which would overflow
+   | |      ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
 LL | |      );
    | |_______-
 
@@ -59,7 +59,7 @@ error: any use of this value will cause an error
    |
 LL | / const VALS_U16: (u16,) = (
 LL | |      u16::MAX + 1,
-   | |      ^^^^^^^^^^^^ attempt to compute `u16::MAX + 1_u16` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `u16::MAX + 1_u16`, which would overflow
 LL | |      );
    | |_______-
 
@@ -68,7 +68,7 @@ error: any use of this value will cause an error
    |
 LL | / const VALS_U32: (u32,) = (
 LL | |      u32::MAX + 1,
-   | |      ^^^^^^^^^^^^ attempt to compute `u32::MAX + 1_u32` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `u32::MAX + 1_u32`, which would overflow
 LL | |      );
    | |_______-
 
@@ -78,7 +78,7 @@ error: any use of this value will cause an error
 LL | / const VALS_U64: (u64,) =
 LL | |     (
 LL | |      u64::MAX + 1,
-   | |      ^^^^^^^^^^^^ attempt to compute `u64::MAX + 1_u64` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `u64::MAX + 1_u64`, which would overflow
 LL | |      );
    | |_______-
 
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr
index 76201524d32bc..e44f94c202166 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | / const VALS_I8: (i8,) =
 LL | |     (
 LL | |      i8::MIN * 2,
-   | |      ^^^^^^^^^^^ attempt to compute `i8::MIN * 2_i8` which would overflow
+   | |      ^^^^^^^^^^^ attempt to compute `i8::MIN * 2_i8`, which would overflow
 LL | |      );
    | |_______-
    |
@@ -20,7 +20,7 @@ error: any use of this value will cause an error
 LL | / const VALS_I16: (i16,) =
 LL | |     (
 LL | |      i16::MIN * 2,
-   | |      ^^^^^^^^^^^^ attempt to compute `i16::MIN * 2_i16` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `i16::MIN * 2_i16`, which would overflow
 LL | |      );
    | |_______-
 
@@ -30,7 +30,7 @@ error: any use of this value will cause an error
 LL | / const VALS_I32: (i32,) =
 LL | |     (
 LL | |      i32::MIN * 2,
-   | |      ^^^^^^^^^^^^ attempt to compute `i32::MIN * 2_i32` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `i32::MIN * 2_i32`, which would overflow
 LL | |      );
    | |_______-
 
@@ -40,7 +40,7 @@ error: any use of this value will cause an error
 LL | / const VALS_I64: (i64,) =
 LL | |     (
 LL | |      i64::MIN * 2,
-   | |      ^^^^^^^^^^^^ attempt to compute `i64::MIN * 2_i64` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `i64::MIN * 2_i64`, which would overflow
 LL | |      );
    | |_______-
 
@@ -50,7 +50,7 @@ error: any use of this value will cause an error
 LL | / const VALS_U8: (u8,) =
 LL | |     (
 LL | |      u8::MAX * 2,
-   | |      ^^^^^^^^^^^ attempt to compute `u8::MAX * 2_u8` which would overflow
+   | |      ^^^^^^^^^^^ attempt to compute `u8::MAX * 2_u8`, which would overflow
 LL | |      );
    | |_______-
 
@@ -59,7 +59,7 @@ error: any use of this value will cause an error
    |
 LL | / const VALS_U16: (u16,) = (
 LL | |      u16::MAX * 2,
-   | |      ^^^^^^^^^^^^ attempt to compute `u16::MAX * 2_u16` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `u16::MAX * 2_u16`, which would overflow
 LL | |      );
    | |_______-
 
@@ -68,7 +68,7 @@ error: any use of this value will cause an error
    |
 LL | / const VALS_U32: (u32,) = (
 LL | |      u32::MAX * 2,
-   | |      ^^^^^^^^^^^^ attempt to compute `u32::MAX * 2_u32` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `u32::MAX * 2_u32`, which would overflow
 LL | |      );
    | |_______-
 
@@ -78,7 +78,7 @@ error: any use of this value will cause an error
 LL | / const VALS_U64: (u64,) =
 LL | |     (
 LL | |      u64::MAX * 2,
-   | |      ^^^^^^^^^^^^ attempt to compute `u64::MAX * 2_u64` which would overflow
+   | |      ^^^^^^^^^^^^ attempt to compute `u64::MAX * 2_u64`, which would overflow
 LL | |      );
    | |_______-
 
diff --git a/src/test/ui/consts/const-eval/erroneous-const.stderr b/src/test/ui/consts/const-eval/erroneous-const.stderr
index f06e2c33fd0cc..7087a6f668c82 100644
--- a/src/test/ui/consts/const-eval/erroneous-const.stderr
+++ b/src/test/ui/consts/const-eval/erroneous-const.stderr
@@ -2,7 +2,7 @@ warning: this operation will panic at runtime
   --> $DIR/erroneous-const.rs:6:22
    |
 LL |     const VOID: () = [()][2];
-   |                      ^^^^^^^ index out of bounds: the len is 1 but the index is 2
+   |                      ^^^^^^^ index out of bounds: the length is 1 but the index is 2
    |
 note: the lint level is defined here
   --> $DIR/erroneous-const.rs:2:20
@@ -16,7 +16,7 @@ warning: any use of this value will cause an error
 LL |     const VOID: () = [()][2];
    |     -----------------^^^^^^^-
    |                      |
-   |                      index out of bounds: the len is 1 but the index is 2
+   |                      index out of bounds: the length is 1 but the index is 2
    |
 note: the lint level is defined here
   --> $DIR/erroneous-const.rs:2:9
diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
index 33e60dd7c9138..8647da90a37d4 100644
--- a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
+++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
@@ -4,7 +4,7 @@ warning: any use of this value will cause an error
 LL |     const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
    |     --------------------------------------------------------^^^^^---
    |                                                             |
-   |                                                             index out of bounds: the len is 0 but the index is 0
+   |                                                             index out of bounds: the length is 0 but the index is 0
    |
 note: the lint level is defined here
   --> $DIR/index-out-of-bounds-never-type.rs:4:9
diff --git a/src/test/ui/consts/const-eval/index_out_of_bounds.stderr b/src/test/ui/consts/const-eval/index_out_of_bounds.stderr
index 1b2974e4e3da4..8bb3a0c67d65b 100644
--- a/src/test/ui/consts/const-eval/index_out_of_bounds.stderr
+++ b/src/test/ui/consts/const-eval/index_out_of_bounds.stderr
@@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/index_out_of_bounds.rs:1:19
    |
 LL | static FOO: i32 = [][0];
-   |                   ^^^^^ index out of bounds: the len is 0 but the index is 0
+   |                   ^^^^^ index out of bounds: the length is 0 but the index is 0
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr
index 4188efd021d13..d247d691dbb1b 100644
--- a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr
+++ b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr
@@ -2,7 +2,7 @@ error: this operation will panic at runtime
   --> $DIR/index_out_of_bounds_propagated.rs:5:5
    |
 LL |     array[1];
-   |     ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |     ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr
index b3e1f496ae3e3..27e067cedbb5c 100644
--- a/src/test/ui/consts/const-eval/issue-43197.stderr
+++ b/src/test/ui/consts/const-eval/issue-43197.stderr
@@ -4,7 +4,7 @@ warning: any use of this value will cause an error
 LL |     const X: u32 = 0 - 1;
    |     ---------------^^^^^-
    |                    |
-   |                    attempt to compute `0_u32 - 1_u32` which would overflow
+   |                    attempt to compute `0_u32 - 1_u32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/issue-43197.rs:3:9
@@ -18,7 +18,7 @@ warning: any use of this value will cause an error
 LL |     const Y: u32 = foo(0 - 1);
    |     -------------------^^^^^--
    |                        |
-   |                        attempt to compute `0_u32 - 1_u32` which would overflow
+   |                        attempt to compute `0_u32 - 1_u32`, which would overflow
 
 error[E0080]: evaluation of constant expression failed
   --> $DIR/issue-43197.rs:14:23
diff --git a/src/test/ui/consts/const-eval/issue-50814-2.stderr b/src/test/ui/consts/const-eval/issue-50814-2.stderr
index e04bf03a20cce..ca8885e935090 100644
--- a/src/test/ui/consts/const-eval/issue-50814-2.stderr
+++ b/src/test/ui/consts/const-eval/issue-50814-2.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL |     const BAR: usize = [5, 6, 7][T::BOO];
    |     -------------------^^^^^^^^^^^^^^^^^-
    |                        |
-   |                        index out of bounds: the len is 3 but the index is 42
+   |                        index out of bounds: the length is 3 but the index is 42
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr
index 4be84f8d1843c..7327138627648 100644
--- a/src/test/ui/consts/const-eval/issue-50814.stderr
+++ b/src/test/ui/consts/const-eval/issue-50814.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL |     const MAX: u8 = A::MAX + B::MAX;
    |     ----------------^^^^^^^^^^^^^^^-
    |                     |
-   |                     attempt to compute `u8::MAX + u8::MAX` which would overflow
+   |                     attempt to compute `u8::MAX + u8::MAX`, which would overflow
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr b/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr
index 52313205dc80b..ce83d8e9bb0c9 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr
@@ -2,7 +2,7 @@ warning: this arithmetic operation will overflow
   --> $DIR/promoted_errors.rs:12:20
    |
 LL |     println!("{}", 0u32 - 1);
-   |                    ^^^^^^^^ attempt to compute `0_u32 - 1_u32` which would overflow
+   |                    ^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/promoted_errors.rs:9:20
@@ -14,13 +14,13 @@ warning: this arithmetic operation will overflow
   --> $DIR/promoted_errors.rs:14:14
    |
 LL |     let _x = 0u32 - 1;
-   |              ^^^^^^^^ attempt to compute `0_u32 - 1_u32` which would overflow
+   |              ^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
 
 warning: this operation will panic at runtime
   --> $DIR/promoted_errors.rs:16:20
    |
 LL |     println!("{}", 1 / (1 - 1));
-   |                    ^^^^^^^^^^^ attempt to divide 1_i32 by zero
+   |                    ^^^^^^^^^^^ attempt to divide `1_i32` by zero
    |
 note: the lint level is defined here
   --> $DIR/promoted_errors.rs:9:41
@@ -50,13 +50,13 @@ warning: this operation will panic at runtime
   --> $DIR/promoted_errors.rs:20:14
    |
 LL |     let _x = 1 / (1 - 1);
-   |              ^^^^^^^^^^^ attempt to divide 1_i32 by zero
+   |              ^^^^^^^^^^^ attempt to divide `1_i32` by zero
 
 warning: this operation will panic at runtime
   --> $DIR/promoted_errors.rs:22:20
    |
 LL |     println!("{}", 1 / (false as u32));
-   |                    ^^^^^^^^^^^^^^^^^^ attempt to divide 1_u32 by zero
+   |                    ^^^^^^^^^^^^^^^^^^ attempt to divide `1_u32` by zero
 
 warning: reaching this expression at runtime will panic or abort
   --> $DIR/promoted_errors.rs:22:20
@@ -74,7 +74,7 @@ warning: this operation will panic at runtime
   --> $DIR/promoted_errors.rs:26:14
    |
 LL |     let _x = 1 / (false as u32);
-   |              ^^^^^^^^^^^^^^^^^^ attempt to divide 1_u32 by zero
+   |              ^^^^^^^^^^^^^^^^^^ attempt to divide `1_u32` by zero
 
 warning: 10 warnings emitted
 
diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr
index b411bb2e7fe20..2c66b175cfc2b 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.opt.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr
@@ -2,7 +2,7 @@ warning: this arithmetic operation will overflow
   --> $DIR/promoted_errors.rs:14:14
    |
 LL |     let _x = 0u32 - 1;
-   |              ^^^^^^^^ attempt to compute `0_u32 - 1_u32` which would overflow
+   |              ^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/promoted_errors.rs:9:20
@@ -14,7 +14,7 @@ warning: this operation will panic at runtime
   --> $DIR/promoted_errors.rs:16:20
    |
 LL |     println!("{}", 1 / (1 - 1));
-   |                    ^^^^^^^^^^^ attempt to divide 1_i32 by zero
+   |                    ^^^^^^^^^^^ attempt to divide `1_i32` by zero
    |
 note: the lint level is defined here
   --> $DIR/promoted_errors.rs:9:41
@@ -44,13 +44,13 @@ warning: this operation will panic at runtime
   --> $DIR/promoted_errors.rs:20:14
    |
 LL |     let _x = 1 / (1 - 1);
-   |              ^^^^^^^^^^^ attempt to divide 1_i32 by zero
+   |              ^^^^^^^^^^^ attempt to divide `1_i32` by zero
 
 warning: this operation will panic at runtime
   --> $DIR/promoted_errors.rs:22:20
    |
 LL |     println!("{}", 1 / (false as u32));
-   |                    ^^^^^^^^^^^^^^^^^^ attempt to divide 1_u32 by zero
+   |                    ^^^^^^^^^^^^^^^^^^ attempt to divide `1_u32` by zero
 
 warning: reaching this expression at runtime will panic or abort
   --> $DIR/promoted_errors.rs:22:20
@@ -68,7 +68,7 @@ warning: this operation will panic at runtime
   --> $DIR/promoted_errors.rs:26:14
    |
 LL |     let _x = 1 / (false as u32);
-   |              ^^^^^^^^^^^^^^^^^^ attempt to divide 1_u32 by zero
+   |              ^^^^^^^^^^^^^^^^^^ attempt to divide `1_u32` by zero
 
 warning: 9 warnings emitted
 
diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr
index 52313205dc80b..ce83d8e9bb0c9 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr
@@ -2,7 +2,7 @@ warning: this arithmetic operation will overflow
   --> $DIR/promoted_errors.rs:12:20
    |
 LL |     println!("{}", 0u32 - 1);
-   |                    ^^^^^^^^ attempt to compute `0_u32 - 1_u32` which would overflow
+   |                    ^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/promoted_errors.rs:9:20
@@ -14,13 +14,13 @@ warning: this arithmetic operation will overflow
   --> $DIR/promoted_errors.rs:14:14
    |
 LL |     let _x = 0u32 - 1;
-   |              ^^^^^^^^ attempt to compute `0_u32 - 1_u32` which would overflow
+   |              ^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
 
 warning: this operation will panic at runtime
   --> $DIR/promoted_errors.rs:16:20
    |
 LL |     println!("{}", 1 / (1 - 1));
-   |                    ^^^^^^^^^^^ attempt to divide 1_i32 by zero
+   |                    ^^^^^^^^^^^ attempt to divide `1_i32` by zero
    |
 note: the lint level is defined here
   --> $DIR/promoted_errors.rs:9:41
@@ -50,13 +50,13 @@ warning: this operation will panic at runtime
   --> $DIR/promoted_errors.rs:20:14
    |
 LL |     let _x = 1 / (1 - 1);
-   |              ^^^^^^^^^^^ attempt to divide 1_i32 by zero
+   |              ^^^^^^^^^^^ attempt to divide `1_i32` by zero
 
 warning: this operation will panic at runtime
   --> $DIR/promoted_errors.rs:22:20
    |
 LL |     println!("{}", 1 / (false as u32));
-   |                    ^^^^^^^^^^^^^^^^^^ attempt to divide 1_u32 by zero
+   |                    ^^^^^^^^^^^^^^^^^^ attempt to divide `1_u32` by zero
 
 warning: reaching this expression at runtime will panic or abort
   --> $DIR/promoted_errors.rs:22:20
@@ -74,7 +74,7 @@ warning: this operation will panic at runtime
   --> $DIR/promoted_errors.rs:26:14
    |
 LL |     let _x = 1 / (false as u32);
-   |              ^^^^^^^^^^^^^^^^^^ attempt to divide 1_u32 by zero
+   |              ^^^^^^^^^^^^^^^^^^ attempt to divide `1_u32` by zero
 
 warning: 10 warnings emitted
 
diff --git a/src/test/ui/consts/const-eval/pub_const_err.stderr b/src/test/ui/consts/const-eval/pub_const_err.stderr
index ecdba2f1c506d..5be0fd96723dd 100644
--- a/src/test/ui/consts/const-eval/pub_const_err.stderr
+++ b/src/test/ui/consts/const-eval/pub_const_err.stderr
@@ -4,7 +4,7 @@ warning: any use of this value will cause an error
 LL | pub const Z: u32 = 0 - 1;
    | -------------------^^^^^-
    |                    |
-   |                    attempt to compute `0_u32 - 1_u32` which would overflow
+   |                    attempt to compute `0_u32 - 1_u32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/pub_const_err.rs:2:9
diff --git a/src/test/ui/consts/const-eval/pub_const_err_bin.stderr b/src/test/ui/consts/const-eval/pub_const_err_bin.stderr
index b2b65767dc059..55f8a58ea9470 100644
--- a/src/test/ui/consts/const-eval/pub_const_err_bin.stderr
+++ b/src/test/ui/consts/const-eval/pub_const_err_bin.stderr
@@ -4,7 +4,7 @@ warning: any use of this value will cause an error
 LL | pub const Z: u32 = 0 - 1;
    | -------------------^^^^^-
    |                    |
-   |                    attempt to compute `0_u32 - 1_u32` which would overflow
+   |                    attempt to compute `0_u32 - 1_u32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/pub_const_err_bin.rs:2:9
diff --git a/src/test/ui/consts/const-eval/shift_overflow.stderr b/src/test/ui/consts/const-eval/shift_overflow.stderr
index 478769ca9ffe1..e8d4076a61a24 100644
--- a/src/test/ui/consts/const-eval/shift_overflow.stderr
+++ b/src/test/ui/consts/const-eval/shift_overflow.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/shift_overflow.rs:3:9
    |
 LL |     X = 1 << ((u32::MAX as u64) + 1),
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to shift left by 4294967296_u64 which would overflow
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to shift left by `4294967296_u64`, which would overflow
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/unused-broken-const.stderr b/src/test/ui/consts/const-eval/unused-broken-const.stderr
index a13cb877888bd..0cb13790f2f53 100644
--- a/src/test/ui/consts/const-eval/unused-broken-const.stderr
+++ b/src/test/ui/consts/const-eval/unused-broken-const.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | const FOO: i32 = [][0];
    | -----------------^^^^^-
    |                  |
-   |                  index out of bounds: the len is 0 but the index is 0
+   |                  index out of bounds: the length is 0 but the index is 0
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/consts/const-external-macro-const-err.stderr b/src/test/ui/consts/const-external-macro-const-err.stderr
index 06a630d82d840..350e4b24de100 100644
--- a/src/test/ui/consts/const-external-macro-const-err.stderr
+++ b/src/test/ui/consts/const-external-macro-const-err.stderr
@@ -2,7 +2,7 @@ error: any use of this value will cause an error
   --> $DIR/const-external-macro-const-err.rs:12:5
    |
 LL |     static_assert!(2 + 2 == 5);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1
    |
    = note: `#[deny(const_err)]` on by default
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/consts/const-len-underflow-separate-spans.stderr b/src/test/ui/consts/const-len-underflow-separate-spans.stderr
index eff50587ca341..2ab6d0ffdef4c 100644
--- a/src/test/ui/consts/const-len-underflow-separate-spans.stderr
+++ b/src/test/ui/consts/const-len-underflow-separate-spans.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | const LEN: usize = ONE - TWO;
    | -------------------^^^^^^^^^-
    |                    |
-   |                    attempt to compute `1_usize - 2_usize` which would overflow
+   |                    attempt to compute `1_usize - 2_usize`, which would overflow
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/consts/const-len-underflow-subspans.rs b/src/test/ui/consts/const-len-underflow-subspans.rs
index 8ef8ef9625c81..ed77e9078425a 100644
--- a/src/test/ui/consts/const-len-underflow-subspans.rs
+++ b/src/test/ui/consts/const-len-underflow-subspans.rs
@@ -7,5 +7,5 @@ const TWO: usize = 2;
 fn main() {
     let a: [i8; ONE - TWO] = unimplemented!();
     //~^ ERROR evaluation of constant value failed
-    //~| attempt to compute `1_usize - 2_usize` which would overflow
+    //~| attempt to compute `1_usize - 2_usize`, which would overflow
 }
diff --git a/src/test/ui/consts/const-len-underflow-subspans.stderr b/src/test/ui/consts/const-len-underflow-subspans.stderr
index e52e64b25b6de..68e958b378da7 100644
--- a/src/test/ui/consts/const-len-underflow-subspans.stderr
+++ b/src/test/ui/consts/const-len-underflow-subspans.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/const-len-underflow-subspans.rs:8:17
    |
 LL |     let a: [i8; ONE - TWO] = unimplemented!();
-   |                 ^^^^^^^^^ attempt to compute `1_usize - 2_usize` which would overflow
+   |                 ^^^^^^^^^ attempt to compute `1_usize - 2_usize`, which would overflow
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-prop-ice.stderr b/src/test/ui/consts/const-prop-ice.stderr
index 7bb4acb235aa7..3bcf2b2de7bd7 100644
--- a/src/test/ui/consts/const-prop-ice.stderr
+++ b/src/test/ui/consts/const-prop-ice.stderr
@@ -2,7 +2,7 @@ error: this operation will panic at runtime
   --> $DIR/const-prop-ice.rs:4:5
    |
 LL |     [0; 3][3u64 as usize];
-   |     ^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 3
+   |     ^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 3
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
diff --git a/src/test/ui/consts/const-prop-ice2.stderr b/src/test/ui/consts/const-prop-ice2.stderr
index 73405eca3408c..2b65ffc2db760 100644
--- a/src/test/ui/consts/const-prop-ice2.stderr
+++ b/src/test/ui/consts/const-prop-ice2.stderr
@@ -2,7 +2,7 @@ error: this operation will panic at runtime
   --> $DIR/const-prop-ice2.rs:6:20
    |
 LL |     println!("{}", xs[Enum::One as usize]);
-   |                    ^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |                    ^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
diff --git a/src/test/ui/consts/const-slice-oob.rs b/src/test/ui/consts/const-slice-oob.rs
index 1775f35fac441..70852f8f56929 100644
--- a/src/test/ui/consts/const-slice-oob.rs
+++ b/src/test/ui/consts/const-slice-oob.rs
@@ -2,7 +2,7 @@
 
 const FOO: &'static[u32] = &[1, 2, 3];
 const BAR: u32 = FOO[5];
-//~^ index out of bounds: the len is 3 but the index is 5
+//~^ index out of bounds: the length is 3 but the index is 5
 //~| ERROR any use of this value will cause an error
 
 fn main() {
diff --git a/src/test/ui/consts/const-slice-oob.stderr b/src/test/ui/consts/const-slice-oob.stderr
index 7e191a6336144..0077bafe9e628 100644
--- a/src/test/ui/consts/const-slice-oob.stderr
+++ b/src/test/ui/consts/const-slice-oob.stderr
@@ -4,7 +4,7 @@ error: any use of this value will cause an error
 LL | const BAR: u32 = FOO[5];
    | -----------------^^^^^^-
    |                  |
-   |                  index out of bounds: the len is 3 but the index is 5
+   |                  index out of bounds: the length is 3 but the index is 5
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/error-codes/E0080.rs b/src/test/ui/error-codes/E0080.rs
index b31cf2ec447e7..ea3264b61b356 100644
--- a/src/test/ui/error-codes/E0080.rs
+++ b/src/test/ui/error-codes/E0080.rs
@@ -1,6 +1,6 @@
 enum Enum {
     X = (1 << 500), //~ ERROR E0080
-    //~| attempt to shift left by 500_i32 which would overflow
+    //~| attempt to shift left by `500_i32`, which would overflow
     Y = (1 / 0) //~ ERROR E0080
 }
 
diff --git a/src/test/ui/error-codes/E0080.stderr b/src/test/ui/error-codes/E0080.stderr
index 3acd15ff6bc9e..60ed9a4358f12 100644
--- a/src/test/ui/error-codes/E0080.stderr
+++ b/src/test/ui/error-codes/E0080.stderr
@@ -2,13 +2,13 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/E0080.rs:2:9
    |
 LL |     X = (1 << 500),
-   |         ^^^^^^^^^^ attempt to shift left by 500_i32 which would overflow
+   |         ^^^^^^^^^^ attempt to shift left by `500_i32`, which would overflow
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/E0080.rs:4:9
    |
 LL |     Y = (1 / 0)
-   |         ^^^^^^^ attempt to divide 1_isize by zero
+   |         ^^^^^^^ attempt to divide `1_isize` by zero
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/eval-enum.rs b/src/test/ui/eval-enum.rs
index 4ef06c78069f2..551f10e66e35b 100644
--- a/src/test/ui/eval-enum.rs
+++ b/src/test/ui/eval-enum.rs
@@ -1,9 +1,9 @@
 enum Test {
     DivZero = 1/0,
-    //~^ attempt to divide 1_isize by zero
+    //~^ attempt to divide `1_isize` by zero
     //~| ERROR evaluation of constant value failed
     RemZero = 1%0,
-    //~^ attempt to calculate the remainder of 1_isize with a divisor of zero
+    //~^ attempt to calculate the remainder of `1_isize` with a divisor of zero
     //~| ERROR evaluation of constant value failed
 }
 
diff --git a/src/test/ui/eval-enum.stderr b/src/test/ui/eval-enum.stderr
index dd89a2d7c3bfc..fb4d903489f7f 100644
--- a/src/test/ui/eval-enum.stderr
+++ b/src/test/ui/eval-enum.stderr
@@ -2,13 +2,13 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/eval-enum.rs:2:15
    |
 LL |     DivZero = 1/0,
-   |               ^^^ attempt to divide 1_isize by zero
+   |               ^^^ attempt to divide `1_isize` by zero
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/eval-enum.rs:5:15
    |
 LL |     RemZero = 1%0,
-   |               ^^^ attempt to calculate the remainder of 1_isize with a divisor of zero
+   |               ^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-54348.stderr b/src/test/ui/issues/issue-54348.stderr
index 6b67125e36cb2..eb85f349843c4 100644
--- a/src/test/ui/issues/issue-54348.stderr
+++ b/src/test/ui/issues/issue-54348.stderr
@@ -2,7 +2,7 @@ error: this operation will panic at runtime
   --> $DIR/issue-54348.rs:5:5
    |
 LL |     [1][1.5 as usize];
-   |     ^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |     ^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
@@ -10,7 +10,7 @@ error: this operation will panic at runtime
   --> $DIR/issue-54348.rs:6:5
    |
 LL |     [1][1u64 as usize];
-   |     ^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
+   |     ^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-8460-const.noopt.stderr b/src/test/ui/issues/issue-8460-const.noopt.stderr
index eb8d66790ccea..739b5468743b2 100644
--- a/src/test/ui/issues/issue-8460-const.noopt.stderr
+++ b/src/test/ui/issues/issue-8460-const.noopt.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:14:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize` which would overflow
+   |                                    ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow
    |
    = note: `#[deny(arithmetic_overflow)]` on by default
 
@@ -10,37 +10,37 @@ error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:16:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8` which would overflow
+   |                                    ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:18:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:20:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:22:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:24:36
    |
 LL |     assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128` which would overflow
+   |                                    ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:26:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
-   |                                    ^^^^^^^^^^ attempt to divide 1_isize by zero
+   |                                    ^^^^^^^^^^ attempt to divide `1_isize` by zero
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
@@ -48,103 +48,103 @@ error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:28:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
-   |                                    ^^^^^^^ attempt to divide 1_i8 by zero
+   |                                    ^^^^^^^ attempt to divide `1_i8` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:30:36
    |
 LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide 1_i16 by zero
+   |                                    ^^^^^^^^ attempt to divide `1_i16` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:32:36
    |
 LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide 1_i32 by zero
+   |                                    ^^^^^^^^ attempt to divide `1_i32` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:34:36
    |
 LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide 1_i64 by zero
+   |                                    ^^^^^^^^ attempt to divide `1_i64` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:36:36
    |
 LL |     assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
-   |                                    ^^^^^^^^^ attempt to divide 1_i128 by zero
+   |                                    ^^^^^^^^^ attempt to divide `1_i128` by zero
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:38:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize` which would overflow
+   |                                    ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:40:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8` which would overflow
+   |                                    ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:42:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:44:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:46:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:48:36
    |
 LL |     assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128` which would overflow
+   |                                    ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:50:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
-   |                                    ^^^^^^^^^^ attempt to calculate the remainder of 1_isize with a divisor of zero
+   |                                    ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:52:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
-   |                                    ^^^^^^^ attempt to calculate the remainder of 1_i8 with a divisor of zero
+   |                                    ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:54:36
    |
 LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder of 1_i16 with a divisor of zero
+   |                                    ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:56:36
    |
 LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder of 1_i32 with a divisor of zero
+   |                                    ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:58:36
    |
 LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder of 1_i64 with a divisor of zero
+   |                                    ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:60:36
    |
 LL |     assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
-   |                                    ^^^^^^^^^ attempt to calculate the remainder of 1_i128 with a divisor of zero
+   |                                    ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
 
 error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/issues/issue-8460-const.opt.stderr b/src/test/ui/issues/issue-8460-const.opt.stderr
index eb8d66790ccea..739b5468743b2 100644
--- a/src/test/ui/issues/issue-8460-const.opt.stderr
+++ b/src/test/ui/issues/issue-8460-const.opt.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:14:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize` which would overflow
+   |                                    ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow
    |
    = note: `#[deny(arithmetic_overflow)]` on by default
 
@@ -10,37 +10,37 @@ error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:16:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8` which would overflow
+   |                                    ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:18:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:20:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:22:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:24:36
    |
 LL |     assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128` which would overflow
+   |                                    ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:26:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
-   |                                    ^^^^^^^^^^ attempt to divide 1_isize by zero
+   |                                    ^^^^^^^^^^ attempt to divide `1_isize` by zero
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
@@ -48,103 +48,103 @@ error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:28:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
-   |                                    ^^^^^^^ attempt to divide 1_i8 by zero
+   |                                    ^^^^^^^ attempt to divide `1_i8` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:30:36
    |
 LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide 1_i16 by zero
+   |                                    ^^^^^^^^ attempt to divide `1_i16` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:32:36
    |
 LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide 1_i32 by zero
+   |                                    ^^^^^^^^ attempt to divide `1_i32` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:34:36
    |
 LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide 1_i64 by zero
+   |                                    ^^^^^^^^ attempt to divide `1_i64` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:36:36
    |
 LL |     assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
-   |                                    ^^^^^^^^^ attempt to divide 1_i128 by zero
+   |                                    ^^^^^^^^^ attempt to divide `1_i128` by zero
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:38:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize` which would overflow
+   |                                    ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:40:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8` which would overflow
+   |                                    ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:42:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:44:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:46:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:48:36
    |
 LL |     assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128` which would overflow
+   |                                    ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:50:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
-   |                                    ^^^^^^^^^^ attempt to calculate the remainder of 1_isize with a divisor of zero
+   |                                    ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:52:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
-   |                                    ^^^^^^^ attempt to calculate the remainder of 1_i8 with a divisor of zero
+   |                                    ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:54:36
    |
 LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder of 1_i16 with a divisor of zero
+   |                                    ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:56:36
    |
 LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder of 1_i32 with a divisor of zero
+   |                                    ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:58:36
    |
 LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder of 1_i64 with a divisor of zero
+   |                                    ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:60:36
    |
 LL |     assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
-   |                                    ^^^^^^^^^ attempt to calculate the remainder of 1_i128 with a divisor of zero
+   |                                    ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
 
 error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr b/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr
index eb8d66790ccea..739b5468743b2 100644
--- a/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr
+++ b/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:14:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize` which would overflow
+   |                                    ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow
    |
    = note: `#[deny(arithmetic_overflow)]` on by default
 
@@ -10,37 +10,37 @@ error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:16:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8` which would overflow
+   |                                    ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:18:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:20:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:22:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:24:36
    |
 LL |     assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128` which would overflow
+   |                                    ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:26:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
-   |                                    ^^^^^^^^^^ attempt to divide 1_isize by zero
+   |                                    ^^^^^^^^^^ attempt to divide `1_isize` by zero
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
@@ -48,103 +48,103 @@ error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:28:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
-   |                                    ^^^^^^^ attempt to divide 1_i8 by zero
+   |                                    ^^^^^^^ attempt to divide `1_i8` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:30:36
    |
 LL |     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide 1_i16 by zero
+   |                                    ^^^^^^^^ attempt to divide `1_i16` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:32:36
    |
 LL |     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide 1_i32 by zero
+   |                                    ^^^^^^^^ attempt to divide `1_i32` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:34:36
    |
 LL |     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to divide 1_i64 by zero
+   |                                    ^^^^^^^^ attempt to divide `1_i64` by zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:36:36
    |
 LL |     assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
-   |                                    ^^^^^^^^^ attempt to divide 1_i128 by zero
+   |                                    ^^^^^^^^^ attempt to divide `1_i128` by zero
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:38:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize` which would overflow
+   |                                    ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:40:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8` which would overflow
+   |                                    ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:42:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:44:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:46:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64` which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
 
 error: this arithmetic operation will overflow
   --> $DIR/issue-8460-const.rs:48:36
    |
 LL |     assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128` which would overflow
+   |                                    ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:50:36
    |
 LL |     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
-   |                                    ^^^^^^^^^^ attempt to calculate the remainder of 1_isize with a divisor of zero
+   |                                    ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:52:36
    |
 LL |     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
-   |                                    ^^^^^^^ attempt to calculate the remainder of 1_i8 with a divisor of zero
+   |                                    ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:54:36
    |
 LL |     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder of 1_i16 with a divisor of zero
+   |                                    ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:56:36
    |
 LL |     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder of 1_i32 with a divisor of zero
+   |                                    ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:58:36
    |
 LL |     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
-   |                                    ^^^^^^^^ attempt to calculate the remainder of 1_i64 with a divisor of zero
+   |                                    ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:60:36
    |
 LL |     assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
-   |                                    ^^^^^^^^^ attempt to calculate the remainder of 1_i128 with a divisor of zero
+   |                                    ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
 
 error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr
index d33b99bdc4387..173f3d0d7b7e6 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr
@@ -2,7 +2,7 @@ warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:18:20
    |
 LL |     const N: i32 = T::N << 42;
-   |                    ^^^^^^^^^^ attempt to shift left by 42_i32 which would overflow
+   |                    ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/lint-exceeding-bitshifts.rs:10:9
@@ -14,139 +14,139 @@ warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:22:13
    |
 LL |     let _ = x << 42;
-   |             ^^^^^^^ attempt to shift left by 42_i32 which would overflow
+   |             ^^^^^^^ attempt to shift left by `42_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:27:15
    |
 LL |       let n = 1u8 << 8;
-   |               ^^^^^^^^ attempt to shift left by 8_i32 which would overflow
+   |               ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:29:15
    |
 LL |       let n = 1u16 << 16;
-   |               ^^^^^^^^^^ attempt to shift left by 16_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:31:15
    |
 LL |       let n = 1u32 << 32;
-   |               ^^^^^^^^^^ attempt to shift left by 32_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:33:15
    |
 LL |       let n = 1u64 << 64;
-   |               ^^^^^^^^^^ attempt to shift left by 64_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:35:15
    |
 LL |       let n = 1i8 << 8;
-   |               ^^^^^^^^ attempt to shift left by 8_i32 which would overflow
+   |               ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:37:15
    |
 LL |       let n = 1i16 << 16;
-   |               ^^^^^^^^^^ attempt to shift left by 16_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:39:15
    |
 LL |       let n = 1i32 << 32;
-   |               ^^^^^^^^^^ attempt to shift left by 32_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:41:15
    |
 LL |       let n = 1i64 << 64;
-   |               ^^^^^^^^^^ attempt to shift left by 64_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:44:15
    |
 LL |       let n = 1u8 >> 8;
-   |               ^^^^^^^^ attempt to shift right by 8_i32 which would overflow
+   |               ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:46:15
    |
 LL |       let n = 1u16 >> 16;
-   |               ^^^^^^^^^^ attempt to shift right by 16_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:48:15
    |
 LL |       let n = 1u32 >> 32;
-   |               ^^^^^^^^^^ attempt to shift right by 32_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:50:15
    |
 LL |       let n = 1u64 >> 64;
-   |               ^^^^^^^^^^ attempt to shift right by 64_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:52:15
    |
 LL |       let n = 1i8 >> 8;
-   |               ^^^^^^^^ attempt to shift right by 8_i32 which would overflow
+   |               ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:54:15
    |
 LL |       let n = 1i16 >> 16;
-   |               ^^^^^^^^^^ attempt to shift right by 16_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:56:15
    |
 LL |       let n = 1i32 >> 32;
-   |               ^^^^^^^^^^ attempt to shift right by 32_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:58:15
    |
 LL |       let n = 1i64 >> 64;
-   |               ^^^^^^^^^^ attempt to shift right by 64_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:62:15
    |
 LL |       let n = n << 8;
-   |               ^^^^^^ attempt to shift left by 8_i32 which would overflow
+   |               ^^^^^^ attempt to shift left by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:64:15
    |
 LL |       let n = 1u8 << -8;
-   |               ^^^^^^^^^ attempt to shift left by -8_i32 which would overflow
+   |               ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:69:15
    |
 LL |       let n = 1u8 << (4+4);
-   |               ^^^^^^^^^^^^ attempt to shift left by 8_i32 which would overflow
+   |               ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:71:15
    |
 LL |       let n = 1i64 >> [64][0];
-   |               ^^^^^^^^^^^^^^^ attempt to shift right by 64_i32 which would overflow
+   |               ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:77:15
    |
 LL |       let n = 1_isize << BITS;
-   |               ^^^^^^^^^^^^^^^ attempt to shift left by %BITS% which would overflow
+   |               ^^^^^^^^^^^^^^^ attempt to shift left by `64_usize`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:78:15
    |
 LL |       let n = 1_usize << BITS;
-   |               ^^^^^^^^^^^^^^^ attempt to shift left by %BITS% which would overflow
+   |               ^^^^^^^^^^^^^^^ attempt to shift left by `64_usize`, which would overflow
 
 warning: 24 warnings emitted
 
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr
index d33b99bdc4387..173f3d0d7b7e6 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr
@@ -2,7 +2,7 @@ warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:18:20
    |
 LL |     const N: i32 = T::N << 42;
-   |                    ^^^^^^^^^^ attempt to shift left by 42_i32 which would overflow
+   |                    ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/lint-exceeding-bitshifts.rs:10:9
@@ -14,139 +14,139 @@ warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:22:13
    |
 LL |     let _ = x << 42;
-   |             ^^^^^^^ attempt to shift left by 42_i32 which would overflow
+   |             ^^^^^^^ attempt to shift left by `42_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:27:15
    |
 LL |       let n = 1u8 << 8;
-   |               ^^^^^^^^ attempt to shift left by 8_i32 which would overflow
+   |               ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:29:15
    |
 LL |       let n = 1u16 << 16;
-   |               ^^^^^^^^^^ attempt to shift left by 16_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:31:15
    |
 LL |       let n = 1u32 << 32;
-   |               ^^^^^^^^^^ attempt to shift left by 32_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:33:15
    |
 LL |       let n = 1u64 << 64;
-   |               ^^^^^^^^^^ attempt to shift left by 64_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:35:15
    |
 LL |       let n = 1i8 << 8;
-   |               ^^^^^^^^ attempt to shift left by 8_i32 which would overflow
+   |               ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:37:15
    |
 LL |       let n = 1i16 << 16;
-   |               ^^^^^^^^^^ attempt to shift left by 16_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:39:15
    |
 LL |       let n = 1i32 << 32;
-   |               ^^^^^^^^^^ attempt to shift left by 32_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:41:15
    |
 LL |       let n = 1i64 << 64;
-   |               ^^^^^^^^^^ attempt to shift left by 64_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:44:15
    |
 LL |       let n = 1u8 >> 8;
-   |               ^^^^^^^^ attempt to shift right by 8_i32 which would overflow
+   |               ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:46:15
    |
 LL |       let n = 1u16 >> 16;
-   |               ^^^^^^^^^^ attempt to shift right by 16_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:48:15
    |
 LL |       let n = 1u32 >> 32;
-   |               ^^^^^^^^^^ attempt to shift right by 32_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:50:15
    |
 LL |       let n = 1u64 >> 64;
-   |               ^^^^^^^^^^ attempt to shift right by 64_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:52:15
    |
 LL |       let n = 1i8 >> 8;
-   |               ^^^^^^^^ attempt to shift right by 8_i32 which would overflow
+   |               ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:54:15
    |
 LL |       let n = 1i16 >> 16;
-   |               ^^^^^^^^^^ attempt to shift right by 16_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:56:15
    |
 LL |       let n = 1i32 >> 32;
-   |               ^^^^^^^^^^ attempt to shift right by 32_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:58:15
    |
 LL |       let n = 1i64 >> 64;
-   |               ^^^^^^^^^^ attempt to shift right by 64_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:62:15
    |
 LL |       let n = n << 8;
-   |               ^^^^^^ attempt to shift left by 8_i32 which would overflow
+   |               ^^^^^^ attempt to shift left by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:64:15
    |
 LL |       let n = 1u8 << -8;
-   |               ^^^^^^^^^ attempt to shift left by -8_i32 which would overflow
+   |               ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:69:15
    |
 LL |       let n = 1u8 << (4+4);
-   |               ^^^^^^^^^^^^ attempt to shift left by 8_i32 which would overflow
+   |               ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:71:15
    |
 LL |       let n = 1i64 >> [64][0];
-   |               ^^^^^^^^^^^^^^^ attempt to shift right by 64_i32 which would overflow
+   |               ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:77:15
    |
 LL |       let n = 1_isize << BITS;
-   |               ^^^^^^^^^^^^^^^ attempt to shift left by %BITS% which would overflow
+   |               ^^^^^^^^^^^^^^^ attempt to shift left by `64_usize`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:78:15
    |
 LL |       let n = 1_usize << BITS;
-   |               ^^^^^^^^^^^^^^^ attempt to shift left by %BITS% which would overflow
+   |               ^^^^^^^^^^^^^^^ attempt to shift left by `64_usize`, which would overflow
 
 warning: 24 warnings emitted
 
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr
index d33b99bdc4387..173f3d0d7b7e6 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr
@@ -2,7 +2,7 @@ warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:18:20
    |
 LL |     const N: i32 = T::N << 42;
-   |                    ^^^^^^^^^^ attempt to shift left by 42_i32 which would overflow
+   |                    ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/lint-exceeding-bitshifts.rs:10:9
@@ -14,139 +14,139 @@ warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:22:13
    |
 LL |     let _ = x << 42;
-   |             ^^^^^^^ attempt to shift left by 42_i32 which would overflow
+   |             ^^^^^^^ attempt to shift left by `42_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:27:15
    |
 LL |       let n = 1u8 << 8;
-   |               ^^^^^^^^ attempt to shift left by 8_i32 which would overflow
+   |               ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:29:15
    |
 LL |       let n = 1u16 << 16;
-   |               ^^^^^^^^^^ attempt to shift left by 16_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:31:15
    |
 LL |       let n = 1u32 << 32;
-   |               ^^^^^^^^^^ attempt to shift left by 32_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:33:15
    |
 LL |       let n = 1u64 << 64;
-   |               ^^^^^^^^^^ attempt to shift left by 64_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:35:15
    |
 LL |       let n = 1i8 << 8;
-   |               ^^^^^^^^ attempt to shift left by 8_i32 which would overflow
+   |               ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:37:15
    |
 LL |       let n = 1i16 << 16;
-   |               ^^^^^^^^^^ attempt to shift left by 16_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:39:15
    |
 LL |       let n = 1i32 << 32;
-   |               ^^^^^^^^^^ attempt to shift left by 32_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:41:15
    |
 LL |       let n = 1i64 << 64;
-   |               ^^^^^^^^^^ attempt to shift left by 64_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:44:15
    |
 LL |       let n = 1u8 >> 8;
-   |               ^^^^^^^^ attempt to shift right by 8_i32 which would overflow
+   |               ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:46:15
    |
 LL |       let n = 1u16 >> 16;
-   |               ^^^^^^^^^^ attempt to shift right by 16_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:48:15
    |
 LL |       let n = 1u32 >> 32;
-   |               ^^^^^^^^^^ attempt to shift right by 32_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:50:15
    |
 LL |       let n = 1u64 >> 64;
-   |               ^^^^^^^^^^ attempt to shift right by 64_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:52:15
    |
 LL |       let n = 1i8 >> 8;
-   |               ^^^^^^^^ attempt to shift right by 8_i32 which would overflow
+   |               ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:54:15
    |
 LL |       let n = 1i16 >> 16;
-   |               ^^^^^^^^^^ attempt to shift right by 16_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:56:15
    |
 LL |       let n = 1i32 >> 32;
-   |               ^^^^^^^^^^ attempt to shift right by 32_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:58:15
    |
 LL |       let n = 1i64 >> 64;
-   |               ^^^^^^^^^^ attempt to shift right by 64_i32 which would overflow
+   |               ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:62:15
    |
 LL |       let n = n << 8;
-   |               ^^^^^^ attempt to shift left by 8_i32 which would overflow
+   |               ^^^^^^ attempt to shift left by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:64:15
    |
 LL |       let n = 1u8 << -8;
-   |               ^^^^^^^^^ attempt to shift left by -8_i32 which would overflow
+   |               ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:69:15
    |
 LL |       let n = 1u8 << (4+4);
-   |               ^^^^^^^^^^^^ attempt to shift left by 8_i32 which would overflow
+   |               ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:71:15
    |
 LL |       let n = 1i64 >> [64][0];
-   |               ^^^^^^^^^^^^^^^ attempt to shift right by 64_i32 which would overflow
+   |               ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:77:15
    |
 LL |       let n = 1_isize << BITS;
-   |               ^^^^^^^^^^^^^^^ attempt to shift left by %BITS% which would overflow
+   |               ^^^^^^^^^^^^^^^ attempt to shift left by `64_usize`, which would overflow
 
 warning: this arithmetic operation will overflow
   --> $DIR/lint-exceeding-bitshifts.rs:78:15
    |
 LL |       let n = 1_usize << BITS;
-   |               ^^^^^^^^^^^^^^^ attempt to shift left by %BITS% which would overflow
+   |               ^^^^^^^^^^^^^^^ attempt to shift left by `64_usize`, which would overflow
 
 warning: 24 warnings emitted
 
diff --git a/src/test/ui/mir/mir_detects_invalid_ops.stderr b/src/test/ui/mir/mir_detects_invalid_ops.stderr
index b4f74a52a74cd..0fe56f4172515 100644
--- a/src/test/ui/mir/mir_detects_invalid_ops.stderr
+++ b/src/test/ui/mir/mir_detects_invalid_ops.stderr
@@ -2,7 +2,7 @@ error: this operation will panic at runtime
   --> $DIR/mir_detects_invalid_ops.rs:11:14
    |
 LL |     let _z = 1 / y;
-   |              ^^^^^ attempt to divide 1_i32 by zero
+   |              ^^^^^ attempt to divide `1_i32` by zero
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
@@ -10,7 +10,7 @@ error: this operation will panic at runtime
   --> $DIR/mir_detects_invalid_ops.rs:16:14
    |
 LL |     let _z = 1 % y;
-   |              ^^^^^ attempt to calculate the remainder of 1_i32 with a divisor of zero
+   |              ^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-1.stderr b/src/test/ui/numbers-arithmetic/overflowing-lsh-1.stderr
index 995afeeed880c..1d029939c7028 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-lsh-1.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-1.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/overflowing-lsh-1.rs:7:14
    |
 LL |     let _x = 1_i32 << 32;
-   |              ^^^^^^^^^^^ attempt to shift left by 32_i32 which would overflow
+   |              ^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/overflowing-lsh-1.rs:4:9
diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-2.stderr b/src/test/ui/numbers-arithmetic/overflowing-lsh-2.stderr
index e6f6b1ccd192d..8598792e08043 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-lsh-2.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-2.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/overflowing-lsh-2.rs:7:14
    |
 LL |     let _x = 1 << -1;
-   |              ^^^^^^^ attempt to shift left by -1_i32 which would overflow
+   |              ^^^^^^^ attempt to shift left by `-1_i32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/overflowing-lsh-2.rs:4:9
diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-3.stderr b/src/test/ui/numbers-arithmetic/overflowing-lsh-3.stderr
index e57b892b8085d..9c6f806f1d65c 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-lsh-3.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-3.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/overflowing-lsh-3.rs:7:14
    |
 LL |     let _x = 1_u64 << 64;
-   |              ^^^^^^^^^^^ attempt to shift left by 64_i32 which would overflow
+   |              ^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/overflowing-lsh-3.rs:4:9
diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-4.stderr b/src/test/ui/numbers-arithmetic/overflowing-lsh-4.stderr
index f20b41c1baa4f..08081a0b7876d 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-lsh-4.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-4.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/overflowing-lsh-4.rs:11:13
    |
 LL |     let x = 1_i8 << 17;
-   |             ^^^^^^^^^^ attempt to shift left by 17_i32 which would overflow
+   |             ^^^^^^^^^^ attempt to shift left by `17_i32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/overflowing-lsh-4.rs:7:9
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-1.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-1.stderr
index 18861a1b96fa8..4d726fa7fec21 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-1.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-1.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/overflowing-rsh-1.rs:7:14
    |
 LL |     let _x = -1_i32 >> 32;
-   |              ^^^^^^^^^^^^ attempt to shift right by 32_i32 which would overflow
+   |              ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/overflowing-rsh-1.rs:4:9
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-2.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-2.stderr
index a2fb2b90535c3..9a8349d5ddb79 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-2.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-2.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/overflowing-rsh-2.rs:7:14
    |
 LL |     let _x = -1_i32 >> -1;
-   |              ^^^^^^^^^^^^ attempt to shift right by -1_i32 which would overflow
+   |              ^^^^^^^^^^^^ attempt to shift right by `-1_i32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/overflowing-rsh-2.rs:4:9
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-3.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-3.stderr
index 24588b4a6b9b6..f48b7ff6de54b 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-3.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-3.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/overflowing-rsh-3.rs:7:14
    |
 LL |     let _x = -1_i64 >> 64;
-   |              ^^^^^^^^^^^^ attempt to shift right by 64_i32 which would overflow
+   |              ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/overflowing-rsh-3.rs:4:9
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-4.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-4.stderr
index 3f59653ea6075..4816a389965d6 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-4.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-4.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/overflowing-rsh-4.rs:11:13
    |
 LL |     let x = 2_i8 >> 17;
-   |             ^^^^^^^^^^ attempt to shift right by 17_i32 which would overflow
+   |             ^^^^^^^^^^ attempt to shift right by `17_i32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/overflowing-rsh-4.rs:7:9
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-5.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-5.stderr
index 8b0daf1551e4b..cd36f543d68b3 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-5.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-5.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/overflowing-rsh-5.rs:7:14
    |
 LL |     let _n = 1i64 >> [64][0];
-   |              ^^^^^^^^^^^^^^^ attempt to shift right by 64_i32 which would overflow
+   |              ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/overflowing-rsh-5.rs:4:9
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-6.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-6.stderr
index 53a1445b54e38..bec8b17df0b4c 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-6.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-6.stderr
@@ -2,7 +2,7 @@ error: this arithmetic operation will overflow
   --> $DIR/overflowing-rsh-6.rs:7:14
    |
 LL |     let _n = 1i64 >> [64][0];
-   |              ^^^^^^^^^^^^^^^ attempt to shift right by 64_i32 which would overflow
+   |              ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
    |
 note: the lint level is defined here
   --> $DIR/overflowing-rsh-6.rs:4:9

From c9c50681def1e3a26226d1f2bbe9a4f866cbfea6 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 15 Sep 2020 20:34:58 +0100
Subject: [PATCH 13/40] `char` not char

---
 compiler/rustc_typeck/src/check/pat.rs        |  2 +-
 src/test/ui/error-codes/E0029-teach.rs        |  2 +-
 src/test/ui/error-codes/E0029-teach.stderr    |  2 +-
 src/test/ui/error-codes/E0029.rs              |  2 +-
 src/test/ui/error-codes/E0029.stderr          |  2 +-
 .../half-open-range-pats-bad-types.rs         |  6 ++---
 .../half-open-range-pats-bad-types.stderr     |  6 ++---
 src/test/ui/match/match-range-fail.rs         |  6 ++---
 src/test/ui/match/match-range-fail.stderr     |  6 ++---
 src/test/ui/parser/recover-range-pats.rs      | 24 +++++++++----------
 src/test/ui/parser/recover-range-pats.stderr  | 24 +++++++++----------
 .../ui/pattern/patkind-litrange-no-expr.rs    |  2 +-
 .../pattern/patkind-litrange-no-expr.stderr   |  2 +-
 .../ui/qualified/qualified-path-params.rs     |  5 ++--
 .../ui/qualified/qualified-path-params.stderr |  2 +-
 15 files changed, 47 insertions(+), 46 deletions(-)

diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 54b0671fab5a7..8c6a47168a10a 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -494,7 +494,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.tcx.sess,
             span,
             E0029,
-            "only char and numeric types are allowed in range patterns"
+            "only `char` and numeric types are allowed in range patterns"
         );
         let msg = |ty| format!("this is of type `{}` but it should be `char` or numeric", ty);
         let mut one_side_err = |first_span, first_ty, second: Option<(bool, Ty<'tcx>, Span)>| {
diff --git a/src/test/ui/error-codes/E0029-teach.rs b/src/test/ui/error-codes/E0029-teach.rs
index 83058d397cf28..3ff8cb348e76a 100644
--- a/src/test/ui/error-codes/E0029-teach.rs
+++ b/src/test/ui/error-codes/E0029-teach.rs
@@ -5,7 +5,7 @@ fn main() {
 
     match s {
         "hello" ..= "world" => {}
-        //~^ ERROR only char and numeric types are allowed in range patterns
+        //~^ ERROR only `char` and numeric types are allowed in range patterns
         _ => {}
     }
 }
diff --git a/src/test/ui/error-codes/E0029-teach.stderr b/src/test/ui/error-codes/E0029-teach.stderr
index ec146ca86f596..b89b2e7d11e8b 100644
--- a/src/test/ui/error-codes/E0029-teach.stderr
+++ b/src/test/ui/error-codes/E0029-teach.stderr
@@ -1,4 +1,4 @@
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/E0029-teach.rs:7:9
    |
 LL |         "hello" ..= "world" => {}
diff --git a/src/test/ui/error-codes/E0029.rs b/src/test/ui/error-codes/E0029.rs
index fe0d851832b3d..d9b53e113c01e 100644
--- a/src/test/ui/error-codes/E0029.rs
+++ b/src/test/ui/error-codes/E0029.rs
@@ -3,7 +3,7 @@ fn main() {
 
     match s {
         "hello" ..= "world" => {}
-        //~^ ERROR only char and numeric types are allowed in range patterns
+        //~^ ERROR only `char` and numeric types are allowed in range patterns
         _ => {}
     }
 }
diff --git a/src/test/ui/error-codes/E0029.stderr b/src/test/ui/error-codes/E0029.stderr
index e54722ae7b9b8..f7250b39d3f91 100644
--- a/src/test/ui/error-codes/E0029.stderr
+++ b/src/test/ui/error-codes/E0029.stderr
@@ -1,4 +1,4 @@
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/E0029.rs:5:9
    |
 LL |         "hello" ..= "world" => {}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
index 7cddf5f652a31..b08732219db7d 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
@@ -2,7 +2,7 @@
 #![feature(exclusive_range_pattern)]
 
 fn main() {
-    let "a".. = "a"; //~ ERROR only char and numeric types are allowed in range patterns
-    let .."a" = "a"; //~ ERROR only char and numeric types are allowed in range patterns
-    let ..="a" = "a"; //~ ERROR only char and numeric types are allowed in range patterns
+    let "a".. = "a"; //~ ERROR only `char` and numeric types are allowed in range patterns
+    let .."a" = "a"; //~ ERROR only `char` and numeric types are allowed in range patterns
+    let ..="a" = "a"; //~ ERROR only `char` and numeric types are allowed in range patterns
 }
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
index 68ca3637150d3..df0dae5696de6 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
@@ -1,16 +1,16 @@
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/half-open-range-pats-bad-types.rs:5:9
    |
 LL |     let "a".. = "a";
    |         ^^^ this is of type `&'static str` but it should be `char` or numeric
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/half-open-range-pats-bad-types.rs:6:11
    |
 LL |     let .."a" = "a";
    |           ^^^ this is of type `&'static str` but it should be `char` or numeric
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/half-open-range-pats-bad-types.rs:7:12
    |
 LL |     let ..="a" = "a";
diff --git a/src/test/ui/match/match-range-fail.rs b/src/test/ui/match/match-range-fail.rs
index c0cdbe342a07d..e53c8463ef4bf 100644
--- a/src/test/ui/match/match-range-fail.rs
+++ b/src/test/ui/match/match-range-fail.rs
@@ -2,17 +2,17 @@ fn main() {
     match "wow" {
         "bar" ..= "foo" => { }
     };
-    //~^^ ERROR only char and numeric types are allowed in range
+    //~^^ ERROR only `char` and numeric types are allowed in range
 
     match "wow" {
         10 ..= "what" => ()
     };
-    //~^^ ERROR only char and numeric types are allowed in range
+    //~^^ ERROR only `char` and numeric types are allowed in range
 
     match "wow" {
         true ..= "what" => {}
     };
-    //~^^ ERROR only char and numeric types are allowed in range
+    //~^^ ERROR only `char` and numeric types are allowed in range
 
     match 5 {
         'c' ..= 100 => { }
diff --git a/src/test/ui/match/match-range-fail.stderr b/src/test/ui/match/match-range-fail.stderr
index 64105dc73d3f5..938c05ac7324c 100644
--- a/src/test/ui/match/match-range-fail.stderr
+++ b/src/test/ui/match/match-range-fail.stderr
@@ -1,4 +1,4 @@
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/match-range-fail.rs:3:9
    |
 LL |         "bar" ..= "foo" => { }
@@ -7,7 +7,7 @@ LL |         "bar" ..= "foo" => { }
    |         |         this is of type `&'static str` but it should be `char` or numeric
    |         this is of type `&'static str` but it should be `char` or numeric
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/match-range-fail.rs:8:16
    |
 LL |         10 ..= "what" => ()
@@ -15,7 +15,7 @@ LL |         10 ..= "what" => ()
    |         |
    |         this is of type `{integer}`
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/match-range-fail.rs:13:9
    |
 LL |         true ..= "what" => {}
diff --git a/src/test/ui/parser/recover-range-pats.rs b/src/test/ui/parser/recover-range-pats.rs
index e07ea6221d7c9..7412b624b09cd 100644
--- a/src/test/ui/parser/recover-range-pats.rs
+++ b/src/test/ui/parser/recover-range-pats.rs
@@ -17,8 +17,8 @@ fn exclusive_from_to() {
     if let 0..Y = 0 {} // OK.
     if let X..3 = 0 {} // OK.
     if let X..Y = 0 {} // OK.
-    if let true..Y = 0 {} //~ ERROR only char and numeric types
-    if let X..true = 0 {} //~ ERROR only char and numeric types
+    if let true..Y = 0 {} //~ ERROR only `char` and numeric types
+    if let X..true = 0 {} //~ ERROR only `char` and numeric types
     if let .0..Y = 0 {} //~ ERROR mismatched types
     //~^ ERROR float literals must have an integer part
     if let X.. .0 = 0 {} //~ ERROR mismatched types
@@ -30,8 +30,8 @@ fn inclusive_from_to() {
     if let 0..=Y = 0 {} // OK.
     if let X..=3 = 0 {} // OK.
     if let X..=Y = 0 {} // OK.
-    if let true..=Y = 0 {} //~ ERROR only char and numeric types
-    if let X..=true = 0 {} //~ ERROR only char and numeric types
+    if let true..=Y = 0 {} //~ ERROR only `char` and numeric types
+    if let X..=true = 0 {} //~ ERROR only `char` and numeric types
     if let .0..=Y = 0 {} //~ ERROR mismatched types
     //~^ ERROR float literals must have an integer part
     if let X..=.0 = 0 {} //~ ERROR mismatched types
@@ -43,9 +43,9 @@ fn inclusive2_from_to() {
     if let 0...Y = 0 {} //~ ERROR `...` range patterns are deprecated
     if let X...3 = 0 {} //~ ERROR `...` range patterns are deprecated
     if let X...Y = 0 {} //~ ERROR `...` range patterns are deprecated
-    if let true...Y = 0 {} //~ ERROR only char and numeric types
+    if let true...Y = 0 {} //~ ERROR only `char` and numeric types
     //~^ ERROR `...` range patterns are deprecated
-    if let X...true = 0 {} //~ ERROR only char and numeric types
+    if let X...true = 0 {} //~ ERROR only `char` and numeric types
     //~^ ERROR `...` range patterns are deprecated
     if let .0...Y = 0 {} //~ ERROR mismatched types
     //~^ ERROR float literals must have an integer part
@@ -59,7 +59,7 @@ fn exclusive_from() {
     if let 0.. = 0 {}
     if let X.. = 0 {}
     if let true.. = 0 {}
-    //~^ ERROR only char and numeric types
+    //~^ ERROR only `char` and numeric types
     if let .0.. = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
@@ -69,7 +69,7 @@ fn inclusive_from() {
     if let 0..= = 0 {} //~ ERROR inclusive range with no end
     if let X..= = 0 {} //~ ERROR inclusive range with no end
     if let true..= = 0 {} //~ ERROR inclusive range with no end
-    //~| ERROR only char and numeric types
+    //~| ERROR only `char` and numeric types
     if let .0..= = 0 {} //~ ERROR inclusive range with no end
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
@@ -79,7 +79,7 @@ fn inclusive2_from() {
     if let 0... = 0 {} //~ ERROR inclusive range with no end
     if let X... = 0 {} //~ ERROR inclusive range with no end
     if let true... = 0 {} //~ ERROR inclusive range with no end
-    //~| ERROR only char and numeric types
+    //~| ERROR only `char` and numeric types
     if let .0... = 0 {} //~ ERROR inclusive range with no end
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
@@ -89,7 +89,7 @@ fn exclusive_to() {
     if let ..0 = 0 {}
     if let ..Y = 0 {}
     if let ..true = 0 {}
-    //~^ ERROR only char and numeric types
+    //~^ ERROR only `char` and numeric types
     if let .. .0 = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
@@ -99,7 +99,7 @@ fn inclusive_to() {
     if let ..=3 = 0 {}
     if let ..=Y = 0 {}
     if let ..=true = 0 {}
-    //~^ ERROR only char and numeric types
+    //~^ ERROR only `char` and numeric types
     if let ..=.0 = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR mismatched types
@@ -112,7 +112,7 @@ fn inclusive2_to() {
     //~^ ERROR range-to patterns with `...` are not allowed
     if let ...true = 0 {}
     //~^ ERROR range-to patterns with `...` are not allowed
-    //~| ERROR only char and numeric types
+    //~| ERROR only `char` and numeric types
     if let ....3 = 0 {}
     //~^ ERROR float literals must have an integer part
     //~| ERROR range-to patterns with `...` are not allowed
diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr
index 0d4db74f9f4fd..e351a9783bf17 100644
--- a/src/test/ui/parser/recover-range-pats.stderr
+++ b/src/test/ui/parser/recover-range-pats.stderr
@@ -258,7 +258,7 @@ LL |     mac2!(0, 1);
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:20:12
    |
 LL |     if let true..Y = 0 {}
@@ -266,7 +266,7 @@ LL |     if let true..Y = 0 {}
    |            |
    |            this is of type `bool` but it should be `char` or numeric
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:21:15
    |
 LL |     if let X..true = 0 {}
@@ -291,7 +291,7 @@ LL |     if let X.. .0 = 0 {}
    |            |   expected integer, found floating-point number
    |            this is of type `u8`
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:33:12
    |
 LL |     if let true..=Y = 0 {}
@@ -299,7 +299,7 @@ LL |     if let true..=Y = 0 {}
    |            |
    |            this is of type `bool` but it should be `char` or numeric
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:34:16
    |
 LL |     if let X..=true = 0 {}
@@ -324,7 +324,7 @@ LL |     if let X..=.0 = 0 {}
    |            |   expected integer, found floating-point number
    |            this is of type `u8`
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:46:12
    |
 LL |     if let true...Y = 0 {}
@@ -332,7 +332,7 @@ LL |     if let true...Y = 0 {}
    |            |
    |            this is of type `bool` but it should be `char` or numeric
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:48:16
    |
 LL |     if let X...true = 0 {}
@@ -357,7 +357,7 @@ LL |     if let X... .0 = 0 {}
    |            |    expected integer, found floating-point number
    |            this is of type `u8`
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:61:12
    |
 LL |     if let true.. = 0 {}
@@ -369,7 +369,7 @@ error[E0308]: mismatched types
 LL |     if let .0.. = 0 {}
    |            ^^ expected integer, found floating-point number
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:71:12
    |
 LL |     if let true..= = 0 {}
@@ -381,7 +381,7 @@ error[E0308]: mismatched types
 LL |     if let .0..= = 0 {}
    |            ^^ expected integer, found floating-point number
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:81:12
    |
 LL |     if let true... = 0 {}
@@ -393,7 +393,7 @@ error[E0308]: mismatched types
 LL |     if let .0... = 0 {}
    |            ^^ expected integer, found floating-point number
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:91:14
    |
 LL |     if let ..true = 0 {}
@@ -405,7 +405,7 @@ error[E0308]: mismatched types
 LL |     if let .. .0 = 0 {}
    |               ^^ expected integer, found floating-point number
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:101:15
    |
 LL |     if let ..=true = 0 {}
@@ -417,7 +417,7 @@ error[E0308]: mismatched types
 LL |     if let ..=.0 = 0 {}
    |               ^^ expected integer, found floating-point number
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:113:15
    |
 LL |     if let ...true = 0 {}
diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.rs b/src/test/ui/pattern/patkind-litrange-no-expr.rs
index 5b3db2e57c836..9464f277fb088 100644
--- a/src/test/ui/pattern/patkind-litrange-no-expr.rs
+++ b/src/test/ui/pattern/patkind-litrange-no-expr.rs
@@ -19,7 +19,7 @@ enum_number!(Change {
     Neg = -1,
     Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns
                    //~| ERROR arbitrary expressions aren't allowed in patterns
-                   //~| ERROR only char and numeric types are allowed in range patterns
+                   //~| ERROR only `char` and numeric types are allowed in range patterns
 });
 
 fn main() {}
diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.stderr b/src/test/ui/pattern/patkind-litrange-no-expr.stderr
index 70dd1a9263f6f..51af167a7c1d1 100644
--- a/src/test/ui/pattern/patkind-litrange-no-expr.stderr
+++ b/src/test/ui/pattern/patkind-litrange-no-expr.stderr
@@ -10,7 +10,7 @@ error: arbitrary expressions aren't allowed in patterns
 LL |     Arith = 1 + 1,
    |             ^^^^^
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/patkind-litrange-no-expr.rs:20:13
    |
 LL |                 $( $value ..= 42 => Some($name::$variant), )* // PatKind::Range
diff --git a/src/test/ui/qualified/qualified-path-params.rs b/src/test/ui/qualified/qualified-path-params.rs
index 65549d909d047..e8a95a46010af 100644
--- a/src/test/ui/qualified/qualified-path-params.rs
+++ b/src/test/ui/qualified/qualified-path-params.rs
@@ -18,7 +18,8 @@ impl S {
 fn main() {
     match 10 {
         <S as Tr>::A::f::<u8> => {}
-    //~^ ERROR expected unit struct, unit variant or constant, found associated function
-        0 ..= <S as Tr>::A::f::<u8> => {} //~ ERROR only char and numeric types are allowed in range
+        //~^ ERROR expected unit struct, unit variant or constant, found associated function
+        0 ..= <S as Tr>::A::f::<u8> => {}
+        //~^ ERROR only `char` and numeric types are allowed in range
     }
 }
diff --git a/src/test/ui/qualified/qualified-path-params.stderr b/src/test/ui/qualified/qualified-path-params.stderr
index 4214e2503c345..2be2deeb75549 100644
--- a/src/test/ui/qualified/qualified-path-params.stderr
+++ b/src/test/ui/qualified/qualified-path-params.stderr
@@ -4,7 +4,7 @@ error[E0533]: expected unit struct, unit variant or constant, found associated f
 LL |         <S as Tr>::A::f::<u8> => {}
    |         ^^^^^^^^^^^^^^^^^^^^^
 
-error[E0029]: only char and numeric types are allowed in range patterns
+error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/qualified-path-params.rs:22:15
    |
 LL |         0 ..= <S as Tr>::A::f::<u8> => {}

From 5ec9e96030f87629a570e45fe4415d07a355502b Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Wed, 16 Sep 2020 00:21:21 +0100
Subject: [PATCH 14/40] Bless mir-opt tests

---
 ...orary.main.SimplifyCfg-elaborate-drops.after.32bit.mir | 2 +-
 .../combine_array_len.norm2.InstCombine.32bit.diff        | 4 ++--
 .../const_prop/array_index.main.ConstProp.32bit.diff      | 4 ++--
 .../const_prop/bad_op_div_by_zero.main.ConstProp.diff     | 8 ++++----
 .../const_prop/bad_op_mod_by_zero.main.ConstProp.diff     | 8 ++++----
 ...bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff | 4 ++--
 .../mir-opt/const_prop/checked_add.main.ConstProp.diff    | 4 ++--
 src/test/mir-opt/const_prop/indirect.main.ConstProp.diff  | 4 ++--
 .../large_array_index.main.ConstProp.32bit.diff           | 4 ++--
 .../optimizes_into_variable.main.ConstProp.32bit.diff     | 8 ++++----
 .../mir-opt/const_prop/repeat.main.ConstProp.32bit.diff   | 4 ++--
 .../mir-opt/const_prop/return_place.add.ConstProp.diff    | 4 ++--
 .../const_prop/slice_len.main.ConstProp.32bit.diff        | 4 ++--
 ...{constant}}.SimplifyCfg-promote-consts.after.32bit.mir | 2 +-
 src/test/mir-opt/issue_72181.foo.mir_map.0.32bit.mir      | 2 +-
 src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir     | 2 +-
 .../nll/region_subtyping_basic.main.nll.0.64bit.mir       | 2 +-
 17 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.32bit.mir b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.32bit.mir
index 2216c2bc92a55..deb5dbad7de67 100644
--- a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.32bit.mir
+++ b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.32bit.mir
@@ -48,7 +48,7 @@ fn main() -> () {
         _7 = _2;                         // scope 3 at $DIR/array-index-is-temporary.rs:16:7: 16:8
         _8 = Len(_1);                    // scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9
         _9 = Lt(_7, _8);                 // scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9
-        assert(move _9, "index out of bounds: the len is {} but the index is {}", move _8, _7) -> bb2; // scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9
+        assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb2; // scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9
     }
 
     bb2: {
diff --git a/src/test/mir-opt/combine_array_len.norm2.InstCombine.32bit.diff b/src/test/mir-opt/combine_array_len.norm2.InstCombine.32bit.diff
index 61e987cc68516..979e5bc4d2118 100644
--- a/src/test/mir-opt/combine_array_len.norm2.InstCombine.32bit.diff
+++ b/src/test/mir-opt/combine_array_len.norm2.InstCombine.32bit.diff
@@ -32,7 +32,7 @@
 -         _4 = Len(_1);                    // scope 0 at $DIR/combine_array_len.rs:5:13: 5:17
 +         _4 = const 2_usize;              // scope 0 at $DIR/combine_array_len.rs:5:13: 5:17
           _5 = Lt(_3, _4);                 // scope 0 at $DIR/combine_array_len.rs:5:13: 5:17
-          assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/combine_array_len.rs:5:13: 5:17
+          assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/combine_array_len.rs:5:13: 5:17
       }
   
       bb1: {
@@ -44,7 +44,7 @@
 -         _8 = Len(_1);                    // scope 1 at $DIR/combine_array_len.rs:6:13: 6:17
 +         _8 = const 2_usize;              // scope 1 at $DIR/combine_array_len.rs:6:13: 6:17
           _9 = Lt(_7, _8);                 // scope 1 at $DIR/combine_array_len.rs:6:13: 6:17
-          assert(move _9, "index out of bounds: the len is {} but the index is {}", move _8, _7) -> bb2; // scope 1 at $DIR/combine_array_len.rs:6:13: 6:17
+          assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb2; // scope 1 at $DIR/combine_array_len.rs:6:13: 6:17
       }
   
       bb2: {
diff --git a/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff
index 1ccda1c5003dc..4664934690845 100644
--- a/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff
@@ -20,9 +20,9 @@
           _3 = const 2_usize;              // scope 0 at $DIR/array_index.rs:5:31: 5:32
           _4 = const 4_usize;              // scope 0 at $DIR/array_index.rs:5:18: 5:33
 -         _5 = Lt(_3, _4);                 // scope 0 at $DIR/array_index.rs:5:18: 5:33
--         assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
 +         _5 = const true;                 // scope 0 at $DIR/array_index.rs:5:18: 5:33
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff
index 30ff6ec860434..ba081f95fa8a9 100644
--- a/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff
@@ -24,21 +24,21 @@
           StorageLive(_3);                 // scope 1 at $DIR/bad_op_div_by_zero.rs:5:18: 5:19
 -         _3 = _1;                         // scope 1 at $DIR/bad_op_div_by_zero.rs:5:18: 5:19
 -         _4 = Eq(_3, const 0_i32);        // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
--         assert(!move _4, "attempt to divide {} by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
+-         assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 +         _3 = const 0_i32;                // scope 1 at $DIR/bad_op_div_by_zero.rs:5:18: 5:19
 +         _4 = const true;                 // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
-+         assert(!const true, "attempt to divide {} by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
++         assert(!const true, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
       }
   
       bb1: {
 -         _5 = Eq(_3, const -1_i32);       // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 -         _6 = Eq(const 1_i32, const i32::MIN); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 -         _7 = BitAnd(move _5, move _6);   // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
--         assert(!move _7, "attempt to compute `{} / {}` which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
+-         assert(!move _7, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 +         _5 = const false;                // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 +         _6 = const false;                // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 +         _7 = const false;                // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
-+         assert(!const false, "attempt to compute `{} / {}` which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
++         assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
       }
   
       bb2: {
diff --git a/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff
index 6e6ce0a613dd6..a843cacf4d93f 100644
--- a/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff
@@ -24,21 +24,21 @@
           StorageLive(_3);                 // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:18: 5:19
 -         _3 = _1;                         // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:18: 5:19
 -         _4 = Eq(_3, const 0_i32);        // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
--         assert(!move _4, "attempt to calculate the remainder of {} with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
+-         assert(!move _4, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 +         _3 = const 0_i32;                // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:18: 5:19
 +         _4 = const true;                 // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
-+         assert(!const true, "attempt to calculate the remainder of {} with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
++         assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
       }
   
       bb1: {
 -         _5 = Eq(_3, const -1_i32);       // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 -         _6 = Eq(const 1_i32, const i32::MIN); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 -         _7 = BitAnd(move _5, move _6);   // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
--         assert(!move _7, "attempt to compute the remainder of `{} % {}` which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
+-         assert(!move _7, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 +         _5 = const false;                // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 +         _6 = const false;                // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 +         _7 = const false;                // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
-+         assert(!const false, "attempt to compute the remainder of `{} % {}` which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
++         assert(!const false, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
       }
   
       bb2: {
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
index 245a7de5e9925..ec00fcf20c4d6 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
@@ -42,9 +42,9 @@
           _6 = const 3_usize;              // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24
           _7 = Len((*_1));                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
 -         _8 = Lt(_6, _7);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
--         assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
+-         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
 +         _8 = Lt(const 3_usize, _7);      // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
-+         assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
++         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff b/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff
index 125d150d3d8a2..f01676b6da863 100644
--- a/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff
@@ -12,7 +12,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/checked_add.rs:5:9: 5:10
 -         _2 = CheckedAdd(const 1_u32, const 1_u32); // scope 0 at $DIR/checked_add.rs:5:18: 5:23
--         assert(!move (_2.1: bool), "attempt to compute `{} + {}` which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:5:18: 5:23
+-         assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:5:18: 5:23
 +         _2 = const (2_u32, false);       // scope 0 at $DIR/checked_add.rs:5:18: 5:23
 +                                          // ty::Const
 +                                          // + ty: (u32, bool)
@@ -20,7 +20,7 @@
 +                                          // mir::Constant
 +                                          // + span: $DIR/checked_add.rs:5:18: 5:23
 +                                          // + literal: Const { ty: (u32, bool), val: Value(ByRef { alloc: Allocation { bytes: [2, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
-+         assert(!const false, "attempt to compute `{} + {}` which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:5:18: 5:23
++         assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:5:18: 5:23
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff b/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff
index e37d0a3ed960f..8c7b35887c915 100644
--- a/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff
@@ -15,7 +15,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/indirect.rs:5:13: 5:25
 -         _2 = const 2_u32 as u8 (Misc);   // scope 0 at $DIR/indirect.rs:5:13: 5:25
 -         _3 = CheckedAdd(_2, const 1_u8); // scope 0 at $DIR/indirect.rs:5:13: 5:29
--         assert(!move (_3.1: bool), "attempt to compute `{} + {}` which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:5:13: 5:29
+-         assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:5:13: 5:29
 +         _2 = const 2_u8;                 // scope 0 at $DIR/indirect.rs:5:13: 5:25
 +         _3 = const (3_u8, false);        // scope 0 at $DIR/indirect.rs:5:13: 5:29
 +                                          // ty::Const
@@ -24,7 +24,7 @@
 +                                          // mir::Constant
 +                                          // + span: $DIR/indirect.rs:5:13: 5:29
 +                                          // + literal: Const { ty: (u8, bool), val: Value(ByRef { alloc: Allocation { bytes: [3, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, size: Size { raw: 2 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
-+         assert(!const false, "attempt to compute `{} + {}` which would overflow", const 2_u8, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:5:13: 5:29
++         assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u8, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:5:13: 5:29
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff
index b1a9e1cb5d7de..fa790822b6bff 100644
--- a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff
@@ -20,9 +20,9 @@
           _3 = const 2_usize;              // scope 0 at $DIR/large_array_index.rs:6:30: 6:31
           _4 = const 5000_usize;           // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
 -         _5 = Lt(_3, _4);                 // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
--         assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
 +         _5 = const true;                 // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", const 5000_usize, const 2_usize) -> bb1; // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> bb1; // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff
index 2c8e7ada39b0a..53ffc01ccaf25 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff
@@ -25,7 +25,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/optimizes_into_variable.rs:12:9: 12:10
 -         _2 = CheckedAdd(const 2_i32, const 2_i32); // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
--         assert(!move (_2.1: bool), "attempt to compute `{} + {}` which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
+-         assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
 +         _2 = const (4_i32, false);       // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
 +                                          // ty::Const
 +                                          // + ty: (i32, bool)
@@ -33,7 +33,7 @@
 +                                          // mir::Constant
 +                                          // + span: $DIR/optimizes_into_variable.rs:12:13: 12:18
 +                                          // + literal: Const { ty: (i32, bool), val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
-+         assert(!const false, "attempt to compute `{} + {}` which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
++         assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
       }
   
       bb1: {
@@ -46,9 +46,9 @@
           _5 = const 3_usize;              // scope 1 at $DIR/optimizes_into_variable.rs:13:32: 13:33
           _6 = const 6_usize;              // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
 -         _7 = Lt(_5, _6);                 // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
--         assert(move _7, "index out of bounds: the len is {} but the index is {}", move _6, _5) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
+-         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
 +         _7 = const true;                 // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
       }
   
       bb2: {
diff --git a/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff
index f14004fc25e00..98f409f326a58 100644
--- a/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff
@@ -22,9 +22,9 @@
           _4 = const 2_usize;              // scope 0 at $DIR/repeat.rs:6:26: 6:27
           _5 = const 8_usize;              // scope 0 at $DIR/repeat.rs:6:18: 6:28
 -         _6 = Lt(_4, _5);                 // scope 0 at $DIR/repeat.rs:6:18: 6:28
--         assert(move _6, "index out of bounds: the len is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28
+-         assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28
 +         _6 = const true;                 // scope 0 at $DIR/repeat.rs:6:18: 6:28
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/return_place.add.ConstProp.diff b/src/test/mir-opt/const_prop/return_place.add.ConstProp.diff
index d61a04d1e0322..fc8a5437232cf 100644
--- a/src/test/mir-opt/const_prop/return_place.add.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/return_place.add.ConstProp.diff
@@ -7,7 +7,7 @@
   
       bb0: {
 -         _1 = CheckedAdd(const 2_u32, const 2_u32); // scope 0 at $DIR/return_place.rs:6:5: 6:10
--         assert(!move (_1.1: bool), "attempt to compute `{} + {}` which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:6:5: 6:10
+-         assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:6:5: 6:10
 +         _1 = const (4_u32, false);       // scope 0 at $DIR/return_place.rs:6:5: 6:10
 +                                          // ty::Const
 +                                          // + ty: (u32, bool)
@@ -15,7 +15,7 @@
 +                                          // mir::Constant
 +                                          // + span: $DIR/return_place.rs:6:5: 6:10
 +                                          // + literal: Const { ty: (u32, bool), val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
-+         assert(!const false, "attempt to compute `{} + {}` which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:6:5: 6:10
++         assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:6:5: 6:10
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
index 02c4391baf560..98e5b5cedc2bb 100644
--- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
@@ -33,10 +33,10 @@
           _6 = const 1_usize;              // scope 0 at $DIR/slice_len.rs:5:31: 5:32
 -         _7 = Len((*_2));                 // scope 0 at $DIR/slice_len.rs:5:5: 5:33
 -         _8 = Lt(_6, _7);                 // scope 0 at $DIR/slice_len.rs:5:5: 5:33
--         assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33
+-         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33
 +         _7 = const 3_usize;              // scope 0 at $DIR/slice_len.rs:5:5: 5:33
 +         _8 = const true;                 // scope 0 at $DIR/slice_len.rs:5:5: 5:33
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33
       }
   
       bb1: {
diff --git a/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.32bit.mir b/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.32bit.mir
index 1cef88fd1096b..84a1149ba1879 100644
--- a/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.32bit.mir
+++ b/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.32bit.mir
@@ -6,7 +6,7 @@
 
     bb0: {
         _1 = CheckedAdd(const 1_usize, const 1_usize); // scope 0 at $DIR/issue-41697.rs:18:19: 18:22
-        assert(!move (_1.1: bool), "attempt to compute `{} + {}` which would overflow", const 1_usize, const 1_usize) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-41697.rs:18:19: 18:22
+        assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_usize, const 1_usize) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-41697.rs:18:19: 18:22
     }
 
     bb1 (cleanup): {
diff --git a/src/test/mir-opt/issue_72181.foo.mir_map.0.32bit.mir b/src/test/mir-opt/issue_72181.foo.mir_map.0.32bit.mir
index 972a36a30a127..c94f6c28cd907 100644
--- a/src/test/mir-opt/issue_72181.foo.mir_map.0.32bit.mir
+++ b/src/test/mir-opt/issue_72181.foo.mir_map.0.32bit.mir
@@ -12,7 +12,7 @@ fn foo(_1: [(Never, u32); 1]) -> u32 {
         _2 = const 0_usize;              // scope 0 at $DIR/issue-72181.rs:16:43: 16:44
         _3 = Len(_1);                    // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
         _4 = Lt(_2, _3);                 // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
-        assert(move _4, "index out of bounds: the len is {} but the index is {}", move _3, _2) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
+        assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, _2) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
     }
 
     bb1 (cleanup): {
diff --git a/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir b/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir
index 89b60121496f4..e003dc2aadb9f 100644
--- a/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir
+++ b/src/test/mir-opt/issue_72181.main.mir_map.0.32bit.mir
@@ -48,7 +48,7 @@ fn main() -> () {
         _6 = const 0_usize;              // scope 4 at $DIR/issue-72181.rs:27:24: 27:25
         _7 = Len(_2);                    // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
         _8 = Lt(_6, _7);                 // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
-        assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb1]; // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
+        assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb1]; // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
     }
 
     bb3: {
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
index 3820f70d5153e..23dcab656c1ce 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
@@ -52,7 +52,7 @@ fn main() -> () {
         _3 = const Const(Value(Scalar(0x0000000000000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17
         _4 = Len(_1);                    // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
         _5 = Lt(_3, _4);                 // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
-        assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> [success: bb2, unwind: bb1]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
+        assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb2, unwind: bb1]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
     }
 
     bb1 (cleanup): {

From e2e000a3c0bfa601c40e330e3902f2d605348b26 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Wed, 16 Sep 2020 13:06:37 +0100
Subject: [PATCH 15/40] Bless mir-opt 32-bit tests

---
 ...orary.main.SimplifyCfg-elaborate-drops.after.64bit.mir | 2 +-
 .../combine_array_len.norm2.InstCombine.64bit.diff        | 4 ++--
 .../const_prop/array_index.main.ConstProp.64bit.diff      | 4 ++--
 ...bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff | 4 ++--
 .../large_array_index.main.ConstProp.64bit.diff           | 4 ++--
 .../optimizes_into_variable.main.ConstProp.64bit.diff     | 8 ++++----
 .../mir-opt/const_prop/repeat.main.ConstProp.64bit.diff   | 4 ++--
 .../const_prop/slice_len.main.ConstProp.64bit.diff        | 4 ++--
 ...{constant}}.SimplifyCfg-promote-consts.after.64bit.mir | 2 +-
 src/test/mir-opt/issue_72181.foo.mir_map.0.64bit.mir      | 2 +-
 src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir     | 2 +-
 .../nll/region_subtyping_basic.main.nll.0.32bit.mir       | 2 +-
 12 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.64bit.mir b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.64bit.mir
index 2216c2bc92a55..deb5dbad7de67 100644
--- a/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.64bit.mir
+++ b/src/test/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.64bit.mir
@@ -48,7 +48,7 @@ fn main() -> () {
         _7 = _2;                         // scope 3 at $DIR/array-index-is-temporary.rs:16:7: 16:8
         _8 = Len(_1);                    // scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9
         _9 = Lt(_7, _8);                 // scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9
-        assert(move _9, "index out of bounds: the len is {} but the index is {}", move _8, _7) -> bb2; // scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9
+        assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb2; // scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9
     }
 
     bb2: {
diff --git a/src/test/mir-opt/combine_array_len.norm2.InstCombine.64bit.diff b/src/test/mir-opt/combine_array_len.norm2.InstCombine.64bit.diff
index 61e987cc68516..979e5bc4d2118 100644
--- a/src/test/mir-opt/combine_array_len.norm2.InstCombine.64bit.diff
+++ b/src/test/mir-opt/combine_array_len.norm2.InstCombine.64bit.diff
@@ -32,7 +32,7 @@
 -         _4 = Len(_1);                    // scope 0 at $DIR/combine_array_len.rs:5:13: 5:17
 +         _4 = const 2_usize;              // scope 0 at $DIR/combine_array_len.rs:5:13: 5:17
           _5 = Lt(_3, _4);                 // scope 0 at $DIR/combine_array_len.rs:5:13: 5:17
-          assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/combine_array_len.rs:5:13: 5:17
+          assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/combine_array_len.rs:5:13: 5:17
       }
   
       bb1: {
@@ -44,7 +44,7 @@
 -         _8 = Len(_1);                    // scope 1 at $DIR/combine_array_len.rs:6:13: 6:17
 +         _8 = const 2_usize;              // scope 1 at $DIR/combine_array_len.rs:6:13: 6:17
           _9 = Lt(_7, _8);                 // scope 1 at $DIR/combine_array_len.rs:6:13: 6:17
-          assert(move _9, "index out of bounds: the len is {} but the index is {}", move _8, _7) -> bb2; // scope 1 at $DIR/combine_array_len.rs:6:13: 6:17
+          assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb2; // scope 1 at $DIR/combine_array_len.rs:6:13: 6:17
       }
   
       bb2: {
diff --git a/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff
index 1ccda1c5003dc..4664934690845 100644
--- a/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff
@@ -20,9 +20,9 @@
           _3 = const 2_usize;              // scope 0 at $DIR/array_index.rs:5:31: 5:32
           _4 = const 4_usize;              // scope 0 at $DIR/array_index.rs:5:18: 5:33
 -         _5 = Lt(_3, _4);                 // scope 0 at $DIR/array_index.rs:5:18: 5:33
--         assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
 +         _5 = const true;                 // scope 0 at $DIR/array_index.rs:5:18: 5:33
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
index 245a7de5e9925..ec00fcf20c4d6 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
@@ -42,9 +42,9 @@
           _6 = const 3_usize;              // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24
           _7 = Len((*_1));                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
 -         _8 = Lt(_6, _7);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
--         assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
+-         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
 +         _8 = Lt(const 3_usize, _7);      // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
-+         assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
++         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff
index b1a9e1cb5d7de..fa790822b6bff 100644
--- a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff
@@ -20,9 +20,9 @@
           _3 = const 2_usize;              // scope 0 at $DIR/large_array_index.rs:6:30: 6:31
           _4 = const 5000_usize;           // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
 -         _5 = Lt(_3, _4);                 // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
--         assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
+-         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
 +         _5 = const true;                 // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", const 5000_usize, const 2_usize) -> bb1; // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 5000_usize, const 2_usize) -> bb1; // scope 0 at $DIR/large_array_index.rs:6:17: 6:32
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff
index 2c8e7ada39b0a..53ffc01ccaf25 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff
@@ -25,7 +25,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/optimizes_into_variable.rs:12:9: 12:10
 -         _2 = CheckedAdd(const 2_i32, const 2_i32); // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
--         assert(!move (_2.1: bool), "attempt to compute `{} + {}` which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
+-         assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
 +         _2 = const (4_i32, false);       // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
 +                                          // ty::Const
 +                                          // + ty: (i32, bool)
@@ -33,7 +33,7 @@
 +                                          // mir::Constant
 +                                          // + span: $DIR/optimizes_into_variable.rs:12:13: 12:18
 +                                          // + literal: Const { ty: (i32, bool), val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
-+         assert(!const false, "attempt to compute `{} + {}` which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
++         assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
       }
   
       bb1: {
@@ -46,9 +46,9 @@
           _5 = const 3_usize;              // scope 1 at $DIR/optimizes_into_variable.rs:13:32: 13:33
           _6 = const 6_usize;              // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
 -         _7 = Lt(_5, _6);                 // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
--         assert(move _7, "index out of bounds: the len is {} but the index is {}", move _6, _5) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
+-         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
 +         _7 = const true;                 // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
       }
   
       bb2: {
diff --git a/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff
index f14004fc25e00..98f409f326a58 100644
--- a/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff
@@ -22,9 +22,9 @@
           _4 = const 2_usize;              // scope 0 at $DIR/repeat.rs:6:26: 6:27
           _5 = const 8_usize;              // scope 0 at $DIR/repeat.rs:6:18: 6:28
 -         _6 = Lt(_4, _5);                 // scope 0 at $DIR/repeat.rs:6:18: 6:28
--         assert(move _6, "index out of bounds: the len is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28
+-         assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28
 +         _6 = const true;                 // scope 0 at $DIR/repeat.rs:6:18: 6:28
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
index 02c4391baf560..98e5b5cedc2bb 100644
--- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
@@ -33,10 +33,10 @@
           _6 = const 1_usize;              // scope 0 at $DIR/slice_len.rs:5:31: 5:32
 -         _7 = Len((*_2));                 // scope 0 at $DIR/slice_len.rs:5:5: 5:33
 -         _8 = Lt(_6, _7);                 // scope 0 at $DIR/slice_len.rs:5:5: 5:33
--         assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33
+-         assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33
 +         _7 = const 3_usize;              // scope 0 at $DIR/slice_len.rs:5:5: 5:33
 +         _8 = const true;                 // scope 0 at $DIR/slice_len.rs:5:5: 5:33
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33
++         assert(const true, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33
       }
   
       bb1: {
diff --git a/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.64bit.mir b/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.64bit.mir
index 1cef88fd1096b..84a1149ba1879 100644
--- a/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.64bit.mir
+++ b/src/test/mir-opt/issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.64bit.mir
@@ -6,7 +6,7 @@
 
     bb0: {
         _1 = CheckedAdd(const 1_usize, const 1_usize); // scope 0 at $DIR/issue-41697.rs:18:19: 18:22
-        assert(!move (_1.1: bool), "attempt to compute `{} + {}` which would overflow", const 1_usize, const 1_usize) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-41697.rs:18:19: 18:22
+        assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_usize, const 1_usize) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-41697.rs:18:19: 18:22
     }
 
     bb1 (cleanup): {
diff --git a/src/test/mir-opt/issue_72181.foo.mir_map.0.64bit.mir b/src/test/mir-opt/issue_72181.foo.mir_map.0.64bit.mir
index 972a36a30a127..c94f6c28cd907 100644
--- a/src/test/mir-opt/issue_72181.foo.mir_map.0.64bit.mir
+++ b/src/test/mir-opt/issue_72181.foo.mir_map.0.64bit.mir
@@ -12,7 +12,7 @@ fn foo(_1: [(Never, u32); 1]) -> u32 {
         _2 = const 0_usize;              // scope 0 at $DIR/issue-72181.rs:16:43: 16:44
         _3 = Len(_1);                    // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
         _4 = Lt(_2, _3);                 // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
-        assert(move _4, "index out of bounds: the len is {} but the index is {}", move _3, _2) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
+        assert(move _4, "index out of bounds: the length is {} but the index is {}", move _3, _2) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
     }
 
     bb1 (cleanup): {
diff --git a/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir b/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir
index 89b60121496f4..e003dc2aadb9f 100644
--- a/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir
+++ b/src/test/mir-opt/issue_72181.main.mir_map.0.64bit.mir
@@ -48,7 +48,7 @@ fn main() -> () {
         _6 = const 0_usize;              // scope 4 at $DIR/issue-72181.rs:27:24: 27:25
         _7 = Len(_2);                    // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
         _8 = Lt(_6, _7);                 // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
-        assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb1]; // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
+        assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb1]; // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
     }
 
     bb3: {
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
index 2885dd8eb7845..91135fbf41a71 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
@@ -52,7 +52,7 @@ fn main() -> () {
         _3 = const Const(Value(Scalar(0x00000000)): usize); // bb0[5]: scope 1 at $DIR/region-subtyping-basic.rs:18:16: 18:17
         _4 = Len(_1);                    // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
         _5 = Lt(_3, _4);                 // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
-        assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> [success: bb2, unwind: bb1]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
+        assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb2, unwind: bb1]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:18:14: 18:18
     }
 
     bb1 (cleanup): {

From e3c6e46168758642f0bab64da374f93ed21b1cd0 Mon Sep 17 00:00:00 2001
From: Christiaan Dirkx <christiaan@dirkx.email>
Date: Fri, 18 Sep 2020 19:23:50 +0200
Subject: [PATCH 16/40] Make some methods of `Pin<&mut T>` unstable const

Make the following methods unstable const under the `const_pin` feature:
- `into_ref`
- `get_mut`
- `get_unchecked_mut`
---
 library/core/src/pin.rs   | 13 ++++++++-----
 library/core/tests/lib.rs |  1 +
 library/core/tests/pin.rs | 12 +++++++++++-
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index fa5b37edc36e6..9f0284d5d9542 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -708,8 +708,9 @@ impl<'a, T: ?Sized> Pin<&'a T> {
 impl<'a, T: ?Sized> Pin<&'a mut T> {
     /// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime.
     #[inline(always)]
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
     #[stable(feature = "pin", since = "1.33.0")]
-    pub fn into_ref(self) -> Pin<&'a T> {
+    pub const fn into_ref(self) -> Pin<&'a T> {
         Pin { pointer: self.pointer }
     }
 
@@ -722,9 +723,10 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
     /// that lives for as long as the borrow of the `Pin`, not the lifetime of
     /// the `Pin` itself. This method allows turning the `Pin` into a reference
     /// with the same lifetime as the original `Pin`.
-    #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn get_mut(self) -> &'a mut T
+    #[stable(feature = "pin", since = "1.33.0")]
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    pub const fn get_mut(self) -> &'a mut T
     where
         T: Unpin,
     {
@@ -741,9 +743,10 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
     ///
     /// If the underlying data is `Unpin`, `Pin::get_mut` should be used
     /// instead.
-    #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub unsafe fn get_unchecked_mut(self) -> &'a mut T {
+    #[stable(feature = "pin", since = "1.33.0")]
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    pub const unsafe fn get_unchecked_mut(self) -> &'a mut T {
         self.pointer
     }
 
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index b8d67d7266543..490f016ab8b2e 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -39,6 +39,7 @@
 #![feature(iter_order_by)]
 #![feature(cmp_min_max_by)]
 #![feature(iter_map_while)]
+#![feature(const_mut_refs)]
 #![feature(const_pin)]
 #![feature(const_slice_from_raw_parts)]
 #![feature(const_raw_ptr_deref)]
diff --git a/library/core/tests/pin.rs b/library/core/tests/pin.rs
index 1363353163829..6f617c8d0c297 100644
--- a/library/core/tests/pin.rs
+++ b/library/core/tests/pin.rs
@@ -17,5 +17,15 @@ fn pin_const() {
     assert_eq!(INNER_UNCHECKED, POINTER);
 
     const REF: &'static usize = PINNED.get_ref();
-    assert_eq!(REF, POINTER)
+    assert_eq!(REF, POINTER);
+
+    // Note: `pin_mut_const` tests that the methods of `Pin<&mut T>` are usable in a const context.
+    // A const fn is used because `&mut` is not (yet) usable in constants.
+    const fn pin_mut_const() {
+        let _ = Pin::new(&mut 2).into_ref();
+        let _ = Pin::new(&mut 2).get_mut();
+        let _ = unsafe { Pin::new(&mut 2).get_unchecked_mut() };
+    }
+
+    pin_mut_const();
 }

From 78ff69ba1086decb205b988f05aba7711dddb221 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Sun, 24 May 2020 18:22:04 +0200
Subject: [PATCH 17/40] Implement a destination propagation pass

---
 compiler/rustc_mir/src/dataflow/impls/mod.rs  |   2 +-
 compiler/rustc_mir/src/lib.rs                 |   1 +
 compiler/rustc_mir/src/transform/dest_prop.rs | 732 ++++++++++++++++++
 compiler/rustc_mir/src/transform/mod.rs       |   2 +
 compiler/rustc_mir/src/transform/nrvo.rs      |   6 +
 5 files changed, 742 insertions(+), 1 deletion(-)
 create mode 100644 compiler/rustc_mir/src/transform/dest_prop.rs

diff --git a/compiler/rustc_mir/src/dataflow/impls/mod.rs b/compiler/rustc_mir/src/dataflow/impls/mod.rs
index c42d586785656..1769feaf7a514 100644
--- a/compiler/rustc_mir/src/dataflow/impls/mod.rs
+++ b/compiler/rustc_mir/src/dataflow/impls/mod.rs
@@ -204,7 +204,7 @@ impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
 
 /// `EverInitializedPlaces` tracks all places that might have ever been
 /// initialized upon reaching a particular point in the control flow
-/// for a function, without an intervening `Storage Dead`.
+/// for a function, without an intervening `StorageDead`.
 ///
 /// This dataflow is used to determine if an immutable local variable may
 /// be assigned to.
diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs
index 42717f273843a..251037792c917 100644
--- a/compiler/rustc_mir/src/lib.rs
+++ b/compiler/rustc_mir/src/lib.rs
@@ -6,6 +6,7 @@ Rust MIR: a lowered representation of Rust.
 
 #![feature(nll)]
 #![feature(in_band_lifetimes)]
+#![feature(bindings_after_at)]
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
new file mode 100644
index 0000000000000..19054f36171d9
--- /dev/null
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -0,0 +1,732 @@
+//! Propagates assignment destinations backwards in the CFG to eliminate redundant assignments.
+//!
+//! # Motivation
+//!
+//! MIR building can insert a lot of redundant copies, and Rust code in general often tends to move
+//! values around a lot. The result is a lot of assignments of the form `dest = {move} src;` in MIR.
+//! MIR building for constants in particular tends to create additional locals that are only used
+//! inside a single block to shuffle a value around unnecessarily.
+//!
+//! LLVM by itself is not good enough at eliminating these redundant copies (eg. see
+//! https://github.com/rust-lang/rust/issues/32966), so this leaves some performance on the table
+//! that we can regain by implementing an optimization for removing these assign statements in rustc
+//! itself. When this optimization runs fast enough, it can also speed up the constant evaluation
+//! and code generation phases of rustc due to the reduced number of statements and locals.
+//!
+//! # The Optimization
+//!
+//! Conceptually, this optimization is "destination propagation". It is similar to the Named Return
+//! Value Optimization, or NRVO, known from the C++ world, except that it isn't limited to return
+//! values or the return place `_0`. On a very high level, independent of the actual implementation
+//! details, it does the following:
+//!
+//! 1) Identify `dest = src;` statements that can be soundly eliminated.
+//! 2) Replace all mentions of `src` with `dest` ("unifying" them and propagating the destination
+//!    backwards).
+//! 3) Delete the `dest = src;` statement (by making it a `nop`).
+//!
+//! Step 1) is by far the hardest, so it is explained in more detail below.
+//!
+//! ## Soundness
+//!
+//! Given an `Assign` statement `dest = src;`, where `dest` is a `Place` and `src` is an `Rvalue`,
+//! there are a few requirements that must hold for the optimization to be sound:
+//!
+//! * `dest` must not contain any *indirection* through a pointer. It must access part of the base
+//!   local. Otherwise it might point to arbitrary memory that is hard to track.
+//!
+//!   It must also not contain any indexing projections, since those take an arbitrary `Local` as
+//!   the index, and that local might only be initialized shortly before `dest` is used.
+//!
+//!   Subtle case: If `dest` is a, or projects through a union, then we have to make sure that there
+//!   remains an assignment to it, since that sets the "active field" of the union. But if `src` is
+//!   a ZST, it might not be initialized, so there might not be any use of it before the assignment,
+//!   and performing the optimization would simply delete the assignment, leaving `dest`
+//!   uninitialized.
+//!
+//! * `src` must be a bare `Local` without any indirections or field projections (FIXME: Why?).
+//!   It can be copied or moved by the assignment.
+//!
+//! * The `dest` and `src` locals must never be [*live*][liveness] at the same time. If they are, it
+//!   means that they both hold a (potentially different) value that is needed by a future use of
+//!   the locals. Unifying them would overwrite one of the values.
+//!
+//!   Note that computing liveness of locals that have had their address taken is more difficult:
+//!   Short of doing full escape analysis on the address/pointer/reference, the pass would need to
+//!   assume that any operation that can potentially involve opaque user code (such as function
+//!   calls, destructors, and inline assembly) may access any local that had its address taken
+//!   before that point.
+//!
+//! Here, the first two conditions are simple structural requirements on the `Assign` statements
+//! that can be trivially checked. The liveness requirement however is more difficult and costly to
+//! check.
+//!
+//! ## Previous Work
+//!
+//! A [previous attempt] at implementing an optimization like this turned out to be a significant
+//! regression in compiler performance. Fixing the regressions introduced a lot of undesirable
+//! complexity to the implementation.
+//!
+//! A [subsequent approach] tried to avoid the costly computation by limiting itself to acyclic
+//! CFGs, but still turned out to be far too costly to run due to suboptimal performance within
+//! individual basic blocks, requiring a walk across the entire block for every assignment found
+//! within the block. For the `tuple-stress` benchmark, which has 458745 statements in a single
+//! block, this proved to be far too costly.
+//!
+//! Since the first attempt at this, the compiler has improved dramatically, and new analysis
+//! frameworks have been added that should make this approach viable without requiring a limited
+//! approach that only works for some classes of CFGs:
+//! - rustc now has a powerful dataflow analysis framework that can handle forwards and backwards
+//!   analyses efficiently.
+//! - Layout optimizations for generators have been added to improve code generation for
+//!   async/await, which are very similar in spirit to what this optimization does. Both walk the
+//!   MIR and record conflicting uses of locals in a `BitMatrix`.
+//!
+//! Also, rustc now has a simple NRVO pass (see `nrvo.rs`), which handles a subset of the cases that
+//! this destination propagation pass handles, proving that similar optimizations can be performed
+//! on MIR.
+//!
+//! ## Pre/Post Optimization
+//!
+//! It is recommended to run `SimplifyCfg` and then `SimplifyLocals` some time after this pass, as
+//! it replaces the eliminated assign statements with `nop`s and leaves unused locals behind.
+//!
+//! [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis
+//! [previous attempt]: https://github.com/rust-lang/rust/pull/47954
+//! [subsequent approach]: https://github.com/rust-lang/rust/pull/71003
+
+use crate::dataflow::{self, Analysis};
+use crate::{
+    transform::{MirPass, MirSource},
+    util::{dump_mir, PassWhere},
+};
+use dataflow::{
+    impls::{MaybeInitializedLocals, MaybeLiveLocals},
+    ResultsCursor,
+};
+use rustc_data_structures::unify::{InPlaceUnificationTable, UnifyKey};
+use rustc_index::{
+    bit_set::{BitMatrix, BitSet},
+    vec::IndexVec,
+};
+use rustc_middle::mir::tcx::PlaceTy;
+use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
+use rustc_middle::mir::{
+    traversal, Body, Local, LocalKind, Location, Operand, Place, PlaceElem, Rvalue, Statement,
+    StatementKind, Terminator, TerminatorKind,
+};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+pub struct DestinationPropagation;
+
+impl<'tcx> MirPass<'tcx> for DestinationPropagation {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+        // Only run at mir-opt-level=2 or higher for now (we don't fix up debuginfo and remove
+        // storage statements at the moment).
+        if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
+            return;
+        }
+
+        let mut conflicts = Conflicts::build(tcx, body, source);
+        let mut replacements = Replacements::new(body.local_decls.len());
+        for candidate @ CandidateAssignment { dest, src, loc } in find_candidates(tcx, body) {
+            // Merge locals that don't conflict.
+            if conflicts.contains(dest.local, src) {
+                debug!("at assignment {:?}, conflict {:?} vs. {:?}", loc, dest.local, src);
+                continue;
+            }
+
+            if !tcx.consider_optimizing(|| {
+                format!("DestinationPropagation {:?} {:?}", source.def_id(), candidate)
+            }) {
+                break;
+            }
+
+            if replacements.push(candidate).is_ok() {
+                conflicts.unify(candidate.src, candidate.dest.local);
+            }
+        }
+
+        replacements.flatten(tcx);
+
+        debug!("replacements {:?}", replacements.map);
+
+        Replacer { tcx, replacements, place_elem_cache: Vec::new() }.visit_body(body);
+
+        // FIXME fix debug info
+    }
+}
+
+#[derive(Debug, Eq, PartialEq, Copy, Clone)]
+struct UnifyLocal(Local);
+
+impl From<Local> for UnifyLocal {
+    fn from(l: Local) -> Self {
+        Self(l)
+    }
+}
+
+impl UnifyKey for UnifyLocal {
+    type Value = ();
+    fn index(&self) -> u32 {
+        self.0.as_u32()
+    }
+    fn from_index(u: u32) -> Self {
+        Self(Local::from_u32(u))
+    }
+    fn tag() -> &'static str {
+        "UnifyLocal"
+    }
+}
+
+struct Replacements<'tcx> {
+    /// Maps locals to their replacement.
+    map: IndexVec<Local, Option<Place<'tcx>>>,
+
+    /// Whose locals' live ranges to kill.
+    kill: BitSet<Local>,
+
+    /// Tracks locals that have already been merged together to prevent cycles.
+    unified_locals: InPlaceUnificationTable<UnifyLocal>,
+}
+
+impl Replacements<'tcx> {
+    fn new(locals: usize) -> Self {
+        Self {
+            map: IndexVec::from_elem_n(None, locals),
+            kill: BitSet::new_empty(locals),
+            unified_locals: {
+                let mut table = InPlaceUnificationTable::new();
+                for local in 0..locals {
+                    assert_eq!(table.new_key(()), UnifyLocal(Local::from_usize(local)));
+                }
+                table
+            },
+        }
+    }
+
+    fn push(&mut self, candidate: CandidateAssignment<'tcx>) -> Result<(), ()> {
+        if self.unified_locals.unioned(candidate.src, candidate.dest.local) {
+            // Candidate conflicts with previous replacement (ie. could possibly form a cycle and
+            // hang).
+
+            let replacement = self.map[candidate.src].as_mut().unwrap();
+
+            // If the current replacement is for the same `dest` local, there are 2 or more
+            // equivalent `src = dest;` assignments. This is fine, the replacer will `nop` out all
+            // of them.
+            if replacement.local == candidate.dest.local {
+                assert_eq!(replacement.projection, candidate.dest.projection);
+            }
+
+            // We still return `Err` in any case, as `src` and `dest` do not need to be unified
+            // *again*.
+            return Err(());
+        }
+
+        let entry = &mut self.map[candidate.src];
+        if entry.is_some() {
+            // We're already replacing `src` with something else, so this candidate is out.
+            return Err(());
+        }
+
+        self.unified_locals.union(candidate.src, candidate.dest.local);
+
+        *entry = Some(candidate.dest);
+        self.kill.insert(candidate.src);
+        self.kill.insert(candidate.dest.local);
+
+        Ok(())
+    }
+
+    /// Applies the stored replacements to all replacements, until no replacements would result in
+    /// locals that need further replacements when applied.
+    fn flatten(&mut self, tcx: TyCtxt<'tcx>) {
+        // Note: This assumes that there are no cycles in the replacements, which is enforced via
+        // `self.unified_locals`. Otherwise this can cause an infinite loop.
+
+        for local in self.map.indices() {
+            if let Some(replacement) = self.map[local] {
+                // Substitute the base local of `replacement` until fixpoint.
+                let mut base = replacement.local;
+                let mut reversed_projection_slices = Vec::with_capacity(1);
+                while let Some(replacement_for_replacement) = self.map[base] {
+                    base = replacement_for_replacement.local;
+                    reversed_projection_slices.push(replacement_for_replacement.projection);
+                }
+
+                let projection: Vec<_> = reversed_projection_slices
+                    .iter()
+                    .rev()
+                    .flat_map(|projs| projs.iter())
+                    .chain(replacement.projection.iter())
+                    .collect();
+                let projection = tcx.intern_place_elems(&projection);
+
+                // Replace with the final `Place`.
+                self.map[local] = Some(Place { local: base, projection });
+            }
+        }
+    }
+
+    fn for_src(&self, src: Local) -> Option<&Place<'tcx>> {
+        self.map[src].as_ref()
+    }
+}
+
+struct Replacer<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    replacements: Replacements<'tcx>,
+    place_elem_cache: Vec<PlaceElem<'tcx>>,
+}
+
+impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
+    fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn visit_local(&mut self, local: &mut Local, context: PlaceContext, location: Location) {
+        if context.is_use() && self.replacements.for_src(*local).is_some() {
+            bug!(
+                "use of local {:?} should have been replaced by visit_place; context={:?}, loc={:?}",
+                local,
+                context,
+                location,
+            );
+        }
+    }
+
+    fn process_projection_elem(
+        &mut self,
+        elem: PlaceElem<'tcx>,
+        _: Location,
+    ) -> Option<PlaceElem<'tcx>> {
+        match elem {
+            PlaceElem::Index(local) => {
+                if let Some(replacement) = self.replacements.for_src(local) {
+                    bug!(
+                        "cannot replace {:?} with {:?} in index projection {:?}",
+                        local,
+                        replacement,
+                        elem,
+                    );
+                } else {
+                    None
+                }
+            }
+            _ => None,
+        }
+    }
+
+    fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
+        if let Some(replacement) = self.replacements.for_src(place.local) {
+            // Rebase `place`s projections onto `replacement`'s.
+            self.place_elem_cache.clear();
+            self.place_elem_cache.extend(replacement.projection.iter().chain(place.projection));
+            let projection = self.tcx.intern_place_elems(&self.place_elem_cache);
+            let new_place = Place { local: replacement.local, projection };
+
+            debug!("Replacer: {:?} -> {:?}", place, new_place);
+            *place = new_place;
+        }
+
+        self.super_place(place, context, location);
+    }
+
+    fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
+        self.super_statement(statement, location);
+
+        match &statement.kind {
+            // FIXME: Don't delete storage statements, merge the live ranges instead
+            StatementKind::StorageDead(local) | StatementKind::StorageLive(local)
+                if self.replacements.kill.contains(*local) =>
+            {
+                statement.make_nop()
+            }
+
+            StatementKind::Assign(box (dest, rvalue)) => {
+                match rvalue {
+                    Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) => {
+                        // These might've been turned into self-assignments by the replacement
+                        // (this includes the original statement we wanted to eliminate).
+                        if dest == place {
+                            debug!("{:?} turned into self-assignment, deleting", location);
+                            statement.make_nop();
+                        }
+                    }
+                    _ => {}
+                }
+            }
+
+            _ => {}
+        }
+    }
+}
+
+struct Conflicts {
+    /// The conflict matrix. It is always symmetric and the adjacency matrix of the corresponding
+    /// conflict graph.
+    matrix: BitMatrix<Local, Local>,
+
+    /// Preallocated `BitSet` used by `unify`.
+    unify_cache: BitSet<Local>,
+}
+
+impl Conflicts {
+    fn build<'tcx>(tcx: TyCtxt<'tcx>, body: &'_ Body<'tcx>, source: MirSource<'tcx>) -> Self {
+        // We don't have to look out for locals that have their address taken, since `find_candidates`
+        // already takes care of that.
+
+        let mut conflicts = BitMatrix::from_row_n(
+            &BitSet::new_empty(body.local_decls.len()),
+            body.local_decls.len(),
+        );
+
+        let mut record_conflicts =
+            |init: &ResultsCursor<'_, '_, MaybeInitializedLocals>,
+             live: &ResultsCursor<'_, '_, MaybeLiveLocals>| {
+                let mut requires_storage = init.get().clone();
+                requires_storage.intersect(live.get());
+
+                for local in requires_storage.iter() {
+                    conflicts.union_row_with(&requires_storage, local);
+                }
+            };
+
+        let def_id = source.def_id();
+        let mut init = MaybeInitializedLocals
+            .into_engine(tcx, body, def_id)
+            .iterate_to_fixpoint()
+            .into_results_cursor(body);
+        let mut live = MaybeLiveLocals
+            .into_engine(tcx, body, def_id)
+            .iterate_to_fixpoint()
+            .into_results_cursor(body);
+
+        dump_mir(
+            tcx,
+            None,
+            "DestinationPropagation-dataflow",
+            &"",
+            source,
+            body,
+            |pass_where, w| {
+                match pass_where {
+                    PassWhere::BeforeLocation(loc) => {
+                        init.seek_before_primary_effect(loc);
+                        live.seek_after_primary_effect(loc);
+
+                        writeln!(w, "        // init: {:?}", init.get())?;
+                        writeln!(w, "        // live: {:?}", live.get())?;
+                    }
+                    PassWhere::AfterTerminator(bb) => {
+                        let loc = body.terminator_loc(bb);
+                        init.seek_after_primary_effect(loc);
+                        live.seek_before_primary_effect(loc);
+
+                        writeln!(w, "        // init: {:?}", init.get())?;
+                        writeln!(w, "        // live: {:?}", live.get())?;
+                    }
+
+                    PassWhere::BeforeBlock(bb) => {
+                        init.seek_to_block_start(bb);
+                        live.seek_to_block_start(bb);
+
+                        writeln!(w, "    // init: {:?}", init.get())?;
+                        writeln!(w, "    // live: {:?}", live.get())?;
+                    }
+
+                    PassWhere::BeforeCFG | PassWhere::AfterCFG | PassWhere::AfterLocation(_) => {}
+                }
+
+                Ok(())
+            },
+        );
+
+        // Visit only reachable basic blocks. The exact order is not important.
+        for (block, data) in traversal::preorder(body) {
+            // Observe the dataflow state *before* all possible locations (statement or terminator) in
+            // each basic block...
+            for statement_index in 0..=data.statements.len() {
+                let loc = Location { block, statement_index };
+                trace!("record conflicts at {:?}", loc);
+                init.seek_before_primary_effect(loc);
+                live.seek_after_primary_effect(loc);
+                // FIXME: liveness is backwards, so this is slow
+
+                record_conflicts(&init, &live);
+            }
+
+            // ...and then observe the state *after* the terminator effect is applied. As long as
+            // neither `init` nor `borrowed` has a "before" effect, we will observe all possible
+            // dataflow states here or in the loop above.
+            trace!("record conflicts at end of {:?}", block);
+            init.seek_to_block_end(block);
+            live.seek_to_block_end(block);
+            record_conflicts(&init, &live);
+        }
+
+        Self { matrix: conflicts, unify_cache: BitSet::new_empty(body.local_decls.len()) }
+    }
+
+    fn contains(&self, a: Local, b: Local) -> bool {
+        self.matrix.contains(a, b)
+    }
+
+    /// Merges the conflicts of `a` and `b`, so that each one inherits all conflicts of the other.
+    ///
+    /// This is called when the pass makes the decision to unify `a` and `b` (or parts of `a` and
+    /// `b`) and is needed to ensure that future unification decisions take potentially newly
+    /// introduced conflicts into account.
+    ///
+    /// For an example, assume we have locals `_0`, `_1`, `_2`, and `_3`. There are these conflicts:
+    ///
+    /// * `_0` <-> `_1`
+    /// * `_1` <-> `_2`
+    /// * `_3` <-> `_0`
+    ///
+    /// We then decide to merge `_2` with `_3` since they don't conflict. Then we decide to merge
+    /// `_2` with `_0`, which also doesn't have a conflict in the above list. However `_2` is now
+    /// `_3`, which does conflict with `_0`.
+    fn unify(&mut self, a: Local, b: Local) {
+        // FIXME: This might be somewhat slow. Conflict graphs are undirected, maybe we can use
+        // something with union-find to speed this up?
+
+        // Make all locals that conflict with `a` also conflict with `b`, and vice versa.
+        self.unify_cache.clear();
+        for conflicts_with_a in self.matrix.iter(a) {
+            self.unify_cache.insert(conflicts_with_a);
+        }
+        for conflicts_with_b in self.matrix.iter(b) {
+            self.unify_cache.insert(conflicts_with_b);
+        }
+        for conflicts_with_a_or_b in self.unify_cache.iter() {
+            // Set both `a` and `b` for this local's row.
+            self.matrix.insert(conflicts_with_a_or_b, a);
+            self.matrix.insert(conflicts_with_a_or_b, b);
+        }
+
+        // Write the locals `a` conflicts with to `b`'s row.
+        self.matrix.union_rows(a, b);
+        // Write the locals `b` conflicts with to `a`'s row.
+        self.matrix.union_rows(b, a);
+    }
+}
+
+/// A `dest = {move} src;` statement at `loc`.
+///
+/// We want to consider merging `dest` and `src` due to this assignment.
+#[derive(Debug, Copy, Clone)]
+struct CandidateAssignment<'tcx> {
+    /// Does not contain indirection or indexing (so the only local it contains is the place base).
+    dest: Place<'tcx>,
+    src: Local,
+    loc: Location,
+}
+
+/// Scans the MIR for assignments between locals that we might want to consider merging.
+///
+/// This will filter out assignments that do not match the right form (as described in the top-level
+/// comment) and also throw out assignments that involve a local that has its address taken or is
+/// otherwise ineligible (eg. locals used as array indices are ignored because we cannot propagate
+/// arbitrary places into array indices).
+fn find_candidates<'a, 'tcx>(
+    tcx: TyCtxt<'tcx>,
+    body: &'a Body<'tcx>,
+) -> Vec<CandidateAssignment<'tcx>> {
+    struct FindAssignments<'a, 'tcx> {
+        tcx: TyCtxt<'tcx>,
+        body: &'a Body<'tcx>,
+        candidates: Vec<CandidateAssignment<'tcx>>,
+        ever_borrowed_locals: BitSet<Local>,
+        locals_used_as_array_index: BitSet<Local>,
+    }
+
+    impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> {
+        fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
+            if let StatementKind::Assign(box (
+                dest,
+                Rvalue::Use(Operand::Copy(src) | Operand::Move(src)),
+            )) = &statement.kind
+            {
+                // `dest` must not have pointer indirection.
+                if dest.is_indirect() {
+                    return;
+                }
+
+                // `src` must be a plain local.
+                if !src.projection.is_empty() {
+                    return;
+                }
+
+                // Since we want to replace `src` with `dest`, `src` must not be required.
+                if is_local_required(src.local, self.body) {
+                    return;
+                }
+
+                // Can't optimize if both locals ever have their address taken (can introduce
+                // aliasing).
+                // FIXME: This can be smarter and take `StorageDead` into account (which
+                // invalidates borrows).
+                if self.ever_borrowed_locals.contains(dest.local)
+                    && self.ever_borrowed_locals.contains(src.local)
+                {
+                    return;
+                }
+
+                assert_ne!(dest.local, src.local, "self-assignments are UB");
+
+                // We can't replace locals occurring in `PlaceElem::Index` for now.
+                if self.locals_used_as_array_index.contains(src.local) {
+                    return;
+                }
+
+                // Handle the "subtle case" described above by rejecting any `dest` that is or
+                // projects through a union.
+                let is_union = |ty: Ty<'_>| {
+                    if let ty::Adt(def, _) = ty.kind() {
+                        if def.is_union() {
+                            return true;
+                        }
+                    }
+
+                    false
+                };
+                let mut place_ty = PlaceTy::from_ty(self.body.local_decls[dest.local].ty);
+                if is_union(place_ty.ty) {
+                    return;
+                }
+                for elem in dest.projection {
+                    if let PlaceElem::Index(_) = elem {
+                        // `dest` contains an indexing projection.
+                        return;
+                    }
+
+                    place_ty = place_ty.projection_ty(self.tcx, elem);
+                    if is_union(place_ty.ty) {
+                        return;
+                    }
+                }
+
+                self.candidates.push(CandidateAssignment {
+                    dest: *dest,
+                    src: src.local,
+                    loc: location,
+                });
+            }
+        }
+    }
+
+    let mut visitor = FindAssignments {
+        tcx,
+        body,
+        candidates: Vec::new(),
+        ever_borrowed_locals: ever_borrowed_locals(body),
+        locals_used_as_array_index: locals_used_as_array_index(body),
+    };
+    visitor.visit_body(body);
+    visitor.candidates
+}
+
+/// Some locals are part of the function's interface and can not be removed.
+///
+/// Note that these locals *can* still be merged with non-required locals by removing that other
+/// local.
+fn is_local_required(local: Local, body: &Body<'_>) -> bool {
+    match body.local_kind(local) {
+        LocalKind::Arg | LocalKind::ReturnPointer => true,
+        LocalKind::Var | LocalKind::Temp => false,
+    }
+}
+
+/// Walks MIR to find all locals that have their address taken anywhere.
+fn ever_borrowed_locals(body: &Body<'_>) -> BitSet<Local> {
+    struct BorrowCollector {
+        locals: BitSet<Local>,
+    }
+
+    impl<'tcx> Visitor<'tcx> for BorrowCollector {
+        fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
+            self.super_rvalue(rvalue, location);
+
+            match rvalue {
+                Rvalue::AddressOf(_, borrowed_place) | Rvalue::Ref(_, _, borrowed_place) => {
+                    if !borrowed_place.is_indirect() {
+                        self.locals.insert(borrowed_place.local);
+                    }
+                }
+
+                Rvalue::Cast(..)
+                | Rvalue::Use(..)
+                | Rvalue::Repeat(..)
+                | Rvalue::Len(..)
+                | Rvalue::BinaryOp(..)
+                | Rvalue::CheckedBinaryOp(..)
+                | Rvalue::NullaryOp(..)
+                | Rvalue::UnaryOp(..)
+                | Rvalue::Discriminant(..)
+                | Rvalue::Aggregate(..)
+                | Rvalue::ThreadLocalRef(..) => {}
+            }
+        }
+
+        fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
+            self.super_terminator(terminator, location);
+
+            match terminator.kind {
+                TerminatorKind::Drop { place: dropped_place, .. }
+                | TerminatorKind::DropAndReplace { place: dropped_place, .. } => {
+                    self.locals.insert(dropped_place.local);
+                }
+
+                TerminatorKind::Abort
+                | TerminatorKind::Assert { .. }
+                | TerminatorKind::Call { .. }
+                | TerminatorKind::FalseEdge { .. }
+                | TerminatorKind::FalseUnwind { .. }
+                | TerminatorKind::GeneratorDrop
+                | TerminatorKind::Goto { .. }
+                | TerminatorKind::Resume
+                | TerminatorKind::Return
+                | TerminatorKind::SwitchInt { .. }
+                | TerminatorKind::Unreachable
+                | TerminatorKind::Yield { .. }
+                | TerminatorKind::InlineAsm { .. } => {}
+            }
+        }
+    }
+
+    let mut visitor = BorrowCollector { locals: BitSet::new_empty(body.local_decls.len()) };
+    visitor.visit_body(body);
+    visitor.locals
+}
+
+/// `PlaceElem::Index` only stores a `Local`, so we can't replace that with a full `Place`.
+///
+/// Collect locals used as indices so we don't generate candidates that are impossible to apply
+/// later.
+fn locals_used_as_array_index(body: &Body<'_>) -> BitSet<Local> {
+    struct IndexCollector {
+        locals: BitSet<Local>,
+    }
+
+    impl<'tcx> Visitor<'tcx> for IndexCollector {
+        fn visit_projection_elem(
+            &mut self,
+            local: Local,
+            proj_base: &[PlaceElem<'tcx>],
+            elem: PlaceElem<'tcx>,
+            context: PlaceContext,
+            location: Location,
+        ) {
+            if let PlaceElem::Index(i) = elem {
+                self.locals.insert(i);
+            }
+            self.super_projection_elem(local, proj_base, elem, context, location);
+        }
+    }
+
+    let mut visitor = IndexCollector { locals: BitSet::new_empty(body.local_decls.len()) };
+    visitor.visit_body(body);
+    visitor.locals
+}
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs
index 226282fe4263c..fc9854ba499f8 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir/src/transform/mod.rs
@@ -24,6 +24,7 @@ pub mod cleanup_post_borrowck;
 pub mod const_prop;
 pub mod copy_prop;
 pub mod deaggregator;
+pub mod dest_prop;
 pub mod dump_mir;
 pub mod elaborate_drops;
 pub mod generator;
@@ -467,6 +468,7 @@ fn run_optimization_passes<'tcx>(
         &simplify_comparison_integral::SimplifyComparisonIntegral,
         &simplify_try::SimplifyArmIdentity,
         &simplify_try::SimplifyBranchSame,
+        &dest_prop::DestinationPropagation,
         &copy_prop::CopyPropagation,
         &simplify_branches::SimplifyBranches::new("after-copy-prop"),
         &remove_noop_landing_pads::RemoveNoopLandingPads,
diff --git a/compiler/rustc_mir/src/transform/nrvo.rs b/compiler/rustc_mir/src/transform/nrvo.rs
index 3673b6a4aa223..1ffb5a87c4762 100644
--- a/compiler/rustc_mir/src/transform/nrvo.rs
+++ b/compiler/rustc_mir/src/transform/nrvo.rs
@@ -36,6 +36,12 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
             return;
         }
 
+        if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
+            // The `DestinationPropagation` pass runs at level 2, so this pass is redundant (and
+            // fails some asserts).
+            return;
+        }
+
         let returned_local = match local_eligible_for_nrvo(body) {
             Some(l) => l,
             None => {

From 43ad8e4260bec289c522a2fd3597c275e9e3c39c Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Mon, 25 May 2020 23:22:19 +0200
Subject: [PATCH 18/40] simplify_try: print dest_prop diff and bless

The new diff is to convince me that this is correct and nothing funky
is going on.
---
 ...c.try_identity.DestinationPropagation.diff | 72 +++++++++++++++++++
 src/test/mir-opt/simplify_try.rs              |  2 +
 ...y.try_identity.DestinationPropagation.diff | 72 +++++++++++++++++++
 ..._try.try_identity.SimplifyLocals.after.mir |  4 +-
 4 files changed, 148 insertions(+), 2 deletions(-)
 create mode 100644 src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff
 create mode 100644 src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff

diff --git a/src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff b/src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff
new file mode 100644
index 0000000000000..ff84af7491dbf
--- /dev/null
+++ b/src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff
@@ -0,0 +1,72 @@
+- // MIR for `try_identity` before DestinationPropagation
++ // MIR for `try_identity` after DestinationPropagation
+  
+  fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
+      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:5:17: 5:18
+      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:5:41: 5:57
+      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:6:9: 6:10
+      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
+      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
+      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:7:8: 7:9
+      scope 1 {
+          debug y => _2;                   // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10
+      }
+      scope 2 {
+          debug err => _6;                 // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15
+          scope 3 {
+              scope 7 {
+                  debug t => _9;           // in scope 7 at $SRC_DIR/libcore/convert/mod.rs:LL:COL
+              }
+              scope 8 {
+                  debug v => _8;           // in scope 8 at $SRC_DIR/libcore/result.rs:LL:COL
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:6:14: 6:15
+              }
+          }
+      }
+      scope 4 {
+          debug val => _10;                // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15
+          scope 5 {
+          }
+      }
+      scope 6 {
+-         debug self => _4;                // in scope 6 at $SRC_DIR/libcore/result.rs:LL:COL
++         debug self => _0;                // in scope 6 at $SRC_DIR/libcore/result.rs:LL:COL
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:6:9: 6:10
+-         StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
+-         StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+-         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+-         _3 = move _4;                    // scope 6 at $SRC_DIR/libcore/result.rs:LL:COL
+-         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+-         _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
++         _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
++         nop;                             // scope 6 at $SRC_DIR/libcore/result.rs:LL:COL
++         nop;                             // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
++         _5 = discriminant(_0);           // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+          goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+      }
+  
+      bb1: {
+-         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
+-         StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
++         nop;                             // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
++         nop;                             // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:8:1: 8:2
+          goto -> bb2;                     // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+      }
+  
+      bb2: {
+          return;                          // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs
index fa127de13dfd9..d77e17c1c62fb 100644
--- a/src/test/mir-opt/simplify_try.rs
+++ b/src/test/mir-opt/simplify_try.rs
@@ -10,3 +10,5 @@ fn try_identity(x: Result<u32, i32>) -> Result<u32, i32> {
 fn main() {
     let _ = try_identity(Ok(0));
 }
+
+// EMIT_MIR simplify_try.try_identity.DestinationPropagation.diff
diff --git a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
new file mode 100644
index 0000000000000..78b0b24bf1109
--- /dev/null
+++ b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
@@ -0,0 +1,72 @@
+- // MIR for `try_identity` before DestinationPropagation
++ // MIR for `try_identity` after DestinationPropagation
+  
+  fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
+      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:5:17: 5:18
+      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:5:41: 5:57
+      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:6:9: 6:10
+      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
+      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
+      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:7:8: 7:9
+      scope 1 {
+          debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10
+      }
+      scope 2 {
+          debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15
+          scope 3 {
+              scope 7 {
+                  debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+              }
+              scope 8 {
+                  debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:6:14: 6:15
+              }
+          }
+      }
+      scope 4 {
+          debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15
+          scope 5 {
+          }
+      }
+      scope 6 {
+-         debug self => _4;                // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++         debug self => _0;                // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:6:9: 6:10
+-         StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
+-         StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+-         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+-         _3 = move _4;                    // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+-         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+-         _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
++         _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
++         nop;                             // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++         nop;                             // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
++         _5 = discriminant(_0);           // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+          goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+      }
+  
+      bb1: {
+-         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
+-         StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
++         nop;                             // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
++         nop;                             // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:8:1: 8:2
+          goto -> bb2;                     // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+      }
+  
+      bb2: {
+          return;                          // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
index d65a2b12c0fd3..d11e4454d2538 100644
--- a/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
@@ -23,11 +23,11 @@ fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i
         }
     }
     scope 6 {
-        debug self => _1;                // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+        debug self => _0;                // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb0: {
-        _0 = move _1;                    // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
+        _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
         return;                          // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
     }
 }

From 16498953856a41e781da65709f1d111cef66af91 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Mon, 25 May 2020 23:22:47 +0200
Subject: [PATCH 19/40] simplify_try: clean up test

---
 ...c.try_identity.DestinationPropagation.diff |  70 ++++++------
 src/test/mir-opt/simplify_try.rs              |   3 +-
 ...y.try_identity.DestinationPropagation.diff |  70 ++++++------
 ..._try.try_identity.SimplifyArmIdentity.diff | 102 +++++++++---------
 ....try_identity.SimplifyBranchSame.after.mir |  56 +++++-----
 ..._try.try_identity.SimplifyLocals.after.mir |  14 +--
 6 files changed, 157 insertions(+), 158 deletions(-)

diff --git a/src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff b/src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff
index ff84af7491dbf..c3e503bf2c686 100644
--- a/src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff
+++ b/src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff
@@ -2,35 +2,35 @@
 + // MIR for `try_identity` after DestinationPropagation
   
   fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
-      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:5:17: 5:18
-      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:5:41: 5:57
-      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:6:9: 6:10
-      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:14
-      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:7:8: 7:9
+      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:6:17: 6:18
+      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:6:41: 6:57
+      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:8:8: 8:9
       scope 1 {
-          debug y => _2;                   // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10
+          debug y => _2;                   // in scope 1 at $DIR/simplify_try.rs:7:9: 7:10
       }
       scope 2 {
-          debug err => _6;                 // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15
+          debug err => _6;                 // in scope 2 at $DIR/simplify_try.rs:7:14: 7:15
           scope 3 {
               scope 7 {
                   debug t => _9;           // in scope 7 at $SRC_DIR/libcore/convert/mod.rs:LL:COL
               }
               scope 8 {
                   debug v => _8;           // in scope 8 at $SRC_DIR/libcore/result.rs:LL:COL
-                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:6:14: 6:15
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:7:14: 7:15
               }
           }
       }
       scope 4 {
-          debug val => _10;                // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15
+          debug val => _10;                // in scope 4 at $DIR/simplify_try.rs:7:13: 7:15
           scope 5 {
           }
       }
@@ -40,33 +40,33 @@
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:6:9: 6:10
--         StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
--         StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
--         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+-         StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+-         StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+-         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
 -         _3 = move _4;                    // scope 6 at $SRC_DIR/libcore/result.rs:LL:COL
--         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
--         _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-+         nop;                             // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-+         nop;                             // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
-+         _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+-         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+-         _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
++         _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
 +         nop;                             // scope 6 at $SRC_DIR/libcore/result.rs:LL:COL
-+         nop;                             // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-+         _5 = discriminant(_0);           // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-          goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
++         _5 = discriminant(_0);           // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+          goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
       }
   
       bb1: {
--         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
--         StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
-+         nop;                             // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
-+         nop;                             // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:8:1: 8:2
-          goto -> bb2;                     // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+-         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
+-         StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
++         nop;                             // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:9:1: 9:2
+          goto -> bb2;                     // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
       }
   
       bb2: {
-          return;                          // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+          return;                          // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
       }
   }
   
diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs
index d77e17c1c62fb..fca80bee89679 100644
--- a/src/test/mir-opt/simplify_try.rs
+++ b/src/test/mir-opt/simplify_try.rs
@@ -1,6 +1,7 @@
 // EMIT_MIR simplify_try.try_identity.SimplifyArmIdentity.diff
 // EMIT_MIR simplify_try.try_identity.SimplifyBranchSame.after.mir
 // EMIT_MIR simplify_try.try_identity.SimplifyLocals.after.mir
+// EMIT_MIR simplify_try.try_identity.DestinationPropagation.diff
 
 fn try_identity(x: Result<u32, i32>) -> Result<u32, i32> {
     let y = x?;
@@ -10,5 +11,3 @@ fn try_identity(x: Result<u32, i32>) -> Result<u32, i32> {
 fn main() {
     let _ = try_identity(Ok(0));
 }
-
-// EMIT_MIR simplify_try.try_identity.DestinationPropagation.diff
diff --git a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
index 78b0b24bf1109..187a3cfbb896d 100644
--- a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
+++ b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
@@ -2,35 +2,35 @@
 + // MIR for `try_identity` after DestinationPropagation
   
   fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
-      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:5:17: 5:18
-      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:5:41: 5:57
-      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:6:9: 6:10
-      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:14
-      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:7:8: 7:9
+      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:6:17: 6:18
+      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:6:41: 6:57
+      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:8:8: 8:9
       scope 1 {
-          debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10
+          debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:7:9: 7:10
       }
       scope 2 {
-          debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15
+          debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:7:14: 7:15
           scope 3 {
               scope 7 {
                   debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
               }
               scope 8 {
                   debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:6:14: 6:15
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:7:14: 7:15
               }
           }
       }
       scope 4 {
-          debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15
+          debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:7:13: 7:15
           scope 5 {
           }
       }
@@ -40,33 +40,33 @@
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:6:9: 6:10
--         StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
--         StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
--         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+-         StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+-         StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+-         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
 -         _3 = move _4;                    // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
--         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
--         _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-+         nop;                             // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-+         nop;                             // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
-+         _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+-         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+-         _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
++         _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
 +         nop;                             // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
-+         nop;                             // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-+         _5 = discriminant(_0);           // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-          goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
++         _5 = discriminant(_0);           // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+          goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
       }
   
       bb1: {
--         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
--         StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
-+         nop;                             // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
-+         nop;                             // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:8:1: 8:2
-          goto -> bb2;                     // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+-         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
+-         StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
++         nop;                             // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:9:1: 9:2
+          goto -> bb2;                     // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
       }
   
       bb2: {
-          return;                          // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+          return;                          // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
       }
   }
   
diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
index 26ce290b5496a..0c687684c508e 100644
--- a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
@@ -2,25 +2,25 @@
 + // MIR for `try_identity` after SimplifyArmIdentity
   
   fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
-      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:5:17: 5:18
-      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:5:41: 5:57
-      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:6:9: 6:10
-      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:14
-      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:7:8: 7:9
+      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:6:17: 6:18
+      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:6:41: 6:57
+      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:8:8: 8:9
       scope 1 {
--         debug y => _2;                   // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10
-+         debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10
+-         debug y => _2;                   // in scope 1 at $DIR/simplify_try.rs:7:9: 7:10
++         debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:7:9: 7:10
       }
       scope 2 {
--         debug err => _6;                 // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15
-+         debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15
+-         debug err => _6;                 // in scope 2 at $DIR/simplify_try.rs:7:14: 7:15
++         debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:7:14: 7:15
           scope 3 {
               scope 7 {
 -                 debug t => _9;           // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
@@ -29,13 +29,13 @@
               scope 8 {
 -                 debug v => _8;           // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 +                 debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:6:14: 6:15
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:7:14: 7:15
               }
           }
       }
       scope 4 {
--         debug val => _10;                // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15
-+         debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15
+-         debug val => _10;                // in scope 4 at $DIR/simplify_try.rs:7:13: 7:15
++         debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:7:13: 7:15
           scope 5 {
           }
       }
@@ -44,55 +44,55 @@
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:6:9: 6:10
-          StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-          StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
-          _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+          StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+          StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+          _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
           _3 = move _4;                    // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
-          StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-          _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-          switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+          StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+          _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+          switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
       }
   
       bb1: {
--         StorageLive(_10);                // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
--         _10 = ((_3 as Ok).0: u32);       // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
--         _2 = _10;                        // scope 5 at $DIR/simplify_try.rs:6:13: 6:15
--         StorageDead(_10);                // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-+         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
-          StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
--         StorageLive(_11);                // scope 1 at $DIR/simplify_try.rs:7:8: 7:9
--         _11 = _2;                        // scope 1 at $DIR/simplify_try.rs:7:8: 7:9
--         ((_0 as Ok).0: u32) = move _11;  // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
--         discriminant(_0) = 0;            // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
--         StorageDead(_11);                // scope 1 at $DIR/simplify_try.rs:7:9: 7:10
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:8:1: 8:2
-          goto -> bb3;                     // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+-         StorageLive(_10);                // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+-         _10 = ((_3 as Ok).0: u32);       // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+-         _2 = _10;                        // scope 5 at $DIR/simplify_try.rs:7:13: 7:15
+-         StorageDead(_10);                // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
++         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
+          StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
+-         StorageLive(_11);                // scope 1 at $DIR/simplify_try.rs:8:8: 8:9
+-         _11 = _2;                        // scope 1 at $DIR/simplify_try.rs:8:8: 8:9
+-         ((_0 as Ok).0: u32) = move _11;  // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
+-         discriminant(_0) = 0;            // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
+-         StorageDead(_11);                // scope 1 at $DIR/simplify_try.rs:8:9: 8:10
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:9:1: 9:2
+          goto -> bb3;                     // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
       }
   
       bb2: {
--         StorageLive(_6);                 // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
--         _6 = ((_3 as Err).0: i32);       // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
--         StorageLive(_8);                 // scope 3 at $DIR/simplify_try.rs:6:14: 6:15
--         StorageLive(_9);                 // scope 3 at $DIR/simplify_try.rs:6:14: 6:15
--         _9 = _6;                         // scope 3 at $DIR/simplify_try.rs:6:14: 6:15
+-         StorageLive(_6);                 // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+-         _6 = ((_3 as Err).0: i32);       // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+-         StorageLive(_8);                 // scope 3 at $DIR/simplify_try.rs:7:14: 7:15
+-         StorageLive(_9);                 // scope 3 at $DIR/simplify_try.rs:7:14: 7:15
+-         _9 = _6;                         // scope 3 at $DIR/simplify_try.rs:7:14: 7:15
 -         _8 = move _9;                    // scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
--         StorageDead(_9);                 // scope 3 at $DIR/simplify_try.rs:6:14: 6:15
+-         StorageDead(_9);                 // scope 3 at $DIR/simplify_try.rs:7:14: 7:15
 -         StorageLive(_12);                // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 -         _12 = move _8;                   // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 -         ((_0 as Err).0: i32) = move _12; // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 -         discriminant(_0) = 1;            // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 -         StorageDead(_12);                // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
--         StorageDead(_8);                 // scope 3 at $DIR/simplify_try.rs:6:14: 6:15
--         StorageDead(_6);                 // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+-         StorageDead(_8);                 // scope 3 at $DIR/simplify_try.rs:7:14: 7:15
+-         StorageDead(_6);                 // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
 +         _0 = move _3;                    // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-          StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:8:1: 8:2
-          goto -> bb3;                     // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+          StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:9:1: 9:2
+          goto -> bb3;                     // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
       }
   
       bb3: {
-          return;                          // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+          return;                          // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
       }
   }
   
diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
index dc4aae176f2c4..9428d305c8731 100644
--- a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
@@ -1,35 +1,35 @@
 // MIR for `try_identity` after SimplifyBranchSame
 
 fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
-    debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:5:17: 5:18
-    let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:5:41: 5:57
-    let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:6:9: 6:10
-    let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-    let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:14
-    let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-    let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-    let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-    let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-    let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-    let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-    let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:7:8: 7:9
+    debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:6:17: 6:18
+    let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:6:41: 6:57
+    let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+    let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+    let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+    let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+    let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+    let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+    let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+    let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+    let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+    let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:8:8: 8:9
     scope 1 {
-        debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10
+        debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:7:9: 7:10
     }
     scope 2 {
-        debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15
+        debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:7:14: 7:15
         scope 3 {
             scope 7 {
                 debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
             }
             scope 8 {
                 debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-                let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:6:14: 6:15
+                let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:7:14: 7:15
             }
         }
     }
     scope 4 {
-        debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15
+        debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:7:13: 7:15
         scope 5 {
         }
     }
@@ -38,24 +38,24 @@ fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i
     }
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:6:9: 6:10
-        StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-        StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
-        _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+        StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+        StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+        StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+        _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
         _3 = move _4;                    // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
-        StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-        _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-        goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+        StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+        _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+        goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
     }
 
     bb1: {
-        _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
-        StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
-        StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:8:1: 8:2
-        goto -> bb2;                     // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+        _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
+        StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
+        StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:9:1: 9:2
+        goto -> bb2;                     // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
     }
 
     bb2: {
-        return;                          // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+        return;                          // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
     }
 }
diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
index d11e4454d2538..a25472f6a5e05 100644
--- a/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
@@ -1,13 +1,13 @@
 // MIR for `try_identity` after SimplifyLocals
 
 fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
-    debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:5:17: 5:18
-    let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:5:41: 5:57
+    debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:6:17: 6:18
+    let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:6:41: 6:57
     scope 1 {
-        debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10
+        debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:7:9: 7:10
     }
     scope 2 {
-        debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15
+        debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:7:14: 7:15
         scope 3 {
             scope 7 {
                 debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
@@ -18,7 +18,7 @@ fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i
         }
     }
     scope 4 {
-        debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15
+        debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:7:13: 7:15
         scope 5 {
         }
     }
@@ -27,7 +27,7 @@ fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i
     }
 
     bb0: {
-        _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
-        return;                          // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+        _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+        return;                          // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
     }
 }

From 8a7b1c38940e8c0a013dacf52db6a7884f156d3e Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Mon, 25 May 2020 23:37:10 +0200
Subject: [PATCH 20/40] Make nrvo-simple set mir-opt-level=1

The additional copies are due to the lack of copy propagation
---
 src/test/mir-opt/nrvo-simple.rs               |  2 +
 .../nrvo_simple.nrvo.RenameReturnPlace.diff   | 55 ++++++++++---------
 2 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/src/test/mir-opt/nrvo-simple.rs b/src/test/mir-opt/nrvo-simple.rs
index f0eb711b3f0a7..ab46d7b94c72c 100644
--- a/src/test/mir-opt/nrvo-simple.rs
+++ b/src/test/mir-opt/nrvo-simple.rs
@@ -1,3 +1,5 @@
+// compile-flags: -Zmir-opt-level=1
+
 // EMIT_MIR nrvo_simple.nrvo.RenameReturnPlace.diff
 fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
     let mut buf = [0; 1024];
diff --git a/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff b/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff
index 924e87ea8c0ad..f438eaa002780 100644
--- a/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff
+++ b/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff
@@ -2,39 +2,42 @@
 + // MIR for `nrvo` after RenameReturnPlace
   
   fn nrvo(_1: for<'r> fn(&'r mut [u8; 1024])) -> [u8; 1024] {
-      debug init => _1;                    // in scope 0 at $DIR/nrvo-simple.rs:2:9: 2:13
--     let mut _0: [u8; 1024];              // return place in scope 0 at $DIR/nrvo-simple.rs:2:39: 2:49
-+     let mut _0: [u8; 1024];              // return place in scope 0 at $DIR/nrvo-simple.rs:3:9: 3:16
-      let mut _2: [u8; 1024];              // in scope 0 at $DIR/nrvo-simple.rs:3:9: 3:16
-      let _3: ();                          // in scope 0 at $DIR/nrvo-simple.rs:4:5: 4:19
-      let mut _4: for<'r> fn(&'r mut [u8; 1024]); // in scope 0 at $DIR/nrvo-simple.rs:4:5: 4:9
-      let mut _5: &mut [u8; 1024];         // in scope 0 at $DIR/nrvo-simple.rs:4:10: 4:18
-      let mut _6: &mut [u8; 1024];         // in scope 0 at $DIR/nrvo-simple.rs:4:10: 4:18
+      debug init => _1;                    // in scope 0 at $DIR/nrvo-simple.rs:4:9: 4:13
+-     let mut _0: [u8; 1024];              // return place in scope 0 at $DIR/nrvo-simple.rs:4:39: 4:49
++     let mut _0: [u8; 1024];              // return place in scope 0 at $DIR/nrvo-simple.rs:5:9: 5:16
+      let mut _2: [u8; 1024];              // in scope 0 at $DIR/nrvo-simple.rs:5:9: 5:16
+      let _3: ();                          // in scope 0 at $DIR/nrvo-simple.rs:6:5: 6:19
+      let mut _4: for<'r> fn(&'r mut [u8; 1024]); // in scope 0 at $DIR/nrvo-simple.rs:6:5: 6:9
+      let mut _5: &mut [u8; 1024];         // in scope 0 at $DIR/nrvo-simple.rs:6:10: 6:18
+      let mut _6: &mut [u8; 1024];         // in scope 0 at $DIR/nrvo-simple.rs:6:10: 6:18
       scope 1 {
--         debug buf => _2;                 // in scope 1 at $DIR/nrvo-simple.rs:3:9: 3:16
-+         debug buf => _0;                 // in scope 1 at $DIR/nrvo-simple.rs:3:9: 3:16
+-         debug buf => _2;                 // in scope 1 at $DIR/nrvo-simple.rs:5:9: 5:16
++         debug buf => _0;                 // in scope 1 at $DIR/nrvo-simple.rs:5:9: 5:16
       }
   
       bb0: {
--         StorageLive(_2);                 // scope 0 at $DIR/nrvo-simple.rs:3:9: 3:16
--         _2 = [const 0_u8; 1024];         // scope 0 at $DIR/nrvo-simple.rs:3:19: 3:28
-+         _0 = [const 0_u8; 1024];         // scope 0 at $DIR/nrvo-simple.rs:3:19: 3:28
-          StorageLive(_3);                 // scope 1 at $DIR/nrvo-simple.rs:4:5: 4:19
-          StorageLive(_5);                 // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18
-          StorageLive(_6);                 // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18
--         _6 = &mut _2;                    // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18
-+         _6 = &mut _0;                    // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18
-          _5 = &mut (*_6);                 // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18
-          _3 = move _1(move _5) -> bb1;    // scope 1 at $DIR/nrvo-simple.rs:4:5: 4:19
+-         StorageLive(_2);                 // scope 0 at $DIR/nrvo-simple.rs:5:9: 5:16
+-         _2 = [const 0_u8; 1024];         // scope 0 at $DIR/nrvo-simple.rs:5:19: 5:28
++         _0 = [const 0_u8; 1024];         // scope 0 at $DIR/nrvo-simple.rs:5:19: 5:28
+          StorageLive(_3);                 // scope 1 at $DIR/nrvo-simple.rs:6:5: 6:19
+          StorageLive(_4);                 // scope 1 at $DIR/nrvo-simple.rs:6:5: 6:9
+          _4 = _1;                         // scope 1 at $DIR/nrvo-simple.rs:6:5: 6:9
+          StorageLive(_5);                 // scope 1 at $DIR/nrvo-simple.rs:6:10: 6:18
+          StorageLive(_6);                 // scope 1 at $DIR/nrvo-simple.rs:6:10: 6:18
+-         _6 = &mut _2;                    // scope 1 at $DIR/nrvo-simple.rs:6:10: 6:18
++         _6 = &mut _0;                    // scope 1 at $DIR/nrvo-simple.rs:6:10: 6:18
+          _5 = &mut (*_6);                 // scope 1 at $DIR/nrvo-simple.rs:6:10: 6:18
+          _3 = move _4(move _5) -> bb1;    // scope 1 at $DIR/nrvo-simple.rs:6:5: 6:19
       }
   
       bb1: {
-          StorageDead(_5);                 // scope 1 at $DIR/nrvo-simple.rs:4:18: 4:19
-          StorageDead(_6);                 // scope 1 at $DIR/nrvo-simple.rs:4:19: 4:20
-          StorageDead(_3);                 // scope 1 at $DIR/nrvo-simple.rs:4:19: 4:20
--         _0 = _2;                         // scope 1 at $DIR/nrvo-simple.rs:5:5: 5:8
--         StorageDead(_2);                 // scope 0 at $DIR/nrvo-simple.rs:6:1: 6:2
-          return;                          // scope 0 at $DIR/nrvo-simple.rs:6:2: 6:2
+          StorageDead(_5);                 // scope 1 at $DIR/nrvo-simple.rs:6:18: 6:19
+          StorageDead(_4);                 // scope 1 at $DIR/nrvo-simple.rs:6:18: 6:19
+          StorageDead(_6);                 // scope 1 at $DIR/nrvo-simple.rs:6:19: 6:20
+          StorageDead(_3);                 // scope 1 at $DIR/nrvo-simple.rs:6:19: 6:20
+-         _0 = _2;                         // scope 1 at $DIR/nrvo-simple.rs:7:5: 7:8
+-         StorageDead(_2);                 // scope 0 at $DIR/nrvo-simple.rs:8:1: 8:2
+          return;                          // scope 0 at $DIR/nrvo-simple.rs:8:2: 8:2
       }
   }
   

From 8a3e2b78bb0595bc9205b29898eb128836b5c57f Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Sat, 12 Sep 2020 14:58:46 +0200
Subject: [PATCH 21/40] Bless mir-opt tests

---
 ..._allocation.main.ConstProp.after.32bit.mir |  28 +--
 ..._allocation.main.ConstProp.after.64bit.mir |  32 +--
 ...allocation2.main.ConstProp.after.32bit.mir |  26 +--
 ...allocation2.main.ConstProp.after.64bit.mir |  28 +--
 ...allocation3.main.ConstProp.after.32bit.mir |   4 +-
 ...allocation3.main.ConstProp.after.64bit.mir |   4 +-
 ...copy_propagation.test.CopyPropagation.diff |  15 +-
 ...opagation_arg.arg_src.CopyPropagation.diff |  10 +-
 ...y_propagation_arg.baz.CopyPropagation.diff |   8 +-
 ...y_propagation_arg.foo.CopyPropagation.diff |   8 +-
 ...line_closure_captures.foo.Inline.after.mir |  24 +-
 .../issue_73223.main.PreCodegen.32bit.diff    | 207 +++++++-----------
 .../issue_73223.main.PreCodegen.64bit.diff    | 207 +++++++-----------
 13 files changed, 259 insertions(+), 342 deletions(-)

diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
index a137d7fadba10..8b09eade06704 100644
--- a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
+++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
@@ -24,42 +24,42 @@ fn main() -> () {
 }
 
 alloc0 (static: FOO, size: 8, align: 4) {
-    ╾─alloc17─╼ 03 00 00 00                         │ ╾──╼....
+    ╾─alloc14─╼ 03 00 00 00                         │ ╾──╼....
 }
 
-alloc17 (size: 48, align: 4) {
+alloc14 (size: 48, align: 4) {
     0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc4──╼ 00 00 00 00 │ ....░░░░╾──╼....
-    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 02 00 00 00 │ ....░░░░╾──╼....
-    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc13─╼ 03 00 00 00 │ ....*...╾──╼....
+    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc7──╼ 02 00 00 00 │ ....░░░░╾──╼....
+    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc11─╼ 03 00 00 00 │ ....*...╾──╼....
 }
 
 alloc4 (size: 0, align: 4) {}
 
-alloc8 (size: 16, align: 4) {
-    ╾─alloc7──╼ 03 00 00 00 ╾─alloc9──╼ 03 00 00 00 │ ╾──╼....╾──╼....
+alloc7 (size: 16, align: 4) {
+    ╾─alloc6──╼ 03 00 00 00 ╾─alloc8──╼ 03 00 00 00 │ ╾──╼....╾──╼....
 }
 
-alloc7 (size: 3, align: 1) {
+alloc6 (size: 3, align: 1) {
     66 6f 6f                                        │ foo
 }
 
-alloc9 (size: 3, align: 1) {
+alloc8 (size: 3, align: 1) {
     62 61 72                                        │ bar
 }
 
-alloc13 (size: 24, align: 4) {
-    0x00 │ ╾─alloc12─╼ 03 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ╾──╼....╾──╼....
-    0x10 │ ╾─alloc15─╼ 04 00 00 00                         │ ╾──╼....
+alloc11 (size: 24, align: 4) {
+    0x00 │ ╾─alloc10─╼ 03 00 00 00 ╾─alloc12─╼ 03 00 00 00 │ ╾──╼....╾──╼....
+    0x10 │ ╾─alloc13─╼ 04 00 00 00                         │ ╾──╼....
 }
 
-alloc12 (size: 3, align: 1) {
+alloc10 (size: 3, align: 1) {
     6d 65 68                                        │ meh
 }
 
-alloc14 (size: 3, align: 1) {
+alloc12 (size: 3, align: 1) {
     6d 6f 70                                        │ mop
 }
 
-alloc15 (size: 4, align: 1) {
+alloc13 (size: 4, align: 1) {
     6d c3 b6 70                                     │ m..p
 }
diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
index ef98cf9c09148..2853a0ac18b0d 100644
--- a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
+++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
@@ -24,46 +24,46 @@ fn main() -> () {
 }
 
 alloc0 (static: FOO, size: 16, align: 8) {
-    ╾───────alloc17───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc17 (size: 72, align: 8) {
+alloc14 (size: 72, align: 8) {
     0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc4────────╼ │ ....░░░░╾──────╼
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
-    0x20 │ ╾───────alloc8────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc13───────╼ │ ....*...╾──────╼
+    0x20 │ ╾───────alloc7────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc11───────╼ │ ....*...╾──────╼
     0x40 │ 03 00 00 00 00 00 00 00                         │ ........
 }
 
 alloc4 (size: 0, align: 8) {}
 
-alloc8 (size: 32, align: 8) {
-    0x00 │ ╾───────alloc7────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x10 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc7 (size: 32, align: 8) {
+    0x00 │ ╾───────alloc6────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x10 │ ╾───────alloc8────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc7 (size: 3, align: 1) {
+alloc6 (size: 3, align: 1) {
     66 6f 6f                                        │ foo
 }
 
-alloc9 (size: 3, align: 1) {
+alloc8 (size: 3, align: 1) {
     62 61 72                                        │ bar
 }
 
-alloc13 (size: 48, align: 8) {
-    0x00 │ ╾───────alloc12───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x10 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x20 │ ╾───────alloc15───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc11 (size: 48, align: 8) {
+    0x00 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x10 │ ╾───────alloc12───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x20 │ ╾───────alloc13───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc12 (size: 3, align: 1) {
+alloc10 (size: 3, align: 1) {
     6d 65 68                                        │ meh
 }
 
-alloc14 (size: 3, align: 1) {
+alloc12 (size: 3, align: 1) {
     6d 6f 70                                        │ mop
 }
 
-alloc15 (size: 4, align: 1) {
+alloc13 (size: 4, align: 1) {
     6d c3 b6 70                                     │ m..p
 }
diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
index c4f10064890a7..710ffeeda075a 100644
--- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
@@ -24,41 +24,41 @@ fn main() -> () {
 }
 
 alloc0 (static: FOO, size: 8, align: 4) {
-    ╾─alloc23─╼ 03 00 00 00                         │ ╾──╼....
+    ╾─alloc20─╼ 03 00 00 00                         │ ╾──╼....
 }
 
-alloc23 (size: 48, align: 4) {
+alloc20 (size: 48, align: 4) {
     0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 00 00 00 00 │ ....░░░░╾──╼....
-    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc13─╼ 02 00 00 00 │ ....░░░░╾──╼....
-    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc21─╼ 03 00 00 00 │ ....*...╾──╼....
+    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc12─╼ 02 00 00 00 │ ....░░░░╾──╼....
+    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc19─╼ 03 00 00 00 │ ....*...╾──╼....
 }
 
 alloc8 (size: 0, align: 4) {}
 
-alloc13 (size: 8, align: 4) {
-    ╾─alloc11─╼ ╾─alloc12─╼                         │ ╾──╼╾──╼
+alloc12 (size: 8, align: 4) {
+    ╾─alloc10─╼ ╾─alloc11─╼                         │ ╾──╼╾──╼
 }
 
-alloc11 (size: 1, align: 1) {
+alloc10 (size: 1, align: 1) {
     05                                              │ .
 }
 
-alloc12 (size: 1, align: 1) {
+alloc11 (size: 1, align: 1) {
     06                                              │ .
 }
 
-alloc21 (size: 12, align: 4) {
-    ╾─a17+0x3─╼ ╾─alloc18─╼ ╾─a20+0x2─╼             │ ╾──╼╾──╼╾──╼
+alloc19 (size: 12, align: 4) {
+    ╾─a15+0x3─╼ ╾─alloc16─╼ ╾─a18+0x2─╼             │ ╾──╼╾──╼╾──╼
 }
 
-alloc17 (size: 4, align: 1) {
+alloc15 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
 
-alloc18 (size: 1, align: 1) {
+alloc16 (size: 1, align: 1) {
     2a                                              │ *
 }
 
-alloc20 (size: 4, align: 1) {
+alloc18 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
index b16b85c4e95ac..97a7f76f6bb5d 100644
--- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
@@ -24,44 +24,44 @@ fn main() -> () {
 }
 
 alloc0 (static: FOO, size: 16, align: 8) {
-    ╾───────alloc23───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    ╾───────alloc20───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc23 (size: 72, align: 8) {
+alloc20 (size: 72, align: 8) {
     0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc8────────╼ │ ....░░░░╾──────╼
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
-    0x20 │ ╾───────alloc13───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc21───────╼ │ ....*...╾──────╼
+    0x20 │ ╾───────alloc12───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc19───────╼ │ ....*...╾──────╼
     0x40 │ 03 00 00 00 00 00 00 00                         │ ........
 }
 
 alloc8 (size: 0, align: 8) {}
 
-alloc13 (size: 16, align: 8) {
-    ╾───────alloc11───────╼ ╾───────alloc12───────╼ │ ╾──────╼╾──────╼
+alloc12 (size: 16, align: 8) {
+    ╾───────alloc10───────╼ ╾───────alloc11───────╼ │ ╾──────╼╾──────╼
 }
 
-alloc11 (size: 1, align: 1) {
+alloc10 (size: 1, align: 1) {
     05                                              │ .
 }
 
-alloc12 (size: 1, align: 1) {
+alloc11 (size: 1, align: 1) {
     06                                              │ .
 }
 
-alloc21 (size: 24, align: 8) {
-    0x00 │ ╾─────alloc17+0x3─────╼ ╾───────alloc18───────╼ │ ╾──────╼╾──────╼
-    0x10 │ ╾─────alloc20+0x2─────╼                         │ ╾──────╼
+alloc19 (size: 24, align: 8) {
+    0x00 │ ╾─────alloc15+0x3─────╼ ╾───────alloc16───────╼ │ ╾──────╼╾──────╼
+    0x10 │ ╾─────alloc18+0x2─────╼                         │ ╾──────╼
 }
 
-alloc17 (size: 4, align: 1) {
+alloc15 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
 
-alloc18 (size: 1, align: 1) {
+alloc16 (size: 1, align: 1) {
     2a                                              │ *
 }
 
-alloc20 (size: 4, align: 1) {
+alloc18 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
index 99d3a278d6922..19d6c51bc75f3 100644
--- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
+++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
@@ -24,10 +24,10 @@ fn main() -> () {
 }
 
 alloc0 (static: FOO, size: 4, align: 4) {
-    ╾─alloc9──╼                                     │ ╾──╼
+    ╾─alloc3──╼                                     │ ╾──╼
 }
 
-alloc9 (size: 168, align: 1) {
+alloc3 (size: 168, align: 1) {
     0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................
     0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc4──╼ │ ............╾──╼
     0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
index d6e49892d4c6a..94388b08c0ec0 100644
--- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
+++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
@@ -24,10 +24,10 @@ fn main() -> () {
 }
 
 alloc0 (static: FOO, size: 8, align: 8) {
-    ╾───────alloc9────────╼                         │ ╾──────╼
+    ╾───────alloc3────────╼                         │ ╾──────╼
 }
 
-alloc9 (size: 180, align: 1) {
+alloc3 (size: 180, align: 1) {
     0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................
     0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc4── │ ............╾───
     0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............
diff --git a/src/test/mir-opt/copy_propagation.test.CopyPropagation.diff b/src/test/mir-opt/copy_propagation.test.CopyPropagation.diff
index f2838638aca0e..1f3e559c1b7f4 100644
--- a/src/test/mir-opt/copy_propagation.test.CopyPropagation.diff
+++ b/src/test/mir-opt/copy_propagation.test.CopyPropagation.diff
@@ -6,19 +6,14 @@
       let mut _0: u32;                     // return place in scope 0 at $DIR/copy_propagation.rs:3:20: 3:23
       let _2: u32;                         // in scope 0 at $DIR/copy_propagation.rs:4:9: 4:10
       scope 1 {
--         debug y => _2;                   // in scope 1 at $DIR/copy_propagation.rs:4:9: 4:10
-+         debug y => _1;                   // in scope 1 at $DIR/copy_propagation.rs:4:9: 4:10
+          debug y => _0;                   // in scope 1 at $DIR/copy_propagation.rs:4:9: 4:10
       }
   
       bb0: {
--         StorageLive(_2);                 // scope 0 at $DIR/copy_propagation.rs:4:9: 4:10
--         _2 = _1;                         // scope 0 at $DIR/copy_propagation.rs:4:13: 4:14
--         _0 = _2;                         // scope 1 at $DIR/copy_propagation.rs:5:5: 5:6
--         StorageDead(_2);                 // scope 0 at $DIR/copy_propagation.rs:6:1: 6:2
-+         nop;                             // scope 0 at $DIR/copy_propagation.rs:4:9: 4:10
-+         nop;                             // scope 0 at $DIR/copy_propagation.rs:4:13: 4:14
-+         _0 = _1;                         // scope 1 at $DIR/copy_propagation.rs:5:5: 5:6
-+         nop;                             // scope 0 at $DIR/copy_propagation.rs:6:1: 6:2
+          nop;                             // scope 0 at $DIR/copy_propagation.rs:4:9: 4:10
+          _0 = _1;                         // scope 0 at $DIR/copy_propagation.rs:4:13: 4:14
+          nop;                             // scope 1 at $DIR/copy_propagation.rs:5:5: 5:6
+          nop;                             // scope 0 at $DIR/copy_propagation.rs:6:1: 6:2
           return;                          // scope 0 at $DIR/copy_propagation.rs:6:2: 6:2
       }
   }
diff --git a/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff
index a4d60ae25d0c4..8aab2299d2651 100644
--- a/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff
+++ b/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff
@@ -6,15 +6,15 @@
       let mut _0: i32;                     // return place in scope 0 at $DIR/copy_propagation_arg.rs:27:27: 27:30
       let _2: i32;                         // in scope 0 at $DIR/copy_propagation_arg.rs:28:9: 28:10
       scope 1 {
-          debug y => _2;                   // in scope 1 at $DIR/copy_propagation_arg.rs:28:9: 28:10
+          debug y => _0;                   // in scope 1 at $DIR/copy_propagation_arg.rs:28:9: 28:10
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:28:9: 28:10
-          _2 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:28:13: 28:14
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:28:9: 28:10
+          _0 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:28:13: 28:14
           _1 = const 123_i32;              // scope 1 at $DIR/copy_propagation_arg.rs:29:5: 29:12
-          _0 = _2;                         // scope 1 at $DIR/copy_propagation_arg.rs:30:5: 30:6
-          StorageDead(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:31:1: 31:2
+          nop;                             // scope 1 at $DIR/copy_propagation_arg.rs:30:5: 30:6
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:31:1: 31:2
           return;                          // scope 0 at $DIR/copy_propagation_arg.rs:31:2: 31:2
       }
   }
diff --git a/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff
index b20003bd7c67e..1ea51fec71069 100644
--- a/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff
+++ b/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff
@@ -7,10 +7,10 @@
       let mut _2: i32;                     // in scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
-          _2 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
-          _1 = move _2;                    // scope 0 at $DIR/copy_propagation_arg.rs:23:5: 23:10
-          StorageDead(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:23:5: 23:10
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
           _0 = const ();                   // scope 0 at $DIR/copy_propagation_arg.rs:21:20: 24:2
           return;                          // scope 0 at $DIR/copy_propagation_arg.rs:24:2: 24:2
       }
diff --git a/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff
index d07a4c0541e1b..48ab37a239c62 100644
--- a/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff
+++ b/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff
@@ -8,10 +8,10 @@
       let mut _3: u8;                      // in scope 0 at $DIR/copy_propagation_arg.rs:11:15: 11:16
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17
           StorageLive(_3);                 // scope 0 at $DIR/copy_propagation_arg.rs:11:15: 11:16
           _3 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:11:15: 11:16
-          _2 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17
+          _1 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17
                                            // mir::Constant
                                            // + span: $DIR/copy_propagation_arg.rs:11:9: 11:14
                                            // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(Scalar(<ZST>)) }
@@ -19,8 +19,8 @@
   
       bb1: {
           StorageDead(_3);                 // scope 0 at $DIR/copy_propagation_arg.rs:11:16: 11:17
-          _1 = move _2;                    // scope 0 at $DIR/copy_propagation_arg.rs:11:5: 11:17
-          StorageDead(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:11:16: 11:17
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:11:5: 11:17
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:11:16: 11:17
           _0 = const ();                   // scope 0 at $DIR/copy_propagation_arg.rs:9:19: 12:2
           return;                          // scope 0 at $DIR/copy_propagation_arg.rs:12:2: 12:2
       }
diff --git a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
index 0258e3c2e4b38..ab194cf532ff3 100644
--- a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
@@ -10,15 +10,14 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
     let mut _6: &[closure@foo<T>::{{closure}}#0 q:&i32, t:&T]; // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:6
     let mut _7: (i32,);                  // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:9
     let mut _8: i32;                     // in scope 0 at $DIR/inline-closure-captures.rs:12:7: 12:8
-    let mut _11: i32;                    // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:9
+    let mut _10: i32;                    // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:9
     scope 1 {
         debug x => _3;                   // in scope 1 at $DIR/inline-closure-captures.rs:11:9: 11:10
         scope 2 {
-            debug _q => _11;             // in scope 2 at $DIR/inline-closure-captures.rs:11:14: 11:16
+            debug _q => _10;             // in scope 2 at $DIR/inline-closure-captures.rs:11:14: 11:16
             debug q => (*((*_6).0: &i32)); // in scope 2 at $DIR/inline-closure-captures.rs:10:23: 10:24
             debug t => (*((*_6).1: &T)); // in scope 2 at $DIR/inline-closure-captures.rs:10:17: 10:18
-            let mut _9: i32;             // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
-            let mut _10: T;              // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
+            let mut _9: T;               // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
         }
     }
 
@@ -38,17 +37,14 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
         StorageLive(_8);                 // scope 1 at $DIR/inline-closure-captures.rs:12:7: 12:8
         _8 = _2;                         // scope 1 at $DIR/inline-closure-captures.rs:12:7: 12:8
         (_7.0: i32) = move _8;           // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
-        StorageLive(_11);                // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
-        _11 = move (_7.0: i32);          // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
-        StorageLive(_9);                 // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20
-        _9 = (*((*_6).0: &i32));         // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20
-        StorageLive(_10);                // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23
-        _10 = (*((*_6).1: &T));          // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23
-        (_0.0: i32) = move _9;           // scope 2 at $DIR/inline-closure-captures.rs:11:18: 11:24
-        (_0.1: T) = move _10;            // scope 2 at $DIR/inline-closure-captures.rs:11:18: 11:24
-        StorageDead(_10);                // scope 2 at $DIR/inline-closure-captures.rs:11:23: 11:24
+        StorageLive(_10);                // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
+        _10 = move (_7.0: i32);          // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
+        (_0.0: i32) = (*((*_6).0: &i32)); // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20
+        StorageLive(_9);                 // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23
+        _9 = (*((*_6).1: &T));           // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23
+        (_0.1: T) = move _9;             // scope 2 at $DIR/inline-closure-captures.rs:11:18: 11:24
         StorageDead(_9);                 // scope 2 at $DIR/inline-closure-captures.rs:11:23: 11:24
-        StorageDead(_11);                // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
+        StorageDead(_10);                // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
         StorageDead(_8);                 // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9
         StorageDead(_7);                 // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9
         StorageDead(_6);                 // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
index f86755cfa7f70..a8662b96566cc 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
@@ -3,66 +3,59 @@
   
   fn main() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/issue-73223.rs:1:11: 1:11
-      let mut _1: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-      let _2: i32;                         // in scope 0 at $DIR/issue-73223.rs:3:14: 3:15
-      let mut _4: i32;                     // in scope 0 at $DIR/issue-73223.rs:7:22: 7:27
-      let mut _5: (&i32, &i32);            // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _6: &i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _9: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _10: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _11: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _12: &std::fmt::Arguments;       // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _13: std::fmt::Arguments;        // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _14: &[&str];                // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _15: &[std::fmt::ArgumentV1]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _16: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _17: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _18: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _19: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _20: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _21: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _24: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _25: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _26: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _27: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _1: i32;                         // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14
+      let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+      let mut _4: (&i32, &i32);            // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _5: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _6: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _7: i32;                     // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _8: &std::fmt::Arguments;    // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _9: std::fmt::Arguments;         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _10: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _11: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _12: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _13: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _14: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _15: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _16: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _17: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
       scope 1 {
-          debug split => _2;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
+          debug split => _1;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
           let _3: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
           scope 3 {
               debug _prev => _3;           // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
-              let _7: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let _8: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
               scope 4 {
-                  debug left_val => _7;    // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  debug right_val => _8;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _22: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _23: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  debug left_val => _13;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  debug right_val => _15;  // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   scope 5 {
-                      debug arg0 => _22;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug arg0 => _20;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                       debug arg1 => _23;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                       scope 6 {
-                          debug x => _22;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          debug f => _25;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          let mut _28: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _29: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          debug x => _20;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                          debug f => _19;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                          let mut _18: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _19: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _20: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
                       }
                       scope 8 {
                           debug x => _23;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          debug f => _27;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          let mut _30: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _31: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          debug f => _22;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                          let mut _21: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _22: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _23: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
                       }
                   }
                   scope 10 {
-                      debug pieces => _14; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                      debug args => _15;   // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                      let mut _32: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      debug pieces => (_9.0: &[&str]); // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                      debug args => _25;   // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                      let mut _24: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      let mut _25: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
                   }
               }
           }
       }
       scope 2 {
-          debug v => _2;                   // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15
+          debug v => _1;                   // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15
       }
       scope 7 {
       }
@@ -70,138 +63,108 @@
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          ((_1 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          discriminant(_1) = 1;            // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          _2 = ((_1 as Some).0: i32);      // scope 0 at $DIR/issue-73223.rs:3:14: 3:15
-          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:5:6: 5:7
-          StorageLive(_3);                 // scope 1 at $DIR/issue-73223.rs:7:9: 7:14
-          StorageLive(_4);                 // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
-          _4 = _2;                         // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
-          ((_3 as Some).0: i32) = move _4; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
+          StorageLive(_2);                 // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          discriminant(_2) = 1;            // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          _1 = ((_2 as Some).0: i32);      // scope 0 at $DIR/issue-73223.rs:3:14: 3:15
+          StorageDead(_2);                 // scope 0 at $DIR/issue-73223.rs:5:6: 5:7
+          ((_3 as Some).0: i32) = _1;      // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
           discriminant(_3) = 1;            // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
-          StorageDead(_4);                 // scope 1 at $DIR/issue-73223.rs:7:27: 7:28
-          StorageLive(_5);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_6);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _6 = &_2;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_5.0: &i32) = move _6;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_5.1: &i32) = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_4.0: &i32) = &_1;              // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_4.1: &i32) = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1])) }
-          StorageDead(_6);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _7 = (_5.0: &i32);               // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _8 = (_5.1: &i32);               // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _11 = (*_7);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _10 = Eq(move _11, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _9 = Not(move _10);              // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(_9) -> [false: bb1, otherwise: bb2]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _13 = (_4.0: &i32);              // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _15 = (_4.1: &i32);              // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_5);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _7 = (*_13);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _6 = Eq(move _7, const 1_i32);   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _5 = Not(move _6);               // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          switchInt(_5) -> [false: bb1, otherwise: bb2]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb1: {
-          StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_5);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_5);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _0 = const ();                   // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
-          StorageDead(_3);                 // scope 1 at $DIR/issue-73223.rs:9:1: 9:2
           return;                          // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
       }
   
       bb2: {
-          StorageLive(_13);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _14 = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_9.0: &[&str]) = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
-          StorageLive(_17);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_18);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_19);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_20);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _20 = _7;                        // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _19 = &_20;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_21);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _21 = &_8;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_18.0: &&i32) = move _19;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_18.1: &&i32) = move _21;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_21);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_19);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _22 = (_18.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _23 = (_18.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_24);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _25 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_11);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_12.0: &&i32) = &_13;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _14 = &_15;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_12.1: &&i32) = move _14;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_14);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _20 = (_12.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _23 = (_12.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _19 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_28);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _28 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _25) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageLive(_18);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _18 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _19) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb3: {
-          StorageLive(_29);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _29 = transmute::<&&i32, &core::fmt::Opaque>(move _22) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_16.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _20) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb4: {
-          (_24.0: &core::fmt::Opaque) = move _29; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_24.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _28; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_29);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_28);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageLive(_26);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _27 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_16.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _18; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageDead(_18);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _22 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_30);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _30 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageLive(_21);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _21 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _22) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb5: {
-          StorageLive(_31);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _31 = transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_17.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb6: {
-          (_26.0: &core::fmt::Opaque) = move _31; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_26.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _30; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_31);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_30);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _17 = [move _24, move _26];      // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_26);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_24);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _16 = &_17;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _15 = move _16 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_32);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          discriminant(_32) = 0;           // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_13.0: &[&str]) = move _14;     // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_13.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _32; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_13.2: &[std::fmt::ArgumentV1]) = move _15; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_32);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _12 = &_13;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          begin_panic_fmt(move _12);       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_17.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _21; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageDead(_21);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _11 = [move _16, move _17];      // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _10 = &_11;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _25 = move _10 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_24);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          discriminant(_24) = 0;           // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_9.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _24; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_9.2: &[std::fmt::ArgumentV1]) = move _25; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageDead(_24);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _8 = &_9;                        // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          begin_panic_fmt(move _8);        // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
index f86755cfa7f70..a8662b96566cc 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
@@ -3,66 +3,59 @@
   
   fn main() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/issue-73223.rs:1:11: 1:11
-      let mut _1: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-      let _2: i32;                         // in scope 0 at $DIR/issue-73223.rs:3:14: 3:15
-      let mut _4: i32;                     // in scope 0 at $DIR/issue-73223.rs:7:22: 7:27
-      let mut _5: (&i32, &i32);            // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _6: &i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _9: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _10: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _11: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _12: &std::fmt::Arguments;       // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _13: std::fmt::Arguments;        // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _14: &[&str];                // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _15: &[std::fmt::ArgumentV1]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _16: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _17: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _18: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _19: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _20: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _21: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _24: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _25: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _26: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _27: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _1: i32;                         // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14
+      let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+      let mut _4: (&i32, &i32);            // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _5: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _6: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _7: i32;                     // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _8: &std::fmt::Arguments;    // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _9: std::fmt::Arguments;         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _10: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _11: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _12: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _13: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _14: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _15: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _16: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _17: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
       scope 1 {
-          debug split => _2;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
+          debug split => _1;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
           let _3: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
           scope 3 {
               debug _prev => _3;           // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
-              let _7: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let _8: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
               scope 4 {
-                  debug left_val => _7;    // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  debug right_val => _8;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _22: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _23: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  debug left_val => _13;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  debug right_val => _15;  // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   scope 5 {
-                      debug arg0 => _22;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug arg0 => _20;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                       debug arg1 => _23;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                       scope 6 {
-                          debug x => _22;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          debug f => _25;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          let mut _28: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _29: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          debug x => _20;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                          debug f => _19;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                          let mut _18: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _19: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _20: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
                       }
                       scope 8 {
                           debug x => _23;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          debug f => _27;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          let mut _30: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _31: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          debug f => _22;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                          let mut _21: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _22: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _23: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
                       }
                   }
                   scope 10 {
-                      debug pieces => _14; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                      debug args => _15;   // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                      let mut _32: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      debug pieces => (_9.0: &[&str]); // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                      debug args => _25;   // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                      let mut _24: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      let mut _25: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
                   }
               }
           }
       }
       scope 2 {
-          debug v => _2;                   // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15
+          debug v => _1;                   // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15
       }
       scope 7 {
       }
@@ -70,138 +63,108 @@
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          ((_1 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          discriminant(_1) = 1;            // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          _2 = ((_1 as Some).0: i32);      // scope 0 at $DIR/issue-73223.rs:3:14: 3:15
-          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:5:6: 5:7
-          StorageLive(_3);                 // scope 1 at $DIR/issue-73223.rs:7:9: 7:14
-          StorageLive(_4);                 // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
-          _4 = _2;                         // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
-          ((_3 as Some).0: i32) = move _4; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
+          StorageLive(_2);                 // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          discriminant(_2) = 1;            // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          _1 = ((_2 as Some).0: i32);      // scope 0 at $DIR/issue-73223.rs:3:14: 3:15
+          StorageDead(_2);                 // scope 0 at $DIR/issue-73223.rs:5:6: 5:7
+          ((_3 as Some).0: i32) = _1;      // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
           discriminant(_3) = 1;            // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
-          StorageDead(_4);                 // scope 1 at $DIR/issue-73223.rs:7:27: 7:28
-          StorageLive(_5);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_6);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _6 = &_2;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_5.0: &i32) = move _6;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_5.1: &i32) = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_4.0: &i32) = &_1;              // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_4.1: &i32) = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1])) }
-          StorageDead(_6);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _7 = (_5.0: &i32);               // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _8 = (_5.1: &i32);               // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _11 = (*_7);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _10 = Eq(move _11, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _9 = Not(move _10);              // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(_9) -> [false: bb1, otherwise: bb2]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _13 = (_4.0: &i32);              // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _15 = (_4.1: &i32);              // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_5);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _7 = (*_13);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _6 = Eq(move _7, const 1_i32);   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _5 = Not(move _6);               // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          switchInt(_5) -> [false: bb1, otherwise: bb2]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb1: {
-          StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_5);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_5);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _0 = const ();                   // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
-          StorageDead(_3);                 // scope 1 at $DIR/issue-73223.rs:9:1: 9:2
           return;                          // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
       }
   
       bb2: {
-          StorageLive(_13);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _14 = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_9.0: &[&str]) = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
-          StorageLive(_17);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_18);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_19);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_20);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _20 = _7;                        // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _19 = &_20;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_21);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _21 = &_8;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_18.0: &&i32) = move _19;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_18.1: &&i32) = move _21;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_21);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_19);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _22 = (_18.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _23 = (_18.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_24);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _25 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_11);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_12.0: &&i32) = &_13;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _14 = &_15;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_12.1: &&i32) = move _14;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_14);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _20 = (_12.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _23 = (_12.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _19 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_28);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _28 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _25) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageLive(_18);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _18 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _19) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb3: {
-          StorageLive(_29);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _29 = transmute::<&&i32, &core::fmt::Opaque>(move _22) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_16.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _20) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb4: {
-          (_24.0: &core::fmt::Opaque) = move _29; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_24.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _28; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_29);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_28);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageLive(_26);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _27 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_16.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _18; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageDead(_18);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _22 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_30);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _30 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageLive(_21);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _21 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _22) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb5: {
-          StorageLive(_31);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _31 = transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_17.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb6: {
-          (_26.0: &core::fmt::Opaque) = move _31; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_26.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _30; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_31);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_30);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _17 = [move _24, move _26];      // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_26);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_24);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _16 = &_17;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _15 = move _16 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_32);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          discriminant(_32) = 0;           // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_13.0: &[&str]) = move _14;     // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_13.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _32; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_13.2: &[std::fmt::ArgumentV1]) = move _15; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_32);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _12 = &_13;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          begin_panic_fmt(move _12);       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_17.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _21; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageDead(_21);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _11 = [move _16, move _17];      // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _10 = &_11;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _25 = move _10 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_24);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          discriminant(_24) = 0;           // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_9.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _24; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_9.2: &[std::fmt::ArgumentV1]) = move _25; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageDead(_24);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _8 = &_9;                        // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          begin_panic_fmt(move _8);        // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt}, val: Value(Scalar(<ZST>)) }

From 812d4bbc8d1a240ecc900ffafacb5ce34f69e9f3 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Sat, 12 Sep 2020 14:58:52 +0200
Subject: [PATCH 22/40] Fix dataflow assert errors

---
 compiler/rustc_mir/src/transform/dest_prop.rs | 20 ++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index 19054f36171d9..3c46e8fc36b8d 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -403,6 +403,7 @@ impl Conflicts {
             .iterate_to_fixpoint()
             .into_results_cursor(body);
 
+        let mut reachable = None;
         dump_mir(
             tcx,
             None,
@@ -411,15 +412,18 @@ impl Conflicts {
             source,
             body,
             |pass_where, w| {
+                let reachable =
+                    reachable.get_or_insert_with(|| traversal::reachable_as_bitset(body));
+
                 match pass_where {
-                    PassWhere::BeforeLocation(loc) => {
+                    PassWhere::BeforeLocation(loc) if reachable.contains(loc.block) => {
                         init.seek_before_primary_effect(loc);
                         live.seek_after_primary_effect(loc);
 
                         writeln!(w, "        // init: {:?}", init.get())?;
                         writeln!(w, "        // live: {:?}", live.get())?;
                     }
-                    PassWhere::AfterTerminator(bb) => {
+                    PassWhere::AfterTerminator(bb) if reachable.contains(bb) => {
                         let loc = body.terminator_loc(bb);
                         init.seek_after_primary_effect(loc);
                         live.seek_before_primary_effect(loc);
@@ -428,7 +432,7 @@ impl Conflicts {
                         writeln!(w, "        // live: {:?}", live.get())?;
                     }
 
-                    PassWhere::BeforeBlock(bb) => {
+                    PassWhere::BeforeBlock(bb) if reachable.contains(bb) => {
                         init.seek_to_block_start(bb);
                         live.seek_to_block_start(bb);
 
@@ -437,6 +441,16 @@ impl Conflicts {
                     }
 
                     PassWhere::BeforeCFG | PassWhere::AfterCFG | PassWhere::AfterLocation(_) => {}
+
+                    PassWhere::BeforeLocation(_) | PassWhere::AfterTerminator(_) => {
+                        writeln!(w, "        // init: <unreachable>")?;
+                        writeln!(w, "        // live: <unreachable>")?;
+                    }
+
+                    PassWhere::BeforeBlock(_) => {
+                        writeln!(w, "    // init: <unreachable>")?;
+                        writeln!(w, "    // live: <unreachable>")?;
+                    }
                 }
 
                 Ok(())

From 7dbc7f76e1a0f1d054655f6fa5786b700745b66e Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Sun, 24 May 2020 21:37:09 +0200
Subject: [PATCH 23/40] Add a few dest-prop MIR tests

---
 src/test/mir-opt/dest-prop/branch.rs          | 21 +++++
 .../rustc.main.DestinationPropagation.diff    | 88 ++++++++++++++++++
 src/test/mir-opt/dest-prop/cycle.rs           | 15 +++
 .../rustc.main.DestinationPropagation.diff    | 91 +++++++++++++++++++
 src/test/mir-opt/dest-prop/simple.rs          | 14 +++
 .../rustc.nrvo.DestinationPropagation.diff    | 56 ++++++++++++
 src/test/mir-opt/dest-prop/union.rs           | 16 ++++
 .../rustc.main.DestinationPropagation.diff    | 61 +++++++++++++
 8 files changed, 362 insertions(+)
 create mode 100644 src/test/mir-opt/dest-prop/branch.rs
 create mode 100644 src/test/mir-opt/dest-prop/branch/rustc.main.DestinationPropagation.diff
 create mode 100644 src/test/mir-opt/dest-prop/cycle.rs
 create mode 100644 src/test/mir-opt/dest-prop/cycle/rustc.main.DestinationPropagation.diff
 create mode 100644 src/test/mir-opt/dest-prop/simple.rs
 create mode 100644 src/test/mir-opt/dest-prop/simple/rustc.nrvo.DestinationPropagation.diff
 create mode 100644 src/test/mir-opt/dest-prop/union.rs
 create mode 100644 src/test/mir-opt/dest-prop/union/rustc.main.DestinationPropagation.diff

diff --git a/src/test/mir-opt/dest-prop/branch.rs b/src/test/mir-opt/dest-prop/branch.rs
new file mode 100644
index 0000000000000..b49ecf07daa39
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/branch.rs
@@ -0,0 +1,21 @@
+//! Tests that assignment in both branches of an `if` are eliminated.
+
+fn val() -> i32 {
+    1
+}
+
+fn cond() -> bool {
+    true
+}
+
+// EMIT_MIR rustc.main.DestinationPropagation.diff
+fn main() {
+    let x = val();
+
+    let y = if cond() {
+        x
+    } else {
+        val();
+        x
+    };
+}
diff --git a/src/test/mir-opt/dest-prop/branch/rustc.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/branch/rustc.main.DestinationPropagation.diff
new file mode 100644
index 0000000000000..b8387ae449387
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/branch/rustc.main.DestinationPropagation.diff
@@ -0,0 +1,88 @@
+- // MIR for `main` before DestinationPropagation
++ // MIR for `main` after DestinationPropagation
+  
+  fn main() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/branch.rs:12:11: 12:11
+      let _1: i32;                         // in scope 0 at $DIR/branch.rs:13:9: 13:10
+      let mut _3: bool;                    // in scope 0 at $DIR/branch.rs:15:16: 15:22
+      let _4: i32;                         // in scope 0 at $DIR/branch.rs:18:9: 18:14
+      scope 1 {
+-         debug x => _1;                   // in scope 1 at $DIR/branch.rs:13:9: 13:10
++         debug x => _2;                   // in scope 1 at $DIR/branch.rs:13:9: 13:10
+          let _2: i32;                     // in scope 1 at $DIR/branch.rs:15:9: 15:10
+          scope 2 {
+              debug y => _2;               // in scope 2 at $DIR/branch.rs:15:9: 15:10
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_1);                 // scope 0 at $DIR/branch.rs:13:9: 13:10
+-         _1 = const val() -> bb1;         // scope 0 at $DIR/branch.rs:13:13: 13:18
++         nop;                             // scope 0 at $DIR/branch.rs:13:9: 13:10
++         _2 = const val() -> bb1;         // scope 0 at $DIR/branch.rs:13:13: 13:18
+                                           // ty::Const
+                                           // + ty: fn() -> i32 {val}
+                                           // + val: Value(Scalar(<ZST>))
+                                           // mir::Constant
+                                           // + span: $DIR/branch.rs:13:13: 13:16
+                                           // + literal: Const { ty: fn() -> i32 {val}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb1: {
+-         StorageLive(_2);                 // scope 1 at $DIR/branch.rs:15:9: 15:10
++         nop;                             // scope 1 at $DIR/branch.rs:15:9: 15:10
+          StorageLive(_3);                 // scope 1 at $DIR/branch.rs:15:16: 15:22
+          _3 = const cond() -> bb2;        // scope 1 at $DIR/branch.rs:15:16: 15:22
+                                           // ty::Const
+                                           // + ty: fn() -> bool {cond}
+                                           // + val: Value(Scalar(<ZST>))
+                                           // mir::Constant
+                                           // + span: $DIR/branch.rs:15:16: 15:20
+                                           // + literal: Const { ty: fn() -> bool {cond}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb2: {
+          switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 1 at $DIR/branch.rs:15:13: 20:6
+      }
+  
+      bb3: {
+          StorageLive(_4);                 // scope 1 at $DIR/branch.rs:18:9: 18:14
+          _4 = const val() -> bb5;         // scope 1 at $DIR/branch.rs:18:9: 18:14
+                                           // ty::Const
+                                           // + ty: fn() -> i32 {val}
+                                           // + val: Value(Scalar(<ZST>))
+                                           // mir::Constant
+                                           // + span: $DIR/branch.rs:18:9: 18:12
+                                           // + literal: Const { ty: fn() -> i32 {val}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb4: {
+-         _2 = _1;                         // scope 1 at $DIR/branch.rs:16:9: 16:10
++         nop;                             // scope 1 at $DIR/branch.rs:16:9: 16:10
+          goto -> bb6;                     // scope 1 at $DIR/branch.rs:15:13: 20:6
+      }
+  
+      bb5: {
+          StorageDead(_4);                 // scope 1 at $DIR/branch.rs:18:14: 18:15
+-         _2 = _1;                         // scope 1 at $DIR/branch.rs:19:9: 19:10
++         nop;                             // scope 1 at $DIR/branch.rs:19:9: 19:10
+          goto -> bb6;                     // scope 1 at $DIR/branch.rs:15:13: 20:6
+      }
+  
+      bb6: {
+          StorageDead(_3);                 // scope 1 at $DIR/branch.rs:20:6: 20:7
+          _0 = const ();                   // scope 0 at $DIR/branch.rs:12:11: 21:2
+                                           // ty::Const
+                                           // + ty: ()
+                                           // + val: Value(Scalar(<ZST>))
+                                           // mir::Constant
+                                           // + span: $DIR/branch.rs:12:11: 21:2
+                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+-         StorageDead(_2);                 // scope 1 at $DIR/branch.rs:21:1: 21:2
+-         StorageDead(_1);                 // scope 0 at $DIR/branch.rs:21:1: 21:2
++         nop;                             // scope 1 at $DIR/branch.rs:21:1: 21:2
++         nop;                             // scope 0 at $DIR/branch.rs:21:1: 21:2
+          return;                          // scope 0 at $DIR/branch.rs:21:2: 21:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/dest-prop/cycle.rs b/src/test/mir-opt/dest-prop/cycle.rs
new file mode 100644
index 0000000000000..d55d527bc65f6
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/cycle.rs
@@ -0,0 +1,15 @@
+//! Tests that cyclic assignments don't hang DestinationPropagation, and result in reasonable code.
+
+fn val() -> i32 {
+    1
+}
+
+// EMIT_MIR rustc.main.DestinationPropagation.diff
+fn main() {
+    let mut x = val();
+    let y = x;
+    let z = y;
+    x = z;
+
+    drop(x);
+}
diff --git a/src/test/mir-opt/dest-prop/cycle/rustc.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/cycle/rustc.main.DestinationPropagation.diff
new file mode 100644
index 0000000000000..5189b665acff1
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/cycle/rustc.main.DestinationPropagation.diff
@@ -0,0 +1,91 @@
+- // MIR for `main` before DestinationPropagation
++ // MIR for `main` after DestinationPropagation
+  
+  fn main() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/cycle.rs:8:11: 8:11
+      let mut _1: i32;                     // in scope 0 at $DIR/cycle.rs:9:9: 9:14
+      let mut _4: i32;                     // in scope 0 at $DIR/cycle.rs:12:9: 12:10
+      let _5: ();                          // in scope 0 at $DIR/cycle.rs:14:5: 14:12
+      let mut _6: i32;                     // in scope 0 at $DIR/cycle.rs:14:10: 14:11
+      scope 1 {
+-         debug x => _1;                   // in scope 1 at $DIR/cycle.rs:9:9: 9:14
++         debug x => _4;                   // in scope 1 at $DIR/cycle.rs:9:9: 9:14
+          let _2: i32;                     // in scope 1 at $DIR/cycle.rs:10:9: 10:10
+          scope 2 {
+-             debug y => _2;               // in scope 2 at $DIR/cycle.rs:10:9: 10:10
++             debug y => _4;               // in scope 2 at $DIR/cycle.rs:10:9: 10:10
+              let _3: i32;                 // in scope 2 at $DIR/cycle.rs:11:9: 11:10
+              scope 3 {
+-                 debug z => _3;           // in scope 3 at $DIR/cycle.rs:11:9: 11:10
++                 debug z => _4;           // in scope 3 at $DIR/cycle.rs:11:9: 11:10
+                  scope 4 {
+                      debug _x => _6;      // in scope 4 at $SRC_DIR/libcore/mem/mod.rs:LL:COL
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_1);                 // scope 0 at $DIR/cycle.rs:9:9: 9:14
+-         _1 = const val() -> bb1;         // scope 0 at $DIR/cycle.rs:9:17: 9:22
++         nop;                             // scope 0 at $DIR/cycle.rs:9:9: 9:14
++         _4 = const val() -> bb1;         // scope 0 at $DIR/cycle.rs:9:17: 9:22
+                                           // ty::Const
+                                           // + ty: fn() -> i32 {val}
+                                           // + val: Value(Scalar(<ZST>))
+                                           // mir::Constant
+                                           // + span: $DIR/cycle.rs:9:17: 9:20
+                                           // + literal: Const { ty: fn() -> i32 {val}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb1: {
+-         StorageLive(_2);                 // scope 1 at $DIR/cycle.rs:10:9: 10:10
+-         _2 = _1;                         // scope 1 at $DIR/cycle.rs:10:13: 10:14
+-         StorageLive(_3);                 // scope 2 at $DIR/cycle.rs:11:9: 11:10
+-         _3 = _2;                         // scope 2 at $DIR/cycle.rs:11:13: 11:14
+-         StorageLive(_4);                 // scope 3 at $DIR/cycle.rs:12:9: 12:10
+-         _4 = _3;                         // scope 3 at $DIR/cycle.rs:12:9: 12:10
+-         _1 = move _4;                    // scope 3 at $DIR/cycle.rs:12:5: 12:10
+-         StorageDead(_4);                 // scope 3 at $DIR/cycle.rs:12:9: 12:10
++         nop;                             // scope 1 at $DIR/cycle.rs:10:9: 10:10
++         nop;                             // scope 1 at $DIR/cycle.rs:10:13: 10:14
++         nop;                             // scope 2 at $DIR/cycle.rs:11:9: 11:10
++         nop;                             // scope 2 at $DIR/cycle.rs:11:13: 11:14
++         nop;                             // scope 3 at $DIR/cycle.rs:12:9: 12:10
++         nop;                             // scope 3 at $DIR/cycle.rs:12:9: 12:10
++         nop;                             // scope 3 at $DIR/cycle.rs:12:5: 12:10
++         nop;                             // scope 3 at $DIR/cycle.rs:12:9: 12:10
+          StorageLive(_5);                 // scope 3 at $DIR/cycle.rs:14:5: 14:12
+          StorageLive(_6);                 // scope 3 at $DIR/cycle.rs:14:10: 14:11
+-         _6 = _1;                         // scope 3 at $DIR/cycle.rs:14:10: 14:11
++         _6 = _4;                         // scope 3 at $DIR/cycle.rs:14:10: 14:11
+          _5 = const ();                   // scope 4 at $SRC_DIR/libcore/mem/mod.rs:LL:COL
+                                           // ty::Const
+                                           // + ty: ()
+                                           // + val: Value(Scalar(<ZST>))
+                                           // mir::Constant
+                                           // + span: $SRC_DIR/libcore/mem/mod.rs:LL:COL
+                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+          drop(_6) -> bb2;                 // scope 4 at $SRC_DIR/libcore/mem/mod.rs:LL:COL
+      }
+  
+      bb2: {
+          StorageDead(_6);                 // scope 3 at $DIR/cycle.rs:14:11: 14:12
+          StorageDead(_5);                 // scope 3 at $DIR/cycle.rs:14:12: 14:13
+          _0 = const ();                   // scope 0 at $DIR/cycle.rs:8:11: 15:2
+                                           // ty::Const
+                                           // + ty: ()
+                                           // + val: Value(Scalar(<ZST>))
+                                           // mir::Constant
+                                           // + span: $DIR/cycle.rs:8:11: 15:2
+                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+-         StorageDead(_3);                 // scope 2 at $DIR/cycle.rs:15:1: 15:2
+-         StorageDead(_2);                 // scope 1 at $DIR/cycle.rs:15:1: 15:2
+-         StorageDead(_1);                 // scope 0 at $DIR/cycle.rs:15:1: 15:2
++         nop;                             // scope 2 at $DIR/cycle.rs:15:1: 15:2
++         nop;                             // scope 1 at $DIR/cycle.rs:15:1: 15:2
++         nop;                             // scope 0 at $DIR/cycle.rs:15:1: 15:2
+          return;                          // scope 0 at $DIR/cycle.rs:15:2: 15:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/dest-prop/simple.rs b/src/test/mir-opt/dest-prop/simple.rs
new file mode 100644
index 0000000000000..add821eafe0b0
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/simple.rs
@@ -0,0 +1,14 @@
+//! Copy of `nrvo-simple.rs`, to ensure that full dest-prop handles it too.
+
+// EMIT_MIR rustc.nrvo.DestinationPropagation.diff
+fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
+    let mut buf = [0; 1024];
+    init(&mut buf);
+    buf
+}
+
+fn main() {
+    let _ = nrvo(|buf| {
+        buf[4] = 4;
+    });
+}
diff --git a/src/test/mir-opt/dest-prop/simple/rustc.nrvo.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/simple/rustc.nrvo.DestinationPropagation.diff
new file mode 100644
index 0000000000000..d59e1f3c0c938
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/simple/rustc.nrvo.DestinationPropagation.diff
@@ -0,0 +1,56 @@
+- // MIR for `nrvo` before DestinationPropagation
++ // MIR for `nrvo` after DestinationPropagation
+  
+  fn nrvo(_1: for<'r> fn(&'r mut [u8; 1024])) -> [u8; 1024] {
+      debug init => _1;                    // in scope 0 at $DIR/simple.rs:4:9: 4:13
+      let mut _0: [u8; 1024];              // return place in scope 0 at $DIR/simple.rs:4:39: 4:49
+      let mut _2: [u8; 1024];              // in scope 0 at $DIR/simple.rs:5:9: 5:16
+      let _3: ();                          // in scope 0 at $DIR/simple.rs:6:5: 6:19
+      let mut _4: for<'r> fn(&'r mut [u8; 1024]); // in scope 0 at $DIR/simple.rs:6:5: 6:9
+      let mut _5: &mut [u8; 1024];         // in scope 0 at $DIR/simple.rs:6:10: 6:18
+      let mut _6: &mut [u8; 1024];         // in scope 0 at $DIR/simple.rs:6:10: 6:18
+      scope 1 {
+-         debug buf => _2;                 // in scope 1 at $DIR/simple.rs:5:9: 5:16
++         debug buf => _0;                 // in scope 1 at $DIR/simple.rs:5:9: 5:16
+      }
+  
+      bb0: {
+-         StorageLive(_2);                 // scope 0 at $DIR/simple.rs:5:9: 5:16
+-         _2 = [const 0u8; 1024];          // scope 0 at $DIR/simple.rs:5:19: 5:28
++         nop;                             // scope 0 at $DIR/simple.rs:5:9: 5:16
++         _0 = [const 0u8; 1024];          // scope 0 at $DIR/simple.rs:5:19: 5:28
+                                           // ty::Const
+                                           // + ty: u8
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/simple.rs:5:20: 5:21
+                                           // + literal: Const { ty: u8, val: Value(Scalar(0x00)) }
+          StorageLive(_3);                 // scope 1 at $DIR/simple.rs:6:5: 6:19
+          StorageLive(_4);                 // scope 1 at $DIR/simple.rs:6:5: 6:9
+          _4 = _1;                         // scope 1 at $DIR/simple.rs:6:5: 6:9
+-         StorageLive(_5);                 // scope 1 at $DIR/simple.rs:6:10: 6:18
+-         StorageLive(_6);                 // scope 1 at $DIR/simple.rs:6:10: 6:18
+-         _6 = &mut _2;                    // scope 1 at $DIR/simple.rs:6:10: 6:18
+-         _5 = move _6;                    // scope 1 at $DIR/simple.rs:6:10: 6:18
++         nop;                             // scope 1 at $DIR/simple.rs:6:10: 6:18
++         nop;                             // scope 1 at $DIR/simple.rs:6:10: 6:18
++         _5 = &mut _0;                    // scope 1 at $DIR/simple.rs:6:10: 6:18
++         nop;                             // scope 1 at $DIR/simple.rs:6:10: 6:18
+          _3 = move _4(move _5) -> bb1;    // scope 1 at $DIR/simple.rs:6:5: 6:19
+      }
+  
+      bb1: {
+-         StorageDead(_5);                 // scope 1 at $DIR/simple.rs:6:18: 6:19
++         nop;                             // scope 1 at $DIR/simple.rs:6:18: 6:19
+          StorageDead(_4);                 // scope 1 at $DIR/simple.rs:6:18: 6:19
+-         StorageDead(_6);                 // scope 1 at $DIR/simple.rs:6:19: 6:20
++         nop;                             // scope 1 at $DIR/simple.rs:6:19: 6:20
+          StorageDead(_3);                 // scope 1 at $DIR/simple.rs:6:19: 6:20
+-         _0 = _2;                         // scope 1 at $DIR/simple.rs:7:5: 7:8
+-         StorageDead(_2);                 // scope 0 at $DIR/simple.rs:8:1: 8:2
++         nop;                             // scope 1 at $DIR/simple.rs:7:5: 7:8
++         nop;                             // scope 0 at $DIR/simple.rs:8:1: 8:2
+          return;                          // scope 0 at $DIR/simple.rs:8:2: 8:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/dest-prop/union.rs b/src/test/mir-opt/dest-prop/union.rs
new file mode 100644
index 0000000000000..ea8364124043e
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/union.rs
@@ -0,0 +1,16 @@
+//! Tests that projections through unions cancel `DestinationPropagation`.
+
+fn val() -> u32 {
+    1
+}
+
+// EMIT_MIR rustc.main.DestinationPropagation.diff
+fn main() {
+    union Un {
+        us: u32,
+    }
+
+    let un = Un { us: val() };
+
+    drop(unsafe { un.us });
+}
diff --git a/src/test/mir-opt/dest-prop/union/rustc.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/union/rustc.main.DestinationPropagation.diff
new file mode 100644
index 0000000000000..f6ebb6cb9403d
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/union/rustc.main.DestinationPropagation.diff
@@ -0,0 +1,61 @@
+- // MIR for `main` before DestinationPropagation
++ // MIR for `main` after DestinationPropagation
+  
+  fn main() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/union.rs:8:11: 8:11
+      let _1: main::Un;                    // in scope 0 at $DIR/union.rs:13:9: 13:11
+      let mut _2: u32;                     // in scope 0 at $DIR/union.rs:13:23: 13:28
+      let _3: ();                          // in scope 0 at $DIR/union.rs:15:5: 15:27
+      let mut _4: u32;                     // in scope 0 at $DIR/union.rs:15:10: 15:26
+      scope 1 {
+          debug un => _1;                  // in scope 1 at $DIR/union.rs:13:9: 13:11
+          scope 2 {
+          }
+          scope 3 {
+              debug _x => _4;              // in scope 3 at $SRC_DIR/libcore/mem/mod.rs:LL:COL
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/union.rs:13:9: 13:11
+          StorageLive(_2);                 // scope 0 at $DIR/union.rs:13:23: 13:28
+          _2 = const val() -> bb1;         // scope 0 at $DIR/union.rs:13:23: 13:28
+                                           // ty::Const
+                                           // + ty: fn() -> u32 {val}
+                                           // + val: Value(Scalar(<ZST>))
+                                           // mir::Constant
+                                           // + span: $DIR/union.rs:13:23: 13:26
+                                           // + literal: Const { ty: fn() -> u32 {val}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb1: {
+          (_1.0: u32) = move _2;           // scope 0 at $DIR/union.rs:13:14: 13:30
+          StorageDead(_2);                 // scope 0 at $DIR/union.rs:13:29: 13:30
+          StorageLive(_3);                 // scope 1 at $DIR/union.rs:15:5: 15:27
+          StorageLive(_4);                 // scope 1 at $DIR/union.rs:15:10: 15:26
+          _4 = (_1.0: u32);                // scope 2 at $DIR/union.rs:15:19: 15:24
+          _3 = const ();                   // scope 3 at $SRC_DIR/libcore/mem/mod.rs:LL:COL
+                                           // ty::Const
+                                           // + ty: ()
+                                           // + val: Value(Scalar(<ZST>))
+                                           // mir::Constant
+                                           // + span: $SRC_DIR/libcore/mem/mod.rs:LL:COL
+                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+          drop(_4) -> bb2;                 // scope 3 at $SRC_DIR/libcore/mem/mod.rs:LL:COL
+      }
+  
+      bb2: {
+          StorageDead(_4);                 // scope 1 at $DIR/union.rs:15:26: 15:27
+          StorageDead(_3);                 // scope 1 at $DIR/union.rs:15:27: 15:28
+          _0 = const ();                   // scope 0 at $DIR/union.rs:8:11: 16:2
+                                           // ty::Const
+                                           // + ty: ()
+                                           // + val: Value(Scalar(<ZST>))
+                                           // mir::Constant
+                                           // + span: $DIR/union.rs:8:11: 16:2
+                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+          StorageDead(_1);                 // scope 0 at $DIR/union.rs:16:1: 16:2
+          return;                          // scope 0 at $DIR/union.rs:16:2: 16:2
+      }
+  }
+  

From 402f863d8ac2e69abf415d9ed9c1b9984e037700 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Sat, 12 Sep 2020 15:10:38 +0200
Subject: [PATCH 24/40] perf: walk liveness backwards in Conflicts::build

---
 compiler/rustc_mir/src/transform/dest_prop.rs | 63 ++++++++++++-------
 1 file changed, 39 insertions(+), 24 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index 3c46e8fc36b8d..8e174ce277a9c 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -100,10 +100,7 @@ use crate::{
     transform::{MirPass, MirSource},
     util::{dump_mir, PassWhere},
 };
-use dataflow::{
-    impls::{MaybeInitializedLocals, MaybeLiveLocals},
-    ResultsCursor,
-};
+use dataflow::impls::{MaybeInitializedLocals, MaybeLiveLocals};
 use rustc_data_structures::unify::{InPlaceUnificationTable, UnifyKey};
 use rustc_index::{
     bit_set::{BitMatrix, BitSet},
@@ -382,16 +379,11 @@ impl Conflicts {
             body.local_decls.len(),
         );
 
-        let mut record_conflicts =
-            |init: &ResultsCursor<'_, '_, MaybeInitializedLocals>,
-             live: &ResultsCursor<'_, '_, MaybeLiveLocals>| {
-                let mut requires_storage = init.get().clone();
-                requires_storage.intersect(live.get());
-
-                for local in requires_storage.iter() {
-                    conflicts.union_row_with(&requires_storage, local);
-                }
-            };
+        let mut record_conflicts = |new_conflicts: &BitSet<_>| {
+            for local in new_conflicts.iter() {
+                conflicts.union_row_with(&new_conflicts, local);
+            }
+        };
 
         let def_id = source.def_id();
         let mut init = MaybeInitializedLocals
@@ -457,27 +449,50 @@ impl Conflicts {
             },
         );
 
+        let mut relevant_locals = Vec::new();
+
         // Visit only reachable basic blocks. The exact order is not important.
         for (block, data) in traversal::preorder(body) {
-            // Observe the dataflow state *before* all possible locations (statement or terminator) in
-            // each basic block...
+            // We need to observe the dataflow state *before* all possible locations (statement or
+            // terminator) in each basic block, and then observe the state *after* the terminator
+            // effect is applied. As long as neither `init` nor `borrowed` has a "before" effect,
+            // we will observe all possible dataflow states.
+
+            // Since liveness is a backwards analysis, we need to walk the results backwards. To do
+            // that, we first collect in the `MaybeInitializedLocals` results in a forwards
+            // traversal.
+
+            relevant_locals.resize_with(data.statements.len() + 1, || {
+                BitSet::new_empty(body.local_decls.len())
+            });
+
+            // First, go forwards for `MaybeInitializedLocals`.
             for statement_index in 0..=data.statements.len() {
                 let loc = Location { block, statement_index };
-                trace!("record conflicts at {:?}", loc);
                 init.seek_before_primary_effect(loc);
+
+                relevant_locals[statement_index].clone_from(init.get());
+            }
+
+            // Now, go backwards and union with the liveness results.
+            for statement_index in (0..=data.statements.len()).rev() {
+                let loc = Location { block, statement_index };
                 live.seek_after_primary_effect(loc);
-                // FIXME: liveness is backwards, so this is slow
 
-                record_conflicts(&init, &live);
+                relevant_locals[statement_index].intersect(live.get());
+
+                trace!("record conflicts at {:?}", loc);
+
+                record_conflicts(&relevant_locals[statement_index]);
             }
 
-            // ...and then observe the state *after* the terminator effect is applied. As long as
-            // neither `init` nor `borrowed` has a "before" effect, we will observe all possible
-            // dataflow states here or in the loop above.
-            trace!("record conflicts at end of {:?}", block);
             init.seek_to_block_end(block);
             live.seek_to_block_end(block);
-            record_conflicts(&init, &live);
+            let mut conflicts = init.get().clone();
+            conflicts.intersect(live.get());
+            trace!("record conflicts at end of {:?}", block);
+
+            record_conflicts(&conflicts);
         }
 
         Self { matrix: conflicts, unify_cache: BitSet::new_empty(body.local_decls.len()) }

From 665a98d21f926fbd8a89fe2af7c448ff34deadc3 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Sat, 12 Sep 2020 15:10:51 +0200
Subject: [PATCH 25/40] Fix dest-prop mir-opt tests

---
 ...> branch.main.DestinationPropagation.diff} | 23 +++-------------
 src/test/mir-opt/dest-prop/branch.rs          |  2 +-
 ...=> cycle.main.DestinationPropagation.diff} | 25 ++++-------------
 src/test/mir-opt/dest-prop/cycle.rs           |  2 +-
 ...> simple.nrvo.DestinationPropagation.diff} | 27 ++++++-------------
 src/test/mir-opt/dest-prop/simple.rs          |  2 +-
 ...=> union.main.DestinationPropagation.diff} | 23 +++-------------
 src/test/mir-opt/dest-prop/union.rs           |  2 +-
 8 files changed, 25 insertions(+), 81 deletions(-)
 rename src/test/mir-opt/dest-prop/{branch/rustc.main.DestinationPropagation.diff => branch.main.DestinationPropagation.diff} (74%)
 rename src/test/mir-opt/dest-prop/{cycle/rustc.main.DestinationPropagation.diff => cycle.main.DestinationPropagation.diff} (78%)
 rename src/test/mir-opt/dest-prop/{simple/rustc.nrvo.DestinationPropagation.diff => simple.nrvo.DestinationPropagation.diff} (63%)
 rename src/test/mir-opt/dest-prop/{union/rustc.main.DestinationPropagation.diff => union.main.DestinationPropagation.diff} (65%)

diff --git a/src/test/mir-opt/dest-prop/branch/rustc.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff
similarity index 74%
rename from src/test/mir-opt/dest-prop/branch/rustc.main.DestinationPropagation.diff
rename to src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff
index b8387ae449387..9c213eaed3c04 100644
--- a/src/test/mir-opt/dest-prop/branch/rustc.main.DestinationPropagation.diff
+++ b/src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff
@@ -17,12 +17,9 @@
   
       bb0: {
 -         StorageLive(_1);                 // scope 0 at $DIR/branch.rs:13:9: 13:10
--         _1 = const val() -> bb1;         // scope 0 at $DIR/branch.rs:13:13: 13:18
+-         _1 = val() -> bb1;               // scope 0 at $DIR/branch.rs:13:13: 13:18
 +         nop;                             // scope 0 at $DIR/branch.rs:13:9: 13:10
-+         _2 = const val() -> bb1;         // scope 0 at $DIR/branch.rs:13:13: 13:18
-                                           // ty::Const
-                                           // + ty: fn() -> i32 {val}
-                                           // + val: Value(Scalar(<ZST>))
++         _2 = val() -> bb1;               // scope 0 at $DIR/branch.rs:13:13: 13:18
                                            // mir::Constant
                                            // + span: $DIR/branch.rs:13:13: 13:16
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value(Scalar(<ZST>)) }
@@ -32,10 +29,7 @@
 -         StorageLive(_2);                 // scope 1 at $DIR/branch.rs:15:9: 15:10
 +         nop;                             // scope 1 at $DIR/branch.rs:15:9: 15:10
           StorageLive(_3);                 // scope 1 at $DIR/branch.rs:15:16: 15:22
-          _3 = const cond() -> bb2;        // scope 1 at $DIR/branch.rs:15:16: 15:22
-                                           // ty::Const
-                                           // + ty: fn() -> bool {cond}
-                                           // + val: Value(Scalar(<ZST>))
+          _3 = cond() -> bb2;              // scope 1 at $DIR/branch.rs:15:16: 15:22
                                            // mir::Constant
                                            // + span: $DIR/branch.rs:15:16: 15:20
                                            // + literal: Const { ty: fn() -> bool {cond}, val: Value(Scalar(<ZST>)) }
@@ -47,10 +41,7 @@
   
       bb3: {
           StorageLive(_4);                 // scope 1 at $DIR/branch.rs:18:9: 18:14
-          _4 = const val() -> bb5;         // scope 1 at $DIR/branch.rs:18:9: 18:14
-                                           // ty::Const
-                                           // + ty: fn() -> i32 {val}
-                                           // + val: Value(Scalar(<ZST>))
+          _4 = val() -> bb5;               // scope 1 at $DIR/branch.rs:18:9: 18:14
                                            // mir::Constant
                                            // + span: $DIR/branch.rs:18:9: 18:12
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value(Scalar(<ZST>)) }
@@ -72,12 +63,6 @@
       bb6: {
           StorageDead(_3);                 // scope 1 at $DIR/branch.rs:20:6: 20:7
           _0 = const ();                   // scope 0 at $DIR/branch.rs:12:11: 21:2
-                                           // ty::Const
-                                           // + ty: ()
-                                           // + val: Value(Scalar(<ZST>))
-                                           // mir::Constant
-                                           // + span: $DIR/branch.rs:12:11: 21:2
-                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
 -         StorageDead(_2);                 // scope 1 at $DIR/branch.rs:21:1: 21:2
 -         StorageDead(_1);                 // scope 0 at $DIR/branch.rs:21:1: 21:2
 +         nop;                             // scope 1 at $DIR/branch.rs:21:1: 21:2
diff --git a/src/test/mir-opt/dest-prop/branch.rs b/src/test/mir-opt/dest-prop/branch.rs
index b49ecf07daa39..7e0e40671ddb2 100644
--- a/src/test/mir-opt/dest-prop/branch.rs
+++ b/src/test/mir-opt/dest-prop/branch.rs
@@ -8,7 +8,7 @@ fn cond() -> bool {
     true
 }
 
-// EMIT_MIR rustc.main.DestinationPropagation.diff
+// EMIT_MIR branch.main.DestinationPropagation.diff
 fn main() {
     let x = val();
 
diff --git a/src/test/mir-opt/dest-prop/cycle/rustc.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff
similarity index 78%
rename from src/test/mir-opt/dest-prop/cycle/rustc.main.DestinationPropagation.diff
rename to src/test/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff
index 5189b665acff1..dd717c1b9c324 100644
--- a/src/test/mir-opt/dest-prop/cycle/rustc.main.DestinationPropagation.diff
+++ b/src/test/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff
@@ -19,7 +19,7 @@
 -                 debug z => _3;           // in scope 3 at $DIR/cycle.rs:11:9: 11:10
 +                 debug z => _4;           // in scope 3 at $DIR/cycle.rs:11:9: 11:10
                   scope 4 {
-                      debug _x => _6;      // in scope 4 at $SRC_DIR/libcore/mem/mod.rs:LL:COL
+                      debug _x => _6;      // in scope 4 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
                   }
               }
           }
@@ -27,12 +27,9 @@
   
       bb0: {
 -         StorageLive(_1);                 // scope 0 at $DIR/cycle.rs:9:9: 9:14
--         _1 = const val() -> bb1;         // scope 0 at $DIR/cycle.rs:9:17: 9:22
+-         _1 = val() -> bb1;               // scope 0 at $DIR/cycle.rs:9:17: 9:22
 +         nop;                             // scope 0 at $DIR/cycle.rs:9:9: 9:14
-+         _4 = const val() -> bb1;         // scope 0 at $DIR/cycle.rs:9:17: 9:22
-                                           // ty::Const
-                                           // + ty: fn() -> i32 {val}
-                                           // + val: Value(Scalar(<ZST>))
++         _4 = val() -> bb1;               // scope 0 at $DIR/cycle.rs:9:17: 9:22
                                            // mir::Constant
                                            // + span: $DIR/cycle.rs:9:17: 9:20
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value(Scalar(<ZST>)) }
@@ -59,26 +56,14 @@
           StorageLive(_6);                 // scope 3 at $DIR/cycle.rs:14:10: 14:11
 -         _6 = _1;                         // scope 3 at $DIR/cycle.rs:14:10: 14:11
 +         _6 = _4;                         // scope 3 at $DIR/cycle.rs:14:10: 14:11
-          _5 = const ();                   // scope 4 at $SRC_DIR/libcore/mem/mod.rs:LL:COL
-                                           // ty::Const
-                                           // + ty: ()
-                                           // + val: Value(Scalar(<ZST>))
-                                           // mir::Constant
-                                           // + span: $SRC_DIR/libcore/mem/mod.rs:LL:COL
-                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
-          drop(_6) -> bb2;                 // scope 4 at $SRC_DIR/libcore/mem/mod.rs:LL:COL
+          _5 = const ();                   // scope 4 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+          drop(_6) -> bb2;                 // scope 4 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
       }
   
       bb2: {
           StorageDead(_6);                 // scope 3 at $DIR/cycle.rs:14:11: 14:12
           StorageDead(_5);                 // scope 3 at $DIR/cycle.rs:14:12: 14:13
           _0 = const ();                   // scope 0 at $DIR/cycle.rs:8:11: 15:2
-                                           // ty::Const
-                                           // + ty: ()
-                                           // + val: Value(Scalar(<ZST>))
-                                           // mir::Constant
-                                           // + span: $DIR/cycle.rs:8:11: 15:2
-                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
 -         StorageDead(_3);                 // scope 2 at $DIR/cycle.rs:15:1: 15:2
 -         StorageDead(_2);                 // scope 1 at $DIR/cycle.rs:15:1: 15:2
 -         StorageDead(_1);                 // scope 0 at $DIR/cycle.rs:15:1: 15:2
diff --git a/src/test/mir-opt/dest-prop/cycle.rs b/src/test/mir-opt/dest-prop/cycle.rs
index d55d527bc65f6..7fbffb1335946 100644
--- a/src/test/mir-opt/dest-prop/cycle.rs
+++ b/src/test/mir-opt/dest-prop/cycle.rs
@@ -4,7 +4,7 @@ fn val() -> i32 {
     1
 }
 
-// EMIT_MIR rustc.main.DestinationPropagation.diff
+// EMIT_MIR cycle.main.DestinationPropagation.diff
 fn main() {
     let mut x = val();
     let y = x;
diff --git a/src/test/mir-opt/dest-prop/simple/rustc.nrvo.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff
similarity index 63%
rename from src/test/mir-opt/dest-prop/simple/rustc.nrvo.DestinationPropagation.diff
rename to src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff
index d59e1f3c0c938..1277c51f2a050 100644
--- a/src/test/mir-opt/dest-prop/simple/rustc.nrvo.DestinationPropagation.diff
+++ b/src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff
@@ -16,35 +16,24 @@
   
       bb0: {
 -         StorageLive(_2);                 // scope 0 at $DIR/simple.rs:5:9: 5:16
--         _2 = [const 0u8; 1024];          // scope 0 at $DIR/simple.rs:5:19: 5:28
+-         _2 = [const 0_u8; 1024];         // scope 0 at $DIR/simple.rs:5:19: 5:28
 +         nop;                             // scope 0 at $DIR/simple.rs:5:9: 5:16
-+         _0 = [const 0u8; 1024];          // scope 0 at $DIR/simple.rs:5:19: 5:28
-                                           // ty::Const
-                                           // + ty: u8
-                                           // + val: Value(Scalar(0x00))
-                                           // mir::Constant
-                                           // + span: $DIR/simple.rs:5:20: 5:21
-                                           // + literal: Const { ty: u8, val: Value(Scalar(0x00)) }
++         _0 = [const 0_u8; 1024];         // scope 0 at $DIR/simple.rs:5:19: 5:28
           StorageLive(_3);                 // scope 1 at $DIR/simple.rs:6:5: 6:19
           StorageLive(_4);                 // scope 1 at $DIR/simple.rs:6:5: 6:9
           _4 = _1;                         // scope 1 at $DIR/simple.rs:6:5: 6:9
--         StorageLive(_5);                 // scope 1 at $DIR/simple.rs:6:10: 6:18
--         StorageLive(_6);                 // scope 1 at $DIR/simple.rs:6:10: 6:18
+          StorageLive(_5);                 // scope 1 at $DIR/simple.rs:6:10: 6:18
+          StorageLive(_6);                 // scope 1 at $DIR/simple.rs:6:10: 6:18
 -         _6 = &mut _2;                    // scope 1 at $DIR/simple.rs:6:10: 6:18
--         _5 = move _6;                    // scope 1 at $DIR/simple.rs:6:10: 6:18
-+         nop;                             // scope 1 at $DIR/simple.rs:6:10: 6:18
-+         nop;                             // scope 1 at $DIR/simple.rs:6:10: 6:18
-+         _5 = &mut _0;                    // scope 1 at $DIR/simple.rs:6:10: 6:18
-+         nop;                             // scope 1 at $DIR/simple.rs:6:10: 6:18
++         _6 = &mut _0;                    // scope 1 at $DIR/simple.rs:6:10: 6:18
+          _5 = &mut (*_6);                 // scope 1 at $DIR/simple.rs:6:10: 6:18
           _3 = move _4(move _5) -> bb1;    // scope 1 at $DIR/simple.rs:6:5: 6:19
       }
   
       bb1: {
--         StorageDead(_5);                 // scope 1 at $DIR/simple.rs:6:18: 6:19
-+         nop;                             // scope 1 at $DIR/simple.rs:6:18: 6:19
+          StorageDead(_5);                 // scope 1 at $DIR/simple.rs:6:18: 6:19
           StorageDead(_4);                 // scope 1 at $DIR/simple.rs:6:18: 6:19
--         StorageDead(_6);                 // scope 1 at $DIR/simple.rs:6:19: 6:20
-+         nop;                             // scope 1 at $DIR/simple.rs:6:19: 6:20
+          StorageDead(_6);                 // scope 1 at $DIR/simple.rs:6:19: 6:20
           StorageDead(_3);                 // scope 1 at $DIR/simple.rs:6:19: 6:20
 -         _0 = _2;                         // scope 1 at $DIR/simple.rs:7:5: 7:8
 -         StorageDead(_2);                 // scope 0 at $DIR/simple.rs:8:1: 8:2
diff --git a/src/test/mir-opt/dest-prop/simple.rs b/src/test/mir-opt/dest-prop/simple.rs
index add821eafe0b0..4655f96699874 100644
--- a/src/test/mir-opt/dest-prop/simple.rs
+++ b/src/test/mir-opt/dest-prop/simple.rs
@@ -1,6 +1,6 @@
 //! Copy of `nrvo-simple.rs`, to ensure that full dest-prop handles it too.
 
-// EMIT_MIR rustc.nrvo.DestinationPropagation.diff
+// EMIT_MIR simple.nrvo.DestinationPropagation.diff
 fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
     let mut buf = [0; 1024];
     init(&mut buf);
diff --git a/src/test/mir-opt/dest-prop/union/rustc.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff
similarity index 65%
rename from src/test/mir-opt/dest-prop/union/rustc.main.DestinationPropagation.diff
rename to src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff
index f6ebb6cb9403d..871f6e35043ec 100644
--- a/src/test/mir-opt/dest-prop/union/rustc.main.DestinationPropagation.diff
+++ b/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff
@@ -12,17 +12,14 @@
           scope 2 {
           }
           scope 3 {
-              debug _x => _4;              // in scope 3 at $SRC_DIR/libcore/mem/mod.rs:LL:COL
+              debug _x => _4;              // in scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
           }
       }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/union.rs:13:9: 13:11
           StorageLive(_2);                 // scope 0 at $DIR/union.rs:13:23: 13:28
-          _2 = const val() -> bb1;         // scope 0 at $DIR/union.rs:13:23: 13:28
-                                           // ty::Const
-                                           // + ty: fn() -> u32 {val}
-                                           // + val: Value(Scalar(<ZST>))
+          _2 = val() -> bb1;               // scope 0 at $DIR/union.rs:13:23: 13:28
                                            // mir::Constant
                                            // + span: $DIR/union.rs:13:23: 13:26
                                            // + literal: Const { ty: fn() -> u32 {val}, val: Value(Scalar(<ZST>)) }
@@ -34,26 +31,14 @@
           StorageLive(_3);                 // scope 1 at $DIR/union.rs:15:5: 15:27
           StorageLive(_4);                 // scope 1 at $DIR/union.rs:15:10: 15:26
           _4 = (_1.0: u32);                // scope 2 at $DIR/union.rs:15:19: 15:24
-          _3 = const ();                   // scope 3 at $SRC_DIR/libcore/mem/mod.rs:LL:COL
-                                           // ty::Const
-                                           // + ty: ()
-                                           // + val: Value(Scalar(<ZST>))
-                                           // mir::Constant
-                                           // + span: $SRC_DIR/libcore/mem/mod.rs:LL:COL
-                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
-          drop(_4) -> bb2;                 // scope 3 at $SRC_DIR/libcore/mem/mod.rs:LL:COL
+          _3 = const ();                   // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+          drop(_4) -> bb2;                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
       }
   
       bb2: {
           StorageDead(_4);                 // scope 1 at $DIR/union.rs:15:26: 15:27
           StorageDead(_3);                 // scope 1 at $DIR/union.rs:15:27: 15:28
           _0 = const ();                   // scope 0 at $DIR/union.rs:8:11: 16:2
-                                           // ty::Const
-                                           // + ty: ()
-                                           // + val: Value(Scalar(<ZST>))
-                                           // mir::Constant
-                                           // + span: $DIR/union.rs:8:11: 16:2
-                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
           StorageDead(_1);                 // scope 0 at $DIR/union.rs:16:1: 16:2
           return;                          // scope 0 at $DIR/union.rs:16:2: 16:2
       }
diff --git a/src/test/mir-opt/dest-prop/union.rs b/src/test/mir-opt/dest-prop/union.rs
index ea8364124043e..b9d831389e8b3 100644
--- a/src/test/mir-opt/dest-prop/union.rs
+++ b/src/test/mir-opt/dest-prop/union.rs
@@ -4,7 +4,7 @@ fn val() -> u32 {
     1
 }
 
-// EMIT_MIR rustc.main.DestinationPropagation.diff
+// EMIT_MIR union.main.DestinationPropagation.diff
 fn main() {
     union Un {
         us: u32,

From ab26fb140c9225c690a219c055a54eba57188d4a Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Tue, 26 May 2020 22:21:10 +0200
Subject: [PATCH 26/40] perf: only calculate conflicts for candidates

---
 compiler/rustc_mir/src/transform/dest_prop.rs | 51 ++++++++++++++-----
 1 file changed, 39 insertions(+), 12 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index 8e174ce277a9c..d22c11f491b40 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -124,9 +124,22 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
             return;
         }
 
-        let mut conflicts = Conflicts::build(tcx, body, source);
+        let candidates = find_candidates(tcx, body);
+        if candidates.is_empty() {
+            debug!("{:?}: no dest prop candidates, done", source.def_id());
+            return;
+        }
+
+        // Collect all locals we care about. We only compute conflicts for these to save time.
+        let mut relevant_locals = BitSet::new_empty(body.local_decls.len());
+        for CandidateAssignment { dest, src, loc: _ } in &candidates {
+            relevant_locals.insert(dest.local);
+            relevant_locals.insert(*src);
+        }
+
+        let mut conflicts = Conflicts::build(tcx, body, source, &relevant_locals);
         let mut replacements = Replacements::new(body.local_decls.len());
-        for candidate @ CandidateAssignment { dest, src, loc } in find_candidates(tcx, body) {
+        for candidate @ CandidateAssignment { dest, src, loc } in candidates {
             // Merge locals that don't conflict.
             if conflicts.contains(dest.local, src) {
                 debug!("at assignment {:?}, conflict {:?} vs. {:?}", loc, dest.local, src);
@@ -370,16 +383,30 @@ struct Conflicts {
 }
 
 impl Conflicts {
-    fn build<'tcx>(tcx: TyCtxt<'tcx>, body: &'_ Body<'tcx>, source: MirSource<'tcx>) -> Self {
-        // We don't have to look out for locals that have their address taken, since `find_candidates`
-        // already takes care of that.
+    fn build<'tcx>(
+        tcx: TyCtxt<'tcx>,
+        body: &'_ Body<'tcx>,
+        source: MirSource<'tcx>,
+        relevant_locals: &BitSet<Local>,
+    ) -> Self {
+        // We don't have to look out for locals that have their address taken, since
+        // `find_candidates` already takes care of that.
+
+        debug!(
+            "Conflicts::build: {}/{} locals relevant",
+            relevant_locals.count(),
+            body.local_decls.len()
+        );
 
         let mut conflicts = BitMatrix::from_row_n(
             &BitSet::new_empty(body.local_decls.len()),
             body.local_decls.len(),
         );
 
-        let mut record_conflicts = |new_conflicts: &BitSet<_>| {
+        let mut record_conflicts = |new_conflicts: &mut BitSet<_>| {
+            // Remove all locals that are not candidates.
+            new_conflicts.intersect(relevant_locals);
+
             for local in new_conflicts.iter() {
                 conflicts.union_row_with(&new_conflicts, local);
             }
@@ -449,7 +476,7 @@ impl Conflicts {
             },
         );
 
-        let mut relevant_locals = Vec::new();
+        let mut live_and_init_locals = Vec::new();
 
         // Visit only reachable basic blocks. The exact order is not important.
         for (block, data) in traversal::preorder(body) {
@@ -462,7 +489,7 @@ impl Conflicts {
             // that, we first collect in the `MaybeInitializedLocals` results in a forwards
             // traversal.
 
-            relevant_locals.resize_with(data.statements.len() + 1, || {
+            live_and_init_locals.resize_with(data.statements.len() + 1, || {
                 BitSet::new_empty(body.local_decls.len())
             });
 
@@ -471,7 +498,7 @@ impl Conflicts {
                 let loc = Location { block, statement_index };
                 init.seek_before_primary_effect(loc);
 
-                relevant_locals[statement_index].clone_from(init.get());
+                live_and_init_locals[statement_index].clone_from(init.get());
             }
 
             // Now, go backwards and union with the liveness results.
@@ -479,11 +506,11 @@ impl Conflicts {
                 let loc = Location { block, statement_index };
                 live.seek_after_primary_effect(loc);
 
-                relevant_locals[statement_index].intersect(live.get());
+                live_and_init_locals[statement_index].intersect(live.get());
 
                 trace!("record conflicts at {:?}", loc);
 
-                record_conflicts(&relevant_locals[statement_index]);
+                record_conflicts(&mut live_and_init_locals[statement_index]);
             }
 
             init.seek_to_block_end(block);
@@ -492,7 +519,7 @@ impl Conflicts {
             conflicts.intersect(live.get());
             trace!("record conflicts at end of {:?}", block);
 
-            record_conflicts(&conflicts);
+            record_conflicts(&mut conflicts);
         }
 
         Self { matrix: conflicts, unify_cache: BitSet::new_empty(body.local_decls.len()) }

From ddd6930b549d069ac13de66b8676fed4feb95ec4 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Tue, 26 May 2020 21:39:24 +0200
Subject: [PATCH 27/40] perf: bail out when there's >500 candidate locals

---
 compiler/rustc_mir/src/transform/dest_prop.rs | 30 +++++++++++++++----
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index d22c11f491b40..cb4321ace7f9a 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -114,6 +114,8 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
+const MAX_LOCALS: usize = 500;
+
 pub struct DestinationPropagation;
 
 impl<'tcx> MirPass<'tcx> for DestinationPropagation {
@@ -137,7 +139,29 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
             relevant_locals.insert(*src);
         }
 
+        // This pass unfortunately has `O(l² * s)` performance, where `l` is the number of locals
+        // and `s` is the number of statements and terminators in the function.
+        // To prevent blowing up compile times too much, we bail out when there are too many locals.
+        let relevant = relevant_locals.count();
+        debug!(
+            "{:?}: {} locals ({} relevant), {} blocks",
+            source.def_id(),
+            body.local_decls.len(),
+            relevant,
+            body.basic_blocks().len()
+        );
+        if relevant > MAX_LOCALS {
+            warn!(
+                "too many candidate locals in {:?} ({}, max is {}), not optimizing",
+                source.def_id(),
+                relevant,
+                MAX_LOCALS
+            );
+            return;
+        }
+
         let mut conflicts = Conflicts::build(tcx, body, source, &relevant_locals);
+
         let mut replacements = Replacements::new(body.local_decls.len());
         for candidate @ CandidateAssignment { dest, src, loc } in candidates {
             // Merge locals that don't conflict.
@@ -392,12 +416,6 @@ impl Conflicts {
         // We don't have to look out for locals that have their address taken, since
         // `find_candidates` already takes care of that.
 
-        debug!(
-            "Conflicts::build: {}/{} locals relevant",
-            relevant_locals.count(),
-            body.local_decls.len()
-        );
-
         let mut conflicts = BitMatrix::from_row_n(
             &BitSet::new_empty(body.local_decls.len()),
             body.local_decls.len(),

From 88538adf9ae1886d9b5c1f45d55b2f76bd6435bd Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Sat, 12 Sep 2020 15:15:05 +0200
Subject: [PATCH 28/40] Record intra-statement/terminator conflicts

Some MIR statements and terminators have an (undocumented...) invariant
that some of their input and outputs must not overlap. This records
conflicts between locals used in these positions.
---
 compiler/rustc_mir/src/transform/dest_prop.rs | 228 ++++++++++++++++--
 1 file changed, 206 insertions(+), 22 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index cb4321ace7f9a..20f8f820176ab 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -109,8 +109,8 @@ use rustc_index::{
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::{
-    traversal, Body, Local, LocalKind, Location, Operand, Place, PlaceElem, Rvalue, Statement,
-    StatementKind, Terminator, TerminatorKind,
+    traversal, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, PlaceElem,
+    Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
 };
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
@@ -397,7 +397,9 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
     }
 }
 
-struct Conflicts {
+struct Conflicts<'a> {
+    relevant_locals: &'a BitSet<Local>,
+
     /// The conflict matrix. It is always symmetric and the adjacency matrix of the corresponding
     /// conflict graph.
     matrix: BitMatrix<Local, Local>,
@@ -406,30 +408,21 @@ struct Conflicts {
     unify_cache: BitSet<Local>,
 }
 
-impl Conflicts {
+impl Conflicts<'a> {
     fn build<'tcx>(
         tcx: TyCtxt<'tcx>,
         body: &'_ Body<'tcx>,
         source: MirSource<'tcx>,
-        relevant_locals: &BitSet<Local>,
+        relevant_locals: &'a BitSet<Local>,
     ) -> Self {
         // We don't have to look out for locals that have their address taken, since
         // `find_candidates` already takes care of that.
 
-        let mut conflicts = BitMatrix::from_row_n(
+        let conflicts = BitMatrix::from_row_n(
             &BitSet::new_empty(body.local_decls.len()),
             body.local_decls.len(),
         );
 
-        let mut record_conflicts = |new_conflicts: &mut BitSet<_>| {
-            // Remove all locals that are not candidates.
-            new_conflicts.intersect(relevant_locals);
-
-            for local in new_conflicts.iter() {
-                conflicts.union_row_with(&new_conflicts, local);
-            }
-        };
-
         let def_id = source.def_id();
         let mut init = MaybeInitializedLocals
             .into_engine(tcx, body, def_id)
@@ -494,6 +487,12 @@ impl Conflicts {
             },
         );
 
+        let mut this = Self {
+            relevant_locals,
+            matrix: conflicts,
+            unify_cache: BitSet::new_empty(body.local_decls.len()),
+        };
+
         let mut live_and_init_locals = Vec::new();
 
         // Visit only reachable basic blocks. The exact order is not important.
@@ -511,14 +510,22 @@ impl Conflicts {
                 BitSet::new_empty(body.local_decls.len())
             });
 
-            // First, go forwards for `MaybeInitializedLocals`.
-            for statement_index in 0..=data.statements.len() {
-                let loc = Location { block, statement_index };
+            // First, go forwards for `MaybeInitializedLocals` and apply intra-statement/terminator
+            // conflicts.
+            for (i, statement) in data.statements.iter().enumerate() {
+                this.record_statement_conflicts(statement);
+
+                let loc = Location { block, statement_index: i };
                 init.seek_before_primary_effect(loc);
 
-                live_and_init_locals[statement_index].clone_from(init.get());
+                live_and_init_locals[i].clone_from(init.get());
             }
 
+            this.record_terminator_conflicts(data.terminator());
+            let term_loc = Location { block, statement_index: data.statements.len() };
+            init.seek_before_primary_effect(term_loc);
+            live_and_init_locals[term_loc.statement_index].clone_from(init.get());
+
             // Now, go backwards and union with the liveness results.
             for statement_index in (0..=data.statements.len()).rev() {
                 let loc = Location { block, statement_index };
@@ -528,7 +535,7 @@ impl Conflicts {
 
                 trace!("record conflicts at {:?}", loc);
 
-                record_conflicts(&mut live_and_init_locals[statement_index]);
+                this.record_conflicts(&mut live_and_init_locals[statement_index]);
             }
 
             init.seek_to_block_end(block);
@@ -537,10 +544,187 @@ impl Conflicts {
             conflicts.intersect(live.get());
             trace!("record conflicts at end of {:?}", block);
 
-            record_conflicts(&mut conflicts);
+            this.record_conflicts(&mut conflicts);
+        }
+
+        this
+    }
+
+    fn record_conflicts(&mut self, new_conflicts: &mut BitSet<Local>) {
+        // Remove all locals that are not candidates.
+        new_conflicts.intersect(self.relevant_locals);
+
+        for local in new_conflicts.iter() {
+            self.matrix.union_row_with(&new_conflicts, local);
+        }
+    }
+
+    /// Records locals that must not overlap during the evaluation of `stmt`. These locals conflict
+    /// and must not be merged.
+    fn record_statement_conflicts(&mut self, stmt: &Statement<'_>) {
+        match &stmt.kind {
+            // While the left and right sides of an assignment must not overlap, we do not mark
+            // conflicts here as that would make this optimization useless. When we optimize, we
+            // eliminate the resulting self-assignments automatically.
+            StatementKind::Assign(_) => {}
+
+            StatementKind::LlvmInlineAsm(asm) => {
+                // Inputs and outputs must not overlap.
+                for (_, input) in &*asm.inputs {
+                    if let Some(in_place) = input.place() {
+                        if !in_place.is_indirect() {
+                            for out_place in &*asm.outputs {
+                                if !out_place.is_indirect() && !in_place.is_indirect() {
+                                    self.matrix.insert(in_place.local, out_place.local);
+                                    self.matrix.insert(out_place.local, in_place.local);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            StatementKind::SetDiscriminant { .. }
+            | StatementKind::StorageLive(_)
+            | StatementKind::StorageDead(_)
+            | StatementKind::Retag(_, _)
+            | StatementKind::FakeRead(_, _)
+            | StatementKind::AscribeUserType(_, _)
+            | StatementKind::Nop => {}
         }
+    }
 
-        Self { matrix: conflicts, unify_cache: BitSet::new_empty(body.local_decls.len()) }
+    fn record_terminator_conflicts(&mut self, term: &Terminator<'_>) {
+        match &term.kind {
+            TerminatorKind::DropAndReplace { location, value, target: _, unwind: _ } => {
+                if let Some(place) = value.place() {
+                    if !place.is_indirect() && !location.is_indirect() {
+                        self.matrix.insert(place.local, location.local);
+                        self.matrix.insert(location.local, place.local);
+                    }
+                }
+            }
+            TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
+                if let Some(place) = value.place() {
+                    if !place.is_indirect() && !resume_arg.is_indirect() {
+                        self.matrix.insert(place.local, resume_arg.local);
+                        self.matrix.insert(resume_arg.local, place.local);
+                    }
+                }
+            }
+            TerminatorKind::Call {
+                func,
+                args,
+                destination: Some((dest_place, _)),
+                cleanup: _,
+                from_hir_call: _,
+            } => {
+                // No arguments may overlap with the destination.
+                for arg in args.iter().chain(Some(func)) {
+                    if let Some(place) = arg.place() {
+                        if !place.is_indirect() && !dest_place.is_indirect() {
+                            self.matrix.insert(dest_place.local, place.local);
+                            self.matrix.insert(place.local, dest_place.local);
+                        }
+                    }
+                }
+            }
+            TerminatorKind::InlineAsm {
+                template: _,
+                operands,
+                options: _,
+                line_spans: _,
+                destination: _,
+            } => {
+                // The intended semantics here aren't documented, we just assume that nothing that
+                // could be written to by the assembly may overlap with any other operands.
+                for op in operands {
+                    match op {
+                        InlineAsmOperand::Out { reg: _, late: _, place: Some(dest_place) }
+                        | InlineAsmOperand::InOut {
+                            reg: _,
+                            late: _,
+                            in_value: _,
+                            out_place: Some(dest_place),
+                        } => {
+                            // For output place `place`, add all places accessed by the inline asm.
+                            for op in operands {
+                                match op {
+                                    InlineAsmOperand::In { reg: _, value } => {
+                                        if let Some(p) = value.place() {
+                                            if !p.is_indirect() && !dest_place.is_indirect() {
+                                                self.matrix.insert(p.local, dest_place.local);
+                                                self.matrix.insert(dest_place.local, p.local);
+                                            }
+                                        }
+                                    }
+                                    InlineAsmOperand::Out {
+                                        reg: _,
+                                        late: _,
+                                        place: Some(place),
+                                    } => {
+                                        if !place.is_indirect() && !dest_place.is_indirect() {
+                                            self.matrix.insert(place.local, dest_place.local);
+                                            self.matrix.insert(dest_place.local, place.local);
+                                        }
+                                    }
+                                    InlineAsmOperand::InOut {
+                                        reg: _,
+                                        late: _,
+                                        in_value,
+                                        out_place,
+                                    } => {
+                                        if let Some(place) = in_value.place() {
+                                            if !place.is_indirect() && !dest_place.is_indirect() {
+                                                self.matrix.insert(place.local, dest_place.local);
+                                                self.matrix.insert(dest_place.local, place.local);
+                                            }
+                                        }
+
+                                        if let Some(place) = out_place {
+                                            if !place.is_indirect() && !dest_place.is_indirect() {
+                                                self.matrix.insert(place.local, dest_place.local);
+                                                self.matrix.insert(dest_place.local, place.local);
+                                            }
+                                        }
+                                    }
+                                    InlineAsmOperand::Out { reg: _, late: _, place: None }
+                                    | InlineAsmOperand::Const { value: _ }
+                                    | InlineAsmOperand::SymFn { value: _ }
+                                    | InlineAsmOperand::SymStatic { value: _ } => {}
+                                }
+                            }
+                        }
+                        InlineAsmOperand::Const { value } => {
+                            assert!(value.place().is_none());
+                        }
+                        InlineAsmOperand::InOut {
+                            reg: _,
+                            late: _,
+                            in_value: _,
+                            out_place: None,
+                        }
+                        | InlineAsmOperand::In { reg: _, value: _ }
+                        | InlineAsmOperand::Out { reg: _, late: _, place: None }
+                        | InlineAsmOperand::SymFn { value: _ }
+                        | InlineAsmOperand::SymStatic { value: _ } => {}
+                    }
+                }
+            }
+
+            TerminatorKind::Goto { .. }
+            | TerminatorKind::Call { destination: None, .. }
+            | TerminatorKind::SwitchInt { .. }
+            | TerminatorKind::Resume
+            | TerminatorKind::Abort
+            | TerminatorKind::Return
+            | TerminatorKind::Unreachable
+            | TerminatorKind::Drop { .. }
+            | TerminatorKind::Assert { .. }
+            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseUnwind { .. } => {}
+        }
     }
 
     fn contains(&self, a: Local, b: Local) -> bool {

From 934634eacc2721e482672a99f91ed458580eb978 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Tue, 23 Jun 2020 01:25:52 +0200
Subject: [PATCH 29/40] More logging

---
 compiler/rustc_mir/src/transform/dest_prop.rs | 80 ++++++++++++++-----
 1 file changed, 59 insertions(+), 21 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index 20f8f820176ab..d8f62e3506270 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -95,12 +95,13 @@
 //! [previous attempt]: https://github.com/rust-lang/rust/pull/47954
 //! [subsequent approach]: https://github.com/rust-lang/rust/pull/71003
 
-use crate::dataflow::{self, Analysis};
+use crate::dataflow::impls::{MaybeInitializedLocals, MaybeLiveLocals};
+use crate::dataflow::Analysis;
 use crate::{
     transform::{MirPass, MirSource},
     util::{dump_mir, PassWhere},
 };
-use dataflow::impls::{MaybeInitializedLocals, MaybeLiveLocals};
+use itertools::Itertools;
 use rustc_data_structures::unify::{InPlaceUnificationTable, UnifyKey};
 use rustc_index::{
     bit_set::{BitMatrix, BitSet},
@@ -255,12 +256,14 @@ impl Replacements<'tcx> {
 
             // We still return `Err` in any case, as `src` and `dest` do not need to be unified
             // *again*.
+            trace!("push({:?}): already unified", candidate);
             return Err(());
         }
 
         let entry = &mut self.map[candidate.src];
         if entry.is_some() {
             // We're already replacing `src` with something else, so this candidate is out.
+            trace!("push({:?}): src already has replacement", candidate);
             return Err(());
         }
 
@@ -270,6 +273,7 @@ impl Replacements<'tcx> {
         self.kill.insert(candidate.src);
         self.kill.insert(candidate.dest.local);
 
+        trace!("push({:?}): accepted", candidate);
         Ok(())
     }
 
@@ -535,7 +539,7 @@ impl Conflicts<'a> {
 
                 trace!("record conflicts at {:?}", loc);
 
-                this.record_conflicts(&mut live_and_init_locals[statement_index]);
+                this.record_dataflow_conflicts(&mut live_and_init_locals[statement_index]);
             }
 
             init.seek_to_block_end(block);
@@ -544,13 +548,13 @@ impl Conflicts<'a> {
             conflicts.intersect(live.get());
             trace!("record conflicts at end of {:?}", block);
 
-            this.record_conflicts(&mut conflicts);
+            this.record_dataflow_conflicts(&mut conflicts);
         }
 
         this
     }
 
-    fn record_conflicts(&mut self, new_conflicts: &mut BitSet<Local>) {
+    fn record_dataflow_conflicts(&mut self, new_conflicts: &mut BitSet<Local>) {
         // Remove all locals that are not candidates.
         new_conflicts.intersect(self.relevant_locals);
 
@@ -559,6 +563,12 @@ impl Conflicts<'a> {
         }
     }
 
+    fn record_local_conflict(&mut self, a: Local, b: Local, why: &str) {
+        trace!("conflict {:?} <-> {:?} due to {}", a, b, why);
+        self.matrix.insert(a, b);
+        self.matrix.insert(b, a);
+    }
+
     /// Records locals that must not overlap during the evaluation of `stmt`. These locals conflict
     /// and must not be merged.
     fn record_statement_conflicts(&mut self, stmt: &Statement<'_>) {
@@ -575,8 +585,11 @@ impl Conflicts<'a> {
                         if !in_place.is_indirect() {
                             for out_place in &*asm.outputs {
                                 if !out_place.is_indirect() && !in_place.is_indirect() {
-                                    self.matrix.insert(in_place.local, out_place.local);
-                                    self.matrix.insert(out_place.local, in_place.local);
+                                    self.record_local_conflict(
+                                        in_place.local,
+                                        out_place.local,
+                                        "aliasing llvm_asm! operands",
+                                    );
                                 }
                             }
                         }
@@ -599,16 +612,22 @@ impl Conflicts<'a> {
             TerminatorKind::DropAndReplace { location, value, target: _, unwind: _ } => {
                 if let Some(place) = value.place() {
                     if !place.is_indirect() && !location.is_indirect() {
-                        self.matrix.insert(place.local, location.local);
-                        self.matrix.insert(location.local, place.local);
+                        self.record_local_conflict(
+                            place.local,
+                            location.local,
+                            "DropAndReplace operand overlap",
+                        );
                     }
                 }
             }
             TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
                 if let Some(place) = value.place() {
                     if !place.is_indirect() && !resume_arg.is_indirect() {
-                        self.matrix.insert(place.local, resume_arg.local);
-                        self.matrix.insert(resume_arg.local, place.local);
+                        self.record_local_conflict(
+                            place.local,
+                            resume_arg.local,
+                            "Yield operand overlap",
+                        );
                     }
                 }
             }
@@ -623,8 +642,11 @@ impl Conflicts<'a> {
                 for arg in args.iter().chain(Some(func)) {
                     if let Some(place) = arg.place() {
                         if !place.is_indirect() && !dest_place.is_indirect() {
-                            self.matrix.insert(dest_place.local, place.local);
-                            self.matrix.insert(place.local, dest_place.local);
+                            self.record_local_conflict(
+                                dest_place.local,
+                                place.local,
+                                "call dest/arg overlap",
+                            );
                         }
                     }
                 }
@@ -653,8 +675,11 @@ impl Conflicts<'a> {
                                     InlineAsmOperand::In { reg: _, value } => {
                                         if let Some(p) = value.place() {
                                             if !p.is_indirect() && !dest_place.is_indirect() {
-                                                self.matrix.insert(p.local, dest_place.local);
-                                                self.matrix.insert(dest_place.local, p.local);
+                                                self.record_local_conflict(
+                                                    p.local,
+                                                    dest_place.local,
+                                                    "asm! operand overlap",
+                                                );
                                             }
                                         }
                                     }
@@ -664,8 +689,11 @@ impl Conflicts<'a> {
                                         place: Some(place),
                                     } => {
                                         if !place.is_indirect() && !dest_place.is_indirect() {
-                                            self.matrix.insert(place.local, dest_place.local);
-                                            self.matrix.insert(dest_place.local, place.local);
+                                            self.record_local_conflict(
+                                                place.local,
+                                                dest_place.local,
+                                                "asm! operand overlap",
+                                            );
                                         }
                                     }
                                     InlineAsmOperand::InOut {
@@ -676,15 +704,21 @@ impl Conflicts<'a> {
                                     } => {
                                         if let Some(place) = in_value.place() {
                                             if !place.is_indirect() && !dest_place.is_indirect() {
-                                                self.matrix.insert(place.local, dest_place.local);
-                                                self.matrix.insert(dest_place.local, place.local);
+                                                self.record_local_conflict(
+                                                    place.local,
+                                                    dest_place.local,
+                                                    "asm! operand overlap",
+                                                );
                                             }
                                         }
 
                                         if let Some(place) = out_place {
                                             if !place.is_indirect() && !dest_place.is_indirect() {
-                                                self.matrix.insert(place.local, dest_place.local);
-                                                self.matrix.insert(dest_place.local, place.local);
+                                                self.record_local_conflict(
+                                                    place.local,
+                                                    dest_place.local,
+                                                    "asm! operand overlap",
+                                                );
                                             }
                                         }
                                     }
@@ -750,6 +784,10 @@ impl Conflicts<'a> {
         // FIXME: This might be somewhat slow. Conflict graphs are undirected, maybe we can use
         // something with union-find to speed this up?
 
+        trace!("unify({:?}, {:?})", a, b);
+        trace!("{:?} conflicts: {:?}", a, self.matrix.iter(a).format(", "));
+        trace!("{:?} conflicts: {:?}", b, self.matrix.iter(b).format(", "));
+
         // Make all locals that conflict with `a` also conflict with `b`, and vice versa.
         self.unify_cache.clear();
         for conflicts_with_a in self.matrix.iter(a) {

From 484db5b08a83bd8875e0e938a0f78ce0a220bb17 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Wed, 24 Jun 2020 02:23:53 +0200
Subject: [PATCH 30/40] Properly inherit conflicts when merging locals

---
 compiler/rustc_mir/src/transform/dest_prop.rs | 113 ++++++++++--------
 src/test/ui/dest-prop/skeptic-miscompile.rs   |  24 ++++
 2 files changed, 84 insertions(+), 53 deletions(-)
 create mode 100644 src/test/ui/dest-prop/skeptic-miscompile.rs

diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index d8f62e3506270..cd3708374054a 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -166,20 +166,24 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
         let mut replacements = Replacements::new(body.local_decls.len());
         for candidate @ CandidateAssignment { dest, src, loc } in candidates {
             // Merge locals that don't conflict.
-            if conflicts.contains(dest.local, src) {
+            if !conflicts.can_unify(dest.local, src) {
                 debug!("at assignment {:?}, conflict {:?} vs. {:?}", loc, dest.local, src);
                 continue;
             }
 
+            if replacements.for_src(candidate.src).is_some() {
+                debug!("src {:?} already has replacement", candidate.src);
+                continue;
+            }
+
             if !tcx.consider_optimizing(|| {
                 format!("DestinationPropagation {:?} {:?}", source.def_id(), candidate)
             }) {
                 break;
             }
 
-            if replacements.push(candidate).is_ok() {
-                conflicts.unify(candidate.src, candidate.dest.local);
-            }
+            replacements.push(candidate);
+            conflicts.unify(candidate.src, candidate.dest.local);
         }
 
         replacements.flatten(tcx);
@@ -220,61 +224,21 @@ struct Replacements<'tcx> {
 
     /// Whose locals' live ranges to kill.
     kill: BitSet<Local>,
-
-    /// Tracks locals that have already been merged together to prevent cycles.
-    unified_locals: InPlaceUnificationTable<UnifyLocal>,
 }
 
 impl Replacements<'tcx> {
     fn new(locals: usize) -> Self {
-        Self {
-            map: IndexVec::from_elem_n(None, locals),
-            kill: BitSet::new_empty(locals),
-            unified_locals: {
-                let mut table = InPlaceUnificationTable::new();
-                for local in 0..locals {
-                    assert_eq!(table.new_key(()), UnifyLocal(Local::from_usize(local)));
-                }
-                table
-            },
-        }
+        Self { map: IndexVec::from_elem_n(None, locals), kill: BitSet::new_empty(locals) }
     }
 
-    fn push(&mut self, candidate: CandidateAssignment<'tcx>) -> Result<(), ()> {
-        if self.unified_locals.unioned(candidate.src, candidate.dest.local) {
-            // Candidate conflicts with previous replacement (ie. could possibly form a cycle and
-            // hang).
-
-            let replacement = self.map[candidate.src].as_mut().unwrap();
-
-            // If the current replacement is for the same `dest` local, there are 2 or more
-            // equivalent `src = dest;` assignments. This is fine, the replacer will `nop` out all
-            // of them.
-            if replacement.local == candidate.dest.local {
-                assert_eq!(replacement.projection, candidate.dest.projection);
-            }
-
-            // We still return `Err` in any case, as `src` and `dest` do not need to be unified
-            // *again*.
-            trace!("push({:?}): already unified", candidate);
-            return Err(());
-        }
-
+    fn push(&mut self, candidate: CandidateAssignment<'tcx>) {
+        trace!("Replacements::push({:?})", candidate);
         let entry = &mut self.map[candidate.src];
-        if entry.is_some() {
-            // We're already replacing `src` with something else, so this candidate is out.
-            trace!("push({:?}): src already has replacement", candidate);
-            return Err(());
-        }
-
-        self.unified_locals.union(candidate.src, candidate.dest.local);
+        assert!(entry.is_none());
 
         *entry = Some(candidate.dest);
         self.kill.insert(candidate.src);
         self.kill.insert(candidate.dest.local);
-
-        trace!("push({:?}): accepted", candidate);
-        Ok(())
     }
 
     /// Applies the stored replacements to all replacements, until no replacements would result in
@@ -410,6 +374,9 @@ struct Conflicts<'a> {
 
     /// Preallocated `BitSet` used by `unify`.
     unify_cache: BitSet<Local>,
+
+    /// Tracks locals that have been merged together to prevent cycles and propagate conflicts.
+    unified_locals: InPlaceUnificationTable<UnifyLocal>,
 }
 
 impl Conflicts<'a> {
@@ -495,6 +462,15 @@ impl Conflicts<'a> {
             relevant_locals,
             matrix: conflicts,
             unify_cache: BitSet::new_empty(body.local_decls.len()),
+            unified_locals: {
+                let mut table = InPlaceUnificationTable::new();
+                // Pre-fill table with all locals (this creates N nodes / "connected" components,
+                // "graph"-ically speaking).
+                for local in 0..body.local_decls.len() {
+                    assert_eq!(table.new_key(()), UnifyLocal(Local::from_usize(local)));
+                }
+                table
+            },
         };
 
         let mut live_and_init_locals = Vec::new();
@@ -761,11 +737,31 @@ impl Conflicts<'a> {
         }
     }
 
-    fn contains(&self, a: Local, b: Local) -> bool {
-        self.matrix.contains(a, b)
+    /// Checks whether `a` and `b` may be merged. Returns `false` if there's a conflict.
+    fn can_unify(&mut self, a: Local, b: Local) -> bool {
+        // After some locals have been unified, their conflicts are only tracked in the root key,
+        // so look that up.
+        let a = self.unified_locals.find(a).0;
+        let b = self.unified_locals.find(b).0;
+
+        if a == b {
+            // Already merged (part of the same connected component).
+            return false;
+        }
+
+        if self.matrix.contains(a, b) {
+            // Conflict (derived via dataflow, intra-statement conflicts, or inherited from another
+            // local during unification).
+            return false;
+        }
+
+        true
     }
 
     /// Merges the conflicts of `a` and `b`, so that each one inherits all conflicts of the other.
+    /// 
+    /// `can_unify` must have returned `true` for the same locals, or this may panic or lead to
+    /// miscompiles.
     ///
     /// This is called when the pass makes the decision to unify `a` and `b` (or parts of `a` and
     /// `b`) and is needed to ensure that future unification decisions take potentially newly
@@ -781,13 +777,24 @@ impl Conflicts<'a> {
     /// `_2` with `_0`, which also doesn't have a conflict in the above list. However `_2` is now
     /// `_3`, which does conflict with `_0`.
     fn unify(&mut self, a: Local, b: Local) {
-        // FIXME: This might be somewhat slow. Conflict graphs are undirected, maybe we can use
-        // something with union-find to speed this up?
-
         trace!("unify({:?}, {:?})", a, b);
+
+        // Get the root local of the connected components. The root local stores the conflicts of
+        // all locals in the connected component (and *is stored* as the conflicting local of other
+        // locals).
+        let a = self.unified_locals.find(a).0;
+        let b = self.unified_locals.find(b).0;
+        assert_ne!(a, b);
+
+        trace!("roots: a={:?}, b={:?}", a, b);
         trace!("{:?} conflicts: {:?}", a, self.matrix.iter(a).format(", "));
         trace!("{:?} conflicts: {:?}", b, self.matrix.iter(b).format(", "));
 
+        self.unified_locals.union(a, b);
+
+        let root = self.unified_locals.find(a).0;
+        assert!(root == a || root == b);
+
         // Make all locals that conflict with `a` also conflict with `b`, and vice versa.
         self.unify_cache.clear();
         for conflicts_with_a in self.matrix.iter(a) {
diff --git a/src/test/ui/dest-prop/skeptic-miscompile.rs b/src/test/ui/dest-prop/skeptic-miscompile.rs
new file mode 100644
index 0000000000000..c27a1f04532e7
--- /dev/null
+++ b/src/test/ui/dest-prop/skeptic-miscompile.rs
@@ -0,0 +1,24 @@
+// run-pass
+
+// compile-flags: -Zmir-opt-level=2
+
+trait IterExt: Iterator {
+    fn fold_ex<B, F>(mut self, init: B, mut f: F) -> B
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> B,
+    {
+        let mut accum = init;
+        while let Some(x) = self.next() {
+            accum = f(accum, x);
+        }
+        accum
+    }
+}
+
+impl<T: Iterator> IterExt for T {}
+
+fn main() {
+    let test = &["\n"];
+    test.iter().fold_ex(String::new(), |_, b| b.to_string());
+}

From 572883444899ea0aecd5cd6cdf3466255dd4c7e0 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Wed, 24 Jun 2020 02:47:16 +0200
Subject: [PATCH 31/40] Fix rebase fallout

---
 compiler/rustc_mir/src/transform/dest_prop.rs | 20 ++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index cd3708374054a..f9071ab9d802c 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -585,12 +585,17 @@ impl Conflicts<'a> {
 
     fn record_terminator_conflicts(&mut self, term: &Terminator<'_>) {
         match &term.kind {
-            TerminatorKind::DropAndReplace { location, value, target: _, unwind: _ } => {
+            TerminatorKind::DropAndReplace {
+                place: dropped_place,
+                value,
+                target: _,
+                unwind: _,
+            } => {
                 if let Some(place) = value.place() {
-                    if !place.is_indirect() && !location.is_indirect() {
+                    if !place.is_indirect() && !dropped_place.is_indirect() {
                         self.record_local_conflict(
                             place.local,
-                            location.local,
+                            dropped_place.local,
                             "DropAndReplace operand overlap",
                         );
                     }
@@ -613,6 +618,7 @@ impl Conflicts<'a> {
                 destination: Some((dest_place, _)),
                 cleanup: _,
                 from_hir_call: _,
+                fn_span: _,
             } => {
                 // No arguments may overlap with the destination.
                 for arg in args.iter().chain(Some(func)) {
@@ -701,7 +707,7 @@ impl Conflicts<'a> {
                                     InlineAsmOperand::Out { reg: _, late: _, place: None }
                                     | InlineAsmOperand::Const { value: _ }
                                     | InlineAsmOperand::SymFn { value: _ }
-                                    | InlineAsmOperand::SymStatic { value: _ } => {}
+                                    | InlineAsmOperand::SymStatic { def_id: _ } => {}
                                 }
                             }
                         }
@@ -717,7 +723,7 @@ impl Conflicts<'a> {
                         | InlineAsmOperand::In { reg: _, value: _ }
                         | InlineAsmOperand::Out { reg: _, late: _, place: None }
                         | InlineAsmOperand::SymFn { value: _ }
-                        | InlineAsmOperand::SymStatic { value: _ } => {}
+                        | InlineAsmOperand::SymStatic { def_id: _ } => {}
                     }
                 }
             }
@@ -732,7 +738,7 @@ impl Conflicts<'a> {
             | TerminatorKind::Drop { .. }
             | TerminatorKind::Assert { .. }
             | TerminatorKind::GeneratorDrop
-            | TerminatorKind::FalseEdges { .. }
+            | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. } => {}
         }
     }
@@ -759,7 +765,7 @@ impl Conflicts<'a> {
     }
 
     /// Merges the conflicts of `a` and `b`, so that each one inherits all conflicts of the other.
-    /// 
+    ///
     /// `can_unify` must have returned `true` for the same locals, or this may panic or lead to
     /// miscompiles.
     ///

From 7af964fecf77696e523020a430fd4a0d0d4bc190 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Wed, 24 Jun 2020 22:55:12 +0200
Subject: [PATCH 32/40] Limit block count

---
 compiler/rustc_mir/src/transform/dest_prop.rs | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index f9071ab9d802c..8080f4a0d6502 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -115,7 +115,12 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
+// Empirical measurements have resulted in some observations:
+// - Running on a body with a single block and 500 locals takes barely any time
+// - Running on a body with ~400 blocks and ~300 relevant locals takes "too long"
+// ...so we just limit both to somewhat reasonable-ish looking values.
 const MAX_LOCALS: usize = 500;
+const MAX_BLOCKS: usize = 250;
 
 pub struct DestinationPropagation;
 
@@ -160,6 +165,15 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
             );
             return;
         }
+        if body.basic_blocks().len() > MAX_BLOCKS {
+            warn!(
+                "too many blocks in {:?} ({}, max is {}), not optimizing",
+                source.def_id(),
+                body.basic_blocks().len(),
+                MAX_BLOCKS
+            );
+            return;
+        }
 
         let mut conflicts = Conflicts::build(tcx, body, source, &relevant_locals);
 

From cd5d7201ad1e5bf9d69e9a15e385ba03f678ad87 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Sat, 12 Sep 2020 15:18:50 +0200
Subject: [PATCH 33/40] Fix rebase fallout

---
 compiler/rustc_mir/src/transform/dest_prop.rs | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index 8080f4a0d6502..cb7b69e0231fb 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -588,11 +588,12 @@ impl Conflicts<'a> {
             }
 
             StatementKind::SetDiscriminant { .. }
-            | StatementKind::StorageLive(_)
-            | StatementKind::StorageDead(_)
-            | StatementKind::Retag(_, _)
-            | StatementKind::FakeRead(_, _)
-            | StatementKind::AscribeUserType(_, _)
+            | StatementKind::StorageLive(..)
+            | StatementKind::StorageDead(..)
+            | StatementKind::Retag(..)
+            | StatementKind::FakeRead(..)
+            | StatementKind::AscribeUserType(..)
+            | StatementKind::Coverage(..)
             | StatementKind::Nop => {}
         }
     }

From 682de94e315eac8be64423815edc4a0aa9e36539 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Sat, 12 Sep 2020 20:36:29 +0200
Subject: [PATCH 34/40] Move inner items outside

---
 compiler/rustc_mir/src/transform/dest_prop.rs | 288 +++++++++---------
 1 file changed, 144 insertions(+), 144 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index cb7b69e0231fb..c8e700909d7ae 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -858,98 +858,98 @@ fn find_candidates<'a, 'tcx>(
     tcx: TyCtxt<'tcx>,
     body: &'a Body<'tcx>,
 ) -> Vec<CandidateAssignment<'tcx>> {
-    struct FindAssignments<'a, 'tcx> {
-        tcx: TyCtxt<'tcx>,
-        body: &'a Body<'tcx>,
-        candidates: Vec<CandidateAssignment<'tcx>>,
-        ever_borrowed_locals: BitSet<Local>,
-        locals_used_as_array_index: BitSet<Local>,
-    }
+    let mut visitor = FindAssignments {
+        tcx,
+        body,
+        candidates: Vec::new(),
+        ever_borrowed_locals: ever_borrowed_locals(body),
+        locals_used_as_array_index: locals_used_as_array_index(body),
+    };
+    visitor.visit_body(body);
+    visitor.candidates
+}
 
-    impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> {
-        fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
-            if let StatementKind::Assign(box (
-                dest,
-                Rvalue::Use(Operand::Copy(src) | Operand::Move(src)),
-            )) = &statement.kind
-            {
-                // `dest` must not have pointer indirection.
-                if dest.is_indirect() {
-                    return;
-                }
+struct FindAssignments<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    body: &'a Body<'tcx>,
+    candidates: Vec<CandidateAssignment<'tcx>>,
+    ever_borrowed_locals: BitSet<Local>,
+    locals_used_as_array_index: BitSet<Local>,
+}
 
-                // `src` must be a plain local.
-                if !src.projection.is_empty() {
-                    return;
-                }
+impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> {
+    fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
+        if let StatementKind::Assign(box (
+            dest,
+            Rvalue::Use(Operand::Copy(src) | Operand::Move(src)),
+        )) = &statement.kind
+        {
+            // `dest` must not have pointer indirection.
+            if dest.is_indirect() {
+                return;
+            }
 
-                // Since we want to replace `src` with `dest`, `src` must not be required.
-                if is_local_required(src.local, self.body) {
-                    return;
-                }
+            // `src` must be a plain local.
+            if !src.projection.is_empty() {
+                return;
+            }
 
-                // Can't optimize if both locals ever have their address taken (can introduce
-                // aliasing).
-                // FIXME: This can be smarter and take `StorageDead` into account (which
-                // invalidates borrows).
-                if self.ever_borrowed_locals.contains(dest.local)
-                    && self.ever_borrowed_locals.contains(src.local)
-                {
-                    return;
-                }
+            // Since we want to replace `src` with `dest`, `src` must not be required.
+            if is_local_required(src.local, self.body) {
+                return;
+            }
 
-                assert_ne!(dest.local, src.local, "self-assignments are UB");
+            // Can't optimize if both locals ever have their address taken (can introduce
+            // aliasing).
+            // FIXME: This can be smarter and take `StorageDead` into account (which
+            // invalidates borrows).
+            if self.ever_borrowed_locals.contains(dest.local)
+                && self.ever_borrowed_locals.contains(src.local)
+            {
+                return;
+            }
 
-                // We can't replace locals occurring in `PlaceElem::Index` for now.
-                if self.locals_used_as_array_index.contains(src.local) {
-                    return;
-                }
+            assert_ne!(dest.local, src.local, "self-assignments are UB");
 
-                // Handle the "subtle case" described above by rejecting any `dest` that is or
-                // projects through a union.
-                let is_union = |ty: Ty<'_>| {
-                    if let ty::Adt(def, _) = ty.kind() {
-                        if def.is_union() {
-                            return true;
-                        }
+            // We can't replace locals occurring in `PlaceElem::Index` for now.
+            if self.locals_used_as_array_index.contains(src.local) {
+                return;
+            }
+
+            // Handle the "subtle case" described above by rejecting any `dest` that is or
+            // projects through a union.
+            let is_union = |ty: Ty<'_>| {
+                if let ty::Adt(def, _) = ty.kind() {
+                    if def.is_union() {
+                        return true;
                     }
+                }
 
-                    false
-                };
-                let mut place_ty = PlaceTy::from_ty(self.body.local_decls[dest.local].ty);
-                if is_union(place_ty.ty) {
+                false
+            };
+            let mut place_ty = PlaceTy::from_ty(self.body.local_decls[dest.local].ty);
+            if is_union(place_ty.ty) {
+                return;
+            }
+            for elem in dest.projection {
+                if let PlaceElem::Index(_) = elem {
+                    // `dest` contains an indexing projection.
                     return;
                 }
-                for elem in dest.projection {
-                    if let PlaceElem::Index(_) = elem {
-                        // `dest` contains an indexing projection.
-                        return;
-                    }
 
-                    place_ty = place_ty.projection_ty(self.tcx, elem);
-                    if is_union(place_ty.ty) {
-                        return;
-                    }
+                place_ty = place_ty.projection_ty(self.tcx, elem);
+                if is_union(place_ty.ty) {
+                    return;
                 }
-
-                self.candidates.push(CandidateAssignment {
-                    dest: *dest,
-                    src: src.local,
-                    loc: location,
-                });
             }
+
+            self.candidates.push(CandidateAssignment {
+                dest: *dest,
+                src: src.local,
+                loc: location,
+            });
         }
     }
-
-    let mut visitor = FindAssignments {
-        tcx,
-        body,
-        candidates: Vec::new(),
-        ever_borrowed_locals: ever_borrowed_locals(body),
-        locals_used_as_array_index: locals_used_as_array_index(body),
-    };
-    visitor.visit_body(body);
-    visitor.candidates
 }
 
 /// Some locals are part of the function's interface and can not be removed.
@@ -965,64 +965,64 @@ fn is_local_required(local: Local, body: &Body<'_>) -> bool {
 
 /// Walks MIR to find all locals that have their address taken anywhere.
 fn ever_borrowed_locals(body: &Body<'_>) -> BitSet<Local> {
-    struct BorrowCollector {
-        locals: BitSet<Local>,
-    }
+    let mut visitor = BorrowCollector { locals: BitSet::new_empty(body.local_decls.len()) };
+    visitor.visit_body(body);
+    visitor.locals
+}
 
-    impl<'tcx> Visitor<'tcx> for BorrowCollector {
-        fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
-            self.super_rvalue(rvalue, location);
+struct BorrowCollector {
+    locals: BitSet<Local>,
+}
 
-            match rvalue {
-                Rvalue::AddressOf(_, borrowed_place) | Rvalue::Ref(_, _, borrowed_place) => {
-                    if !borrowed_place.is_indirect() {
-                        self.locals.insert(borrowed_place.local);
-                    }
-                }
+impl<'tcx> Visitor<'tcx> for BorrowCollector {
+    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
+        self.super_rvalue(rvalue, location);
 
-                Rvalue::Cast(..)
-                | Rvalue::Use(..)
-                | Rvalue::Repeat(..)
-                | Rvalue::Len(..)
-                | Rvalue::BinaryOp(..)
-                | Rvalue::CheckedBinaryOp(..)
-                | Rvalue::NullaryOp(..)
-                | Rvalue::UnaryOp(..)
-                | Rvalue::Discriminant(..)
-                | Rvalue::Aggregate(..)
-                | Rvalue::ThreadLocalRef(..) => {}
+        match rvalue {
+            Rvalue::AddressOf(_, borrowed_place) | Rvalue::Ref(_, _, borrowed_place) => {
+                if !borrowed_place.is_indirect() {
+                    self.locals.insert(borrowed_place.local);
+                }
             }
-        }
 
-        fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
-            self.super_terminator(terminator, location);
+            Rvalue::Cast(..)
+            | Rvalue::Use(..)
+            | Rvalue::Repeat(..)
+            | Rvalue::Len(..)
+            | Rvalue::BinaryOp(..)
+            | Rvalue::CheckedBinaryOp(..)
+            | Rvalue::NullaryOp(..)
+            | Rvalue::UnaryOp(..)
+            | Rvalue::Discriminant(..)
+            | Rvalue::Aggregate(..)
+            | Rvalue::ThreadLocalRef(..) => {}
+        }
+    }
 
-            match terminator.kind {
-                TerminatorKind::Drop { place: dropped_place, .. }
-                | TerminatorKind::DropAndReplace { place: dropped_place, .. } => {
-                    self.locals.insert(dropped_place.local);
-                }
+    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
+        self.super_terminator(terminator, location);
 
-                TerminatorKind::Abort
-                | TerminatorKind::Assert { .. }
-                | TerminatorKind::Call { .. }
-                | TerminatorKind::FalseEdge { .. }
-                | TerminatorKind::FalseUnwind { .. }
-                | TerminatorKind::GeneratorDrop
-                | TerminatorKind::Goto { .. }
-                | TerminatorKind::Resume
-                | TerminatorKind::Return
-                | TerminatorKind::SwitchInt { .. }
-                | TerminatorKind::Unreachable
-                | TerminatorKind::Yield { .. }
-                | TerminatorKind::InlineAsm { .. } => {}
+        match terminator.kind {
+            TerminatorKind::Drop { place: dropped_place, .. }
+            | TerminatorKind::DropAndReplace { place: dropped_place, .. } => {
+                self.locals.insert(dropped_place.local);
             }
+
+            TerminatorKind::Abort
+            | TerminatorKind::Assert { .. }
+            | TerminatorKind::Call { .. }
+            | TerminatorKind::FalseEdge { .. }
+            | TerminatorKind::FalseUnwind { .. }
+            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::Goto { .. }
+            | TerminatorKind::Resume
+            | TerminatorKind::Return
+            | TerminatorKind::SwitchInt { .. }
+            | TerminatorKind::Unreachable
+            | TerminatorKind::Yield { .. }
+            | TerminatorKind::InlineAsm { .. } => {}
         }
     }
-
-    let mut visitor = BorrowCollector { locals: BitSet::new_empty(body.local_decls.len()) };
-    visitor.visit_body(body);
-    visitor.locals
 }
 
 /// `PlaceElem::Index` only stores a `Local`, so we can't replace that with a full `Place`.
@@ -1030,27 +1030,27 @@ fn ever_borrowed_locals(body: &Body<'_>) -> BitSet<Local> {
 /// Collect locals used as indices so we don't generate candidates that are impossible to apply
 /// later.
 fn locals_used_as_array_index(body: &Body<'_>) -> BitSet<Local> {
-    struct IndexCollector {
-        locals: BitSet<Local>,
-    }
-
-    impl<'tcx> Visitor<'tcx> for IndexCollector {
-        fn visit_projection_elem(
-            &mut self,
-            local: Local,
-            proj_base: &[PlaceElem<'tcx>],
-            elem: PlaceElem<'tcx>,
-            context: PlaceContext,
-            location: Location,
-        ) {
-            if let PlaceElem::Index(i) = elem {
-                self.locals.insert(i);
-            }
-            self.super_projection_elem(local, proj_base, elem, context, location);
-        }
-    }
-
     let mut visitor = IndexCollector { locals: BitSet::new_empty(body.local_decls.len()) };
     visitor.visit_body(body);
     visitor.locals
 }
+
+struct IndexCollector {
+    locals: BitSet<Local>,
+}
+
+impl<'tcx> Visitor<'tcx> for IndexCollector {
+    fn visit_projection_elem(
+        &mut self,
+        local: Local,
+        proj_base: &[PlaceElem<'tcx>],
+        elem: PlaceElem<'tcx>,
+        context: PlaceContext,
+        location: Location,
+    ) {
+        if let PlaceElem::Index(i) = elem {
+            self.locals.insert(i);
+        }
+        self.super_projection_elem(local, proj_base, elem, context, location);
+    }
+}

From ffd9445812cf8dc10a12f62db5135a0a17e066f5 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Thu, 17 Sep 2020 22:17:09 +0200
Subject: [PATCH 35/40] Return `Place` by value

---
 compiler/rustc_mir/src/transform/dest_prop.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index c8e700909d7ae..d1c98354e0590 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -285,8 +285,8 @@ impl Replacements<'tcx> {
         }
     }
 
-    fn for_src(&self, src: Local) -> Option<&Place<'tcx>> {
-        self.map[src].as_ref()
+    fn for_src(&self, src: Local) -> Option<Place<'tcx>> {
+        self.map[src]
     }
 }
 

From 2f9271b14c9ec0e5ed72ec91c2e24e850c580f83 Mon Sep 17 00:00:00 2001
From: Jonas Schievink <jonasschievink@gmail.com>
Date: Thu, 17 Sep 2020 22:19:24 +0200
Subject: [PATCH 36/40] Clarify FIXME

---
 compiler/rustc_mir/src/transform/dest_prop.rs | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index d1c98354e0590..46cbced2d54bc 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -44,8 +44,9 @@
 //!   and performing the optimization would simply delete the assignment, leaving `dest`
 //!   uninitialized.
 //!
-//! * `src` must be a bare `Local` without any indirections or field projections (FIXME: Why?).
-//!   It can be copied or moved by the assignment.
+//! * `src` must be a bare `Local` without any indirections or field projections (FIXME: Is this a
+//!   fundamental restriction or just current impl state?). It can be copied or moved by the
+//!   assignment.
 //!
 //! * The `dest` and `src` locals must never be [*live*][liveness] at the same time. If they are, it
 //!   means that they both hold a (potentially different) value that is needed by a future use of

From 4d1ef03c9ed28b6855c3f73535e21dc9cd6f6c5d Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sun, 6 Sep 2020 16:06:39 +0200
Subject: [PATCH 37/40] cleanup promotion const_kind checks

in particular allow a few more promotions for consistency when they were already allowed in other contexts
---
 .../rustc_mir/src/transform/promote_consts.rs | 58 +++++++++----------
 src/test/ui/consts/promote-no-mut.rs          | 10 ----
 src/test/ui/consts/promote-not.rs             | 30 ++++++++++
 ...omote-no-mut.stderr => promote-not.stderr} | 26 ++++++++-
 src/test/ui/consts/promotion.rs               |  2 +-
 src/test/ui/statics/static-promotion.rs       |  2 +-
 6 files changed, 83 insertions(+), 45 deletions(-)
 delete mode 100644 src/test/ui/consts/promote-no-mut.rs
 create mode 100644 src/test/ui/consts/promote-not.rs
 rename src/test/ui/consts/{promote-no-mut.stderr => promote-not.stderr} (51%)

diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs
index b6124049579fd..a4a6a7b03aba4 100644
--- a/compiler/rustc_mir/src/transform/promote_consts.rs
+++ b/compiler/rustc_mir/src/transform/promote_consts.rs
@@ -297,6 +297,17 @@ impl std::ops::Deref for Validator<'a, 'tcx> {
 struct Unpromotable;
 
 impl<'tcx> Validator<'_, 'tcx> {
+    //! Determines if this code could be executed at runtime and thus is subject to codegen.
+    //! That means even unused constants need to be evaluated.
+    //!
+    //! `const_kind` should not be used in this file other than through this method!
+    fn maybe_runtime(&self) -> bool {
+        match self.const_kind {
+            None | Some(hir::ConstContext::ConstFn) => true,
+            Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) => false,
+        }
+    }
+
     fn validate_candidate(&self, candidate: Candidate) -> Result<(), Unpromotable> {
         match candidate {
             Candidate::Ref(loc) => {
@@ -365,10 +376,8 @@ impl<'tcx> Validator<'_, 'tcx> {
                             // mutably without consequences. However, only &mut []
                             // is allowed right now, and only in functions.
                             if let ty::Array(_, len) = ty.kind() {
-                                // FIXME(eddyb) the `self.is_non_const_fn` condition
-                                // seems unnecessary, given that this is merely a ZST.
                                 match len.try_eval_usize(self.tcx, self.param_env) {
-                                    Some(0) if self.const_kind.is_none() => {}
+                                    Some(0) => {}
                                     _ => return Err(Unpromotable),
                                 }
                             } else {
@@ -495,9 +504,10 @@ impl<'tcx> Validator<'_, 'tcx> {
         match place {
             PlaceRef { local, projection: [] } => self.validate_local(local),
             PlaceRef { local, projection: [proj_base @ .., elem] } => {
+                // Validate topmost projection, then recurse.
                 match *elem {
                     ProjectionElem::Deref => {
-                        let mut not_promotable = true;
+                        let mut promotable = false;
                         // This is a special treatment for cases like *&STATIC where STATIC is a
                         // global static variable.
                         // This pattern is generated only when global static variables are directly
@@ -512,6 +522,9 @@ impl<'tcx> Validator<'_, 'tcx> {
                             }) = def_stmt
                             {
                                 if let Some(did) = c.check_static_ptr(self.tcx) {
+                                    // Evaluating a promoted may not read statics except if it got
+                                    // promoted from a static (this is a CTFE check). So we
+                                    // can only promoted static accesses inside statics.
                                     if let Some(hir::ConstContext::Static(..)) = self.const_kind {
                                         // The `is_empty` predicate is introduced to exclude the case
                                         // where the projection operations are [ .field, * ].
@@ -524,13 +537,13 @@ impl<'tcx> Validator<'_, 'tcx> {
                                         if proj_base.is_empty()
                                             && !self.tcx.is_thread_local_static(did)
                                         {
-                                            not_promotable = false;
+                                            promotable = true;
                                         }
                                     }
                                 }
                             }
                         }
-                        if not_promotable {
+                        if !promotable {
                             return Err(Unpromotable);
                         }
                     }
@@ -545,7 +558,7 @@ impl<'tcx> Validator<'_, 'tcx> {
                     }
 
                     ProjectionElem::Field(..) => {
-                        if self.const_kind.is_none() {
+                        if self.maybe_runtime() {
                             let base_ty =
                                 Place::ty_from(place.local, proj_base, self.body, self.tcx).ty;
                             if let Some(def) = base_ty.ty_adt_def() {
@@ -571,13 +584,6 @@ impl<'tcx> Validator<'_, 'tcx> {
             // `validate_rvalue` upon access.
             Operand::Constant(c) => {
                 if let Some(def_id) = c.check_static_ptr(self.tcx) {
-                    // Only allow statics (not consts) to refer to other statics.
-                    // FIXME(eddyb) does this matter at all for promotion?
-                    let is_static = matches!(self.const_kind, Some(hir::ConstContext::Static(_)));
-                    if !is_static {
-                        return Err(Unpromotable);
-                    }
-
                     let is_thread_local = self.tcx.is_thread_local_static(def_id);
                     if is_thread_local {
                         return Err(Unpromotable);
@@ -591,20 +597,20 @@ impl<'tcx> Validator<'_, 'tcx> {
 
     fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> {
         match *rvalue {
-            Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) if self.const_kind.is_none() => {
+            Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) if self.maybe_runtime() => {
                 let operand_ty = operand.ty(self.body, self.tcx);
                 let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
                 let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
                 match (cast_in, cast_out) {
                     (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
-                        // in normal functions, mark such casts as not promotable
+                        // ptr-to-int casts are not promotable
                         return Err(Unpromotable);
                     }
                     _ => {}
                 }
             }
 
-            Rvalue::BinaryOp(op, ref lhs, _) if self.const_kind.is_none() => {
+            Rvalue::BinaryOp(op, ref lhs, _) if self.maybe_runtime() => {
                 if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind() {
                     assert!(
                         op == BinOp::Eq
@@ -623,6 +629,7 @@ impl<'tcx> Validator<'_, 'tcx> {
 
             Rvalue::NullaryOp(NullOp::Box, _) => return Err(Unpromotable),
 
+            // FIXME(RalfJung): the rest is *implicitly considered promotable*... that seems dangerous.
             _ => {}
         }
 
@@ -644,8 +651,8 @@ impl<'tcx> Validator<'_, 'tcx> {
             }
 
             Rvalue::AddressOf(_, place) => {
-                // Raw reborrows can come from reference to pointer coercions,
-                // so are allowed.
+                // We accept `&raw *`, i.e., raw reborrows -- creating a raw pointer is
+                // no problem, only using it is.
                 if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() {
                     let base_ty = Place::ty_from(place.local, proj_base, self.body, self.tcx).ty;
                     if let ty::Ref(..) = base_ty.kind() {
@@ -666,10 +673,8 @@ impl<'tcx> Validator<'_, 'tcx> {
                     // mutably without consequences. However, only &mut []
                     // is allowed right now, and only in functions.
                     if let ty::Array(_, len) = ty.kind() {
-                        // FIXME(eddyb): We only return `Unpromotable` for `&mut []` inside a
-                        // const context which seems unnecessary given that this is merely a ZST.
                         match len.try_eval_usize(self.tcx, self.param_env) {
-                            Some(0) if self.const_kind.is_none() => {}
+                            Some(0) => {}
                             _ => return Err(Unpromotable),
                         }
                     } else {
@@ -734,14 +739,7 @@ impl<'tcx> Validator<'_, 'tcx> {
     ) -> Result<(), Unpromotable> {
         let fn_ty = callee.ty(self.body, self.tcx);
 
-        // `const` and `static` use the explicit rules for promotion regardless of the `Candidate`,
-        // meaning calls to `const fn` can be promoted.
-        let context_uses_explicit_promotion_rules = matches!(
-            self.const_kind,
-            Some(hir::ConstContext::Static(_) | hir::ConstContext::Const)
-        );
-
-        if !self.explicit && !context_uses_explicit_promotion_rules {
+        if !self.explicit && self.maybe_runtime() {
             if let ty::FnDef(def_id, _) = *fn_ty.kind() {
                 // Never promote runtime `const fn` calls of
                 // functions without `#[rustc_promotable]`.
diff --git a/src/test/ui/consts/promote-no-mut.rs b/src/test/ui/consts/promote-no-mut.rs
deleted file mode 100644
index fb57c8bb93458..0000000000000
--- a/src/test/ui/consts/promote-no-mut.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// ignore-tidy-linelength
-// We do not promote mutable references.
-static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]); //~ ERROR temporary value dropped while borrowed
-
-static mut TEST2: &'static mut [i32] = {
-    let x = &mut [1,2,3]; //~ ERROR temporary value dropped while borrowed
-    x
-};
-
-fn main() {}
diff --git a/src/test/ui/consts/promote-not.rs b/src/test/ui/consts/promote-not.rs
new file mode 100644
index 0000000000000..8daac75837734
--- /dev/null
+++ b/src/test/ui/consts/promote-not.rs
@@ -0,0 +1,30 @@
+// ignore-tidy-linelength
+// Test various things that we do not want to promote.
+#![allow(unconditional_panic, const_err)]
+#![feature(const_fn, const_fn_union)]
+
+// We do not promote mutable references.
+static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]); //~ ERROR temporary value dropped while borrowed
+
+static mut TEST2: &'static mut [i32] = {
+    let x = &mut [1,2,3]; //~ ERROR temporary value dropped while borrowed
+    x
+};
+
+// We do not promote fn calls in `fn`, including `const fn`.
+pub const fn promote_cal(b: bool) -> i32 {
+    const fn foo() { [()][42] }
+
+    if b {
+        let _x: &'static () = &foo(); //~ ERROR temporary value dropped while borrowed
+    }
+    13
+}
+
+// We do not promote union field accesses in `fn.
+union U { x: i32, y: i32 }
+pub const fn promote_union() {
+    let _x: &'static i32 = &unsafe { U { x: 0 }.x }; //~ ERROR temporary value dropped while borrowed
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/promote-no-mut.stderr b/src/test/ui/consts/promote-not.stderr
similarity index 51%
rename from src/test/ui/consts/promote-no-mut.stderr
rename to src/test/ui/consts/promote-not.stderr
index 49d96546ada3f..efe921b601104 100644
--- a/src/test/ui/consts/promote-no-mut.stderr
+++ b/src/test/ui/consts/promote-not.stderr
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-no-mut.rs:3:50
+  --> $DIR/promote-not.rs:7:50
    |
 LL | static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]);
    |                                        ----------^^^^^^^^^-
@@ -9,7 +9,7 @@ LL | static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]);
    |                                        using this value as a static requires that borrow lasts for `'static`
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-no-mut.rs:6:18
+  --> $DIR/promote-not.rs:10:18
    |
 LL |     let x = &mut [1,2,3];
    |                  ^^^^^^^ creates a temporary which is freed while still in use
@@ -18,6 +18,26 @@ LL |     x
 LL | };
    | - temporary value is freed at the end of this statement
 
-error: aborting due to 2 previous errors
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:19:32
+   |
+LL |         let _x: &'static () = &foo();
+   |                 -----------    ^^^^^ creates a temporary which is freed while still in use
+   |                 |
+   |                 type annotation requires that borrow lasts for `'static`
+LL |     }
+   |     - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:27:29
+   |
+LL |     let _x: &'static i32 = &unsafe { U { x: 0 }.x };
+   |             ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |             |
+   |             type annotation requires that borrow lasts for `'static`
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/promotion.rs b/src/test/ui/consts/promotion.rs
index 3c5401e421216..5f84030a9e96b 100644
--- a/src/test/ui/consts/promotion.rs
+++ b/src/test/ui/consts/promotion.rs
@@ -1,4 +1,4 @@
-// run-pass
+// check-pass
 
 // compile-flags: -O
 
diff --git a/src/test/ui/statics/static-promotion.rs b/src/test/ui/statics/static-promotion.rs
index bd8910bdb3f3f..b9eff469177e6 100644
--- a/src/test/ui/statics/static-promotion.rs
+++ b/src/test/ui/statics/static-promotion.rs
@@ -1,4 +1,4 @@
-// check-pass
+// run-pass
 
 // Use of global static variables in literal values should be allowed for
 // promotion.

From 7febd5a25770cb20805f20e43ab0d773ed2834ed Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Mon, 7 Sep 2020 13:22:59 +0200
Subject: [PATCH 38/40] fix doc comment

---
 compiler/rustc_mir/src/transform/promote_consts.rs | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs
index a4a6a7b03aba4..e1d704cb6806c 100644
--- a/compiler/rustc_mir/src/transform/promote_consts.rs
+++ b/compiler/rustc_mir/src/transform/promote_consts.rs
@@ -297,10 +297,10 @@ impl std::ops::Deref for Validator<'a, 'tcx> {
 struct Unpromotable;
 
 impl<'tcx> Validator<'_, 'tcx> {
-    //! Determines if this code could be executed at runtime and thus is subject to codegen.
-    //! That means even unused constants need to be evaluated.
-    //!
-    //! `const_kind` should not be used in this file other than through this method!
+    /// Determines if this code could be executed at runtime and thus is subject to codegen.
+    /// That means even unused constants need to be evaluated.
+    ///
+    /// `const_kind` should not be used in this file other than through this method!
     fn maybe_runtime(&self) -> bool {
         match self.const_kind {
             None | Some(hir::ConstContext::ConstFn) => true,

From 7b99c8e1cf096c1ba71ba3ee58b19527a5b69c1a Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Wed, 9 Sep 2020 10:00:23 +0200
Subject: [PATCH 39/40] never promote non-const operations; revert STATIC
 promotion change

---
 .../rustc_mir/src/transform/promote_consts.rs  | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs
index e1d704cb6806c..020857a95fbaa 100644
--- a/compiler/rustc_mir/src/transform/promote_consts.rs
+++ b/compiler/rustc_mir/src/transform/promote_consts.rs
@@ -584,6 +584,16 @@ impl<'tcx> Validator<'_, 'tcx> {
             // `validate_rvalue` upon access.
             Operand::Constant(c) => {
                 if let Some(def_id) = c.check_static_ptr(self.tcx) {
+                    // Only allow statics (not consts) to refer to other statics.
+                    // FIXME(eddyb) does this matter at all for promotion?
+                    // FIXME(RalfJung) it makes little sense to not promote this in `fn/`const fn`,
+                    // and in `const` this cannot occur anyway. The concern is that we might promote
+                    // even `let x = &STATIC` which would be useless.
+                    let is_static = matches!(self.const_kind, Some(hir::ConstContext::Static(_)));
+                    if !is_static {
+                        return Err(Unpromotable);
+                    }
+
                     let is_thread_local = self.tcx.is_thread_local_static(def_id);
                     if is_thread_local {
                         return Err(Unpromotable);
@@ -597,20 +607,20 @@ impl<'tcx> Validator<'_, 'tcx> {
 
     fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> {
         match *rvalue {
-            Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) if self.maybe_runtime() => {
+            Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
                 let operand_ty = operand.ty(self.body, self.tcx);
                 let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
                 let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
                 match (cast_in, cast_out) {
                     (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
-                        // ptr-to-int casts are not promotable
+                        // ptr-to-int casts are not possible in consts and thus not promotable
                         return Err(Unpromotable);
                     }
                     _ => {}
                 }
             }
 
-            Rvalue::BinaryOp(op, ref lhs, _) if self.maybe_runtime() => {
+            Rvalue::BinaryOp(op, ref lhs, _) => {
                 if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind() {
                     assert!(
                         op == BinOp::Eq
@@ -622,7 +632,7 @@ impl<'tcx> Validator<'_, 'tcx> {
                             || op == BinOp::Offset
                     );
 
-                    // raw pointer operations are not allowed inside promoteds
+                    // raw pointer operations are not allowed inside consts and thus not promotable
                     return Err(Unpromotable);
                 }
             }

From 9216eb825839ecd17d67c2731537e5d6afffc54a Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Wed, 9 Sep 2020 12:57:36 +0200
Subject: [PATCH 40/40] fix some comments

---
 compiler/rustc_mir/src/transform/promote_consts.rs | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs
index 020857a95fbaa..37202276161c7 100644
--- a/compiler/rustc_mir/src/transform/promote_consts.rs
+++ b/compiler/rustc_mir/src/transform/promote_consts.rs
@@ -374,7 +374,7 @@ impl<'tcx> Validator<'_, 'tcx> {
 
                             // In theory, any zero-sized value could be borrowed
                             // mutably without consequences. However, only &mut []
-                            // is allowed right now, and only in functions.
+                            // is allowed right now.
                             if let ty::Array(_, len) = ty.kind() {
                                 match len.try_eval_usize(self.tcx, self.param_env) {
                                     Some(0) => {}
@@ -524,7 +524,7 @@ impl<'tcx> Validator<'_, 'tcx> {
                                 if let Some(did) = c.check_static_ptr(self.tcx) {
                                     // Evaluating a promoted may not read statics except if it got
                                     // promoted from a static (this is a CTFE check). So we
-                                    // can only promoted static accesses inside statics.
+                                    // can only promote static accesses inside statics.
                                     if let Some(hir::ConstContext::Static(..)) = self.const_kind {
                                         // The `is_empty` predicate is introduced to exclude the case
                                         // where the projection operations are [ .field, * ].
@@ -586,9 +586,10 @@ impl<'tcx> Validator<'_, 'tcx> {
                 if let Some(def_id) = c.check_static_ptr(self.tcx) {
                     // Only allow statics (not consts) to refer to other statics.
                     // FIXME(eddyb) does this matter at all for promotion?
-                    // FIXME(RalfJung) it makes little sense to not promote this in `fn/`const fn`,
-                    // and in `const` this cannot occur anyway. The concern is that we might promote
-                    // even `let x = &STATIC` which would be useless.
+                    // FIXME(RalfJung) it makes little sense to not promote this in `fn`/`const fn`,
+                    // and in `const` this cannot occur anyway. The only concern is that we might
+                    // promote even `let x = &STATIC` which would be useless, but this applies to
+                    // promotion inside statics as well.
                     let is_static = matches!(self.const_kind, Some(hir::ConstContext::Static(_)));
                     if !is_static {
                         return Err(Unpromotable);
@@ -681,7 +682,7 @@ impl<'tcx> Validator<'_, 'tcx> {
 
                     // In theory, any zero-sized value could be borrowed
                     // mutably without consequences. However, only &mut []
-                    // is allowed right now, and only in functions.
+                    // is allowed right now.
                     if let ty::Array(_, len) = ty.kind() {
                         match len.try_eval_usize(self.tcx, self.param_env) {
                             Some(0) => {}