From fd76552a4b41d132701dc0857a9fee9a3850088e Mon Sep 17 00:00:00 2001
From: joboet <jonasboettiger@icloud.com>
Date: Wed, 18 May 2022 12:18:51 +0200
Subject: [PATCH 01/20] std: use an event flag based thread parker on SOLID

---
 library/std/src/sys/itron/abi.rs              | 48 +++++++++-
 library/std/src/sys/itron/wait_flag.rs        | 67 +++++++++++++
 library/std/src/sys/solid/mod.rs              |  2 +
 .../std/src/sys_common/thread_parker/mod.rs   |  7 +-
 .../src/sys_common/thread_parker/wait_flag.rs | 96 +++++++++++++++++++
 5 files changed, 214 insertions(+), 6 deletions(-)
 create mode 100644 library/std/src/sys/itron/wait_flag.rs
 create mode 100644 library/std/src/sys_common/thread_parker/wait_flag.rs

diff --git a/library/std/src/sys/itron/abi.rs b/library/std/src/sys/itron/abi.rs
index f99ee4fa897ea..5eb14bb7e534b 100644
--- a/library/std/src/sys/itron/abi.rs
+++ b/library/std/src/sys/itron/abi.rs
@@ -30,15 +30,32 @@ pub type ER = int_t;
 /// Error code type, `ID` on success
 pub type ER_ID = int_t;
 
+/// Service call operational mode
+pub type MODE = uint_t;
+
+/// OR waiting condition for an eventflag
+pub const TWF_ORW: MODE = 0x01;
+
+/// Object attributes
+pub type ATR = uint_t;
+
+/// FIFO wait order
+pub const TA_FIFO: ATR = 0;
+/// Only one task is allowed to be in the waiting state for the eventflag
+pub const TA_WSGL: ATR = 0;
+/// The eventflag’s bit pattern is cleared when a task is released from the
+/// waiting state for that eventflag.
+pub const TA_CLR: ATR = 0x04;
+
+/// Bit pattern of an eventflag
+pub type FLGPTN = uint_t;
+
 /// Task or interrupt priority
 pub type PRI = int_t;
 
 /// The special value of `PRI` representing the current task's priority.
 pub const TPRI_SELF: PRI = 0;
 
-/// Object attributes
-pub type ATR = uint_t;
-
 /// Use the priority inheritance protocol
 #[cfg(target_os = "solid_asp3")]
 pub const TA_INHERIT: ATR = 0x02;
@@ -90,6 +107,13 @@ pub struct T_CSEM {
     pub maxsem: uint_t,
 }
 
+#[derive(Clone, Copy)]
+#[repr(C)]
+pub struct T_CFLG {
+    pub flgatr: ATR,
+    pub iflgptn: FLGPTN,
+}
+
 #[derive(Clone, Copy)]
 #[repr(C)]
 pub struct T_CMTX {
@@ -139,6 +163,24 @@ extern "C" {
     pub fn sns_dsp() -> bool_t;
     #[link_name = "__asp3_get_tim"]
     pub fn get_tim(p_systim: *mut SYSTIM) -> ER;
+    #[link_name = "__asp3_acre_flg"]
+    pub fn acre_flg(pk_cflg: *const T_CFLG) -> ER_ID;
+    #[link_name = "__asp3_del_flg"]
+    pub fn del_flg(flgid: ID) -> ER;
+    #[link_name = "__asp3_set_flg"]
+    pub fn set_flg(flgid: ID, setptn: FLGPTN) -> ER;
+    #[link_name = "__asp3_clr_flg"]
+    pub fn clr_flg(flgid: ID, clrptn: FLGPTN) -> ER;
+    #[link_name = "__asp3_wai_flg"]
+    pub fn wai_flg(flgid: ID, waiptn: FLGPTN, wfmode: MODE, p_flgptn: *mut FLGPTN) -> ER;
+    #[link_name = "__asp3_twai_flg"]
+    pub fn twai_flg(
+        flgid: ID,
+        waiptn: FLGPTN,
+        wfmode: MODE,
+        p_flgptn: *mut FLGPTN,
+        tmout: TMO,
+    ) -> ER;
     #[link_name = "__asp3_acre_mtx"]
     pub fn acre_mtx(pk_cmtx: *const T_CMTX) -> ER_ID;
     #[link_name = "__asp3_del_mtx"]
diff --git a/library/std/src/sys/itron/wait_flag.rs b/library/std/src/sys/itron/wait_flag.rs
new file mode 100644
index 0000000000000..805f85a69b6c7
--- /dev/null
+++ b/library/std/src/sys/itron/wait_flag.rs
@@ -0,0 +1,67 @@
+use crate::mem::MaybeUninit;
+use crate::time::Duration;
+
+use super::{
+    abi,
+    error::{expect_success, fail},
+    time::with_tmos,
+};
+
+const CLEAR: abi::FLGPTN = 0;
+const RAISED: abi::FLGPTN = 1;
+
+/// A thread parking primitive that is not susceptible to race conditions,
+/// but provides no atomic ordering guarantees and allows only one `raise` per wait.
+pub struct WaitFlag {
+    flag: abi::ID,
+}
+
+impl WaitFlag {
+    /// Creates a new wait flag.
+    pub fn new() -> WaitFlag {
+        let flag = expect_success(
+            unsafe {
+                abi::acre_flg(&abi::T_CFLG {
+                    flgatr: abi::TA_FIFO | abi::TA_WSGL | abi::TA_CLR,
+                    iflgptn: CLEAR,
+                })
+            },
+            &"acre_flg",
+        );
+
+        WaitFlag { flag }
+    }
+
+    /// Wait for the wait flag to be raised.
+    pub fn wait(&self) {
+        let mut token = MaybeUninit::uninit();
+        expect_success(
+            unsafe { abi::wai_flg(self.flag, RAISED, abi::TWF_ORW, token.as_mut_ptr()) },
+            &"wai_flg",
+        );
+    }
+
+    /// Wait for the wait flag to be raised or the timeout to occur.
+    pub fn wait_timeout(&self, dur: Duration) {
+        let mut token = MaybeUninit::uninit();
+        let er = with_tmos(dur, |tmout| unsafe {
+            abi::twai_flg(self.flag, RAISED, abi::TWF_ORW, token.as_mut_ptr(), tmout)
+        });
+        if er != abi::E_OK && er != abi::E_TMOUT {
+            fail(er, &"twai_flg");
+        }
+    }
+
+    /// Raise the wait flag.
+    ///
+    /// Calls to this function should be balanced with the number of successful waits.
+    pub fn raise(&self) {
+        expect_success(unsafe { abi::set_flg(self.flag, RAISED) }, &"set_flg");
+    }
+}
+
+impl Drop for WaitFlag {
+    fn drop(&mut self) {
+        expect_success(unsafe { abi::del_flg(self.flag) }, &"del_flg");
+    }
+}
diff --git a/library/std/src/sys/solid/mod.rs b/library/std/src/sys/solid/mod.rs
index 5ffa381f2e50f..2d21e4764fc21 100644
--- a/library/std/src/sys/solid/mod.rs
+++ b/library/std/src/sys/solid/mod.rs
@@ -15,6 +15,7 @@ mod itron {
     pub mod thread;
     pub(super) mod time;
     use super::unsupported;
+    pub mod wait_flag;
 }
 
 pub mod alloc;
@@ -43,6 +44,7 @@ pub mod memchr;
 pub mod thread_local_dtor;
 pub mod thread_local_key;
 pub mod time;
+pub use self::itron::wait_flag;
 
 mod rwlock;
 
diff --git a/library/std/src/sys_common/thread_parker/mod.rs b/library/std/src/sys_common/thread_parker/mod.rs
index c789a388e05ad..79d5a498e054f 100644
--- a/library/std/src/sys_common/thread_parker/mod.rs
+++ b/library/std/src/sys_common/thread_parker/mod.rs
@@ -9,9 +9,10 @@ cfg_if::cfg_if! {
     ))] {
         mod futex;
         pub use futex::Parker;
-    } else if #[cfg(windows)] {
-        pub use crate::sys::thread_parker::Parker;
-    } else if #[cfg(target_family = "unix")] {
+    } else if #[cfg(target_os = "solid_asp3")] {
+        mod wait_flag;
+        pub use wait_flag::Parker;
+    } else if #[cfg(any(windows, target_family = "unix"))] {
         pub use crate::sys::thread_parker::Parker;
     } else {
         mod generic;
diff --git a/library/std/src/sys_common/thread_parker/wait_flag.rs b/library/std/src/sys_common/thread_parker/wait_flag.rs
new file mode 100644
index 0000000000000..39a0df1cd3de4
--- /dev/null
+++ b/library/std/src/sys_common/thread_parker/wait_flag.rs
@@ -0,0 +1,96 @@
+//! A wait-flag-based thread parker.
+//!
+//! Some operating systems provide low-level parking primitives like wait counts,
+//! event flags or semaphores which are not susceptible to race conditions (meaning
+//! the wakeup can occure before the wait operation). To implement the `std` thread
+//! parker on top of these primitives, we only have to ensure that parking is fast
+//! when the thread token is available, the atomic ordering guarantees are maintained
+//! and spurious wakeups are minimized.
+//!
+//! To achieve this, this parker uses an atomic variable with three states: `EMPTY`,
+//! `PARKED` and `NOTIFIED`:
+//! * `EMPTY` means the token has not been made available, but the thread is not
+//!    currently waiting on it.
+//! * `PARKED` means the token is not available and the thread is parked.
+//! * `NOTIFIED` means the token is available.
+//!
+//! `park` and `park_timeout` change the state from `EMPTY` to `PARKED` and from
+//! `NOTIFIED` to `EMPTY`. If the state was `NOTIFIED`, the thread was unparked and
+//! execution can continue without calling into the OS. If the state was `EMPTY`,
+//! the token is not available and the thread waits on the primitive (here called
+//! "wait flag").
+//!
+//! `unpark` changes the state to `NOTIFIED`. If the state was `PARKED`, the thread
+//! is or will be sleeping on the wait flag, so we raise it. Only the first thread
+//! to call `unpark` will raise the wait flag, so spurious wakeups are avoided
+//! (this is especially important for semaphores).
+
+use crate::pin::Pin;
+use crate::sync::atomic::AtomicI8;
+use crate::sync::atomic::Ordering::SeqCst;
+use crate::sys::wait_flag::WaitFlag;
+use crate::time::Duration;
+
+const EMPTY: i8 = 0;
+const PARKED: i8 = -1;
+const NOTIFIED: i8 = 1;
+
+pub struct Parker {
+    state: AtomicI8,
+    wait_flag: WaitFlag,
+}
+
+impl Parker {
+    /// Construct a parker for the current thread. The UNIX parker
+    /// implementation requires this to happen in-place.
+    pub unsafe fn new(parker: *mut Parker) {
+        parker.write(Parker { state: AtomicI8::new(EMPTY), wait_flag: WaitFlag::new() })
+    }
+
+    // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
+    pub unsafe fn park(self: Pin<&Self>) {
+        // The state values are chosen so that this subtraction changes
+        // `NOTIFIED` to `EMPTY` and `EMPTY` to `PARKED`.
+        let state = self.state.fetch_sub(1, SeqCst);
+        match state {
+            EMPTY => (),
+            NOTIFIED => return,
+            _ => panic!("inconsistent park state"),
+        }
+
+        self.wait_flag.wait();
+
+        // We need to do a load here to use `Acquire` ordering.
+        self.state.swap(EMPTY, SeqCst);
+    }
+
+    // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
+    pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) {
+        let state = self.state.fetch_sub(1, SeqCst);
+        match state {
+            EMPTY => (),
+            NOTIFIED => return,
+            _ => panic!("inconsistent park state"),
+        }
+
+        self.wait_flag.wait_timeout(dur);
+        let state = self.state.swap(EMPTY, SeqCst);
+        if state == NOTIFIED {
+            // The token was made available after the timeout occurred, but before
+            // we reset the state, so we need to reset the wait flag to avoid
+            // spurious wakeups. This wait has no timeout, but we know it will
+            // return quickly, as the unparking thread will definitely raise the
+            // flag if it has not already done so.
+            self.wait_flag.wait();
+        }
+    }
+
+    // This implementation doesn't require `Pin`, but other implementations do.
+    pub fn unpark(self: Pin<&Self>) {
+        let state = self.state.swap(NOTIFIED, SeqCst);
+
+        if state == PARKED {
+            self.wait_flag.raise();
+        }
+    }
+}

From 3b6ae15058dbb68710f92697265580c7e957629f Mon Sep 17 00:00:00 2001
From: joboet <jonasboettiger@icloud.com>
Date: Thu, 19 May 2022 14:37:29 +0200
Subject: [PATCH 02/20] std: fix deadlock in `Parker`

---
 library/std/src/sys/itron/wait_flag.rs              | 13 +++++++++----
 .../std/src/sys_common/thread_parker/wait_flag.rs   |  8 ++++----
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/library/std/src/sys/itron/wait_flag.rs b/library/std/src/sys/itron/wait_flag.rs
index 805f85a69b6c7..e432edd207754 100644
--- a/library/std/src/sys/itron/wait_flag.rs
+++ b/library/std/src/sys/itron/wait_flag.rs
@@ -42,13 +42,18 @@ impl WaitFlag {
     }
 
     /// Wait for the wait flag to be raised or the timeout to occur.
-    pub fn wait_timeout(&self, dur: Duration) {
+    ///
+    /// Returns whether the flag was raised (`true`) or the operation timed out (`false`).
+    pub fn wait_timeout(&self, dur: Duration) -> bool {
         let mut token = MaybeUninit::uninit();
-        let er = with_tmos(dur, |tmout| unsafe {
+        let res = with_tmos(dur, |tmout| unsafe {
             abi::twai_flg(self.flag, RAISED, abi::TWF_ORW, token.as_mut_ptr(), tmout)
         });
-        if er != abi::E_OK && er != abi::E_TMOUT {
-            fail(er, &"twai_flg");
+
+        match res {
+            abi::E_OK => true,
+            abi::E_TMOUT => false,
+            error => fail(error, &"twai_flg"),
         }
     }
 
diff --git a/library/std/src/sys_common/thread_parker/wait_flag.rs b/library/std/src/sys_common/thread_parker/wait_flag.rs
index 39a0df1cd3de4..f9581ff5d5774 100644
--- a/library/std/src/sys_common/thread_parker/wait_flag.rs
+++ b/library/std/src/sys_common/thread_parker/wait_flag.rs
@@ -2,7 +2,7 @@
 //!
 //! Some operating systems provide low-level parking primitives like wait counts,
 //! event flags or semaphores which are not susceptible to race conditions (meaning
-//! the wakeup can occure before the wait operation). To implement the `std` thread
+//! the wakeup can occur before the wait operation). To implement the `std` thread
 //! parker on top of these primitives, we only have to ensure that parking is fast
 //! when the thread token is available, the atomic ordering guarantees are maintained
 //! and spurious wakeups are minimized.
@@ -73,10 +73,10 @@ impl Parker {
             _ => panic!("inconsistent park state"),
         }
 
-        self.wait_flag.wait_timeout(dur);
+        let wakeup = self.wait_flag.wait_timeout(dur);
         let state = self.state.swap(EMPTY, SeqCst);
-        if state == NOTIFIED {
-            // The token was made available after the timeout occurred, but before
+        if state == NOTIFIED && !wakeup {
+            // The token was made available after the wait timed out, but before
             // we reset the state, so we need to reset the wait flag to avoid
             // spurious wakeups. This wait has no timeout, but we know it will
             // return quickly, as the unparking thread will definitely raise the

From b9660de664cc491b3f22a5c1dadee5a03e506b2a Mon Sep 17 00:00:00 2001
From: joboet <jonasboettiger@icloud.com>
Date: Sat, 4 Jun 2022 20:57:25 +0200
Subject: [PATCH 03/20] std: solve priority issue for Parker

---
 .../src/sys_common/thread_parker/wait_flag.rs | 55 +++++++++++--------
 1 file changed, 31 insertions(+), 24 deletions(-)

diff --git a/library/std/src/sys_common/thread_parker/wait_flag.rs b/library/std/src/sys_common/thread_parker/wait_flag.rs
index f9581ff5d5774..8db12693ef734 100644
--- a/library/std/src/sys_common/thread_parker/wait_flag.rs
+++ b/library/std/src/sys_common/thread_parker/wait_flag.rs
@@ -21,13 +21,11 @@
 //! "wait flag").
 //!
 //! `unpark` changes the state to `NOTIFIED`. If the state was `PARKED`, the thread
-//! is or will be sleeping on the wait flag, so we raise it. Only the first thread
-//! to call `unpark` will raise the wait flag, so spurious wakeups are avoided
-//! (this is especially important for semaphores).
+//! is or will be sleeping on the wait flag, so we raise it.
 
 use crate::pin::Pin;
 use crate::sync::atomic::AtomicI8;
-use crate::sync::atomic::Ordering::SeqCst;
+use crate::sync::atomic::Ordering::{Relaxed, SeqCst};
 use crate::sys::wait_flag::WaitFlag;
 use crate::time::Duration;
 
@@ -49,39 +47,48 @@ impl Parker {
 
     // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
     pub unsafe fn park(self: Pin<&Self>) {
-        // The state values are chosen so that this subtraction changes
-        // `NOTIFIED` to `EMPTY` and `EMPTY` to `PARKED`.
-        let state = self.state.fetch_sub(1, SeqCst);
-        match state {
-            EMPTY => (),
+        match self.state.fetch_sub(1, SeqCst) {
+            // NOTIFIED => EMPTY
             NOTIFIED => return,
+            // EMPTY => PARKED
+            EMPTY => (),
             _ => panic!("inconsistent park state"),
         }
 
-        self.wait_flag.wait();
+        // Avoid waking up from spurious wakeups (these are quite likely, see below).
+        loop {
+            self.wait_flag.wait();
 
-        // We need to do a load here to use `Acquire` ordering.
-        self.state.swap(EMPTY, SeqCst);
+            match self.state.compare_exchange(NOTIFIED, EMPTY, SeqCst, Relaxed) {
+                Ok(_) => return,
+                Err(PARKED) => (),
+                Err(_) => panic!("inconsistent park state"),
+            }
+        }
     }
 
     // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
     pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) {
-        let state = self.state.fetch_sub(1, SeqCst);
-        match state {
-            EMPTY => (),
+        match self.state.fetch_sub(1, SeqCst) {
             NOTIFIED => return,
+            EMPTY => (),
             _ => panic!("inconsistent park state"),
         }
 
-        let wakeup = self.wait_flag.wait_timeout(dur);
-        let state = self.state.swap(EMPTY, SeqCst);
-        if state == NOTIFIED && !wakeup {
-            // The token was made available after the wait timed out, but before
-            // we reset the state, so we need to reset the wait flag to avoid
-            // spurious wakeups. This wait has no timeout, but we know it will
-            // return quickly, as the unparking thread will definitely raise the
-            // flag if it has not already done so.
-            self.wait_flag.wait();
+        self.wait_flag.wait_timeout(dur);
+
+        // Either a wakeup or a timeout occurred. Wakeups may be spurious, as there can be
+        // a race condition when `unpark` is performed between receiving the timeout and
+        // resetting the state, resulting in the eventflag being set unnecessarily. `park`
+        // is protected against this by looping until the token is actually given, but
+        // here we cannot easily tell.
+
+        // Use `swap` to provide acquire ordering (not strictly necessary, but all other
+        // implementations do).
+        match self.state.swap(EMPTY, SeqCst) {
+            NOTIFIED => (),
+            PARKED => (),
+            _ => panic!("inconsistent park state"),
         }
     }
 

From caff72361f9a3d9938032be703295ef7a0c0dd5d Mon Sep 17 00:00:00 2001
From: joboet <jonas.boettiger@icloud.com>
Date: Tue, 7 Jun 2022 11:06:19 +0200
Subject: [PATCH 04/20] std: relax memory orderings in `Parker`

Co-authored-by: Tomoaki Kawada <kawada@kmckk.co.jp>
---
 .../std/src/sys_common/thread_parker/wait_flag.rs | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/library/std/src/sys_common/thread_parker/wait_flag.rs b/library/std/src/sys_common/thread_parker/wait_flag.rs
index 8db12693ef734..6561c186655a5 100644
--- a/library/std/src/sys_common/thread_parker/wait_flag.rs
+++ b/library/std/src/sys_common/thread_parker/wait_flag.rs
@@ -25,7 +25,7 @@
 
 use crate::pin::Pin;
 use crate::sync::atomic::AtomicI8;
-use crate::sync::atomic::Ordering::{Relaxed, SeqCst};
+use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
 use crate::sys::wait_flag::WaitFlag;
 use crate::time::Duration;
 
@@ -47,7 +47,7 @@ impl Parker {
 
     // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
     pub unsafe fn park(self: Pin<&Self>) {
-        match self.state.fetch_sub(1, SeqCst) {
+        match self.state.fetch_sub(1, Acquire) {
             // NOTIFIED => EMPTY
             NOTIFIED => return,
             // EMPTY => PARKED
@@ -59,7 +59,7 @@ impl Parker {
         loop {
             self.wait_flag.wait();
 
-            match self.state.compare_exchange(NOTIFIED, EMPTY, SeqCst, Relaxed) {
+            match self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Relaxed) {
                 Ok(_) => return,
                 Err(PARKED) => (),
                 Err(_) => panic!("inconsistent park state"),
@@ -69,7 +69,7 @@ impl Parker {
 
     // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
     pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) {
-        match self.state.fetch_sub(1, SeqCst) {
+        match self.state.fetch_sub(1, Acquire) {
             NOTIFIED => return,
             EMPTY => (),
             _ => panic!("inconsistent park state"),
@@ -83,9 +83,8 @@ impl Parker {
         // is protected against this by looping until the token is actually given, but
         // here we cannot easily tell.
 
-        // Use `swap` to provide acquire ordering (not strictly necessary, but all other
-        // implementations do).
-        match self.state.swap(EMPTY, SeqCst) {
+        // Use `swap` to provide acquire ordering.
+        match self.state.swap(EMPTY, Acquire) {
             NOTIFIED => (),
             PARKED => (),
             _ => panic!("inconsistent park state"),
@@ -94,7 +93,7 @@ impl Parker {
 
     // This implementation doesn't require `Pin`, but other implementations do.
     pub fn unpark(self: Pin<&Self>) {
-        let state = self.state.swap(NOTIFIED, SeqCst);
+        let state = self.state.swap(NOTIFIED, Release);
 
         if state == PARKED {
             self.wait_flag.raise();

From c2385825f1b5aeb94a186b00cb0f0ede03bb7ce3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Tue, 21 Jun 2022 11:57:45 -0700
Subject: [PATCH 05/20] On partial uninit error point at where we need init

When a binding is declared without a value, borrowck verifies that all
codepaths have *one* assignment to them to initialize them fully. If
there are any cases where a condition can be met that leaves the binding
uninitialized or we attempt to initialize a field of an unitialized
binding, we emit E0381.

We now look at all the statements that initialize the binding, and use
them to explore branching code paths that *don't* and point at them. If
we find *no* potential places where an assignment to the binding might
be missing, we display the spans of all the existing initializers to
provide some context.
---
 .../rustc_borrowck/src/borrowck_errors.rs     |  26 +-
 .../src/diagnostics/conflict_errors.rs        | 222 ++++++++++++++++--
 src/test/ui/asm/x86_64/type-check-5.rs        |   4 +-
 src/test/ui/asm/x86_64/type-check-5.stderr    |  12 +-
 .../no-non-guaranteed-initialization.rs       |   3 +-
 .../no-non-guaranteed-initialization.stderr   |   9 +-
 .../partial-initialization-across-await.rs    |   9 +-
 ...partial-initialization-across-await.stderr |  28 ++-
 .../ui/borrowck/assign_mutable_fields.stderr  |  16 +-
 src/test/ui/borrowck/borrowck-and-init.rs     |   2 +-
 src/test/ui/borrowck/borrowck-and-init.stderr |   9 +-
 src/test/ui/borrowck/borrowck-block-unint.rs  |   2 +-
 .../ui/borrowck/borrowck-block-unint.stderr   |   6 +-
 .../ui/borrowck/borrowck-break-uninit-2.rs    |   2 +-
 .../borrowck/borrowck-break-uninit-2.stderr   |   7 +-
 src/test/ui/borrowck/borrowck-break-uninit.rs |   2 +-
 .../ui/borrowck/borrowck-break-uninit.stderr  |   7 +-
 .../ui/borrowck/borrowck-field-sensitivity.rs |   6 +-
 .../borrowck-field-sensitivity.stderr         |  24 +-
 src/test/ui/borrowck/borrowck-if-no-else.rs   |   2 +-
 .../ui/borrowck/borrowck-if-no-else.stderr    |   8 +-
 src/test/ui/borrowck/borrowck-if-with-else.rs |   2 +-
 .../ui/borrowck/borrowck-if-with-else.stderr  |   9 +-
 .../borrowck-init-in-called-fn-expr.rs        |   2 +-
 .../borrowck-init-in-called-fn-expr.stderr    |   6 +-
 .../ui/borrowck/borrowck-init-in-fn-expr.rs   |   2 +-
 .../borrowck/borrowck-init-in-fn-expr.stderr  |   6 +-
 src/test/ui/borrowck/borrowck-init-in-fru.rs  |   2 +-
 .../ui/borrowck/borrowck-init-in-fru.stderr   |   6 +-
 .../ui/borrowck/borrowck-init-op-equal.rs     |   2 +-
 .../ui/borrowck/borrowck-init-op-equal.stderr |   6 +-
 .../ui/borrowck/borrowck-init-plus-equal.rs   |   2 +-
 .../borrowck/borrowck-init-plus-equal.stderr  |   6 +-
 src/test/ui/borrowck/borrowck-or-init.rs      |   2 +-
 src/test/ui/borrowck/borrowck-or-init.stderr  |   9 +-
 .../ui/borrowck/borrowck-partial-reinit-4.rs  |   3 +-
 .../borrowck/borrowck-partial-reinit-4.stderr |   6 +-
 src/test/ui/borrowck/borrowck-return.rs       |   2 +-
 src/test/ui/borrowck/borrowck-return.stderr   |   6 +-
 .../ui/borrowck/borrowck-storage-dead.stderr  |   6 +-
 .../ui/borrowck/borrowck-uninit-after-item.rs |   2 +-
 .../borrowck-uninit-after-item.stderr         |   7 +-
 .../borrowck-uninit-field-access.stderr       |   6 +-
 .../borrowck/borrowck-uninit-in-assignop.rs   |  20 +-
 .../borrowck-uninit-in-assignop.stderr        |  60 +++--
 .../ui/borrowck/borrowck-uninit-ref-chain.rs  |  14 +-
 .../borrowck/borrowck-uninit-ref-chain.stderr |  50 ++--
 src/test/ui/borrowck/borrowck-uninit.rs       |   2 +-
 src/test/ui/borrowck/borrowck-uninit.stderr   |   6 +-
 .../borrowck/borrowck-union-uninitialized.rs  |   4 +-
 .../borrowck-union-uninitialized.stderr       |  18 +-
 .../borrowck-use-in-index-lvalue.stderr       |  12 +-
 ...wck-use-uninitialized-in-cast-trait.stderr |   6 +-
 .../borrowck-use-uninitialized-in-cast.stderr |   6 +-
 src/test/ui/borrowck/borrowck-while-break.rs  |   2 +-
 .../ui/borrowck/borrowck-while-break.stderr   |   9 +-
 src/test/ui/borrowck/borrowck-while-cond.rs   |   2 +-
 .../ui/borrowck/borrowck-while-cond.stderr    |   6 +-
 src/test/ui/borrowck/borrowck-while.rs        |   2 +-
 src/test/ui/borrowck/borrowck-while.stderr    |   8 +-
 .../disallow-possibly-uninitialized.rs        |   8 +-
 .../disallow-possibly-uninitialized.stderr    |  32 ++-
 src/test/ui/borrowck/issue-24267-flow-exit.rs |   4 +-
 .../ui/borrowck/issue-24267-flow-exit.stderr  |  14 +-
 ...-54499-field-mutation-marks-mut-as-used.rs |   6 +-
 ...99-field-mutation-marks-mut-as-used.stderr |  24 +-
 ...ssue-54499-field-mutation-of-never-init.rs |   6 +-
 ...-54499-field-mutation-of-never-init.stderr |  24 +-
 .../borrowck/issue-62107-match-arm-scopes.rs  |   2 +-
 .../issue-62107-match-arm-scopes.stderr       |   6 +-
 .../reassignment_immutable_fields.stderr      |  16 +-
 ...gnment_immutable_fields_overlapping.stderr |   8 +-
 ...reassignment_immutable_fields_twice.stderr |   8 +-
 .../match/pattern-matching-should-fail.rs     |  17 +-
 .../match/pattern-matching-should-fail.stderr |  53 +++--
 .../const-generic-default-wont-borrowck.rs    |   3 +-
 ...const-generic-default-wont-borrowck.stderr |   6 +-
 src/test/ui/consts/issue-78655.rs             |   2 +-
 src/test/ui/consts/issue-78655.stderr         |   6 +-
 src/test/ui/drop/repeat-drop-2.rs             |   2 +-
 src/test/ui/drop/repeat-drop-2.stderr         |   6 +-
 .../partial-initialization-across-yield.rs    |   9 +-
 ...partial-initialization-across-yield.stderr |  28 ++-
 src/test/ui/loops/loop-proper-liveness.rs     |   2 +-
 src/test/ui/loops/loop-proper-liveness.stderr |   7 +-
 .../drop-elaboration-after-borrowck-error.rs  |   2 +-
 ...op-elaboration-after-borrowck-error.stderr |   7 +-
 .../ui/moves/issue-72649-uninit-in-loop.rs    |  12 +-
 .../moves/issue-72649-uninit-in-loop.stderr   |  13 +-
 src/test/ui/moves/move-into-dead-array-1.rs   |   2 +-
 .../ui/moves/move-into-dead-array-1.stderr    |   6 +-
 src/test/ui/moves/move-of-addr-of-mut.rs      |   2 +-
 src/test/ui/moves/move-of-addr-of-mut.stderr  |   6 +-
 ...ue-21232-partial-init-and-erroneous-use.rs |  12 +-
 ...1232-partial-init-and-erroneous-use.stderr |  38 ++-
 .../nll/issue-21232-partial-init-and-use.rs   |  36 +--
 .../issue-21232-partial-init-and-use.stderr   | 140 +++++++----
 src/test/ui/nll/match-cfg-fake-edges.rs       |   2 +-
 src/test/ui/nll/match-cfg-fake-edges.stderr   |   9 +-
 src/test/ui/nll/match-on-borrowed.stderr      |   6 +-
 .../chains-without-let.rs                     |   6 +-
 .../chains-without-let.stderr                 |  24 +-
 src/test/ui/try-block/try-block-opt-init.rs   |   2 +-
 .../ui/try-block/try-block-opt-init.stderr    |  10 +-
 .../privately-uninhabited-mir-call.rs         |   2 +-
 .../privately-uninhabited-mir-call.stderr     |   7 +-
 106 files changed, 935 insertions(+), 441 deletions(-)

diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index a1233d62cb02e..b6cf5275394fb 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -31,22 +31,6 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         err
     }
 
-    pub(crate) fn cannot_act_on_uninitialized_variable(
-        &self,
-        span: Span,
-        verb: &str,
-        desc: &str,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
-        struct_span_err!(
-            self,
-            span,
-            E0381,
-            "{} of possibly-uninitialized variable: `{}`",
-            verb,
-            desc,
-        )
-    }
-
     pub(crate) fn cannot_mutably_borrow_multiply(
         &self,
         new_loan_span: Span,
@@ -173,8 +157,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
             self,
             new_loan_span,
             E0501,
-            "cannot borrow {}{} as {} because previous closure \
-             requires unique access",
+            "cannot borrow {}{} as {} because previous closure requires unique access",
             desc_new,
             opt_via,
             kind_new,
@@ -451,9 +434,8 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
             self,
             closure_span,
             E0373,
-            "{} may outlive the current function, \
-             but it borrows {}, \
-             which is owned by the current function",
+            "{} may outlive the current function, but it borrows {}, which is owned by the current \
+             function",
             closure_kind,
             borrowed_path,
         );
@@ -476,7 +458,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
         struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",)
     }
 
-    fn struct_span_err_with_code<S: Into<MultiSpan>>(
+    pub(crate) fn struct_span_err_with_code<S: Into<MultiSpan>>(
         &self,
         sp: S,
         msg: &str,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 73c0bf16a1f99..1f7cb972fcec8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -2,9 +2,12 @@ use either::Either;
 use rustc_const_eval::util::CallKind;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{
+    struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
+};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::ObligationCause;
@@ -94,32 +97,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 return;
             }
 
-            let item_msg =
-                match self.describe_place_with_options(used_place, IncludingDowncast(true)) {
-                    Some(name) => format!("`{}`", name),
-                    None => "value".to_owned(),
-                };
-            let mut err = self.cannot_act_on_uninitialized_variable(
-                span,
-                desired_action.as_noun(),
-                &self
-                    .describe_place_with_options(moved_place, IncludingDowncast(true))
-                    .unwrap_or_else(|| "_".to_owned()),
-            );
-            err.span_label(span, format!("use of possibly-uninitialized {}", item_msg));
-
-            use_spans.var_span_label_path_only(
-                &mut err,
-                format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()),
-            );
-
+            let err =
+                self.report_use_of_uninitialized(mpi, used_place, desired_action, span, use_spans);
             self.buffer_error(err);
         } else {
             if let Some((reported_place, _)) = self.has_move_error(&move_out_indices) {
                 if self.prefixes(*reported_place, PrefixSet::All).any(|p| p == used_place) {
                     debug!(
-                        "report_use_of_moved_or_uninitialized place: error suppressed \
-                         mois={:?}",
+                        "report_use_of_moved_or_uninitialized place: error suppressed mois={:?}",
                         move_out_indices
                     );
                     return;
@@ -326,6 +311,99 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
     }
 
+    fn report_use_of_uninitialized(
+        &self,
+        mpi: MovePathIndex,
+        used_place: PlaceRef<'tcx>,
+        desired_action: InitializationRequiringAction,
+        span: Span,
+        use_spans: UseSpans<'tcx>,
+    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+        // We need all statements in the body where the binding was assigned to to later find all
+        // the branching code paths where the binding *wasn't* assigned to.
+        let inits = &self.move_data.init_path_map[mpi];
+        let move_path = &self.move_data.move_paths[mpi];
+        let decl_span = self.body.local_decls[move_path.place.local].source_info.span;
+        let mut spans = vec![];
+        for init_idx in inits {
+            let init = &self.move_data.inits[*init_idx];
+            let span = init.span(&self.body);
+            spans.push(span);
+        }
+
+        let (item_msg, name, desc) =
+            match self.describe_place_with_options(used_place, IncludingDowncast(true)) {
+                Some(name) => (format!("`{name}`"), format!("`{name}`"), format!("`{name}` ")),
+                None => ("value".to_string(), "the variable".to_string(), String::new()),
+            };
+        let initialized = if let InitializationRequiringAction::PartialAssignment = desired_action {
+            // The same error is emitted for bindings that are *sometimes* initialized and the ones
+            // that are *partially* initialized by assigning to a field of an uninitialized
+            // binding. We differentiate between them for more accurate wording here.
+            "fully initialized"
+        } else if spans.iter().filter(|i| !i.contains(span)).count() == 0 {
+            // We filter above to avoid misleading wording in cases like:
+            // ```
+            // let x;
+            // x += 1;
+            // ```
+            "initialized"
+        } else {
+            "initialized in all conditions"
+        };
+        let mut err = struct_span_err!(self, span, E0381, "binding {desc}isn't {initialized}");
+        use_spans.var_span_label_path_only(
+            &mut err,
+            format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()),
+        );
+
+        if let InitializationRequiringAction::PartialAssignment = desired_action {
+            err.help(
+                "partial initialization isn't supported, fully initialize the binding with \
+                a default value and mutate, or use `std::mem::MaybeUninit`",
+            );
+        }
+        let verb = desired_action.as_verb_in_past_tense();
+        err.span_label(span, format!("{item_msg} {verb} here but it isn't {initialized}",));
+
+        // We use the statements were the binding was initialized, and inspect the HIR to look
+        // for the branching codepaths that aren't covered, to point at them.
+        let hir_id = self.mir_hir_id();
+        let map = self.infcx.tcx.hir();
+        let body_id = map.body_owned_by(hir_id);
+        let body = map.body(body_id);
+
+        let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
+        visitor.visit_body(&body);
+        if visitor.errors.is_empty() {
+            for sp in &spans {
+                if *sp < span && !sp.overlaps(span) {
+                    err.span_label(*sp, "binding initialized here in some conditions");
+                }
+            }
+        }
+        for (sp, label) in visitor.errors {
+            if sp < span && !sp.overlaps(span) {
+                // When we have a case like `match-cfg-fake-edges.rs`, we don't want to mention
+                // match arms coming after the primary span because they aren't relevant:
+                // ```
+                // let x;
+                // match y {
+                //     _ if { x = 2; true } => {}
+                //     _ if {
+                //         x; //~ ERROR
+                //         false
+                //     } => {}
+                //     _ => {} // We don't want to point to this.
+                // };
+                // ```
+                err.span_label(sp, &label);
+            }
+        }
+        err.span_label(decl_span, "variable declared here");
+        err
+    }
+
     fn suggest_borrow_fn_like(
         &self,
         err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
@@ -2448,3 +2526,103 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
         }
     }
 }
+
+/// Detect whether one of the provided spans is a statement nested within the top-most visited expr
+struct ReferencedStatementsVisitor<'a>(&'a [Span], bool);
+
+impl<'a, 'v> Visitor<'v> for ReferencedStatementsVisitor<'a> {
+    fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) {
+        match s.kind {
+            hir::StmtKind::Semi(expr) if self.0.contains(&expr.span) => {
+                self.1 = true;
+            }
+            _ => {}
+        }
+    }
+}
+
+/// Given a set of spans representing statements initializing the relevant binding, visit all the
+/// function expressions looking for branching code paths that *do not* initialize the binding.
+struct ConditionVisitor<'b> {
+    spans: &'b [Span],
+    name: &'b str,
+    errors: Vec<(Span, String)>,
+}
+
+impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
+    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+        match ex.kind {
+            hir::ExprKind::If(cond, body, None) => {
+                // `if` expressions with no `else` that initialize the binding might be missing an
+                // `else` arm.
+                let mut v = ReferencedStatementsVisitor(self.spans, false);
+                v.visit_expr(body);
+                if v.1 {
+                    self.errors.push((
+                        cond.span,
+                        format!(
+                            "this `if` expression might be missing an `else` arm where {} is \
+                             initialized",
+                            self.name,
+                        ),
+                    ));
+                }
+            }
+            hir::ExprKind::If(cond, body, Some(other)) => {
+                // `if` expressions where the binding is only initialized in one of the two arms
+                // might be missing a binding initialization.
+                let mut a = ReferencedStatementsVisitor(self.spans, false);
+                a.visit_expr(body);
+                let mut b = ReferencedStatementsVisitor(self.spans, false);
+                b.visit_expr(other);
+                match (a.1, b.1) {
+                    (true, true) | (false, false) => {}
+                    (true, false) => {
+                        self.errors.push((
+                            cond.span,
+                            format!("{} is uninitialized if this condition isn't met", self.name,),
+                        ));
+                    }
+                    (false, true) => {
+                        self.errors.push((
+                            cond.span,
+                            format!("{} is uninitialized if this condition is met", self.name),
+                        ));
+                    }
+                }
+            }
+            hir::ExprKind::Match(_, arms, _) => {
+                // If the binding is initialized in one of the match arms, then the other match
+                // arms might be missing an initialization.
+                let results: Vec<bool> = arms
+                    .iter()
+                    .map(|arm| {
+                        let mut v = ReferencedStatementsVisitor(self.spans, false);
+                        v.visit_arm(arm);
+                        v.1
+                    })
+                    .collect();
+                if results.iter().any(|x| *x) && !results.iter().all(|x| *x) {
+                    for (arm, seen) in arms.iter().zip(results) {
+                        if !seen {
+                            self.errors.push((
+                                arm.pat.span,
+                                format!(
+                                    "{} is uninitialized if this pattern is matched",
+                                    self.name
+                                ),
+                            ));
+                        }
+                    }
+                }
+            }
+            // FIXME: should we also account for binops, particularly `&&` and `||`? `try` should
+            // also be accounted for. For now it is fine, as if we don't find *any* relevant
+            // branching code paths, we point at the places where the binding *is* initialized for
+            // *some* context. We should also specialize the output for `while` and `for` loops,
+            // but for now we can rely on their desugaring to provide appropriate output.
+            _ => {}
+        }
+        walk_expr(self, ex);
+    }
+}
diff --git a/src/test/ui/asm/x86_64/type-check-5.rs b/src/test/ui/asm/x86_64/type-check-5.rs
index 474478f6a88e1..6190e0b52f4e9 100644
--- a/src/test/ui/asm/x86_64/type-check-5.rs
+++ b/src/test/ui/asm/x86_64/type-check-5.rs
@@ -13,10 +13,10 @@ fn main() {
 
         let x: u64;
         asm!("{}", in(reg) x);
-        //~^ ERROR use of possibly-uninitialized variable: `x`
+        //~^ ERROR E0381
         let mut y: u64;
         asm!("{}", inout(reg) y);
-        //~^ ERROR use of possibly-uninitialized variable: `y`
+        //~^ ERROR E0381
         let _ = y;
 
         // Outputs require mutable places
diff --git a/src/test/ui/asm/x86_64/type-check-5.stderr b/src/test/ui/asm/x86_64/type-check-5.stderr
index 181ecaf585585..26aac4ed2c1e0 100644
--- a/src/test/ui/asm/x86_64/type-check-5.stderr
+++ b/src/test/ui/asm/x86_64/type-check-5.stderr
@@ -1,14 +1,18 @@
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/type-check-5.rs:15:28
    |
+LL |         let x: u64;
+   |             - variable declared here
 LL |         asm!("{}", in(reg) x);
-   |                            ^ use of possibly-uninitialized `x`
+   |                            ^ `x` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `y`
+error[E0381]: binding `y` isn't initialized
   --> $DIR/type-check-5.rs:18:9
    |
+LL |         let mut y: u64;
+   |             ----- variable declared here
 LL |         asm!("{}", inout(reg) y);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized
 
 error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
   --> $DIR/type-check-5.rs:26:29
diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.rs b/src/test/ui/async-await/no-non-guaranteed-initialization.rs
index 24070fe33083c..c4d81bf83a3c4 100644
--- a/src/test/ui/async-await/no-non-guaranteed-initialization.rs
+++ b/src/test/ui/async-await/no-non-guaranteed-initialization.rs
@@ -6,8 +6,7 @@ async fn no_non_guaranteed_initialization(x: usize) -> usize {
     if x > 5 {
         y = echo(10).await;
     }
-    y
-    //~^ use of possibly-uninitialized variable: `y`
+    y //~ ERROR E0381
 }
 
 async fn echo(x: usize) -> usize { x + 1 }
diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr
index f5991f4bccac9..c6490c7bf4dbf 100644
--- a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr
+++ b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr
@@ -1,8 +1,13 @@
-error[E0381]: use of possibly-uninitialized variable: `y`
+error[E0381]: binding `y` isn't initialized in all conditions
   --> $DIR/no-non-guaranteed-initialization.rs:9:5
    |
+LL |     let y;
+   |         - variable declared here
+LL |     if x > 5 {
+   |        ----- this `if` expression might be missing an `else` arm where `y` is initialized
+...
 LL |     y
-   |     ^ use of possibly-uninitialized `y`
+   |     ^ `y` used here but it isn't initialized in all conditions
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/partial-initialization-across-await.rs b/src/test/ui/async-await/partial-initialization-across-await.rs
index 8a98a4b0f6bb4..7577aee3fb7d6 100644
--- a/src/test/ui/async-await/partial-initialization-across-await.rs
+++ b/src/test/ui/async-await/partial-initialization-across-await.rs
@@ -10,8 +10,7 @@ async fn noop() {}
 
 async fn test_tuple() {
     let mut t: (i32, i32);
-    t.0 = 42;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+    t.0 = 42; //~ ERROR E0381
     noop().await;
     t.1 = 88;
     let _ = t;
@@ -19,8 +18,7 @@ async fn test_tuple() {
 
 async fn test_tuple_struct() {
     let mut t: T;
-    t.0 = 42;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+    t.0 = 42; //~ ERROR E0381
     noop().await;
     t.1 = 88;
     let _ = t;
@@ -28,8 +26,7 @@ async fn test_tuple_struct() {
 
 async fn test_struct() {
     let mut t: S;
-    t.x = 42;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+    t.x = 42; //~ ERROR E0381
     noop().await;
     t.y = 88;
     let _ = t;
diff --git a/src/test/ui/async-await/partial-initialization-across-await.stderr b/src/test/ui/async-await/partial-initialization-across-await.stderr
index 9a510c22c4b1e..981e32cadd9de 100644
--- a/src/test/ui/async-await/partial-initialization-across-await.stderr
+++ b/src/test/ui/async-await/partial-initialization-across-await.stderr
@@ -1,20 +1,32 @@
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
+error[E0381]: binding `t` isn't fully initialized
   --> $DIR/partial-initialization-across-await.rs:13:5
    |
+LL |     let mut t: (i32, i32);
+   |         ----- variable declared here
 LL |     t.0 = 42;
-   |     ^^^^^^^^ use of possibly-uninitialized `t`
+   |     ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
-  --> $DIR/partial-initialization-across-await.rs:22:5
+error[E0381]: binding `t` isn't fully initialized
+  --> $DIR/partial-initialization-across-await.rs:21:5
    |
+LL |     let mut t: T;
+   |         ----- variable declared here
 LL |     t.0 = 42;
-   |     ^^^^^^^^ use of possibly-uninitialized `t`
+   |     ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
-  --> $DIR/partial-initialization-across-await.rs:31:5
+error[E0381]: binding `t` isn't fully initialized
+  --> $DIR/partial-initialization-across-await.rs:29:5
    |
+LL |     let mut t: S;
+   |         ----- variable declared here
 LL |     t.x = 42;
-   |     ^^^^^^^^ use of possibly-uninitialized `t`
+   |     ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/assign_mutable_fields.stderr b/src/test/ui/borrowck/assign_mutable_fields.stderr
index 40f1aae092dc6..57787b8924998 100644
--- a/src/test/ui/borrowck/assign_mutable_fields.stderr
+++ b/src/test/ui/borrowck/assign_mutable_fields.stderr
@@ -1,14 +1,22 @@
-error[E0381]: assign to part of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't fully initialized
   --> $DIR/assign_mutable_fields.rs:9:5
    |
+LL |     let mut x: (u32, u32);
+   |         ----- variable declared here
 LL |     x.0 = 1;
-   |     ^^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't fully initialized
   --> $DIR/assign_mutable_fields.rs:17:5
    |
+LL |     let mut x: (u32, u32);
+   |         ----- variable declared here
 LL |     x.0 = 1;
-   |     ^^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-and-init.rs b/src/test/ui/borrowck/borrowck-and-init.rs
index f11d44e2217ba..eeb4f05d60c96 100644
--- a/src/test/ui/borrowck/borrowck-and-init.rs
+++ b/src/test/ui/borrowck/borrowck-and-init.rs
@@ -2,5 +2,5 @@ fn main() {
     let i: isize;
 
     println!("{}", false && { i = 5; true });
-    println!("{}", i); //~ ERROR borrow of possibly-uninitialized variable: `i`
+    println!("{}", i); //~ ERROR E0381
 }
diff --git a/src/test/ui/borrowck/borrowck-and-init.stderr b/src/test/ui/borrowck/borrowck-and-init.stderr
index d2c7473c036b8..de57243a5dbf7 100644
--- a/src/test/ui/borrowck/borrowck-and-init.stderr
+++ b/src/test/ui/borrowck/borrowck-and-init.stderr
@@ -1,8 +1,13 @@
-error[E0381]: borrow of possibly-uninitialized variable: `i`
+error[E0381]: binding `i` isn't initialized in all conditions
   --> $DIR/borrowck-and-init.rs:5:20
    |
+LL |     let i: isize;
+   |         - variable declared here
+LL |
+LL |     println!("{}", false && { i = 5; true });
+   |                               ----- binding initialized here in some conditions
 LL |     println!("{}", i);
-   |                    ^ use of possibly-uninitialized `i`
+   |                    ^ `i` borrowed here but it isn't initialized in all conditions
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/borrowck-block-unint.rs b/src/test/ui/borrowck/borrowck-block-unint.rs
index 1e7306acaee98..8d13b25a35756 100644
--- a/src/test/ui/borrowck/borrowck-block-unint.rs
+++ b/src/test/ui/borrowck/borrowck-block-unint.rs
@@ -1,7 +1,7 @@
 fn force<F>(f: F) where F: FnOnce() { f(); }
 fn main() {
     let x: isize;
-    force(|| {  //~ ERROR borrow of possibly-uninitialized variable: `x`
+    force(|| {  //~ ERROR E0381
         println!("{}", x);
     });
 }
diff --git a/src/test/ui/borrowck/borrowck-block-unint.stderr b/src/test/ui/borrowck/borrowck-block-unint.stderr
index 578f89df46ce1..0f0fbedaf17e7 100644
--- a/src/test/ui/borrowck/borrowck-block-unint.stderr
+++ b/src/test/ui/borrowck/borrowck-block-unint.stderr
@@ -1,8 +1,10 @@
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-block-unint.rs:4:11
    |
+LL |     let x: isize;
+   |         - variable declared here
 LL |     force(|| {
-   |           ^^ use of possibly-uninitialized `x`
+   |           ^^ `x` borrowed here but it isn't initialized
 LL |         println!("{}", x);
    |                        - borrow occurs due to use in closure
 
diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.rs b/src/test/ui/borrowck/borrowck-break-uninit-2.rs
index 126d991a51c6e..3abca33a84add 100644
--- a/src/test/ui/borrowck/borrowck-break-uninit-2.rs
+++ b/src/test/ui/borrowck/borrowck-break-uninit-2.rs
@@ -6,7 +6,7 @@ fn foo() -> isize {
         x = 0;
     }
 
-    println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x`
+    println!("{}", x); //~ ERROR E0381
 
     return 17;
 }
diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
index b134f5cc2d8e3..2b5547dbf9556 100644
--- a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
+++ b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
@@ -1,8 +1,11 @@
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-break-uninit-2.rs:9:20
    |
+LL |     let x: isize;
+   |         - variable declared here
+...
 LL |     println!("{}", x);
-   |                    ^ use of possibly-uninitialized `x`
+   |                    ^ `x` borrowed here but it isn't initialized
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/borrowck-break-uninit.rs b/src/test/ui/borrowck/borrowck-break-uninit.rs
index 8ccb21ae8eebf..824f91dbc62c2 100644
--- a/src/test/ui/borrowck/borrowck-break-uninit.rs
+++ b/src/test/ui/borrowck/borrowck-break-uninit.rs
@@ -6,7 +6,7 @@ fn foo() -> isize {
         x = 0;
     }
 
-    println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x`
+    println!("{}", x); //~ ERROR E0381
 
     return 17;
 }
diff --git a/src/test/ui/borrowck/borrowck-break-uninit.stderr b/src/test/ui/borrowck/borrowck-break-uninit.stderr
index 652d7d3076fbd..9d0fd5dac933f 100644
--- a/src/test/ui/borrowck/borrowck-break-uninit.stderr
+++ b/src/test/ui/borrowck/borrowck-break-uninit.stderr
@@ -1,8 +1,11 @@
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-break-uninit.rs:9:20
    |
+LL |     let x: isize;
+   |         - variable declared here
+...
 LL |     println!("{}", x);
-   |                    ^ use of possibly-uninitialized `x`
+   |                    ^ `x` borrowed here but it isn't initialized
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.rs b/src/test/ui/borrowck/borrowck-field-sensitivity.rs
index 50edfb6ba2db1..03edf445ee97b 100644
--- a/src/test/ui/borrowck/borrowck-field-sensitivity.rs
+++ b/src/test/ui/borrowck/borrowck-field-sensitivity.rs
@@ -78,20 +78,20 @@ fn fu_move_after_fu_move() {
 
 fn copy_after_field_assign_after_uninit() {
     let mut x: A;
-    x.a = 1; //~ ERROR assign to part of possibly-uninitialized variable: `x`
+    x.a = 1; //~ ERROR E0381
     drop(x.a);
 }
 
 fn borrow_after_field_assign_after_uninit() {
     let mut x: A;
-    x.a = 1; //~ ERROR assign to part of possibly-uninitialized variable: `x`
+    x.a = 1; //~ ERROR E0381
     let p = &x.a;
     drop(*p);
 }
 
 fn move_after_field_assign_after_uninit() {
     let mut x: A;
-    x.b = Box::new(1); //~ ERROR assign to part of possibly-uninitialized variable: `x`
+    x.b = Box::new(1); //~ ERROR E0381
     drop(x.b);
 }
 
diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr
index bb4d2f06016b9..492bbfa9eb2d4 100644
--- a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr
+++ b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr
@@ -108,23 +108,35 @@ LL |     let _z = A { a: 4, .. x };
    |
    = note: move occurs because `x.b` has type `Box<isize>`, which does not implement the `Copy` trait
 
-error[E0381]: assign to part of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't fully initialized
   --> $DIR/borrowck-field-sensitivity.rs:81:5
    |
+LL |     let mut x: A;
+   |         ----- variable declared here
 LL |     x.a = 1;
-   |     ^^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't fully initialized
   --> $DIR/borrowck-field-sensitivity.rs:87:5
    |
+LL |     let mut x: A;
+   |         ----- variable declared here
 LL |     x.a = 1;
-   |     ^^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't fully initialized
   --> $DIR/borrowck-field-sensitivity.rs:94:5
    |
+LL |     let mut x: A;
+   |         ----- variable declared here
 LL |     x.b = Box::new(1);
-   |     ^^^ use of possibly-uninitialized `x`
+   |     ^^^ `x` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error: aborting due to 14 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-if-no-else.rs b/src/test/ui/borrowck/borrowck-if-no-else.rs
index f59bcad6f61d7..534d771be1dfa 100644
--- a/src/test/ui/borrowck/borrowck-if-no-else.rs
+++ b/src/test/ui/borrowck/borrowck-if-no-else.rs
@@ -2,5 +2,5 @@ fn foo(x: isize) { println!("{}", x); }
 
 fn main() {
     let x: isize; if 1 > 2 { x = 10; }
-    foo(x); //~ ERROR use of possibly-uninitialized variable: `x`
+    foo(x); //~ ERROR E0381
 }
diff --git a/src/test/ui/borrowck/borrowck-if-no-else.stderr b/src/test/ui/borrowck/borrowck-if-no-else.stderr
index 3e9d3d4f6d513..178381e847786 100644
--- a/src/test/ui/borrowck/borrowck-if-no-else.stderr
+++ b/src/test/ui/borrowck/borrowck-if-no-else.stderr
@@ -1,8 +1,12 @@
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized in all conditions
   --> $DIR/borrowck-if-no-else.rs:5:9
    |
+LL |     let x: isize; if 1 > 2 { x = 10; }
+   |         -            ----- this `if` expression might be missing an `else` arm where `x` is initialized
+   |         |
+   |         variable declared here
 LL |     foo(x);
-   |         ^ use of possibly-uninitialized `x`
+   |         ^ `x` used here but it isn't initialized in all conditions
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-if-with-else.rs b/src/test/ui/borrowck/borrowck-if-with-else.rs
index c13318b16c2fa..69d450c59891a 100644
--- a/src/test/ui/borrowck/borrowck-if-with-else.rs
+++ b/src/test/ui/borrowck/borrowck-if-with-else.rs
@@ -7,5 +7,5 @@ fn main() {
     } else {
         x = 10;
     }
-    foo(x); //~ ERROR use of possibly-uninitialized variable: `x`
+    foo(x); //~ ERROR E0381
 }
diff --git a/src/test/ui/borrowck/borrowck-if-with-else.stderr b/src/test/ui/borrowck/borrowck-if-with-else.stderr
index 53b8a6bba2c76..f1af7b67b1c1b 100644
--- a/src/test/ui/borrowck/borrowck-if-with-else.stderr
+++ b/src/test/ui/borrowck/borrowck-if-with-else.stderr
@@ -1,8 +1,13 @@
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized in all conditions
   --> $DIR/borrowck-if-with-else.rs:10:9
    |
+LL |     let x: isize;
+   |         - variable declared here
+LL |     if 1 > 2 {
+   |        ----- `x` is uninitialized if this condition is met
+...
 LL |     foo(x);
-   |         ^ use of possibly-uninitialized `x`
+   |         ^ `x` used here but it isn't initialized in all conditions
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs
index 9905e420f948d..e6476b9c1bef7 100644
--- a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs
+++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.rs
@@ -1,7 +1,7 @@
 fn main() {
     let j = || -> isize {
         let i: isize;
-        i //~ ERROR use of possibly-uninitialized variable: `i`
+        i //~ ERROR E0381
     };
     j();
 }
diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
index 2d1d9bc8fa41d..8bdccd0dad6d2 100644
--- a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
+++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
@@ -1,8 +1,10 @@
-error[E0381]: use of possibly-uninitialized variable: `i`
+error[E0381]: binding `i` isn't initialized
   --> $DIR/borrowck-init-in-called-fn-expr.rs:4:9
    |
+LL |         let i: isize;
+   |             - variable declared here
 LL |         i
-   |         ^ use of possibly-uninitialized `i`
+   |         ^ `i` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs b/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs
index 7dd3396c8c2cb..7eb204a0d1672 100644
--- a/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs
+++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.rs
@@ -1,7 +1,7 @@
 fn main() {
     let f  = || -> isize {
         let i: isize;
-        i //~ ERROR use of possibly-uninitialized variable: `i`
+        i //~ ERROR E0381
     };
     println!("{}", f());
 }
diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
index fd8b90eda6032..84ec5598abb89 100644
--- a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
+++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
@@ -1,8 +1,10 @@
-error[E0381]: use of possibly-uninitialized variable: `i`
+error[E0381]: binding `i` isn't initialized
   --> $DIR/borrowck-init-in-fn-expr.rs:4:9
    |
+LL |         let i: isize;
+   |             - variable declared here
 LL |         i
-   |         ^ use of possibly-uninitialized `i`
+   |         ^ `i` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.rs b/src/test/ui/borrowck/borrowck-init-in-fru.rs
index d7ec2ed75c85c..c07957ab13973 100644
--- a/src/test/ui/borrowck/borrowck-init-in-fru.rs
+++ b/src/test/ui/borrowck/borrowck-init-in-fru.rs
@@ -7,6 +7,6 @@ struct Point {
 fn main() {
     let mut origin: Point;
     origin = Point { x: 10, ..origin };
-    //~^ ERROR use of possibly-uninitialized variable: `origin` [E0381]
+    //~^ ERROR E0381
     origin.clone();
 }
diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.stderr
index f01afe1466aef..ddb2473d1ebee 100644
--- a/src/test/ui/borrowck/borrowck-init-in-fru.stderr
+++ b/src/test/ui/borrowck/borrowck-init-in-fru.stderr
@@ -1,8 +1,10 @@
-error[E0381]: use of possibly-uninitialized variable: `origin`
+error[E0381]: binding `origin.y` isn't initialized
   --> $DIR/borrowck-init-in-fru.rs:9:14
    |
+LL |     let mut origin: Point;
+   |         ---------- variable declared here
 LL |     origin = Point { x: 10, ..origin };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `origin.y`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ `origin.y` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.rs b/src/test/ui/borrowck/borrowck-init-op-equal.rs
index 784eb8cf85b8a..3d08c1b81a79b 100644
--- a/src/test/ui/borrowck/borrowck-init-op-equal.rs
+++ b/src/test/ui/borrowck/borrowck-init-op-equal.rs
@@ -1,6 +1,6 @@
 fn test() {
     let v: isize;
-    v += 1; //~ ERROR use of possibly-uninitialized variable: `v`
+    v += 1; //~ ERROR E0381
     v.clone();
 }
 
diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.stderr b/src/test/ui/borrowck/borrowck-init-op-equal.stderr
index 6c88778ae0e5a..f1d7ec6a446d4 100644
--- a/src/test/ui/borrowck/borrowck-init-op-equal.stderr
+++ b/src/test/ui/borrowck/borrowck-init-op-equal.stderr
@@ -1,8 +1,10 @@
-error[E0381]: use of possibly-uninitialized variable: `v`
+error[E0381]: binding `v` isn't initialized
   --> $DIR/borrowck-init-op-equal.rs:3:5
    |
+LL |     let v: isize;
+   |         - variable declared here
 LL |     v += 1;
-   |     ^^^^^^ use of possibly-uninitialized `v`
+   |     ^^^^^^ `v` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.rs b/src/test/ui/borrowck/borrowck-init-plus-equal.rs
index d9d20a2a9c148..2a52a3f4e5eb1 100644
--- a/src/test/ui/borrowck/borrowck-init-plus-equal.rs
+++ b/src/test/ui/borrowck/borrowck-init-plus-equal.rs
@@ -1,6 +1,6 @@
 fn test() {
     let mut v: isize;
-    v = v + 1; //~ ERROR use of possibly-uninitialized variable: `v`
+    v = v + 1; //~ ERROR E0381
     v.clone();
 }
 
diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
index fe09c8581df0e..26422af9c639a 100644
--- a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
+++ b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
@@ -1,8 +1,10 @@
-error[E0381]: use of possibly-uninitialized variable: `v`
+error[E0381]: binding `v` isn't initialized
   --> $DIR/borrowck-init-plus-equal.rs:3:9
    |
+LL |     let mut v: isize;
+   |         ----- variable declared here
 LL |     v = v + 1;
-   |         ^ use of possibly-uninitialized `v`
+   |         ^ `v` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-or-init.rs b/src/test/ui/borrowck/borrowck-or-init.rs
index 81b0b80bf11b5..079cf899e6dbf 100644
--- a/src/test/ui/borrowck/borrowck-or-init.rs
+++ b/src/test/ui/borrowck/borrowck-or-init.rs
@@ -2,5 +2,5 @@ fn main() {
     let i: isize;
 
     println!("{}", false || { i = 5; true });
-    println!("{}", i); //~ ERROR borrow of possibly-uninitialized variable: `i`
+    println!("{}", i); //~ ERROR E0381
 }
diff --git a/src/test/ui/borrowck/borrowck-or-init.stderr b/src/test/ui/borrowck/borrowck-or-init.stderr
index 6c757759f7134..7fcec3046474d 100644
--- a/src/test/ui/borrowck/borrowck-or-init.stderr
+++ b/src/test/ui/borrowck/borrowck-or-init.stderr
@@ -1,8 +1,13 @@
-error[E0381]: borrow of possibly-uninitialized variable: `i`
+error[E0381]: binding `i` isn't initialized in all conditions
   --> $DIR/borrowck-or-init.rs:5:20
    |
+LL |     let i: isize;
+   |         - variable declared here
+LL |
+LL |     println!("{}", false || { i = 5; true });
+   |                               ----- binding initialized here in some conditions
 LL |     println!("{}", i);
-   |                    ^ use of possibly-uninitialized `i`
+   |                    ^ `i` borrowed here but it isn't initialized in all conditions
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.rs b/src/test/ui/borrowck/borrowck-partial-reinit-4.rs
index 5e5a8cdf4232b..a43a1936678ff 100644
--- a/src/test/ui/borrowck/borrowck-partial-reinit-4.rs
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.rs
@@ -14,8 +14,7 @@ impl Drop for Test2 {
 
 fn stuff() {
     let mut x : (Test2, Test2);
-    (x.0).0 = Some(Test);
-    //~^ ERROR assign of possibly-uninitialized variable: `x.0`
+    (x.0).0 = Some(Test); //~ ERROR E0381
 }
 
 fn main() {
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
index 218c4f2de5bc7..be5de8a0a5a61 100644
--- a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
@@ -1,8 +1,10 @@
-error[E0381]: assign of possibly-uninitialized variable: `x.0`
+error[E0381]: binding `x.0` isn't initialized
   --> $DIR/borrowck-partial-reinit-4.rs:17:5
    |
+LL |     let mut x : (Test2, Test2);
+   |         ----- variable declared here
 LL |     (x.0).0 = Some(Test);
-   |     ^^^^^^^ use of possibly-uninitialized `x.0`
+   |     ^^^^^^^ `x.0` assigned here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-return.rs b/src/test/ui/borrowck/borrowck-return.rs
index 8c623356f6c6b..a63ffcff732ee 100644
--- a/src/test/ui/borrowck/borrowck-return.rs
+++ b/src/test/ui/borrowck/borrowck-return.rs
@@ -1,6 +1,6 @@
 fn f() -> isize {
     let x: isize;
-    return x; //~ ERROR use of possibly-uninitialized variable: `x`
+    return x; //~ ERROR E0381
 }
 
 fn main() { f(); }
diff --git a/src/test/ui/borrowck/borrowck-return.stderr b/src/test/ui/borrowck/borrowck-return.stderr
index bc74e8e343848..f42ac9fc54159 100644
--- a/src/test/ui/borrowck/borrowck-return.stderr
+++ b/src/test/ui/borrowck/borrowck-return.stderr
@@ -1,8 +1,10 @@
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-return.rs:3:12
    |
+LL |     let x: isize;
+   |         - variable declared here
 LL |     return x;
-   |            ^ use of possibly-uninitialized `x`
+   |            ^ `x` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-storage-dead.stderr b/src/test/ui/borrowck/borrowck-storage-dead.stderr
index 8e4932142f0db..6168961bd16db 100644
--- a/src/test/ui/borrowck/borrowck-storage-dead.stderr
+++ b/src/test/ui/borrowck/borrowck-storage-dead.stderr
@@ -1,8 +1,10 @@
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-storage-dead.rs:16:17
    |
+LL |         let x: i32;
+   |             - variable declared here
 LL |         let _ = x + 1;
-   |                 ^ use of possibly-uninitialized `x`
+   |                 ^ `x` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.rs b/src/test/ui/borrowck/borrowck-uninit-after-item.rs
index e9a389657c8fd..e97ce6aa407ed 100644
--- a/src/test/ui/borrowck/borrowck-uninit-after-item.rs
+++ b/src/test/ui/borrowck/borrowck-uninit-after-item.rs
@@ -1,5 +1,5 @@
 fn main() {
     let bar;
     fn baz(_x: isize) { }
-    baz(bar); //~ ERROR use of possibly-uninitialized variable: `bar`
+    baz(bar); //~ ERROR E0381
 }
diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
index f7f069b81be02..64bccecf68a94 100644
--- a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
@@ -1,8 +1,11 @@
-error[E0381]: use of possibly-uninitialized variable: `bar`
+error[E0381]: binding `bar` isn't initialized
   --> $DIR/borrowck-uninit-after-item.rs:4:9
    |
+LL |     let bar;
+   |         --- variable declared here
+LL |     fn baz(_x: isize) { }
 LL |     baz(bar);
-   |         ^^^ use of possibly-uninitialized `bar`
+   |         ^^^ `bar` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
index 7951a5b1b5d70..0ffa5cee5f167 100644
--- a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
@@ -1,8 +1,10 @@
-error[E0381]: use of possibly-uninitialized variable: `a`
+error[E0381]: binding `a.x` isn't initialized
   --> $DIR/borrowck-uninit-field-access.rs:21:13
    |
+LL |     let mut a: Point;
+   |         ----- variable declared here
 LL |     let _ = a.x + 1;
-   |             ^^^ use of possibly-uninitialized `a.x`
+   |             ^^^ `a.x` used here but it isn't initialized
 
 error[E0382]: use of moved value: `line1.origin`
   --> $DIR/borrowck-uninit-field-access.rs:25:13
diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs b/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs
index 20350d61d5bb6..92c3692bd2f69 100644
--- a/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs
+++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.rs
@@ -3,32 +3,32 @@
 
 pub fn main() {
     let x: isize;
-    x += 1; //~ ERROR use of possibly-uninitialized variable: `x`
+    x += 1; //~ ERROR E0381
 
     let x: isize;
-    x -= 1; //~ ERROR use of possibly-uninitialized variable: `x`
+    x -= 1; //~ ERROR E0381
 
     let x: isize;
-    x *= 1; //~ ERROR use of possibly-uninitialized variable: `x`
+    x *= 1; //~ ERROR E0381
 
     let x: isize;
-    x /= 1; //~ ERROR use of possibly-uninitialized variable: `x`
+    x /= 1; //~ ERROR E0381
 
     let x: isize;
-    x %= 1; //~ ERROR use of possibly-uninitialized variable: `x`
+    x %= 1; //~ ERROR E0381
 
     let x: isize;
-    x ^= 1; //~ ERROR use of possibly-uninitialized variable: `x`
+    x ^= 1; //~ ERROR E0381
 
     let x: isize;
-    x &= 1; //~ ERROR use of possibly-uninitialized variable: `x`
+    x &= 1; //~ ERROR E0381
 
     let x: isize;
-    x |= 1; //~ ERROR use of possibly-uninitialized variable: `x`
+    x |= 1; //~ ERROR E0381
 
     let x: isize;
-    x <<= 1;    //~ ERROR use of possibly-uninitialized variable: `x`
+    x <<= 1; //~ ERROR E0381
 
     let x: isize;
-    x >>= 1;    //~ ERROR use of possibly-uninitialized variable: `x`
+    x >>= 1; //~ ERROR E0381
 }
diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
index f2036df3ce92a..273370a4eef3a 100644
--- a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
@@ -1,62 +1,82 @@
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:6:5
    |
+LL |     let x: isize;
+   |         - variable declared here
 LL |     x += 1;
-   |     ^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:9:5
    |
+LL |     let x: isize;
+   |         - variable declared here
 LL |     x -= 1;
-   |     ^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:12:5
    |
+LL |     let x: isize;
+   |         - variable declared here
 LL |     x *= 1;
-   |     ^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:15:5
    |
+LL |     let x: isize;
+   |         - variable declared here
 LL |     x /= 1;
-   |     ^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:18:5
    |
+LL |     let x: isize;
+   |         - variable declared here
 LL |     x %= 1;
-   |     ^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:21:5
    |
+LL |     let x: isize;
+   |         - variable declared here
 LL |     x ^= 1;
-   |     ^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:24:5
    |
+LL |     let x: isize;
+   |         - variable declared here
 LL |     x &= 1;
-   |     ^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:27:5
    |
+LL |     let x: isize;
+   |         - variable declared here
 LL |     x |= 1;
-   |     ^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:30:5
    |
+LL |     let x: isize;
+   |         - variable declared here
 LL |     x <<= 1;
-   |     ^^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:33:5
    |
+LL |     let x: isize;
+   |         - variable declared here
 LL |     x >>= 1;
-   |     ^^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^^ `x` used here but it isn't initialized
 
 error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs
index 0ccea49f329bb..c36b9707d2287 100644
--- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.rs
@@ -5,29 +5,29 @@ struct S<X, Y> {
 
 fn main() {
     let x: &&Box<i32>;
-    let _y = &**x; //~ [E0381]
+    let _y = &**x; //~ ERROR [E0381]
 
     let x: &&S<i32, i32>;
-    let _y = &**x; //~ [E0381]
+    let _y = &**x; //~ ERROR [E0381]
 
     let x: &&i32;
-    let _y = &**x; //~ [E0381]
+    let _y = &**x; //~ ERROR [E0381]
 
 
     let mut a: S<i32, i32>;
-    a.x = 0;            //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381]
+    a.x = 0; //~ ERROR [E0381]
     let _b = &a.x;
 
     let mut a: S<&&i32, &&i32>;
-    a.x = &&0;          //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381]
+    a.x = &&0; //~ ERROR [E0381]
     let _b = &**a.x;
 
 
     let mut a: S<i32, i32>;
-    a.x = 0;            //~ ERROR assign to part of possibly-uninitialized variable: `a` [E0381]
+    a.x = 0; //~ ERROR [E0381]
     let _b = &a.y;
 
     let mut a: S<&&i32, &&i32>;
-    a.x = &&0;          //~ assign to part of possibly-uninitialized variable: `a` [E0381]
+    a.x = &&0; //~ ERROR [E0381]
     let _b = &**a.y;
 }
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
index d99a50df75b8c..e78f5888df62d 100644
--- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
@@ -1,44 +1,66 @@
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `**x` isn't initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:8:14
    |
+LL |     let x: &&Box<i32>;
+   |         - variable declared here
 LL |     let _y = &**x;
-   |              ^^^^ use of possibly-uninitialized `**x`
+   |              ^^^^ `**x` borrowed here but it isn't initialized
 
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `**x` isn't initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:11:14
    |
+LL |     let x: &&S<i32, i32>;
+   |         - variable declared here
 LL |     let _y = &**x;
-   |              ^^^^ use of possibly-uninitialized `**x`
+   |              ^^^^ `**x` borrowed here but it isn't initialized
 
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `**x` isn't initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:14:14
    |
+LL |     let x: &&i32;
+   |         - variable declared here
 LL |     let _y = &**x;
-   |              ^^^^ use of possibly-uninitialized `**x`
+   |              ^^^^ `**x` borrowed here but it isn't initialized
 
-error[E0381]: assign to part of possibly-uninitialized variable: `a`
+error[E0381]: binding `a` isn't fully initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:18:5
    |
+LL |     let mut a: S<i32, i32>;
+   |         ----- variable declared here
 LL |     a.x = 0;
-   |     ^^^^^^^ use of possibly-uninitialized `a`
+   |     ^^^^^^^ `a` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `a`
+error[E0381]: binding `a` isn't fully initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:22:5
    |
+LL |     let mut a: S<&&i32, &&i32>;
+   |         ----- variable declared here
 LL |     a.x = &&0;
-   |     ^^^^^^^^^ use of possibly-uninitialized `a`
+   |     ^^^^^^^^^ `a` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `a`
+error[E0381]: binding `a` isn't fully initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:27:5
    |
+LL |     let mut a: S<i32, i32>;
+   |         ----- variable declared here
 LL |     a.x = 0;
-   |     ^^^^^^^ use of possibly-uninitialized `a`
+   |     ^^^^^^^ `a` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `a`
+error[E0381]: binding `a` isn't fully initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:31:5
    |
+LL |     let mut a: S<&&i32, &&i32>;
+   |         ----- variable declared here
 LL |     a.x = &&0;
-   |     ^^^^^^^^^ use of possibly-uninitialized `a`
+   |     ^^^^^^^^^ `a` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-uninit.rs b/src/test/ui/borrowck/borrowck-uninit.rs
index 017b955a39535..5d0ebabb00872 100644
--- a/src/test/ui/borrowck/borrowck-uninit.rs
+++ b/src/test/ui/borrowck/borrowck-uninit.rs
@@ -2,5 +2,5 @@ fn foo(x: isize) { println!("{}", x); }
 
 fn main() {
     let x: isize;
-    foo(x); //~ ERROR use of possibly-uninitialized variable: `x`
+    foo(x); //~ ERROR E0381
 }
diff --git a/src/test/ui/borrowck/borrowck-uninit.stderr b/src/test/ui/borrowck/borrowck-uninit.stderr
index effc209e81659..c5ee9cfd29747 100644
--- a/src/test/ui/borrowck/borrowck-uninit.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit.stderr
@@ -1,8 +1,10 @@
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-uninit.rs:5:9
    |
+LL |     let x: isize;
+   |         - variable declared here
 LL |     foo(x);
-   |         ^ use of possibly-uninitialized `x`
+   |         ^ `x` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.rs b/src/test/ui/borrowck/borrowck-union-uninitialized.rs
index 3cc71e7cece0e..bbe9f22aac307 100644
--- a/src/test/ui/borrowck/borrowck-union-uninitialized.rs
+++ b/src/test/ui/borrowck/borrowck-union-uninitialized.rs
@@ -10,8 +10,8 @@ fn main() {
     unsafe {
         let mut s: S;
         let mut u: U;
-        s.a = 0; //~ ERROR assign to part of possibly-uninitialized variable: `s`
-        u.a = 0; //~ ERROR assign to part of possibly-uninitialized variable: `u`
+        s.a = 0; //~ ERROR E0381
+        u.a = 0; //~ ERROR E0381
         let sa = s.a;
         let ua = u.a;
     }
diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.stderr b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr
index bd9ec5e579ca9..eee04f790337e 100644
--- a/src/test/ui/borrowck/borrowck-union-uninitialized.stderr
+++ b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr
@@ -1,14 +1,24 @@
-error[E0381]: assign to part of possibly-uninitialized variable: `s`
+error[E0381]: binding `s` isn't fully initialized
   --> $DIR/borrowck-union-uninitialized.rs:13:9
    |
+LL |         let mut s: S;
+   |             ----- variable declared here
+LL |         let mut u: U;
 LL |         s.a = 0;
-   |         ^^^^^^^ use of possibly-uninitialized `s`
+   |         ^^^^^^^ `s` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `u`
+error[E0381]: binding `u` isn't fully initialized
   --> $DIR/borrowck-union-uninitialized.rs:14:9
    |
+LL |         let mut u: U;
+   |             ----- variable declared here
+LL |         s.a = 0;
 LL |         u.a = 0;
-   |         ^^^^^^^ use of possibly-uninitialized `u`
+   |         ^^^^^^^ `u` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
index d1b396aba8257..f7975c8ac920f 100644
--- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
+++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
@@ -1,14 +1,18 @@
-error[E0381]: use of possibly-uninitialized variable: `w`
+error[E0381]: binding `*w` isn't initialized
   --> $DIR/borrowck-use-in-index-lvalue.rs:3:5
    |
+LL |     let w: &mut [isize];
+   |         - variable declared here
 LL |     w[5] = 0;
-   |     ^^^^ use of possibly-uninitialized `*w`
+   |     ^^^^ `*w` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `w`
+error[E0381]: binding `*w` isn't initialized
   --> $DIR/borrowck-use-in-index-lvalue.rs:6:5
    |
+LL |     let mut w: &mut [isize];
+   |         ----- variable declared here
 LL |     w[5] = 0;
-   |     ^^^^ use of possibly-uninitialized `*w`
+   |     ^^^^ `*w` used here but it isn't initialized
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
index ca5227c98c862..3d024b531ef7c 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
@@ -1,8 +1,10 @@
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `*x` isn't initialized
   --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:9:13
    |
+LL |     let x: &i32;
+   |         - variable declared here
 LL |     let y = x as *const dyn Foo;
-   |             ^ use of possibly-uninitialized `*x`
+   |             ^ `*x` borrowed here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
index 24897a0f2dc9c..20a5dcaade7e2 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
@@ -1,8 +1,10 @@
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `*x` isn't initialized
   --> $DIR/borrowck-use-uninitialized-in-cast.rs:7:13
    |
+LL |     let x: &i32;
+   |         - variable declared here
 LL |     let y = x as *const i32;
-   |             ^ use of possibly-uninitialized `*x`
+   |             ^ `*x` borrowed here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-while-break.rs b/src/test/ui/borrowck/borrowck-while-break.rs
index 48e4221470221..7100b713031d2 100644
--- a/src/test/ui/borrowck/borrowck-while-break.rs
+++ b/src/test/ui/borrowck/borrowck-while-break.rs
@@ -4,7 +4,7 @@ fn test(cond: bool) {
         v = 3;
         break;
     }
-    println!("{}", v); //~ ERROR borrow of possibly-uninitialized variable: `v`
+    println!("{}", v); //~ ERROR E0381
 }
 
 fn main() {
diff --git a/src/test/ui/borrowck/borrowck-while-break.stderr b/src/test/ui/borrowck/borrowck-while-break.stderr
index fc144a066bb27..501f0c6515177 100644
--- a/src/test/ui/borrowck/borrowck-while-break.stderr
+++ b/src/test/ui/borrowck/borrowck-while-break.stderr
@@ -1,8 +1,13 @@
-error[E0381]: borrow of possibly-uninitialized variable: `v`
+error[E0381]: binding `v` isn't initialized in all conditions
   --> $DIR/borrowck-while-break.rs:7:20
    |
+LL |     let v;
+   |         - variable declared here
+LL |     while cond {
+   |           ---- `v` is uninitialized if this condition isn't met
+...
 LL |     println!("{}", v);
-   |                    ^ use of possibly-uninitialized `v`
+   |                    ^ `v` borrowed here but it isn't initialized in all conditions
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/borrowck-while-cond.rs b/src/test/ui/borrowck/borrowck-while-cond.rs
index b3ec20711c12b..62a9bdd202055 100644
--- a/src/test/ui/borrowck/borrowck-while-cond.rs
+++ b/src/test/ui/borrowck/borrowck-while-cond.rs
@@ -1,4 +1,4 @@
 fn main() {
     let x: bool;
-    while x { } //~ ERROR use of possibly-uninitialized variable: `x`
+    while x { } //~ ERROR E0381
 }
diff --git a/src/test/ui/borrowck/borrowck-while-cond.stderr b/src/test/ui/borrowck/borrowck-while-cond.stderr
index 92937a9c5730e..87d505b5fbbcd 100644
--- a/src/test/ui/borrowck/borrowck-while-cond.stderr
+++ b/src/test/ui/borrowck/borrowck-while-cond.stderr
@@ -1,8 +1,10 @@
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/borrowck-while-cond.rs:3:11
    |
+LL |     let x: bool;
+   |         - variable declared here
 LL |     while x { }
-   |           ^ use of possibly-uninitialized `x`
+   |           ^ `x` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-while.rs b/src/test/ui/borrowck/borrowck-while.rs
index 6b3220c7d8591..f49a778eb6bbe 100644
--- a/src/test/ui/borrowck/borrowck-while.rs
+++ b/src/test/ui/borrowck/borrowck-while.rs
@@ -1,7 +1,7 @@
 fn f() -> isize {
     let mut x: isize;
     while 1 == 1 { x = 10; }
-    return x; //~ ERROR use of possibly-uninitialized variable: `x`
+    return x; //~ ERROR E0381
 }
 
 fn main() { f(); }
diff --git a/src/test/ui/borrowck/borrowck-while.stderr b/src/test/ui/borrowck/borrowck-while.stderr
index a1f8f64725dcd..36dda8ee13f77 100644
--- a/src/test/ui/borrowck/borrowck-while.stderr
+++ b/src/test/ui/borrowck/borrowck-while.stderr
@@ -1,8 +1,12 @@
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized in all conditions
   --> $DIR/borrowck-while.rs:4:12
    |
+LL |     let mut x: isize;
+   |         ----- variable declared here
+LL |     while 1 == 1 { x = 10; }
+   |           ------ `x` is uninitialized if this condition isn't met
 LL |     return x;
-   |            ^ use of possibly-uninitialized `x`
+   |            ^ `x` used here but it isn't initialized in all conditions
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.rs b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs
index 7043cb3a164e7..17de40d5ba967 100644
--- a/src/test/ui/borrowck/disallow-possibly-uninitialized.rs
+++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.rs
@@ -4,19 +4,19 @@
 fn main() {
     let mut t: (u64, u64);
     t.0 = 1;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+    //~^ ERROR E0381
     t.1 = 1;
 
     let mut t: (u64, u64);
     t.1 = 1;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+    //~^ ERROR E0381
     t.0 = 1;
 
     let mut t: (u64, u64);
     t.0 = 1;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+    //~^ ERROR E0381
 
     let mut t: (u64,);
     t.0 = 1;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+    //~^ ERROR E0381
 }
diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr
index 8d5b39341c109..f6a0e3dbae053 100644
--- a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr
+++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr
@@ -1,26 +1,42 @@
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
+error[E0381]: binding `t` isn't fully initialized
   --> $DIR/disallow-possibly-uninitialized.rs:6:5
    |
+LL |     let mut t: (u64, u64);
+   |         ----- variable declared here
 LL |     t.0 = 1;
-   |     ^^^^^^^ use of possibly-uninitialized `t`
+   |     ^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
+error[E0381]: binding `t` isn't fully initialized
   --> $DIR/disallow-possibly-uninitialized.rs:11:5
    |
+LL |     let mut t: (u64, u64);
+   |         ----- variable declared here
 LL |     t.1 = 1;
-   |     ^^^^^^^ use of possibly-uninitialized `t`
+   |     ^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
+error[E0381]: binding `t` isn't fully initialized
   --> $DIR/disallow-possibly-uninitialized.rs:16:5
    |
+LL |     let mut t: (u64, u64);
+   |         ----- variable declared here
 LL |     t.0 = 1;
-   |     ^^^^^^^ use of possibly-uninitialized `t`
+   |     ^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
+error[E0381]: binding `t` isn't fully initialized
   --> $DIR/disallow-possibly-uninitialized.rs:20:5
    |
+LL |     let mut t: (u64,);
+   |         ----- variable declared here
 LL |     t.0 = 1;
-   |     ^^^^^^^ use of possibly-uninitialized `t`
+   |     ^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/borrowck/issue-24267-flow-exit.rs b/src/test/ui/borrowck/issue-24267-flow-exit.rs
index d6809ee4143b0..c419c5840d9a8 100644
--- a/src/test/ui/borrowck/issue-24267-flow-exit.rs
+++ b/src/test/ui/borrowck/issue-24267-flow-exit.rs
@@ -9,11 +9,11 @@ pub fn main() {
 pub fn foo1() {
     let x: i32;
     loop { x = break; }
-    println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x`
+    println!("{}", x); //~ ERROR E0381
 }
 
 pub fn foo2() {
     let x: i32;
     for _ in 0..10 { x = continue; }
-    println!("{}", x); //~ ERROR borrow of possibly-uninitialized variable: `x`
+    println!("{}", x); //~ ERROR E0381
 }
diff --git a/src/test/ui/borrowck/issue-24267-flow-exit.stderr b/src/test/ui/borrowck/issue-24267-flow-exit.stderr
index e29cf7a1a7519..25f7df4f58243 100644
--- a/src/test/ui/borrowck/issue-24267-flow-exit.stderr
+++ b/src/test/ui/borrowck/issue-24267-flow-exit.stderr
@@ -1,16 +1,22 @@
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/issue-24267-flow-exit.rs:12:20
    |
+LL |     let x: i32;
+   |         - variable declared here
+LL |     loop { x = break; }
 LL |     println!("{}", x);
-   |                    ^ use of possibly-uninitialized `x`
+   |                    ^ `x` borrowed here but it isn't initialized
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/issue-24267-flow-exit.rs:18:20
    |
+LL |     let x: i32;
+   |         - variable declared here
+LL |     for _ in 0..10 { x = continue; }
 LL |     println!("{}", x);
-   |                    ^ use of possibly-uninitialized `x`
+   |                    ^ `x` borrowed here but it isn't initialized
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs
index f031a144443b3..205ea10c90bf0 100644
--- a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs
@@ -10,7 +10,7 @@ fn main() {
     {
         let mut t: Tuple;
         t.0 = S(1);
-        //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+        //~^ ERROR E0381
         t.1 = 2;
         println!("{:?} {:?}", t.0, t.1);
     }
@@ -18,7 +18,7 @@ fn main() {
     {
         let mut u: Tpair;
         u.0 = S(1);
-        //~^ ERROR assign to part of possibly-uninitialized variable: `u` [E0381]
+        //~^ ERROR E0381
         u.1 = 2;
         println!("{:?} {:?}", u.0, u.1);
     }
@@ -26,7 +26,7 @@ fn main() {
     {
         let mut v: Spair;
         v.x = S(1);
-        //~^ ERROR assign to part of possibly-uninitialized variable: `v` [E0381]
+        //~^ ERROR E0381
         v.y = 2;
         println!("{:?} {:?}", v.x, v.y);
     }
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr
index 22c6c3964edc1..99c25ad5446a2 100644
--- a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr
@@ -1,20 +1,32 @@
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
+error[E0381]: binding `t` isn't fully initialized
   --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:12:9
    |
+LL |         let mut t: Tuple;
+   |             ----- variable declared here
 LL |         t.0 = S(1);
-   |         ^^^^^^^^^^ use of possibly-uninitialized `t`
+   |         ^^^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `u`
+error[E0381]: binding `u` isn't fully initialized
   --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:20:9
    |
+LL |         let mut u: Tpair;
+   |             ----- variable declared here
 LL |         u.0 = S(1);
-   |         ^^^^^^^^^^ use of possibly-uninitialized `u`
+   |         ^^^^^^^^^^ `u` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `v`
+error[E0381]: binding `v` isn't fully initialized
   --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:28:9
    |
+LL |         let mut v: Spair;
+   |             ----- variable declared here
 LL |         v.x = S(1);
-   |         ^^^^^^^^^^ use of possibly-uninitialized `v`
+   |         ^^^^^^^^^^ `v` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs
index 660d9e85ef54e..50d0c40fdf6f5 100644
--- a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.rs
@@ -10,7 +10,7 @@ fn main() {
     {
         let t: Tuple;
         t.0 = S(1);
-        //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+        //~^ ERROR E0381
         t.1 = 2;
         println!("{:?} {:?}", t.0, t.1);
     }
@@ -18,7 +18,7 @@ fn main() {
     {
         let u: Tpair;
         u.0 = S(1);
-        //~^ ERROR assign to part of possibly-uninitialized variable: `u` [E0381]
+        //~^ ERROR E0381
         u.1 = 2;
         println!("{:?} {:?}", u.0, u.1);
     }
@@ -26,7 +26,7 @@ fn main() {
     {
         let v: Spair;
         v.x = S(1);
-        //~^ ERROR assign to part of possibly-uninitialized variable: `v` [E0381]
+        //~^ ERROR E0381
         v.y = 2;
         println!("{:?} {:?}", v.x, v.y);
     }
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr
index 5f9c978c342f6..1c78524a1b1a8 100644
--- a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr
@@ -1,20 +1,32 @@
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
+error[E0381]: binding `t` isn't fully initialized
   --> $DIR/issue-54499-field-mutation-of-never-init.rs:12:9
    |
+LL |         let t: Tuple;
+   |             - variable declared here
 LL |         t.0 = S(1);
-   |         ^^^^^^^^^^ use of possibly-uninitialized `t`
+   |         ^^^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `u`
+error[E0381]: binding `u` isn't fully initialized
   --> $DIR/issue-54499-field-mutation-of-never-init.rs:20:9
    |
+LL |         let u: Tpair;
+   |             - variable declared here
 LL |         u.0 = S(1);
-   |         ^^^^^^^^^^ use of possibly-uninitialized `u`
+   |         ^^^^^^^^^^ `u` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `v`
+error[E0381]: binding `v` isn't fully initialized
   --> $DIR/issue-54499-field-mutation-of-never-init.rs:28:9
    |
+LL |         let v: Spair;
+   |             - variable declared here
 LL |         v.x = S(1);
-   |         ^^^^^^^^^^ use of possibly-uninitialized `v`
+   |         ^^^^^^^^^^ `v` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs b/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs
index f8efa8c891eb3..93ce34d2fe535 100644
--- a/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs
+++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.rs
@@ -1,7 +1,7 @@
 fn main() {
     let e: i32;
     match e {
-        //~^ ERROR use of possibly-uninitialized variable
+        //~^ ERROR E0381
         ref u if true => {}
         ref v if true => {
             let tx = 0;
diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr
index 0eca447b55159..f809b7d4c3b0c 100644
--- a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr
+++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr
@@ -1,8 +1,10 @@
-error[E0381]: use of possibly-uninitialized variable: `e`
+error[E0381]: binding `e` isn't initialized
   --> $DIR/issue-62107-match-arm-scopes.rs:3:11
    |
+LL |     let e: i32;
+   |         - variable declared here
 LL |     match e {
-   |           ^ use of possibly-uninitialized `e`
+   |           ^ `e` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields.stderr b/src/test/ui/borrowck/reassignment_immutable_fields.stderr
index f09db378a75b4..045f95632d83e 100644
--- a/src/test/ui/borrowck/reassignment_immutable_fields.stderr
+++ b/src/test/ui/borrowck/reassignment_immutable_fields.stderr
@@ -1,14 +1,22 @@
-error[E0381]: assign to part of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't fully initialized
   --> $DIR/reassignment_immutable_fields.rs:7:5
    |
+LL |     let x: (u32, u32);
+   |         - variable declared here
 LL |     x.0 = 1;
-   |     ^^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't fully initialized
   --> $DIR/reassignment_immutable_fields.rs:15:5
    |
+LL |     let x: (u32, u32);
+   |         - variable declared here
 LL |     x.0 = 1;
-   |     ^^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr
index 0eae2c71e4a19..d848679272375 100644
--- a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr
+++ b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr
@@ -1,8 +1,12 @@
-error[E0381]: assign to part of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't fully initialized
   --> $DIR/reassignment_immutable_fields_overlapping.rs:12:5
    |
+LL |     let x: Foo;
+   |         - variable declared here
 LL |     x.a = 1;
-   |     ^^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error[E0594]: cannot assign to `x.b`, as `x` is not declared as mutable
   --> $DIR/reassignment_immutable_fields_overlapping.rs:13:5
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr
index f55e1a27f475e..db69f0b0db704 100644
--- a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr
+++ b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr
@@ -7,11 +7,15 @@ LL |     x = (22, 44);
 LL |     x.0 = 1;
    |     ^^^^^^^ cannot assign
 
-error[E0381]: assign to part of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't fully initialized
   --> $DIR/reassignment_immutable_fields_twice.rs:12:5
    |
+LL |     let x: (u32, u32);
+   |         - variable declared here
 LL |     x.0 = 1;
-   |     ^^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs
index 0f288ffa95a87..69cf920de9478 100644
--- a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs
+++ b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs
@@ -6,14 +6,14 @@
 fn test1() {
     let x: !;
     let c1 = || match x { };
-    //~^ ERROR: use of possibly-uninitialized variable: `x`
+    //~^ ERROR E0381
 }
 
 // Should fake read the discriminant and throw an error
 fn test2() {
     let x: !;
     let c2 = || match x { _ => () };
-    //~^ ERROR: borrow of possibly-uninitialized variable: `x`
+    //~^ ERROR E0381
 }
 
 // Testing single variant patterns
@@ -25,7 +25,7 @@ enum SingleVariant {
 fn test3() {
     let variant: !;
     let c = || {
-    //~^ ERROR: borrow of possibly-uninitialized variable: `variant`
+    //~^ ERROR E0381
         match variant {
             SingleVariant::Points(_) => {}
         }
@@ -36,8 +36,7 @@ fn test3() {
 // Should fake read the discriminant and throw an error
 fn test4() {
     let variant: !;
-    let c = || {
-    //~^ ERROR: borrow of possibly-uninitialized variable: `variant`
+    let c = || { //~ ERROR E0381
         match variant {
             SingleVariant::Points(a) => {
                 println!("{:?}", a);
@@ -52,11 +51,9 @@ fn test5() {
     let g: !;
 
     let a = || {
-        match g { };
-        //~^ ERROR: use of possibly-uninitialized variable: `g`
+        match g { }; //~ ERROR E0381
         let c = ||  {
-            match t { };
-            //~^ ERROR: use of possibly-uninitialized variable: `t`
+            match t { }; //~ ERROR E0381
         };
 
         c();
@@ -68,7 +65,7 @@ fn test5() {
 fn test6() {
     let x: u8;
     let c1 = || match x { };
-    //~^ ERROR: use of possibly-uninitialized variable: `x`
+    //~^ ERROR E0381
     //~| ERROR: non-exhaustive patterns: type `u8` is non-empty
 }
 
diff --git a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
index e55fb7ce4bbe9..c891fff228a27 100644
--- a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/pattern-matching-should-fail.rs:70:23
+  --> $DIR/pattern-matching-should-fail.rs:67:23
    |
 LL |     let c1 = || match x { };
    |                       ^
@@ -12,55 +12,70 @@ LL +         _ => todo!(),
 LL ~     };
    |
 
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/pattern-matching-should-fail.rs:8:23
    |
+LL |     let x: !;
+   |         - variable declared here
 LL |     let c1 = || match x { };
-   |                       ^ use of possibly-uninitialized `x`
+   |                       ^ `x` used here but it isn't initialized
 
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/pattern-matching-should-fail.rs:15:14
    |
+LL |     let x: !;
+   |         - variable declared here
 LL |     let c2 = || match x { _ => () };
    |              ^^       - borrow occurs due to use in closure
    |              |
-   |              use of possibly-uninitialized `x`
+   |              `x` borrowed here but it isn't initialized
 
-error[E0381]: borrow of possibly-uninitialized variable: `variant`
+error[E0381]: binding `variant` isn't initialized
   --> $DIR/pattern-matching-should-fail.rs:27:13
    |
+LL |     let variant: !;
+   |         ------- variable declared here
 LL |     let c = || {
-   |             ^^ use of possibly-uninitialized `variant`
+   |             ^^ `variant` borrowed here but it isn't initialized
 LL |
 LL |         match variant {
    |               ------- borrow occurs due to use in closure
 
-error[E0381]: borrow of possibly-uninitialized variable: `variant`
+error[E0381]: binding `variant` isn't initialized
   --> $DIR/pattern-matching-should-fail.rs:39:13
    |
+LL |     let variant: !;
+   |         ------- variable declared here
 LL |     let c = || {
-   |             ^^ use of possibly-uninitialized `variant`
-LL |
+   |             ^^ `variant` borrowed here but it isn't initialized
 LL |         match variant {
    |               ------- borrow occurs due to use in closure
 
-error[E0381]: use of possibly-uninitialized variable: `g`
-  --> $DIR/pattern-matching-should-fail.rs:55:15
+error[E0381]: binding `g` isn't initialized
+  --> $DIR/pattern-matching-should-fail.rs:54:15
    |
+LL |     let g: !;
+   |         - variable declared here
+...
 LL |         match g { };
-   |               ^ use of possibly-uninitialized `g`
+   |               ^ `g` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `t`
-  --> $DIR/pattern-matching-should-fail.rs:58:19
+error[E0381]: binding `t` isn't initialized
+  --> $DIR/pattern-matching-should-fail.rs:56:19
    |
+LL |     let t: !;
+   |         - variable declared here
+...
 LL |             match t { };
-   |                   ^ use of possibly-uninitialized `t`
+   |                   ^ `t` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `x`
-  --> $DIR/pattern-matching-should-fail.rs:70:23
+error[E0381]: binding `x` isn't initialized
+  --> $DIR/pattern-matching-should-fail.rs:67:23
    |
+LL |     let x: u8;
+   |         - variable declared here
 LL |     let c1 = || match x { };
-   |                       ^ use of possibly-uninitialized `x`
+   |                       ^ `x` used here but it isn't initialized
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/const-generics/const-generic-default-wont-borrowck.rs b/src/test/ui/const-generics/const-generic-default-wont-borrowck.rs
index bb5a2f1766f1b..e64adacac9fd2 100644
--- a/src/test/ui/const-generics/const-generic-default-wont-borrowck.rs
+++ b/src/test/ui/const-generics/const-generic-default-wont-borrowck.rs
@@ -1,6 +1,5 @@
 struct X<const N: usize = {
-    let s: &'static str; s.len()
-    //~^ ERROR borrow of possibly-uninitialized variable
+    let s: &'static str; s.len() //~ ERROR E0381
 }>;
 
 fn main() {}
diff --git a/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr
index 6c25019b0ceb3..0638a9c61c17e 100644
--- a/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr
+++ b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr
@@ -1,8 +1,10 @@
-error[E0381]: borrow of possibly-uninitialized variable: `s`
+error[E0381]: binding `*s` isn't initialized
   --> $DIR/const-generic-default-wont-borrowck.rs:2:26
    |
 LL |     let s: &'static str; s.len()
-   |                          ^^^^^^^ use of possibly-uninitialized `*s`
+   |         -                ^^^^^^^ `*s` borrowed here but it isn't initialized
+   |         |
+   |         variable declared here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/issue-78655.rs b/src/test/ui/consts/issue-78655.rs
index b85e612992549..82d2d7c21d859 100644
--- a/src/test/ui/consts/issue-78655.rs
+++ b/src/test/ui/consts/issue-78655.rs
@@ -1,6 +1,6 @@
 const FOO: *const u32 = {
     let x;
-    &x //~ ERROR borrow of possibly-uninitialized variable: `x`
+    &x //~ ERROR E0381
 };
 
 fn main() {
diff --git a/src/test/ui/consts/issue-78655.stderr b/src/test/ui/consts/issue-78655.stderr
index 734266a3453b5..1c1a30d405d70 100644
--- a/src/test/ui/consts/issue-78655.stderr
+++ b/src/test/ui/consts/issue-78655.stderr
@@ -1,8 +1,10 @@
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/issue-78655.rs:3:5
    |
+LL |     let x;
+   |         - variable declared here
 LL |     &x
-   |     ^^ use of possibly-uninitialized `x`
+   |     ^^ `x` borrowed here but it isn't initialized
 
 error: could not evaluate constant pattern
   --> $DIR/issue-78655.rs:7:9
diff --git a/src/test/ui/drop/repeat-drop-2.rs b/src/test/ui/drop/repeat-drop-2.rs
index 2e7855328ecbf..59d5ef202051a 100644
--- a/src/test/ui/drop/repeat-drop-2.rs
+++ b/src/test/ui/drop/repeat-drop-2.rs
@@ -9,7 +9,7 @@ const _: [String; 0] = [String::new(); 0];
 
 fn must_be_init() {
     let x: u8;
-    let _ = [x; 0]; //~ ERROR: use of possibly-uninitialized variable: `x`
+    let _ = [x; 0]; //~ ERROR E0381
 }
 
 fn main() {}
diff --git a/src/test/ui/drop/repeat-drop-2.stderr b/src/test/ui/drop/repeat-drop-2.stderr
index cdc58180c37b4..845b6de798fa7 100644
--- a/src/test/ui/drop/repeat-drop-2.stderr
+++ b/src/test/ui/drop/repeat-drop-2.stderr
@@ -17,11 +17,13 @@ LL | const _: [String; 0] = [String::new(); 0];
    |                        |constants cannot evaluate destructors
    |                        value is dropped here
 
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/repeat-drop-2.rs:12:14
    |
+LL |     let x: u8;
+   |         - variable declared here
 LL |     let _ = [x; 0];
-   |              ^ use of possibly-uninitialized `x`
+   |              ^ `x` used here but it isn't initialized
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/generator/partial-initialization-across-yield.rs b/src/test/ui/generator/partial-initialization-across-yield.rs
index 8b75721420351..65d9e6d39ca5a 100644
--- a/src/test/ui/generator/partial-initialization-across-yield.rs
+++ b/src/test/ui/generator/partial-initialization-across-yield.rs
@@ -9,8 +9,7 @@ struct T(i32, i32);
 fn test_tuple() {
     let _ = || {
         let mut t: (i32, i32);
-        t.0 = 42;
-        //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+        t.0 = 42; //~ ERROR E0381
         yield;
         t.1 = 88;
         let _ = t;
@@ -20,8 +19,7 @@ fn test_tuple() {
 fn test_tuple_struct() {
     let _ = || {
         let mut t: T;
-        t.0 = 42;
-        //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+        t.0 = 42; //~ ERROR E0381
         yield;
         t.1 = 88;
         let _ = t;
@@ -31,8 +29,7 @@ fn test_tuple_struct() {
 fn test_struct() {
     let _ = || {
         let mut t: S;
-        t.x = 42;
-        //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+        t.x = 42; //~ ERROR E0381
         yield;
         t.y = 88;
         let _ = t;
diff --git a/src/test/ui/generator/partial-initialization-across-yield.stderr b/src/test/ui/generator/partial-initialization-across-yield.stderr
index 66b86488eaec7..26f45538023bb 100644
--- a/src/test/ui/generator/partial-initialization-across-yield.stderr
+++ b/src/test/ui/generator/partial-initialization-across-yield.stderr
@@ -1,20 +1,32 @@
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
+error[E0381]: binding `t` isn't fully initialized
   --> $DIR/partial-initialization-across-yield.rs:12:9
    |
+LL |         let mut t: (i32, i32);
+   |             ----- variable declared here
 LL |         t.0 = 42;
-   |         ^^^^^^^^ use of possibly-uninitialized `t`
+   |         ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
-  --> $DIR/partial-initialization-across-yield.rs:23:9
+error[E0381]: binding `t` isn't fully initialized
+  --> $DIR/partial-initialization-across-yield.rs:22:9
    |
+LL |         let mut t: T;
+   |             ----- variable declared here
 LL |         t.0 = 42;
-   |         ^^^^^^^^ use of possibly-uninitialized `t`
+   |         ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
-  --> $DIR/partial-initialization-across-yield.rs:34:9
+error[E0381]: binding `t` isn't fully initialized
+  --> $DIR/partial-initialization-across-yield.rs:32:9
    |
+LL |         let mut t: S;
+   |             ----- variable declared here
 LL |         t.x = 42;
-   |         ^^^^^^^^ use of possibly-uninitialized `t`
+   |         ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/loops/loop-proper-liveness.rs b/src/test/ui/loops/loop-proper-liveness.rs
index b242ec4296d66..6546e397785ca 100644
--- a/src/test/ui/loops/loop-proper-liveness.rs
+++ b/src/test/ui/loops/loop-proper-liveness.rs
@@ -6,7 +6,7 @@ fn test1() {
     'a: loop {
         x = loop { break 'a };
     }
-    println!("{:?}", x); //~ ERROR borrow of possibly-uninitialized variable
+    println!("{:?}", x); //~ ERROR E0381
 }
 
 // test2 and test3 should not fail.
diff --git a/src/test/ui/loops/loop-proper-liveness.stderr b/src/test/ui/loops/loop-proper-liveness.stderr
index 20d5c66a3f205..dd6949b19f624 100644
--- a/src/test/ui/loops/loop-proper-liveness.stderr
+++ b/src/test/ui/loops/loop-proper-liveness.stderr
@@ -1,8 +1,11 @@
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/loop-proper-liveness.rs:9:22
    |
+LL |     let x: i32;
+   |         - variable declared here
+...
 LL |     println!("{:?}", x);
-   |                      ^ use of possibly-uninitialized `x`
+   |                      ^ `x` borrowed here but it isn't initialized
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs b/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs
index c44dd51a5ec86..fc7341a563bb2 100644
--- a/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs
+++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs
@@ -6,7 +6,7 @@ static A: () = {
     //~^ ERROR destructors cannot be evaluated at compile-time
     a[0] = String::new();
     //~^ ERROR destructors cannot be evaluated at compile-time
-    //~| ERROR use of possibly-uninitialized variable
+    //~| ERROR binding `a` isn't initialized
 };
 
 struct B<T>([T; 1]);
diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr
index 80d5fc7ec672c..ad2e5c9f64373 100644
--- a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr
+++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr
@@ -16,11 +16,14 @@ LL |     let a: [String; 1];
 LL | };
    | - value is dropped here
 
-error[E0381]: use of possibly-uninitialized variable: `a`
+error[E0381]: binding `a` isn't initialized
   --> $DIR/drop-elaboration-after-borrowck-error.rs:7:5
    |
+LL |     let a: [String; 1];
+   |         - variable declared here
+LL |
 LL |     a[0] = String::new();
-   |     ^^^^ use of possibly-uninitialized `a`
+   |     ^^^^ `a` used here but it isn't initialized
 
 error[E0493]: destructors cannot be evaluated at compile-time
   --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9
diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.rs b/src/test/ui/moves/issue-72649-uninit-in-loop.rs
index e6bc4e22ec22c..e796466397b1e 100644
--- a/src/test/ui/moves/issue-72649-uninit-in-loop.rs
+++ b/src/test/ui/moves/issue-72649-uninit-in-loop.rs
@@ -57,17 +57,17 @@ fn moved_loop_2() {
 
 fn uninit_1() {
     loop {
-        let value: NonCopy;
-        let _used = value; //~ ERROR use of possibly-uninitialized variable: `value`
-        //~^ NOTE use of possibly-uninitialized `value`
+        let value: NonCopy; //~ NOTE variable declared here
+        let _used = value; //~ ERROR binding `value` isn't initialized
+        //~^ NOTE `value` used here but it isn't initialized
     }
 }
 
 fn uninit_2() {
-    let mut value: NonCopy;
+    let mut value: NonCopy; //~ NOTE variable declared here
     loop {
-        let _used = value; //~ ERROR use of possibly-uninitialized variable: `value`
-        //~^ NOTE use of possibly-uninitialized `value`
+        let _used = value; //~ ERROR binding `value` isn't initialized
+        //~^ NOTE `value` used here but it isn't initialized
     }
 }
 
diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr
index 076d3dff14086..52dab5cabf817 100644
--- a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr
+++ b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr
@@ -40,17 +40,22 @@ LL |     let mut value = NonCopy{};
 LL |         let _used2 = value;
    |                      ^^^^^ value moved here, in previous iteration of loop
 
-error[E0381]: use of possibly-uninitialized variable: `value`
+error[E0381]: binding `value` isn't initialized
   --> $DIR/issue-72649-uninit-in-loop.rs:61:21
    |
+LL |         let value: NonCopy;
+   |             ----- variable declared here
 LL |         let _used = value;
-   |                     ^^^^^ use of possibly-uninitialized `value`
+   |                     ^^^^^ `value` used here but it isn't initialized
 
-error[E0381]: use of possibly-uninitialized variable: `value`
+error[E0381]: binding `value` isn't initialized
   --> $DIR/issue-72649-uninit-in-loop.rs:69:21
    |
+LL |     let mut value: NonCopy;
+   |         --------- variable declared here
+LL |     loop {
 LL |         let _used = value;
-   |                     ^^^^^ use of possibly-uninitialized `value`
+   |                     ^^^^^ `value` used here but it isn't initialized
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/moves/move-into-dead-array-1.rs b/src/test/ui/moves/move-into-dead-array-1.rs
index 2d0ff58526393..0b8d76def872c 100644
--- a/src/test/ui/moves/move-into-dead-array-1.rs
+++ b/src/test/ui/moves/move-into-dead-array-1.rs
@@ -11,5 +11,5 @@ fn main() {
 
 fn foo(i: usize) {
     let mut a: [D; 4];
-    a[i] = d();        //~ ERROR use of possibly-uninitialized variable: `a`
+    a[i] = d(); //~ ERROR E0381
 }
diff --git a/src/test/ui/moves/move-into-dead-array-1.stderr b/src/test/ui/moves/move-into-dead-array-1.stderr
index 5f20ccfeddf48..b5478196ef668 100644
--- a/src/test/ui/moves/move-into-dead-array-1.stderr
+++ b/src/test/ui/moves/move-into-dead-array-1.stderr
@@ -1,8 +1,10 @@
-error[E0381]: use of possibly-uninitialized variable: `a`
+error[E0381]: binding `a` isn't initialized
   --> $DIR/move-into-dead-array-1.rs:14:5
    |
+LL |     let mut a: [D; 4];
+   |         ----- variable declared here
 LL |     a[i] = d();
-   |     ^^^^ use of possibly-uninitialized `a`
+   |     ^^^^ `a` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/move-of-addr-of-mut.rs b/src/test/ui/moves/move-of-addr-of-mut.rs
index f2f64e43cd2de..19fd7028692d4 100644
--- a/src/test/ui/moves/move-of-addr-of-mut.rs
+++ b/src/test/ui/moves/move-of-addr-of-mut.rs
@@ -5,7 +5,7 @@ struct S;
 
 fn main() {
     let mut x: S;
-    std::ptr::addr_of_mut!(x); //~ borrow of
+    std::ptr::addr_of_mut!(x); //~ ERROR E0381
 
     let y = x; // Should error here if `addr_of_mut` is ever allowed on uninitialized variables
     drop(y);
diff --git a/src/test/ui/moves/move-of-addr-of-mut.stderr b/src/test/ui/moves/move-of-addr-of-mut.stderr
index ce8fb0283165c..a145b6223c187 100644
--- a/src/test/ui/moves/move-of-addr-of-mut.stderr
+++ b/src/test/ui/moves/move-of-addr-of-mut.stderr
@@ -1,8 +1,10 @@
-error[E0381]: borrow of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized
   --> $DIR/move-of-addr-of-mut.rs:8:5
    |
+LL |     let mut x: S;
+   |         ----- variable declared here
 LL |     std::ptr::addr_of_mut!(x);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `x`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ `x` borrowed here but it isn't initialized
    |
    = note: this error originates in the macro `std::ptr::addr_of_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs
index ebea6d3d9d1ea..46a156d2af9ee 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs
+++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs
@@ -25,14 +25,12 @@ impl Drop for D {
 
 fn cannot_partially_init_adt_with_drop() {
     let d: D;
-    d.x = 10;
-    //~^ ERROR assign of possibly-uninitialized variable: `d` [E0381]
+    d.x = 10; //~ ERROR E0381
 }
 
 fn cannot_partially_init_mutable_adt_with_drop() {
     let mut d: D;
-    d.x = 10;
-    //~^ ERROR assign of possibly-uninitialized variable: `d` [E0381]
+    d.x = 10; //~ ERROR E0381
 }
 
 fn cannot_partially_reinit_adt_with_drop() {
@@ -44,14 +42,12 @@ fn cannot_partially_reinit_adt_with_drop() {
 
 fn cannot_partially_init_inner_adt_via_outer_with_drop() {
     let d: D;
-    d.s.y = 20;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `d` [E0381]
+    d.s.y = 20; //~ ERROR E0381
 }
 
 fn cannot_partially_init_inner_adt_via_mutable_outer_with_drop() {
     let mut d: D;
-    d.s.y = 20;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `d` [E0381]
+    d.s.y = 20; //~ ERROR E0381
 }
 
 fn cannot_partially_reinit_inner_adt_via_outer_with_drop() {
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
index 1b66e034d3785..71029065db1cf 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
+++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
@@ -1,17 +1,21 @@
-error[E0381]: assign of possibly-uninitialized variable: `d`
+error[E0381]: binding `d` isn't initialized
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:28:5
    |
+LL |     let d: D;
+   |         - variable declared here
 LL |     d.x = 10;
-   |     ^^^^^^^^ use of possibly-uninitialized `d`
+   |     ^^^^^^^^ `d` assigned here but it isn't initialized
 
-error[E0381]: assign of possibly-uninitialized variable: `d`
-  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:34:5
+error[E0381]: binding `d` isn't initialized
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:33:5
    |
+LL |     let mut d: D;
+   |         ----- variable declared here
 LL |     d.x = 10;
-   |     ^^^^^^^^ use of possibly-uninitialized `d`
+   |     ^^^^^^^^ `d` assigned here but it isn't initialized
 
 error[E0382]: assign of moved value: `d`
-  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:41:5
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:39:5
    |
 LL |     let mut d = D { x: 0, s: S{ y: 0, z: 0 } };
    |         ----- move occurs because `d` has type `D`, which does not implement the `Copy` trait
@@ -20,20 +24,28 @@ LL |     drop(d);
 LL |     d.x = 10;
    |     ^^^^^^^^ value assigned here after move
 
-error[E0381]: assign to part of possibly-uninitialized variable: `d`
-  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:47:5
+error[E0381]: binding `d.s` isn't fully initialized
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:45:5
    |
+LL |     let d: D;
+   |         - variable declared here
 LL |     d.s.y = 20;
-   |     ^^^^^^^^^^ use of possibly-uninitialized `d.s`
+   |     ^^^^^^^^^^ `d.s` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `d`
-  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:53:5
+error[E0381]: binding `d.s` isn't fully initialized
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:50:5
    |
+LL |     let mut d: D;
+   |         ----- variable declared here
 LL |     d.s.y = 20;
-   |     ^^^^^^^^^^ use of possibly-uninitialized `d.s`
+   |     ^^^^^^^^^^ `d.s` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error[E0382]: assign to part of moved value: `d`
-  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:60:5
+  --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:56:5
    |
 LL |     let mut d = D { x: 0, s: S{ y: 0, z: 0} };
    |         ----- move occurs because `d` has type `D`, which does not implement the `Copy` trait
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-use.rs
index 1836f766cc7ef..4cd1e406f9440 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-use.rs
+++ b/src/test/ui/nll/issue-21232-partial-init-and-use.rs
@@ -94,15 +94,13 @@ macro_rules! use_part {
 
 fn test_0000_local_fully_init_and_use_struct() {
     let s: S<B>;
-    s.x = 10; s.y = Box::new(20);
-    //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381]
+    s.x = 10; s.y = Box::new(20); //~ ERROR E0381
     use_fully!(struct s);
 }
 
 fn test_0001_local_fully_init_and_use_tuple() {
     let t: T;
-    t.0 = 10; t.1 = Box::new(20);
-    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+    t.0 = 10; t.1 = Box::new(20); //~ ERROR E0381
     use_fully!(tuple t);
 }
 
@@ -122,15 +120,13 @@ fn test_0011_local_fully_reinit_and_use_tuple() {
 
 fn test_0100_local_partial_init_and_use_struct() {
     let s: S<B>;
-    s.x = 10;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381]
+    s.x = 10; //~ ERROR E0381
     use_part!(struct s);
 }
 
 fn test_0101_local_partial_init_and_use_tuple() {
     let t: T;
-    t.0 = 10;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+    t.0 = 10; //~ ERROR E0381
     use_part!(tuple t);
 }
 
@@ -150,15 +146,13 @@ fn test_0111_local_partial_reinit_and_use_tuple() {
 
 fn test_0200_local_void_init_and_use_struct() {
     let s: S<Void>;
-    s.x = 10;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `s` [E0381]
+    s.x = 10; //~ ERROR E0381
     use_part!(struct s);
 }
 
 fn test_0201_local_void_init_and_use_tuple() {
     let t: Tvoid;
-    t.0 = 10;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `t` [E0381]
+    t.0 = 10; //~ ERROR E0381
     use_part!(tuple t);
 }
 
@@ -173,15 +167,13 @@ fn test_0201_local_void_init_and_use_tuple() {
 
 fn test_1000_field_fully_init_and_use_struct() {
     let q: Q<S<B>>;
-    q.r.f.x = 10; q.r.f.y = Box::new(20);
-    //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
+    q.r.f.x = 10; q.r.f.y = Box::new(20); //~ ERROR E0381
     use_fully!(struct q.r.f);
 }
 
 fn test_1001_field_fully_init_and_use_tuple() {
     let q: Q<T>;
-    q.r.f.0 = 10; q.r.f.1 = Box::new(20);
-    //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
+    q.r.f.0 = 10; q.r.f.1 = Box::new(20); //~ ERROR E0381
     use_fully!(tuple q.r.f);
 }
 
@@ -201,15 +193,13 @@ fn test_1011_field_fully_reinit_and_use_tuple() {
 
 fn test_1100_field_partial_init_and_use_struct() {
     let q: Q<S<B>>;
-    q.r.f.x = 10;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
+    q.r.f.x = 10; //~ ERROR E0381
     use_part!(struct q.r.f);
 }
 
 fn test_1101_field_partial_init_and_use_tuple() {
     let q: Q<T>;
-    q.r.f.0 = 10;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
+    q.r.f.0 = 10; //~ ERROR E0381
     use_part!(tuple q.r.f);
 }
 
@@ -229,15 +219,13 @@ fn test_1111_field_partial_reinit_and_use_tuple() {
 
 fn test_1200_field_void_init_and_use_struct() {
     let mut q: Q<S<Void>>;
-    q.r.f.x = 10;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
+    q.r.f.x = 10; //~ ERROR E0381
     use_part!(struct q.r.f);
 }
 
 fn test_1201_field_void_init_and_use_tuple() {
     let mut q: Q<Tvoid>;
-    q.r.f.0 = 10;
-    //~^ ERROR assign to part of possibly-uninitialized variable: `q` [E0381]
+    q.r.f.0 = 10; //~ ERROR E0381
     use_part!(tuple q.r.f);
 }
 
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
index 77fa484c21d7e..df60868d840c0 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
+++ b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
@@ -1,17 +1,25 @@
-error[E0381]: assign to part of possibly-uninitialized variable: `s`
+error[E0381]: binding `s` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:97:5
    |
+LL |     let s: S<B>;
+   |         - variable declared here
 LL |     s.x = 10; s.y = Box::new(20);
-   |     ^^^^^^^^ use of possibly-uninitialized `s`
+   |     ^^^^^^^^ `s` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
-  --> $DIR/issue-21232-partial-init-and-use.rs:104:5
+error[E0381]: binding `t` isn't fully initialized
+  --> $DIR/issue-21232-partial-init-and-use.rs:103:5
    |
+LL |     let t: T;
+   |         - variable declared here
 LL |     t.0 = 10; t.1 = Box::new(20);
-   |     ^^^^^^^^ use of possibly-uninitialized `t`
+   |     ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error[E0382]: assign to part of moved value: `s`
-  --> $DIR/issue-21232-partial-init-and-use.rs:111:5
+  --> $DIR/issue-21232-partial-init-and-use.rs:109:5
    |
 LL |     let mut s: S<B> = S::new(); drop(s);
    |         -----                        - value moved here
@@ -21,7 +29,7 @@ LL |     s.x = 10; s.y = Box::new(20);
    |     ^^^^^^^^ value partially assigned here after move
 
 error[E0382]: assign to part of moved value: `t`
-  --> $DIR/issue-21232-partial-init-and-use.rs:118:5
+  --> $DIR/issue-21232-partial-init-and-use.rs:116:5
    |
 LL |     let mut t: T = (0, Box::new(0)); drop(t);
    |         -----                             - value moved here
@@ -30,20 +38,28 @@ LL |     let mut t: T = (0, Box::new(0)); drop(t);
 LL |     t.0 = 10; t.1 = Box::new(20);
    |     ^^^^^^^^ value partially assigned here after move
 
-error[E0381]: assign to part of possibly-uninitialized variable: `s`
-  --> $DIR/issue-21232-partial-init-and-use.rs:125:5
+error[E0381]: binding `s` isn't fully initialized
+  --> $DIR/issue-21232-partial-init-and-use.rs:123:5
    |
+LL |     let s: S<B>;
+   |         - variable declared here
 LL |     s.x = 10;
-   |     ^^^^^^^^ use of possibly-uninitialized `s`
+   |     ^^^^^^^^ `s` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
-  --> $DIR/issue-21232-partial-init-and-use.rs:132:5
+error[E0381]: binding `t` isn't fully initialized
+  --> $DIR/issue-21232-partial-init-and-use.rs:129:5
    |
+LL |     let t: T;
+   |         - variable declared here
 LL |     t.0 = 10;
-   |     ^^^^^^^^ use of possibly-uninitialized `t`
+   |     ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error[E0382]: assign to part of moved value: `s`
-  --> $DIR/issue-21232-partial-init-and-use.rs:139:5
+  --> $DIR/issue-21232-partial-init-and-use.rs:135:5
    |
 LL |     let mut s: S<B> = S::new(); drop(s);
    |         -----                        - value moved here
@@ -53,7 +69,7 @@ LL |     s.x = 10;
    |     ^^^^^^^^ value partially assigned here after move
 
 error[E0382]: assign to part of moved value: `t`
-  --> $DIR/issue-21232-partial-init-and-use.rs:146:5
+  --> $DIR/issue-21232-partial-init-and-use.rs:142:5
    |
 LL |     let mut t: T = (0, Box::new(0)); drop(t);
    |         -----                             - value moved here
@@ -62,32 +78,48 @@ LL |     let mut t: T = (0, Box::new(0)); drop(t);
 LL |     t.0 = 10;
    |     ^^^^^^^^ value partially assigned here after move
 
-error[E0381]: assign to part of possibly-uninitialized variable: `s`
-  --> $DIR/issue-21232-partial-init-and-use.rs:153:5
+error[E0381]: binding `s` isn't fully initialized
+  --> $DIR/issue-21232-partial-init-and-use.rs:149:5
    |
+LL |     let s: S<Void>;
+   |         - variable declared here
 LL |     s.x = 10;
-   |     ^^^^^^^^ use of possibly-uninitialized `s`
+   |     ^^^^^^^^ `s` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `t`
-  --> $DIR/issue-21232-partial-init-and-use.rs:160:5
+error[E0381]: binding `t` isn't fully initialized
+  --> $DIR/issue-21232-partial-init-and-use.rs:155:5
    |
+LL |     let t: Tvoid;
+   |         - variable declared here
 LL |     t.0 = 10;
-   |     ^^^^^^^^ use of possibly-uninitialized `t`
+   |     ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `q`
-  --> $DIR/issue-21232-partial-init-and-use.rs:176:5
+error[E0381]: binding `q.r.f` isn't fully initialized
+  --> $DIR/issue-21232-partial-init-and-use.rs:170:5
    |
+LL |     let q: Q<S<B>>;
+   |         - variable declared here
 LL |     q.r.f.x = 10; q.r.f.y = Box::new(20);
-   |     ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f`
+   |     ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `q`
-  --> $DIR/issue-21232-partial-init-and-use.rs:183:5
+error[E0381]: binding `q.r.f` isn't fully initialized
+  --> $DIR/issue-21232-partial-init-and-use.rs:176:5
    |
+LL |     let q: Q<T>;
+   |         - variable declared here
 LL |     q.r.f.0 = 10; q.r.f.1 = Box::new(20);
-   |     ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f`
+   |     ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error[E0382]: assign to part of moved value: `q.r`
-  --> $DIR/issue-21232-partial-init-and-use.rs:190:5
+  --> $DIR/issue-21232-partial-init-and-use.rs:182:5
    |
 LL |     let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
    |                                                 --- value moved here
@@ -97,7 +129,7 @@ LL |     q.r.f.x = 10; q.r.f.y = Box::new(20);
    = note: move occurs because `q.r` has type `R<S<Box<u32>>>`, which does not implement the `Copy` trait
 
 error[E0382]: assign to part of moved value: `q.r`
-  --> $DIR/issue-21232-partial-init-and-use.rs:197:5
+  --> $DIR/issue-21232-partial-init-and-use.rs:189:5
    |
 LL |     let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
    |                                                      --- value moved here
@@ -106,20 +138,28 @@ LL |     q.r.f.0 = 10; q.r.f.1 = Box::new(20);
    |
    = note: move occurs because `q.r` has type `R<(u32, Box<u32>)>`, which does not implement the `Copy` trait
 
-error[E0381]: assign to part of possibly-uninitialized variable: `q`
-  --> $DIR/issue-21232-partial-init-and-use.rs:204:5
+error[E0381]: binding `q.r.f` isn't fully initialized
+  --> $DIR/issue-21232-partial-init-and-use.rs:196:5
    |
+LL |     let q: Q<S<B>>;
+   |         - variable declared here
 LL |     q.r.f.x = 10;
-   |     ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f`
+   |     ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `q`
-  --> $DIR/issue-21232-partial-init-and-use.rs:211:5
+error[E0381]: binding `q.r.f` isn't fully initialized
+  --> $DIR/issue-21232-partial-init-and-use.rs:202:5
    |
+LL |     let q: Q<T>;
+   |         - variable declared here
 LL |     q.r.f.0 = 10;
-   |     ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f`
+   |     ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error[E0382]: assign to part of moved value: `q.r`
-  --> $DIR/issue-21232-partial-init-and-use.rs:218:5
+  --> $DIR/issue-21232-partial-init-and-use.rs:208:5
    |
 LL |     let mut q: Q<S<B>> = Q::new(S::new()); drop(q.r);
    |                                                 --- value moved here
@@ -129,7 +169,7 @@ LL |     q.r.f.x = 10;
    = note: move occurs because `q.r` has type `R<S<Box<u32>>>`, which does not implement the `Copy` trait
 
 error[E0382]: assign to part of moved value: `q.r`
-  --> $DIR/issue-21232-partial-init-and-use.rs:225:5
+  --> $DIR/issue-21232-partial-init-and-use.rs:215:5
    |
 LL |     let mut q: Q<T> = Q::new((0, Box::new(0))); drop(q.r);
    |                                                      --- value moved here
@@ -138,20 +178,28 @@ LL |     q.r.f.0 = 10;
    |
    = note: move occurs because `q.r` has type `R<(u32, Box<u32>)>`, which does not implement the `Copy` trait
 
-error[E0381]: assign to part of possibly-uninitialized variable: `q`
-  --> $DIR/issue-21232-partial-init-and-use.rs:232:5
+error[E0381]: binding `q.r.f` isn't fully initialized
+  --> $DIR/issue-21232-partial-init-and-use.rs:222:5
    |
+LL |     let mut q: Q<S<Void>>;
+   |         ----- variable declared here
 LL |     q.r.f.x = 10;
-   |     ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f`
+   |     ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
-error[E0381]: assign to part of possibly-uninitialized variable: `q`
-  --> $DIR/issue-21232-partial-init-and-use.rs:239:5
+error[E0381]: binding `q.r.f` isn't fully initialized
+  --> $DIR/issue-21232-partial-init-and-use.rs:228:5
    |
+LL |     let mut q: Q<Tvoid>;
+   |         ----- variable declared here
 LL |     q.r.f.0 = 10;
-   |     ^^^^^^^^^^^^ use of possibly-uninitialized `q.r.f`
+   |     ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
 
 error[E0382]: assign to part of moved value: `c`
-  --> $DIR/issue-21232-partial-init-and-use.rs:257:13
+  --> $DIR/issue-21232-partial-init-and-use.rs:245:13
    |
 LL |     let mut c = (1, "".to_owned());
    |         ----- move occurs because `c` has type `(i32, String)`, which does not implement the `Copy` trait
@@ -162,7 +210,7 @@ LL |             c.0 = 2;
    |             ^^^^^^^ value partially assigned here after move
 
 error[E0382]: assign to part of moved value: `c`
-  --> $DIR/issue-21232-partial-init-and-use.rs:267:13
+  --> $DIR/issue-21232-partial-init-and-use.rs:255:13
    |
 LL |     let mut c = (1, (1, "".to_owned()));
    |         ----- move occurs because `c` has type `(i32, (i32, String))`, which does not implement the `Copy` trait
@@ -173,7 +221,7 @@ LL |             (c.1).0 = 2;
    |             ^^^^^^^^^^^ value partially assigned here after move
 
 error[E0382]: assign to part of moved value: `c.1`
-  --> $DIR/issue-21232-partial-init-and-use.rs:275:13
+  --> $DIR/issue-21232-partial-init-and-use.rs:263:13
    |
 LL |         c2 => {
    |         -- value moved here
diff --git a/src/test/ui/nll/match-cfg-fake-edges.rs b/src/test/ui/nll/match-cfg-fake-edges.rs
index 2e6d675fb641e..252f7f8ba07cf 100644
--- a/src/test/ui/nll/match-cfg-fake-edges.rs
+++ b/src/test/ui/nll/match-cfg-fake-edges.rs
@@ -18,7 +18,7 @@ fn guard_may_be_skipped(y: i32) {
     match y {
         _ if { x = 2; true } => 1,
         _ if {
-            x; //~ ERROR use of possibly-uninitialized variable: `x`
+            x; //~ ERROR E0381
             false
         } => 2,
         _ => 3,
diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr
index 4b3817929fd84..43950433e621d 100644
--- a/src/test/ui/nll/match-cfg-fake-edges.stderr
+++ b/src/test/ui/nll/match-cfg-fake-edges.stderr
@@ -1,8 +1,13 @@
-error[E0381]: use of possibly-uninitialized variable: `x`
+error[E0381]: binding `x` isn't initialized in all conditions
   --> $DIR/match-cfg-fake-edges.rs:21:13
    |
+LL |     let x;
+   |         - variable declared here
+...
+LL |         _ if {
+   |         - `x` is uninitialized if this pattern is matched
 LL |             x;
-   |             ^ use of possibly-uninitialized `x`
+   |             ^ `x` used here but it isn't initialized in all conditions
 
 error[E0382]: use of moved value: `x`
   --> $DIR/match-cfg-fake-edges.rs:35:13
diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr
index 2121b59b02da3..0480aaa99c274 100644
--- a/src/test/ui/nll/match-on-borrowed.stderr
+++ b/src/test/ui/nll/match-on-borrowed.stderr
@@ -33,11 +33,13 @@ LL |     match t {
 LL |     x;
    |     - borrow later used here
 
-error[E0381]: use of possibly-uninitialized variable: `n`
+error[E0381]: binding `n` isn't initialized
   --> $DIR/match-on-borrowed.rs:93:11
    |
+LL |     let n: Never;
+   |         - variable declared here
 LL |     match n {}
-   |           ^ use of possibly-uninitialized `n`
+   |           ^ `n` used here but it isn't initialized
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/rfc-2497-if-let-chains/chains-without-let.rs b/src/test/ui/rfc-2497-if-let-chains/chains-without-let.rs
index a7e108d72d1ff..e0dded1521760 100644
--- a/src/test/ui/rfc-2497-if-let-chains/chains-without-let.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/chains-without-let.rs
@@ -1,19 +1,19 @@
 fn and_chain() {
     let z;
     if true && { z = 3; true} && z == 3 {}
-    //~^ ERROR use of possibly-uninitialized
+    //~^ ERROR E0381
 }
 
 fn and_chain_2() {
     let z;
     true && { z = 3; true} && z == 3;
-    //~^ ERROR use of possibly-uninitialized
+    //~^ ERROR E0381
 }
 
 fn or_chain() {
     let z;
     if false || { z = 3; false} || z == 3 {}
-    //~^ ERROR use of possibly-uninitialized
+    //~^ ERROR E0381
 }
 
 fn main() {
diff --git a/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr b/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr
index 3c47040cc8c24..1fb643b98aebe 100644
--- a/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr
@@ -1,20 +1,32 @@
-error[E0381]: use of possibly-uninitialized variable: `z`
+error[E0381]: binding `z` isn't initialized in all conditions
   --> $DIR/chains-without-let.rs:3:34
    |
+LL |     let z;
+   |         - variable declared here
 LL |     if true && { z = 3; true} && z == 3 {}
-   |                                  ^ use of possibly-uninitialized `z`
+   |                  -----           ^ `z` used here but it isn't initialized in all conditions
+   |                  |
+   |                  binding initialized here in some conditions
 
-error[E0381]: use of possibly-uninitialized variable: `z`
+error[E0381]: binding `z` isn't initialized in all conditions
   --> $DIR/chains-without-let.rs:9:31
    |
+LL |     let z;
+   |         - variable declared here
 LL |     true && { z = 3; true} && z == 3;
-   |                               ^ use of possibly-uninitialized `z`
+   |               -----           ^ `z` used here but it isn't initialized in all conditions
+   |               |
+   |               binding initialized here in some conditions
 
-error[E0381]: use of possibly-uninitialized variable: `z`
+error[E0381]: binding `z` isn't initialized in all conditions
   --> $DIR/chains-without-let.rs:15:36
    |
+LL |     let z;
+   |         - variable declared here
 LL |     if false || { z = 3; false} || z == 3 {}
-   |                                    ^ use of possibly-uninitialized `z`
+   |                   -----            ^ `z` used here but it isn't initialized in all conditions
+   |                   |
+   |                   binding initialized here in some conditions
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/try-block/try-block-opt-init.rs b/src/test/ui/try-block/try-block-opt-init.rs
index ef10b47fd1305..f4f45abcc75b1 100644
--- a/src/test/ui/try-block/try-block-opt-init.rs
+++ b/src/test/ui/try-block/try-block-opt-init.rs
@@ -12,5 +12,5 @@ pub fn main() {
         Ok::<(), ()>(())?;
         use_val(cfg_res);
     };
-    assert_eq!(cfg_res, 5); //~ ERROR borrow of possibly-uninitialized variable: `cfg_res`
+    assert_eq!(cfg_res, 5); //~ ERROR E0381
 }
diff --git a/src/test/ui/try-block/try-block-opt-init.stderr b/src/test/ui/try-block/try-block-opt-init.stderr
index bd145fd64e765..17349f9c9f35a 100644
--- a/src/test/ui/try-block/try-block-opt-init.stderr
+++ b/src/test/ui/try-block/try-block-opt-init.stderr
@@ -1,8 +1,14 @@
-error[E0381]: borrow of possibly-uninitialized variable: `cfg_res`
+error[E0381]: binding `cfg_res` isn't initialized in all conditions
   --> $DIR/try-block-opt-init.rs:15:5
    |
+LL |     let cfg_res;
+   |         ------- variable declared here
+...
+LL |         cfg_res = 5;
+   |         ----------- binding initialized here in some conditions
+...
 LL |     assert_eq!(cfg_res, 5);
-   |     ^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `cfg_res`
+   |     ^^^^^^^^^^^^^^^^^^^^^^ `cfg_res` borrowed here but it isn't initialized in all conditions
    |
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/uninhabited/privately-uninhabited-mir-call.rs b/src/test/ui/uninhabited/privately-uninhabited-mir-call.rs
index b37ec2696de2f..2764bb563d307 100644
--- a/src/test/ui/uninhabited/privately-uninhabited-mir-call.rs
+++ b/src/test/ui/uninhabited/privately-uninhabited-mir-call.rs
@@ -25,5 +25,5 @@ fn main() {
     widget::Widget::new();
     // Error. Widget type is not known to be uninhabited here,
     // so the following code is considered reachable.
-    *y = 2; //~ ERROR use of possibly-uninitialized variable
+    *y = 2; //~ ERROR E0381
 }
diff --git a/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr b/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr
index fb1953411685e..61e6295fa3f2c 100644
--- a/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr
+++ b/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr
@@ -1,8 +1,11 @@
-error[E0381]: use of possibly-uninitialized variable: `y`
+error[E0381]: binding `y` isn't initialized
   --> $DIR/privately-uninhabited-mir-call.rs:28:5
    |
+LL |     let y: &mut u32;
+   |         - variable declared here
+...
 LL |     *y = 2;
-   |     ^^^^^^ use of possibly-uninitialized `y`
+   |     ^^^^^^ `y` used here but it isn't initialized
 
 error: aborting due to previous error
 

From a944456d3a787524a2dd0e835f86f278fb2c337d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Tue, 21 Jun 2022 15:54:17 -0700
Subject: [PATCH 06/20] Tweak wording and spans

---
 .../src/diagnostics/conflict_errors.rs        | 82 +++++++++++++------
 compiler/rustc_borrowck/src/lib.rs            | 10 +++
 src/test/ui/asm/x86_64/type-check-5.stderr    |  8 +-
 .../no-non-guaranteed-initialization.stderr   |  6 +-
 ...partial-initialization-across-await.stderr | 18 ++--
 .../ui/borrowck/assign_mutable_fields.stderr  | 12 +--
 src/test/ui/borrowck/borrowck-and-init.stderr |  6 +-
 .../ui/borrowck/borrowck-block-unint.stderr   |  6 +-
 .../borrowck/borrowck-break-uninit-2.stderr   |  6 +-
 .../ui/borrowck/borrowck-break-uninit.stderr  |  6 +-
 .../borrowck-field-sensitivity.stderr         | 18 ++--
 .../ui/borrowck/borrowck-if-no-else.stderr    |  6 +-
 .../ui/borrowck/borrowck-if-with-else.stderr  |  4 +-
 .../borrowck-init-in-called-fn-expr.stderr    |  4 +-
 .../borrowck/borrowck-init-in-fn-expr.stderr  |  4 +-
 .../ui/borrowck/borrowck-init-in-fru.stderr   |  4 +-
 .../ui/borrowck/borrowck-init-op-equal.stderr |  4 +-
 .../borrowck/borrowck-init-plus-equal.stderr  |  4 +-
 src/test/ui/borrowck/borrowck-or-init.stderr  |  6 +-
 .../borrowck/borrowck-partial-reinit-4.stderr |  4 +-
 src/test/ui/borrowck/borrowck-return.stderr   |  4 +-
 .../ui/borrowck/borrowck-storage-dead.stderr  |  4 +-
 .../borrowck-uninit-after-item.stderr         |  4 +-
 .../borrowck-uninit-field-access.stderr       |  4 +-
 .../borrowck-uninit-in-assignop.stderr        | 40 ++++-----
 .../borrowck/borrowck-uninit-ref-chain.stderr | 42 +++++-----
 src/test/ui/borrowck/borrowck-uninit.stderr   |  4 +-
 .../borrowck-union-uninitialized.stderr       | 12 +--
 .../borrowck-use-in-index-lvalue.stderr       |  8 +-
 ...wck-use-uninitialized-in-cast-trait.stderr |  6 +-
 .../borrowck-use-uninitialized-in-cast.stderr |  6 +-
 .../ui/borrowck/borrowck-while-break.stderr   |  8 +-
 .../ui/borrowck/borrowck-while-cond.stderr    |  4 +-
 src/test/ui/borrowck/borrowck-while.stderr    |  6 +-
 .../disallow-possibly-uninitialized.stderr    | 24 +++---
 .../ui/borrowck/issue-24267-flow-exit.stderr  | 12 +--
 ...99-field-mutation-marks-mut-as-used.stderr | 18 ++--
 ...-54499-field-mutation-of-never-init.stderr | 18 ++--
 .../issue-62107-match-arm-scopes.stderr       |  4 +-
 .../reassignment_immutable_fields.stderr      | 12 +--
 ...gnment_immutable_fields_overlapping.stderr |  6 +-
 ...reassignment_immutable_fields_twice.stderr |  6 +-
 .../match/pattern-matching-should-fail.stderr | 34 ++++----
 ...const-generic-default-wont-borrowck.stderr |  6 +-
 src/test/ui/consts/issue-78655.stderr         |  6 +-
 src/test/ui/drop/repeat-drop-2.stderr         |  4 +-
 ...partial-initialization-across-yield.stderr | 18 ++--
 src/test/ui/loops/loop-proper-liveness.stderr |  6 +-
 ...op-elaboration-after-borrowck-error.stderr |  4 +-
 .../ui/moves/issue-72649-uninit-in-loop.rs    |  4 +-
 .../moves/issue-72649-uninit-in-loop.stderr   |  8 +-
 .../ui/moves/move-into-dead-array-1.stderr    |  4 +-
 src/test/ui/moves/move-of-addr-of-mut.stderr  |  6 +-
 ...1232-partial-init-and-erroneous-use.stderr | 20 ++---
 .../issue-21232-partial-init-and-use.stderr   | 72 ++++++++--------
 src/test/ui/nll/match-cfg-fake-edges.stderr   |  6 +-
 src/test/ui/nll/match-on-borrowed.stderr      |  4 +-
 .../chains-without-let.stderr                 | 12 +--
 .../ui/try-block/try-block-opt-init.stderr    |  6 +-
 .../privately-uninhabited-mir-call.stderr     |  4 +-
 60 files changed, 368 insertions(+), 326 deletions(-)

diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 1f7cb972fcec8..daeaac9415def 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -21,6 +21,7 @@ use rustc_middle::ty::{
     self, subst::Subst, suggest_constraining_type_params, EarlyBinder, PredicateKind, Ty,
 };
 use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
+use rustc_span::hygiene::DesugaringKind;
 use rustc_span::symbol::sym;
 use rustc_span::{BytePos, Span};
 use rustc_trait_selection::infer::InferCtxtExt;
@@ -331,7 +332,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             spans.push(span);
         }
 
-        let (item_msg, name, desc) =
+        let (binding, name, desc) =
             match self.describe_place_with_options(used_place, IncludingDowncast(true)) {
                 Some(name) => (format!("`{name}`"), format!("`{name}`"), format!("`{name}` ")),
                 None => ("value".to_string(), "the variable".to_string(), String::new()),
@@ -351,7 +352,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         } else {
             "initialized in all conditions"
         };
-        let mut err = struct_span_err!(self, span, E0381, "binding {desc}isn't {initialized}");
+        let used = desired_action.as_general_verb_in_past_tense();
+        let mut err =
+            struct_span_err!(self, span, E0381, "{used} binding {desc}isn't {initialized}");
         use_spans.var_span_label_path_only(
             &mut err,
             format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()),
@@ -359,12 +362,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         if let InitializationRequiringAction::PartialAssignment = desired_action {
             err.help(
-                "partial initialization isn't supported, fully initialize the binding with \
-                a default value and mutate, or use `std::mem::MaybeUninit`",
+                "partial initialization isn't supported, fully initialize the binding with a \
+                 default value and mutate it, or use `std::mem::MaybeUninit`",
             );
         }
-        let verb = desired_action.as_verb_in_past_tense();
-        err.span_label(span, format!("{item_msg} {verb} here but it isn't {initialized}",));
+        err.span_label(span, format!("{binding} {used} here but it isn't {initialized}"));
 
         // We use the statements were the binding was initialized, and inspect the HIR to look
         // for the branching codepaths that aren't covered, to point at them.
@@ -400,7 +402,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 err.span_label(sp, &label);
             }
         }
-        err.span_label(decl_span, "variable declared here");
+        err.span_label(decl_span, "binding declared here but left uninitialized");
         err
     }
 
@@ -2559,10 +2561,10 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                 v.visit_expr(body);
                 if v.1 {
                     self.errors.push((
-                        cond.span,
+                        ex.span.to(cond.span),
                         format!(
-                            "this `if` expression might be missing an `else` arm where {} is \
-                             initialized",
+                            "this `if` expression might be missing an `else` arm that initializes \
+                             {}",
                             self.name,
                         ),
                     ));
@@ -2578,10 +2580,24 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                 match (a.1, b.1) {
                     (true, true) | (false, false) => {}
                     (true, false) => {
-                        self.errors.push((
-                            cond.span,
-                            format!("{} is uninitialized if this condition isn't met", self.name,),
-                        ));
+                        if other.span.is_desugaring(DesugaringKind::WhileLoop) {
+                            self.errors.push((
+                                cond.span,
+                                format!(
+                                    "{} is uninitialized if this condition isn't met and the \
+                                     `while` loop runs 0 times",
+                                    self.name
+                                ),
+                            ));
+                        } else {
+                            self.errors.push((
+                                body.span.shrink_to_hi().until(other.span),
+                                format!(
+                                    "{} is uninitialized if this `else` arm is executed",
+                                    self.name
+                                ),
+                            ));
+                        }
                     }
                     (false, true) => {
                         self.errors.push((
@@ -2591,7 +2607,7 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                     }
                 }
             }
-            hir::ExprKind::Match(_, arms, _) => {
+            hir::ExprKind::Match(e, arms, loop_desugar) => {
                 // If the binding is initialized in one of the match arms, then the other match
                 // arms might be missing an initialization.
                 let results: Vec<bool> = arms
@@ -2605,13 +2621,32 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                 if results.iter().any(|x| *x) && !results.iter().all(|x| *x) {
                     for (arm, seen) in arms.iter().zip(results) {
                         if !seen {
-                            self.errors.push((
-                                arm.pat.span,
-                                format!(
-                                    "{} is uninitialized if this pattern is matched",
-                                    self.name
-                                ),
-                            ));
+                            if loop_desugar == hir::MatchSource::ForLoopDesugar {
+                                self.errors.push((
+                                    e.span,
+                                    format!(
+                                        "{} is uninitialized if the `for` loop runs 0 times",
+                                        self.name
+                                    ),
+                                ));
+                            } else if let Some(guard) = &arm.guard {
+                                self.errors.push((
+                                    arm.pat.span.to(guard.body().span),
+                                    format!(
+                                        "{} is uninitialized if this pattern and condition are \
+                                         matched",
+                                        self.name
+                                    ),
+                                ));
+                            } else {
+                                self.errors.push((
+                                    arm.pat.span,
+                                    format!(
+                                        "{} is uninitialized if this pattern is matched",
+                                        self.name
+                                    ),
+                                ));
+                            }
                         }
                     }
                 }
@@ -2619,8 +2654,7 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
             // FIXME: should we also account for binops, particularly `&&` and `||`? `try` should
             // also be accounted for. For now it is fine, as if we don't find *any* relevant
             // branching code paths, we point at the places where the binding *is* initialized for
-            // *some* context. We should also specialize the output for `while` and `for` loops,
-            // but for now we can rely on their desugaring to provide appropriate output.
+            // *some* context.
             _ => {}
         }
         walk_expr(self, ex);
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 8ef2974c37232..3e31dc199a084 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -905,6 +905,16 @@ impl InitializationRequiringAction {
             InitializationRequiringAction::PartialAssignment => "partially assigned",
         }
     }
+
+    fn as_general_verb_in_past_tense(self) -> &'static str {
+        match self {
+            InitializationRequiringAction::Borrow
+            | InitializationRequiringAction::MatchOn
+            | InitializationRequiringAction::Use => "used",
+            InitializationRequiringAction::Assignment => "assigned",
+            InitializationRequiringAction::PartialAssignment => "partially assigned",
+        }
+    }
 }
 
 impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
diff --git a/src/test/ui/asm/x86_64/type-check-5.stderr b/src/test/ui/asm/x86_64/type-check-5.stderr
index 26aac4ed2c1e0..e9c93fea561a8 100644
--- a/src/test/ui/asm/x86_64/type-check-5.stderr
+++ b/src/test/ui/asm/x86_64/type-check-5.stderr
@@ -1,16 +1,16 @@
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/type-check-5.rs:15:28
    |
 LL |         let x: u64;
-   |             - variable declared here
+   |             - binding declared here but left uninitialized
 LL |         asm!("{}", in(reg) x);
    |                            ^ `x` used here but it isn't initialized
 
-error[E0381]: binding `y` isn't initialized
+error[E0381]: used binding `y` isn't initialized
   --> $DIR/type-check-5.rs:18:9
    |
 LL |         let mut y: u64;
-   |             ----- variable declared here
+   |             ----- binding declared here but left uninitialized
 LL |         asm!("{}", inout(reg) y);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized
 
diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr
index c6490c7bf4dbf..b23e2da0e0920 100644
--- a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr
+++ b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr
@@ -1,10 +1,10 @@
-error[E0381]: binding `y` isn't initialized in all conditions
+error[E0381]: used binding `y` isn't initialized in all conditions
   --> $DIR/no-non-guaranteed-initialization.rs:9:5
    |
 LL |     let y;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     if x > 5 {
-   |        ----- this `if` expression might be missing an `else` arm where `y` is initialized
+   |        ----- this `if` expression might be missing an `else` arm that initializes `y`
 ...
 LL |     y
    |     ^ `y` used here but it isn't initialized in all conditions
diff --git a/src/test/ui/async-await/partial-initialization-across-await.stderr b/src/test/ui/async-await/partial-initialization-across-await.stderr
index 981e32cadd9de..6a0eeffb94611 100644
--- a/src/test/ui/async-await/partial-initialization-across-await.stderr
+++ b/src/test/ui/async-await/partial-initialization-across-await.stderr
@@ -1,32 +1,32 @@
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/partial-initialization-across-await.rs:13:5
    |
 LL |     let mut t: (i32, i32);
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     t.0 = 42;
    |     ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/partial-initialization-across-await.rs:21:5
    |
 LL |     let mut t: T;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     t.0 = 42;
    |     ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/partial-initialization-across-await.rs:29:5
    |
 LL |     let mut t: S;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     t.x = 42;
    |     ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/assign_mutable_fields.stderr b/src/test/ui/borrowck/assign_mutable_fields.stderr
index 57787b8924998..1ed92865da55b 100644
--- a/src/test/ui/borrowck/assign_mutable_fields.stderr
+++ b/src/test/ui/borrowck/assign_mutable_fields.stderr
@@ -1,22 +1,22 @@
-error[E0381]: binding `x` isn't fully initialized
+error[E0381]: partially assigned binding `x` isn't fully initialized
   --> $DIR/assign_mutable_fields.rs:9:5
    |
 LL |     let mut x: (u32, u32);
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     x.0 = 1;
    |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `x` isn't fully initialized
+error[E0381]: partially assigned binding `x` isn't fully initialized
   --> $DIR/assign_mutable_fields.rs:17:5
    |
 LL |     let mut x: (u32, u32);
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     x.0 = 1;
    |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-and-init.stderr b/src/test/ui/borrowck/borrowck-and-init.stderr
index de57243a5dbf7..a78ac1e593a05 100644
--- a/src/test/ui/borrowck/borrowck-and-init.stderr
+++ b/src/test/ui/borrowck/borrowck-and-init.stderr
@@ -1,13 +1,13 @@
-error[E0381]: binding `i` isn't initialized in all conditions
+error[E0381]: used binding `i` isn't initialized in all conditions
   --> $DIR/borrowck-and-init.rs:5:20
    |
 LL |     let i: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |
 LL |     println!("{}", false && { i = 5; true });
    |                               ----- binding initialized here in some conditions
 LL |     println!("{}", i);
-   |                    ^ `i` borrowed here but it isn't initialized in all conditions
+   |                    ^ `i` used here but it isn't initialized in all conditions
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/borrowck-block-unint.stderr b/src/test/ui/borrowck/borrowck-block-unint.stderr
index 0f0fbedaf17e7..e720db1c6961b 100644
--- a/src/test/ui/borrowck/borrowck-block-unint.stderr
+++ b/src/test/ui/borrowck/borrowck-block-unint.stderr
@@ -1,10 +1,10 @@
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-block-unint.rs:4:11
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     force(|| {
-   |           ^^ `x` borrowed here but it isn't initialized
+   |           ^^ `x` used here but it isn't initialized
 LL |         println!("{}", x);
    |                        - borrow occurs due to use in closure
 
diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
index 2b5547dbf9556..23ea1a2de7fc7 100644
--- a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
+++ b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
@@ -1,11 +1,11 @@
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-break-uninit-2.rs:9:20
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 ...
 LL |     println!("{}", x);
-   |                    ^ `x` borrowed here but it isn't initialized
+   |                    ^ `x` used here but it isn't initialized
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/borrowck-break-uninit.stderr b/src/test/ui/borrowck/borrowck-break-uninit.stderr
index 9d0fd5dac933f..2b9b0a190f6c8 100644
--- a/src/test/ui/borrowck/borrowck-break-uninit.stderr
+++ b/src/test/ui/borrowck/borrowck-break-uninit.stderr
@@ -1,11 +1,11 @@
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-break-uninit.rs:9:20
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 ...
 LL |     println!("{}", x);
-   |                    ^ `x` borrowed here but it isn't initialized
+   |                    ^ `x` used here but it isn't initialized
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr
index 492bbfa9eb2d4..e009f5913edd0 100644
--- a/src/test/ui/borrowck/borrowck-field-sensitivity.stderr
+++ b/src/test/ui/borrowck/borrowck-field-sensitivity.stderr
@@ -108,35 +108,35 @@ LL |     let _z = A { a: 4, .. x };
    |
    = note: move occurs because `x.b` has type `Box<isize>`, which does not implement the `Copy` trait
 
-error[E0381]: binding `x` isn't fully initialized
+error[E0381]: partially assigned binding `x` isn't fully initialized
   --> $DIR/borrowck-field-sensitivity.rs:81:5
    |
 LL |     let mut x: A;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     x.a = 1;
    |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `x` isn't fully initialized
+error[E0381]: partially assigned binding `x` isn't fully initialized
   --> $DIR/borrowck-field-sensitivity.rs:87:5
    |
 LL |     let mut x: A;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     x.a = 1;
    |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `x` isn't fully initialized
+error[E0381]: partially assigned binding `x` isn't fully initialized
   --> $DIR/borrowck-field-sensitivity.rs:94:5
    |
 LL |     let mut x: A;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     x.b = Box::new(1);
    |     ^^^ `x` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error: aborting due to 14 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-if-no-else.stderr b/src/test/ui/borrowck/borrowck-if-no-else.stderr
index 178381e847786..134e7d5df4b09 100644
--- a/src/test/ui/borrowck/borrowck-if-no-else.stderr
+++ b/src/test/ui/borrowck/borrowck-if-no-else.stderr
@@ -1,10 +1,10 @@
-error[E0381]: binding `x` isn't initialized in all conditions
+error[E0381]: used binding `x` isn't initialized in all conditions
   --> $DIR/borrowck-if-no-else.rs:5:9
    |
 LL |     let x: isize; if 1 > 2 { x = 10; }
-   |         -            ----- this `if` expression might be missing an `else` arm where `x` is initialized
+   |         -            ----- this `if` expression might be missing an `else` arm that initializes `x`
    |         |
-   |         variable declared here
+   |         binding declared here but left uninitialized
 LL |     foo(x);
    |         ^ `x` used here but it isn't initialized in all conditions
 
diff --git a/src/test/ui/borrowck/borrowck-if-with-else.stderr b/src/test/ui/borrowck/borrowck-if-with-else.stderr
index f1af7b67b1c1b..f4b0c39307452 100644
--- a/src/test/ui/borrowck/borrowck-if-with-else.stderr
+++ b/src/test/ui/borrowck/borrowck-if-with-else.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `x` isn't initialized in all conditions
+error[E0381]: used binding `x` isn't initialized in all conditions
   --> $DIR/borrowck-if-with-else.rs:10:9
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     if 1 > 2 {
    |        ----- `x` is uninitialized if this condition is met
 ...
diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
index 8bdccd0dad6d2..e8a2fbc91ea64 100644
--- a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
+++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `i` isn't initialized
+error[E0381]: used binding `i` isn't initialized
   --> $DIR/borrowck-init-in-called-fn-expr.rs:4:9
    |
 LL |         let i: isize;
-   |             - variable declared here
+   |             - binding declared here but left uninitialized
 LL |         i
    |         ^ `i` used here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
index 84ec5598abb89..1e950d6a20def 100644
--- a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
+++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `i` isn't initialized
+error[E0381]: used binding `i` isn't initialized
   --> $DIR/borrowck-init-in-fn-expr.rs:4:9
    |
 LL |         let i: isize;
-   |             - variable declared here
+   |             - binding declared here but left uninitialized
 LL |         i
    |         ^ `i` used here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.stderr
index ddb2473d1ebee..7a35a9a537cac 100644
--- a/src/test/ui/borrowck/borrowck-init-in-fru.stderr
+++ b/src/test/ui/borrowck/borrowck-init-in-fru.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `origin.y` isn't initialized
+error[E0381]: used binding `origin.y` isn't initialized
   --> $DIR/borrowck-init-in-fru.rs:9:14
    |
 LL |     let mut origin: Point;
-   |         ---------- variable declared here
+   |         ---------- binding declared here but left uninitialized
 LL |     origin = Point { x: 10, ..origin };
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^ `origin.y` used here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.stderr b/src/test/ui/borrowck/borrowck-init-op-equal.stderr
index f1d7ec6a446d4..74704b2abfee8 100644
--- a/src/test/ui/borrowck/borrowck-init-op-equal.stderr
+++ b/src/test/ui/borrowck/borrowck-init-op-equal.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `v` isn't initialized
+error[E0381]: used binding `v` isn't initialized
   --> $DIR/borrowck-init-op-equal.rs:3:5
    |
 LL |     let v: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     v += 1;
    |     ^^^^^^ `v` used here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
index 26422af9c639a..7542576d636be 100644
--- a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
+++ b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `v` isn't initialized
+error[E0381]: used binding `v` isn't initialized
   --> $DIR/borrowck-init-plus-equal.rs:3:9
    |
 LL |     let mut v: isize;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     v = v + 1;
    |         ^ `v` used here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/borrowck-or-init.stderr b/src/test/ui/borrowck/borrowck-or-init.stderr
index 7fcec3046474d..633c4017d16ac 100644
--- a/src/test/ui/borrowck/borrowck-or-init.stderr
+++ b/src/test/ui/borrowck/borrowck-or-init.stderr
@@ -1,13 +1,13 @@
-error[E0381]: binding `i` isn't initialized in all conditions
+error[E0381]: used binding `i` isn't initialized in all conditions
   --> $DIR/borrowck-or-init.rs:5:20
    |
 LL |     let i: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |
 LL |     println!("{}", false || { i = 5; true });
    |                               ----- binding initialized here in some conditions
 LL |     println!("{}", i);
-   |                    ^ `i` borrowed here but it isn't initialized in all conditions
+   |                    ^ `i` used here but it isn't initialized in all conditions
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
index be5de8a0a5a61..06351a943064b 100644
--- a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `x.0` isn't initialized
+error[E0381]: assigned binding `x.0` isn't initialized
   --> $DIR/borrowck-partial-reinit-4.rs:17:5
    |
 LL |     let mut x : (Test2, Test2);
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     (x.0).0 = Some(Test);
    |     ^^^^^^^ `x.0` assigned here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/borrowck-return.stderr b/src/test/ui/borrowck/borrowck-return.stderr
index f42ac9fc54159..1c916e223175c 100644
--- a/src/test/ui/borrowck/borrowck-return.stderr
+++ b/src/test/ui/borrowck/borrowck-return.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-return.rs:3:12
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     return x;
    |            ^ `x` used here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/borrowck-storage-dead.stderr b/src/test/ui/borrowck/borrowck-storage-dead.stderr
index 6168961bd16db..2cea4392d6adb 100644
--- a/src/test/ui/borrowck/borrowck-storage-dead.stderr
+++ b/src/test/ui/borrowck/borrowck-storage-dead.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-storage-dead.rs:16:17
    |
 LL |         let x: i32;
-   |             - variable declared here
+   |             - binding declared here but left uninitialized
 LL |         let _ = x + 1;
    |                 ^ `x` used here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
index 64bccecf68a94..588b1b0c9729c 100644
--- a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `bar` isn't initialized
+error[E0381]: used binding `bar` isn't initialized
   --> $DIR/borrowck-uninit-after-item.rs:4:9
    |
 LL |     let bar;
-   |         --- variable declared here
+   |         --- binding declared here but left uninitialized
 LL |     fn baz(_x: isize) { }
 LL |     baz(bar);
    |         ^^^ `bar` used here but it isn't initialized
diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
index 0ffa5cee5f167..3bc3a47778778 100644
--- a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `a.x` isn't initialized
+error[E0381]: used binding `a.x` isn't initialized
   --> $DIR/borrowck-uninit-field-access.rs:21:13
    |
 LL |     let mut a: Point;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     let _ = a.x + 1;
    |             ^^^ `a.x` used here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
index 273370a4eef3a..744cb14e662b3 100644
--- a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
@@ -1,80 +1,80 @@
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:6:5
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x += 1;
    |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:9:5
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x -= 1;
    |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:12:5
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x *= 1;
    |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:15:5
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x /= 1;
    |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:18:5
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x %= 1;
    |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:21:5
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x ^= 1;
    |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:24:5
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x &= 1;
    |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:27:5
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x |= 1;
    |     ^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:30:5
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x <<= 1;
    |     ^^^^^^^ `x` used here but it isn't initialized
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-in-assignop.rs:33:5
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x >>= 1;
    |     ^^^^^^^ `x` used here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
index e78f5888df62d..9f33a163e084f 100644
--- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
@@ -1,66 +1,66 @@
-error[E0381]: binding `**x` isn't initialized
+error[E0381]: used binding `**x` isn't initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:8:14
    |
 LL |     let x: &&Box<i32>;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     let _y = &**x;
-   |              ^^^^ `**x` borrowed here but it isn't initialized
+   |              ^^^^ `**x` used here but it isn't initialized
 
-error[E0381]: binding `**x` isn't initialized
+error[E0381]: used binding `**x` isn't initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:11:14
    |
 LL |     let x: &&S<i32, i32>;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     let _y = &**x;
-   |              ^^^^ `**x` borrowed here but it isn't initialized
+   |              ^^^^ `**x` used here but it isn't initialized
 
-error[E0381]: binding `**x` isn't initialized
+error[E0381]: used binding `**x` isn't initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:14:14
    |
 LL |     let x: &&i32;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     let _y = &**x;
-   |              ^^^^ `**x` borrowed here but it isn't initialized
+   |              ^^^^ `**x` used here but it isn't initialized
 
-error[E0381]: binding `a` isn't fully initialized
+error[E0381]: partially assigned binding `a` isn't fully initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:18:5
    |
 LL |     let mut a: S<i32, i32>;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     a.x = 0;
    |     ^^^^^^^ `a` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `a` isn't fully initialized
+error[E0381]: partially assigned binding `a` isn't fully initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:22:5
    |
 LL |     let mut a: S<&&i32, &&i32>;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     a.x = &&0;
    |     ^^^^^^^^^ `a` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `a` isn't fully initialized
+error[E0381]: partially assigned binding `a` isn't fully initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:27:5
    |
 LL |     let mut a: S<i32, i32>;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     a.x = 0;
    |     ^^^^^^^ `a` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `a` isn't fully initialized
+error[E0381]: partially assigned binding `a` isn't fully initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:31:5
    |
 LL |     let mut a: S<&&i32, &&i32>;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     a.x = &&0;
    |     ^^^^^^^^^ `a` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-uninit.stderr b/src/test/ui/borrowck/borrowck-uninit.stderr
index c5ee9cfd29747..d5566691a8200 100644
--- a/src/test/ui/borrowck/borrowck-uninit.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit.rs:5:9
    |
 LL |     let x: isize;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     foo(x);
    |         ^ `x` used here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/borrowck-union-uninitialized.stderr b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr
index eee04f790337e..b7ff5f3955ee5 100644
--- a/src/test/ui/borrowck/borrowck-union-uninitialized.stderr
+++ b/src/test/ui/borrowck/borrowck-union-uninitialized.stderr
@@ -1,24 +1,24 @@
-error[E0381]: binding `s` isn't fully initialized
+error[E0381]: partially assigned binding `s` isn't fully initialized
   --> $DIR/borrowck-union-uninitialized.rs:13:9
    |
 LL |         let mut s: S;
-   |             ----- variable declared here
+   |             ----- binding declared here but left uninitialized
 LL |         let mut u: U;
 LL |         s.a = 0;
    |         ^^^^^^^ `s` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `u` isn't fully initialized
+error[E0381]: partially assigned binding `u` isn't fully initialized
   --> $DIR/borrowck-union-uninitialized.rs:14:9
    |
 LL |         let mut u: U;
-   |             ----- variable declared here
+   |             ----- binding declared here but left uninitialized
 LL |         s.a = 0;
 LL |         u.a = 0;
    |         ^^^^^^^ `u` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
index f7975c8ac920f..6372096caef02 100644
--- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
+++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
@@ -1,16 +1,16 @@
-error[E0381]: binding `*w` isn't initialized
+error[E0381]: used binding `*w` isn't initialized
   --> $DIR/borrowck-use-in-index-lvalue.rs:3:5
    |
 LL |     let w: &mut [isize];
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     w[5] = 0;
    |     ^^^^ `*w` used here but it isn't initialized
 
-error[E0381]: binding `*w` isn't initialized
+error[E0381]: used binding `*w` isn't initialized
   --> $DIR/borrowck-use-in-index-lvalue.rs:6:5
    |
 LL |     let mut w: &mut [isize];
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     w[5] = 0;
    |     ^^^^ `*w` used here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
index 3d024b531ef7c..fea69c2e40d66 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
@@ -1,10 +1,10 @@
-error[E0381]: binding `*x` isn't initialized
+error[E0381]: used binding `*x` isn't initialized
   --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:9:13
    |
 LL |     let x: &i32;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     let y = x as *const dyn Foo;
-   |             ^ `*x` borrowed here but it isn't initialized
+   |             ^ `*x` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
index 20a5dcaade7e2..e75e033529607 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
@@ -1,10 +1,10 @@
-error[E0381]: binding `*x` isn't initialized
+error[E0381]: used binding `*x` isn't initialized
   --> $DIR/borrowck-use-uninitialized-in-cast.rs:7:13
    |
 LL |     let x: &i32;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     let y = x as *const i32;
-   |             ^ `*x` borrowed here but it isn't initialized
+   |             ^ `*x` used here but it isn't initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-while-break.stderr b/src/test/ui/borrowck/borrowck-while-break.stderr
index 501f0c6515177..ab7d50b834a4e 100644
--- a/src/test/ui/borrowck/borrowck-while-break.stderr
+++ b/src/test/ui/borrowck/borrowck-while-break.stderr
@@ -1,13 +1,13 @@
-error[E0381]: binding `v` isn't initialized in all conditions
+error[E0381]: used binding `v` isn't initialized in all conditions
   --> $DIR/borrowck-while-break.rs:7:20
    |
 LL |     let v;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     while cond {
-   |           ---- `v` is uninitialized if this condition isn't met
+   |           ---- `v` is uninitialized if this condition isn't met and the `while` loop runs 0 times
 ...
 LL |     println!("{}", v);
-   |                    ^ `v` borrowed here but it isn't initialized in all conditions
+   |                    ^ `v` used here but it isn't initialized in all conditions
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/borrowck-while-cond.stderr b/src/test/ui/borrowck/borrowck-while-cond.stderr
index 87d505b5fbbcd..e41c1c55e6024 100644
--- a/src/test/ui/borrowck/borrowck-while-cond.stderr
+++ b/src/test/ui/borrowck/borrowck-while-cond.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-while-cond.rs:3:11
    |
 LL |     let x: bool;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     while x { }
    |           ^ `x` used here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/borrowck-while.stderr b/src/test/ui/borrowck/borrowck-while.stderr
index 36dda8ee13f77..5bb86b11ba503 100644
--- a/src/test/ui/borrowck/borrowck-while.stderr
+++ b/src/test/ui/borrowck/borrowck-while.stderr
@@ -1,10 +1,10 @@
-error[E0381]: binding `x` isn't initialized in all conditions
+error[E0381]: used binding `x` isn't initialized in all conditions
   --> $DIR/borrowck-while.rs:4:12
    |
 LL |     let mut x: isize;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     while 1 == 1 { x = 10; }
-   |           ------ `x` is uninitialized if this condition isn't met
+   |           ------ `x` is uninitialized if this condition isn't met and the `while` loop runs 0 times
 LL |     return x;
    |            ^ `x` used here but it isn't initialized in all conditions
 
diff --git a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr
index f6a0e3dbae053..9a84c6fefae59 100644
--- a/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr
+++ b/src/test/ui/borrowck/disallow-possibly-uninitialized.stderr
@@ -1,42 +1,42 @@
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/disallow-possibly-uninitialized.rs:6:5
    |
 LL |     let mut t: (u64, u64);
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     t.0 = 1;
    |     ^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/disallow-possibly-uninitialized.rs:11:5
    |
 LL |     let mut t: (u64, u64);
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     t.1 = 1;
    |     ^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/disallow-possibly-uninitialized.rs:16:5
    |
 LL |     let mut t: (u64, u64);
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     t.0 = 1;
    |     ^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/disallow-possibly-uninitialized.rs:20:5
    |
 LL |     let mut t: (u64,);
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     t.0 = 1;
    |     ^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/borrowck/issue-24267-flow-exit.stderr b/src/test/ui/borrowck/issue-24267-flow-exit.stderr
index 25f7df4f58243..d436e8ff9096c 100644
--- a/src/test/ui/borrowck/issue-24267-flow-exit.stderr
+++ b/src/test/ui/borrowck/issue-24267-flow-exit.stderr
@@ -1,22 +1,22 @@
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/issue-24267-flow-exit.rs:12:20
    |
 LL |     let x: i32;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     loop { x = break; }
 LL |     println!("{}", x);
-   |                    ^ `x` borrowed here but it isn't initialized
+   |                    ^ `x` used here but it isn't initialized
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/issue-24267-flow-exit.rs:18:20
    |
 LL |     let x: i32;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     for _ in 0..10 { x = continue; }
 LL |     println!("{}", x);
-   |                    ^ `x` borrowed here but it isn't initialized
+   |                    ^ `x` used here but it isn't initialized
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr
index 99c25ad5446a2..2a0eba396f144 100644
--- a/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.stderr
@@ -1,32 +1,32 @@
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:12:9
    |
 LL |         let mut t: Tuple;
-   |             ----- variable declared here
+   |             ----- binding declared here but left uninitialized
 LL |         t.0 = S(1);
    |         ^^^^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `u` isn't fully initialized
+error[E0381]: partially assigned binding `u` isn't fully initialized
   --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:20:9
    |
 LL |         let mut u: Tpair;
-   |             ----- variable declared here
+   |             ----- binding declared here but left uninitialized
 LL |         u.0 = S(1);
    |         ^^^^^^^^^^ `u` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `v` isn't fully initialized
+error[E0381]: partially assigned binding `v` isn't fully initialized
   --> $DIR/issue-54499-field-mutation-marks-mut-as-used.rs:28:9
    |
 LL |         let mut v: Spair;
-   |             ----- variable declared here
+   |             ----- binding declared here but left uninitialized
 LL |         v.x = S(1);
    |         ^^^^^^^^^^ `v` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr
index 1c78524a1b1a8..67a62583057f6 100644
--- a/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr
+++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-never-init.stderr
@@ -1,32 +1,32 @@
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/issue-54499-field-mutation-of-never-init.rs:12:9
    |
 LL |         let t: Tuple;
-   |             - variable declared here
+   |             - binding declared here but left uninitialized
 LL |         t.0 = S(1);
    |         ^^^^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `u` isn't fully initialized
+error[E0381]: partially assigned binding `u` isn't fully initialized
   --> $DIR/issue-54499-field-mutation-of-never-init.rs:20:9
    |
 LL |         let u: Tpair;
-   |             - variable declared here
+   |             - binding declared here but left uninitialized
 LL |         u.0 = S(1);
    |         ^^^^^^^^^^ `u` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `v` isn't fully initialized
+error[E0381]: partially assigned binding `v` isn't fully initialized
   --> $DIR/issue-54499-field-mutation-of-never-init.rs:28:9
    |
 LL |         let v: Spair;
-   |             - variable declared here
+   |             - binding declared here but left uninitialized
 LL |         v.x = S(1);
    |         ^^^^^^^^^^ `v` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr
index f809b7d4c3b0c..f5d2eecfa91a3 100644
--- a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr
+++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `e` isn't initialized
+error[E0381]: used binding `e` isn't initialized
   --> $DIR/issue-62107-match-arm-scopes.rs:3:11
    |
 LL |     let e: i32;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     match e {
    |           ^ `e` used here but it isn't initialized
 
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields.stderr b/src/test/ui/borrowck/reassignment_immutable_fields.stderr
index 045f95632d83e..e6b25573e7040 100644
--- a/src/test/ui/borrowck/reassignment_immutable_fields.stderr
+++ b/src/test/ui/borrowck/reassignment_immutable_fields.stderr
@@ -1,22 +1,22 @@
-error[E0381]: binding `x` isn't fully initialized
+error[E0381]: partially assigned binding `x` isn't fully initialized
   --> $DIR/reassignment_immutable_fields.rs:7:5
    |
 LL |     let x: (u32, u32);
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x.0 = 1;
    |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `x` isn't fully initialized
+error[E0381]: partially assigned binding `x` isn't fully initialized
   --> $DIR/reassignment_immutable_fields.rs:15:5
    |
 LL |     let x: (u32, u32);
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x.0 = 1;
    |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr
index d848679272375..a3885b5f5caea 100644
--- a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr
+++ b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr
@@ -1,12 +1,12 @@
-error[E0381]: binding `x` isn't fully initialized
+error[E0381]: partially assigned binding `x` isn't fully initialized
   --> $DIR/reassignment_immutable_fields_overlapping.rs:12:5
    |
 LL |     let x: Foo;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x.a = 1;
    |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error[E0594]: cannot assign to `x.b`, as `x` is not declared as mutable
   --> $DIR/reassignment_immutable_fields_overlapping.rs:13:5
diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr
index db69f0b0db704..49c81adad4937 100644
--- a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr
+++ b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr
@@ -7,15 +7,15 @@ LL |     x = (22, 44);
 LL |     x.0 = 1;
    |     ^^^^^^^ cannot assign
 
-error[E0381]: binding `x` isn't fully initialized
+error[E0381]: partially assigned binding `x` isn't fully initialized
   --> $DIR/reassignment_immutable_fields_twice.rs:12:5
    |
 LL |     let x: (u32, u32);
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     x.0 = 1;
    |     ^^^^^^^ `x` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
index c891fff228a27..fea5441ec673d 100644
--- a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
@@ -12,68 +12,68 @@ LL +         _ => todo!(),
 LL ~     };
    |
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/pattern-matching-should-fail.rs:8:23
    |
 LL |     let x: !;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     let c1 = || match x { };
    |                       ^ `x` used here but it isn't initialized
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/pattern-matching-should-fail.rs:15:14
    |
 LL |     let x: !;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     let c2 = || match x { _ => () };
    |              ^^       - borrow occurs due to use in closure
    |              |
-   |              `x` borrowed here but it isn't initialized
+   |              `x` used here but it isn't initialized
 
-error[E0381]: binding `variant` isn't initialized
+error[E0381]: used binding `variant` isn't initialized
   --> $DIR/pattern-matching-should-fail.rs:27:13
    |
 LL |     let variant: !;
-   |         ------- variable declared here
+   |         ------- binding declared here but left uninitialized
 LL |     let c = || {
-   |             ^^ `variant` borrowed here but it isn't initialized
+   |             ^^ `variant` used here but it isn't initialized
 LL |
 LL |         match variant {
    |               ------- borrow occurs due to use in closure
 
-error[E0381]: binding `variant` isn't initialized
+error[E0381]: used binding `variant` isn't initialized
   --> $DIR/pattern-matching-should-fail.rs:39:13
    |
 LL |     let variant: !;
-   |         ------- variable declared here
+   |         ------- binding declared here but left uninitialized
 LL |     let c = || {
-   |             ^^ `variant` borrowed here but it isn't initialized
+   |             ^^ `variant` used here but it isn't initialized
 LL |         match variant {
    |               ------- borrow occurs due to use in closure
 
-error[E0381]: binding `g` isn't initialized
+error[E0381]: used binding `g` isn't initialized
   --> $DIR/pattern-matching-should-fail.rs:54:15
    |
 LL |     let g: !;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 ...
 LL |         match g { };
    |               ^ `g` used here but it isn't initialized
 
-error[E0381]: binding `t` isn't initialized
+error[E0381]: used binding `t` isn't initialized
   --> $DIR/pattern-matching-should-fail.rs:56:19
    |
 LL |     let t: !;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 ...
 LL |             match t { };
    |                   ^ `t` used here but it isn't initialized
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/pattern-matching-should-fail.rs:67:23
    |
 LL |     let x: u8;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     let c1 = || match x { };
    |                       ^ `x` used here but it isn't initialized
 
diff --git a/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr
index 0638a9c61c17e..33f839c2866e9 100644
--- a/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr
+++ b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr
@@ -1,10 +1,10 @@
-error[E0381]: binding `*s` isn't initialized
+error[E0381]: used binding `*s` isn't initialized
   --> $DIR/const-generic-default-wont-borrowck.rs:2:26
    |
 LL |     let s: &'static str; s.len()
-   |         -                ^^^^^^^ `*s` borrowed here but it isn't initialized
+   |         -                ^^^^^^^ `*s` used here but it isn't initialized
    |         |
-   |         variable declared here
+   |         binding declared here but left uninitialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/issue-78655.stderr b/src/test/ui/consts/issue-78655.stderr
index 1c1a30d405d70..f5b1123e7f343 100644
--- a/src/test/ui/consts/issue-78655.stderr
+++ b/src/test/ui/consts/issue-78655.stderr
@@ -1,10 +1,10 @@
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/issue-78655.rs:3:5
    |
 LL |     let x;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     &x
-   |     ^^ `x` borrowed here but it isn't initialized
+   |     ^^ `x` used here but it isn't initialized
 
 error: could not evaluate constant pattern
   --> $DIR/issue-78655.rs:7:9
diff --git a/src/test/ui/drop/repeat-drop-2.stderr b/src/test/ui/drop/repeat-drop-2.stderr
index 845b6de798fa7..48fa2bfa975c0 100644
--- a/src/test/ui/drop/repeat-drop-2.stderr
+++ b/src/test/ui/drop/repeat-drop-2.stderr
@@ -17,11 +17,11 @@ LL | const _: [String; 0] = [String::new(); 0];
    |                        |constants cannot evaluate destructors
    |                        value is dropped here
 
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/repeat-drop-2.rs:12:14
    |
 LL |     let x: u8;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     let _ = [x; 0];
    |              ^ `x` used here but it isn't initialized
 
diff --git a/src/test/ui/generator/partial-initialization-across-yield.stderr b/src/test/ui/generator/partial-initialization-across-yield.stderr
index 26f45538023bb..3f9f1c046ba4b 100644
--- a/src/test/ui/generator/partial-initialization-across-yield.stderr
+++ b/src/test/ui/generator/partial-initialization-across-yield.stderr
@@ -1,32 +1,32 @@
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/partial-initialization-across-yield.rs:12:9
    |
 LL |         let mut t: (i32, i32);
-   |             ----- variable declared here
+   |             ----- binding declared here but left uninitialized
 LL |         t.0 = 42;
    |         ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/partial-initialization-across-yield.rs:22:9
    |
 LL |         let mut t: T;
-   |             ----- variable declared here
+   |             ----- binding declared here but left uninitialized
 LL |         t.0 = 42;
    |         ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/partial-initialization-across-yield.rs:32:9
    |
 LL |         let mut t: S;
-   |             ----- variable declared here
+   |             ----- binding declared here but left uninitialized
 LL |         t.x = 42;
    |         ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/loops/loop-proper-liveness.stderr b/src/test/ui/loops/loop-proper-liveness.stderr
index dd6949b19f624..7504103173652 100644
--- a/src/test/ui/loops/loop-proper-liveness.stderr
+++ b/src/test/ui/loops/loop-proper-liveness.stderr
@@ -1,11 +1,11 @@
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/loop-proper-liveness.rs:9:22
    |
 LL |     let x: i32;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 ...
 LL |     println!("{:?}", x);
-   |                      ^ `x` borrowed here but it isn't initialized
+   |                      ^ `x` used here but it isn't initialized
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr
index ad2e5c9f64373..d8154f8d2cbc4 100644
--- a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr
+++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr
@@ -16,11 +16,11 @@ LL |     let a: [String; 1];
 LL | };
    | - value is dropped here
 
-error[E0381]: binding `a` isn't initialized
+error[E0381]: used binding `a` isn't initialized
   --> $DIR/drop-elaboration-after-borrowck-error.rs:7:5
    |
 LL |     let a: [String; 1];
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |
 LL |     a[0] = String::new();
    |     ^^^^ `a` used here but it isn't initialized
diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.rs b/src/test/ui/moves/issue-72649-uninit-in-loop.rs
index e796466397b1e..d76b69ecdc8bb 100644
--- a/src/test/ui/moves/issue-72649-uninit-in-loop.rs
+++ b/src/test/ui/moves/issue-72649-uninit-in-loop.rs
@@ -57,14 +57,14 @@ fn moved_loop_2() {
 
 fn uninit_1() {
     loop {
-        let value: NonCopy; //~ NOTE variable declared here
+        let value: NonCopy; //~ NOTE declared here
         let _used = value; //~ ERROR binding `value` isn't initialized
         //~^ NOTE `value` used here but it isn't initialized
     }
 }
 
 fn uninit_2() {
-    let mut value: NonCopy; //~ NOTE variable declared here
+    let mut value: NonCopy; //~ NOTE declared here
     loop {
         let _used = value; //~ ERROR binding `value` isn't initialized
         //~^ NOTE `value` used here but it isn't initialized
diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr
index 52dab5cabf817..c7373b5be9d8d 100644
--- a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr
+++ b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr
@@ -40,19 +40,19 @@ LL |     let mut value = NonCopy{};
 LL |         let _used2 = value;
    |                      ^^^^^ value moved here, in previous iteration of loop
 
-error[E0381]: binding `value` isn't initialized
+error[E0381]: used binding `value` isn't initialized
   --> $DIR/issue-72649-uninit-in-loop.rs:61:21
    |
 LL |         let value: NonCopy;
-   |             ----- variable declared here
+   |             ----- binding declared here but left uninitialized
 LL |         let _used = value;
    |                     ^^^^^ `value` used here but it isn't initialized
 
-error[E0381]: binding `value` isn't initialized
+error[E0381]: used binding `value` isn't initialized
   --> $DIR/issue-72649-uninit-in-loop.rs:69:21
    |
 LL |     let mut value: NonCopy;
-   |         --------- variable declared here
+   |         --------- binding declared here but left uninitialized
 LL |     loop {
 LL |         let _used = value;
    |                     ^^^^^ `value` used here but it isn't initialized
diff --git a/src/test/ui/moves/move-into-dead-array-1.stderr b/src/test/ui/moves/move-into-dead-array-1.stderr
index b5478196ef668..344a6bbf0c92c 100644
--- a/src/test/ui/moves/move-into-dead-array-1.stderr
+++ b/src/test/ui/moves/move-into-dead-array-1.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `a` isn't initialized
+error[E0381]: used binding `a` isn't initialized
   --> $DIR/move-into-dead-array-1.rs:14:5
    |
 LL |     let mut a: [D; 4];
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     a[i] = d();
    |     ^^^^ `a` used here but it isn't initialized
 
diff --git a/src/test/ui/moves/move-of-addr-of-mut.stderr b/src/test/ui/moves/move-of-addr-of-mut.stderr
index a145b6223c187..e75f2b1c0894c 100644
--- a/src/test/ui/moves/move-of-addr-of-mut.stderr
+++ b/src/test/ui/moves/move-of-addr-of-mut.stderr
@@ -1,10 +1,10 @@
-error[E0381]: binding `x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/move-of-addr-of-mut.rs:8:5
    |
 LL |     let mut x: S;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     std::ptr::addr_of_mut!(x);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ `x` borrowed here but it isn't initialized
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ `x` used here but it isn't initialized
    |
    = note: this error originates in the macro `std::ptr::addr_of_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
index 71029065db1cf..f56b6294c2093 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
+++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
@@ -1,16 +1,16 @@
-error[E0381]: binding `d` isn't initialized
+error[E0381]: assigned binding `d` isn't initialized
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:28:5
    |
 LL |     let d: D;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     d.x = 10;
    |     ^^^^^^^^ `d` assigned here but it isn't initialized
 
-error[E0381]: binding `d` isn't initialized
+error[E0381]: assigned binding `d` isn't initialized
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:33:5
    |
 LL |     let mut d: D;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     d.x = 10;
    |     ^^^^^^^^ `d` assigned here but it isn't initialized
 
@@ -24,25 +24,25 @@ LL |     drop(d);
 LL |     d.x = 10;
    |     ^^^^^^^^ value assigned here after move
 
-error[E0381]: binding `d.s` isn't fully initialized
+error[E0381]: partially assigned binding `d.s` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:45:5
    |
 LL |     let d: D;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     d.s.y = 20;
    |     ^^^^^^^^^^ `d.s` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `d.s` isn't fully initialized
+error[E0381]: partially assigned binding `d.s` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:50:5
    |
 LL |     let mut d: D;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     d.s.y = 20;
    |     ^^^^^^^^^^ `d.s` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error[E0382]: assign to part of moved value: `d`
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:56:5
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
index df60868d840c0..2f5883b156300 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
+++ b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
@@ -1,22 +1,22 @@
-error[E0381]: binding `s` isn't fully initialized
+error[E0381]: partially assigned binding `s` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:97:5
    |
 LL |     let s: S<B>;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     s.x = 10; s.y = Box::new(20);
    |     ^^^^^^^^ `s` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:103:5
    |
 LL |     let t: T;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     t.0 = 10; t.1 = Box::new(20);
    |     ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error[E0382]: assign to part of moved value: `s`
   --> $DIR/issue-21232-partial-init-and-use.rs:109:5
@@ -38,25 +38,25 @@ LL |     let mut t: T = (0, Box::new(0)); drop(t);
 LL |     t.0 = 10; t.1 = Box::new(20);
    |     ^^^^^^^^ value partially assigned here after move
 
-error[E0381]: binding `s` isn't fully initialized
+error[E0381]: partially assigned binding `s` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:123:5
    |
 LL |     let s: S<B>;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     s.x = 10;
    |     ^^^^^^^^ `s` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:129:5
    |
 LL |     let t: T;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     t.0 = 10;
    |     ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error[E0382]: assign to part of moved value: `s`
   --> $DIR/issue-21232-partial-init-and-use.rs:135:5
@@ -78,45 +78,45 @@ LL |     let mut t: T = (0, Box::new(0)); drop(t);
 LL |     t.0 = 10;
    |     ^^^^^^^^ value partially assigned here after move
 
-error[E0381]: binding `s` isn't fully initialized
+error[E0381]: partially assigned binding `s` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:149:5
    |
 LL |     let s: S<Void>;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     s.x = 10;
    |     ^^^^^^^^ `s` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `t` isn't fully initialized
+error[E0381]: partially assigned binding `t` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:155:5
    |
 LL |     let t: Tvoid;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     t.0 = 10;
    |     ^^^^^^^^ `t` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `q.r.f` isn't fully initialized
+error[E0381]: partially assigned binding `q.r.f` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:170:5
    |
 LL |     let q: Q<S<B>>;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     q.r.f.x = 10; q.r.f.y = Box::new(20);
    |     ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `q.r.f` isn't fully initialized
+error[E0381]: partially assigned binding `q.r.f` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:176:5
    |
 LL |     let q: Q<T>;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     q.r.f.0 = 10; q.r.f.1 = Box::new(20);
    |     ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error[E0382]: assign to part of moved value: `q.r`
   --> $DIR/issue-21232-partial-init-and-use.rs:182:5
@@ -138,25 +138,25 @@ LL |     q.r.f.0 = 10; q.r.f.1 = Box::new(20);
    |
    = note: move occurs because `q.r` has type `R<(u32, Box<u32>)>`, which does not implement the `Copy` trait
 
-error[E0381]: binding `q.r.f` isn't fully initialized
+error[E0381]: partially assigned binding `q.r.f` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:196:5
    |
 LL |     let q: Q<S<B>>;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     q.r.f.x = 10;
    |     ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `q.r.f` isn't fully initialized
+error[E0381]: partially assigned binding `q.r.f` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:202:5
    |
 LL |     let q: Q<T>;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     q.r.f.0 = 10;
    |     ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error[E0382]: assign to part of moved value: `q.r`
   --> $DIR/issue-21232-partial-init-and-use.rs:208:5
@@ -178,25 +178,25 @@ LL |     q.r.f.0 = 10;
    |
    = note: move occurs because `q.r` has type `R<(u32, Box<u32>)>`, which does not implement the `Copy` trait
 
-error[E0381]: binding `q.r.f` isn't fully initialized
+error[E0381]: partially assigned binding `q.r.f` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:222:5
    |
 LL |     let mut q: Q<S<Void>>;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     q.r.f.x = 10;
    |     ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: binding `q.r.f` isn't fully initialized
+error[E0381]: partially assigned binding `q.r.f` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:228:5
    |
 LL |     let mut q: Q<Tvoid>;
-   |         ----- variable declared here
+   |         ----- binding declared here but left uninitialized
 LL |     q.r.f.0 = 10;
    |     ^^^^^^^^^^^^ `q.r.f` partially assigned here but it isn't fully initialized
    |
-   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate, or use `std::mem::MaybeUninit`
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error[E0382]: assign to part of moved value: `c`
   --> $DIR/issue-21232-partial-init-and-use.rs:245:13
diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr
index 43950433e621d..39933db364803 100644
--- a/src/test/ui/nll/match-cfg-fake-edges.stderr
+++ b/src/test/ui/nll/match-cfg-fake-edges.stderr
@@ -1,11 +1,9 @@
-error[E0381]: binding `x` isn't initialized in all conditions
+error[E0381]: used binding `x` isn't initialized in all conditions
   --> $DIR/match-cfg-fake-edges.rs:21:13
    |
 LL |     let x;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 ...
-LL |         _ if {
-   |         - `x` is uninitialized if this pattern is matched
 LL |             x;
    |             ^ `x` used here but it isn't initialized in all conditions
 
diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr
index 0480aaa99c274..664f36f695cf3 100644
--- a/src/test/ui/nll/match-on-borrowed.stderr
+++ b/src/test/ui/nll/match-on-borrowed.stderr
@@ -33,11 +33,11 @@ LL |     match t {
 LL |     x;
    |     - borrow later used here
 
-error[E0381]: binding `n` isn't initialized
+error[E0381]: used binding `n` isn't initialized
   --> $DIR/match-on-borrowed.rs:93:11
    |
 LL |     let n: Never;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     match n {}
    |           ^ `n` used here but it isn't initialized
 
diff --git a/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr b/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr
index 1fb643b98aebe..a3d8c608f4b8b 100644
--- a/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr
@@ -1,28 +1,28 @@
-error[E0381]: binding `z` isn't initialized in all conditions
+error[E0381]: used binding `z` isn't initialized in all conditions
   --> $DIR/chains-without-let.rs:3:34
    |
 LL |     let z;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     if true && { z = 3; true} && z == 3 {}
    |                  -----           ^ `z` used here but it isn't initialized in all conditions
    |                  |
    |                  binding initialized here in some conditions
 
-error[E0381]: binding `z` isn't initialized in all conditions
+error[E0381]: used binding `z` isn't initialized in all conditions
   --> $DIR/chains-without-let.rs:9:31
    |
 LL |     let z;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     true && { z = 3; true} && z == 3;
    |               -----           ^ `z` used here but it isn't initialized in all conditions
    |               |
    |               binding initialized here in some conditions
 
-error[E0381]: binding `z` isn't initialized in all conditions
+error[E0381]: used binding `z` isn't initialized in all conditions
   --> $DIR/chains-without-let.rs:15:36
    |
 LL |     let z;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 LL |     if false || { z = 3; false} || z == 3 {}
    |                   -----            ^ `z` used here but it isn't initialized in all conditions
    |                   |
diff --git a/src/test/ui/try-block/try-block-opt-init.stderr b/src/test/ui/try-block/try-block-opt-init.stderr
index 17349f9c9f35a..72e732599c00e 100644
--- a/src/test/ui/try-block/try-block-opt-init.stderr
+++ b/src/test/ui/try-block/try-block-opt-init.stderr
@@ -1,14 +1,14 @@
-error[E0381]: binding `cfg_res` isn't initialized in all conditions
+error[E0381]: used binding `cfg_res` isn't initialized in all conditions
   --> $DIR/try-block-opt-init.rs:15:5
    |
 LL |     let cfg_res;
-   |         ------- variable declared here
+   |         ------- binding declared here but left uninitialized
 ...
 LL |         cfg_res = 5;
    |         ----------- binding initialized here in some conditions
 ...
 LL |     assert_eq!(cfg_res, 5);
-   |     ^^^^^^^^^^^^^^^^^^^^^^ `cfg_res` borrowed here but it isn't initialized in all conditions
+   |     ^^^^^^^^^^^^^^^^^^^^^^ `cfg_res` used here but it isn't initialized in all conditions
    |
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr b/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr
index 61e6295fa3f2c..95c209f47c92a 100644
--- a/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr
+++ b/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr
@@ -1,8 +1,8 @@
-error[E0381]: binding `y` isn't initialized
+error[E0381]: used binding `y` isn't initialized
   --> $DIR/privately-uninhabited-mir-call.rs:28:5
    |
 LL |     let y: &mut u32;
-   |         - variable declared here
+   |         - binding declared here but left uninitialized
 ...
 LL |     *y = 2;
    |     ^^^^^^ `y` used here but it isn't initialized

From 328522e3cdc3c485cd022edf537c13866b74e89f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Wed, 22 Jun 2022 11:04:36 -0700
Subject: [PATCH 07/20] Review comments: wording

---
 .../src/diagnostics/conflict_errors.rs        | 69 +++++++++++--------
 .../no-non-guaranteed-initialization.stderr   | 10 +--
 src/test/ui/borrowck/borrowck-and-init.stderr |  4 +-
 .../ui/borrowck/borrowck-if-no-else.stderr    |  9 +--
 .../ui/borrowck/borrowck-if-with-else.stderr  |  6 +-
 src/test/ui/borrowck/borrowck-or-init.stderr  |  4 +-
 .../ui/borrowck/borrowck-while-break.stderr   |  6 +-
 src/test/ui/borrowck/borrowck-while.stderr    |  6 +-
 src/test/ui/nll/match-cfg-fake-edges.stderr   |  4 +-
 .../chains-without-let.stderr                 | 12 ++--
 .../ui/try-block/try-block-opt-init.stderr    |  4 +-
 11 files changed, 74 insertions(+), 60 deletions(-)

diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index daeaac9415def..54dff1b6c6b14 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -329,7 +329,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         for init_idx in inits {
             let init = &self.move_data.inits[*init_idx];
             let span = init.span(&self.body);
-            spans.push(span);
+            if !span.is_dummy() {
+                spans.push(span);
+            }
         }
 
         let (binding, name, desc) =
@@ -337,24 +339,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 Some(name) => (format!("`{name}`"), format!("`{name}`"), format!("`{name}` ")),
                 None => ("value".to_string(), "the variable".to_string(), String::new()),
             };
-        let initialized = if let InitializationRequiringAction::PartialAssignment = desired_action {
-            // The same error is emitted for bindings that are *sometimes* initialized and the ones
-            // that are *partially* initialized by assigning to a field of an uninitialized
-            // binding. We differentiate between them for more accurate wording here.
-            "fully initialized"
-        } else if spans.iter().filter(|i| !i.contains(span)).count() == 0 {
-            // We filter above to avoid misleading wording in cases like:
-            // ```
-            // let x;
-            // x += 1;
-            // ```
-            "initialized"
-        } else {
-            "initialized in all conditions"
-        };
+        let isnt_initialized =
+            if let InitializationRequiringAction::PartialAssignment = desired_action {
+                // The same error is emitted for bindings that are *sometimes* initialized and the ones
+                // that are *partially* initialized by assigning to a field of an uninitialized
+                // binding. We differentiate between them for more accurate wording here.
+                "isn't fully initialized"
+            } else if spans.iter().filter(|i| !i.contains(span)).count() == 0 {
+                // We filter above to avoid misleading wording in cases like the following, where `x`
+                // has an `init`, but it is in the same place we're looking at:
+                // ```
+                // let x;
+                // x += 1;
+                // ```
+                "isn't initialized"
+            } else {
+                "is possibly-uninitialized"
+            };
         let used = desired_action.as_general_verb_in_past_tense();
         let mut err =
-            struct_span_err!(self, span, E0381, "{used} binding {desc}isn't {initialized}");
+            struct_span_err!(self, span, E0381, "{used} binding {desc}{isnt_initialized}");
         use_spans.var_span_label_path_only(
             &mut err,
             format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()),
@@ -366,7 +370,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                  default value and mutate it, or use `std::mem::MaybeUninit`",
             );
         }
-        err.span_label(span, format!("{binding} {used} here but it isn't {initialized}"));
+        err.span_label(span, format!("{binding} {used} here but it {isnt_initialized}"));
 
         // We use the statements were the binding was initialized, and inspect the HIR to look
         // for the branching codepaths that aren't covered, to point at them.
@@ -2561,13 +2565,16 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                 v.visit_expr(body);
                 if v.1 {
                     self.errors.push((
-                        ex.span.to(cond.span),
+                        cond.span,
                         format!(
-                            "this `if` expression might be missing an `else` arm that initializes \
-                             {}",
+                            "if this `if` condition is `false`, {} is not initialized",
                             self.name,
                         ),
                     ));
+                    self.errors.push((
+                        ex.span.shrink_to_hi(),
+                        format!("an `else` arm might be missing here, initializing {}", self.name),
+                    ));
                 }
             }
             hir::ExprKind::If(cond, body, Some(other)) => {
@@ -2584,8 +2591,8 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                             self.errors.push((
                                 cond.span,
                                 format!(
-                                    "{} is uninitialized if this condition isn't met and the \
-                                     `while` loop runs 0 times",
+                                    "if this condition isn't met and the `while` loop runs 0 \
+                                     times, {} is not initialized",
                                     self.name
                                 ),
                             ));
@@ -2593,7 +2600,8 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                             self.errors.push((
                                 body.span.shrink_to_hi().until(other.span),
                                 format!(
-                                    "{} is uninitialized if this `else` arm is executed",
+                                    "if the `if` condition is `false` and this `else` arm is \
+                                     executed, {} is not initialized",
                                     self.name
                                 ),
                             ));
@@ -2602,7 +2610,10 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                     (false, true) => {
                         self.errors.push((
                             cond.span,
-                            format!("{} is uninitialized if this condition is met", self.name),
+                            format!(
+                                "if this condition is `true`, {} is not initialized",
+                                self.name
+                            ),
                         ));
                     }
                 }
@@ -2625,7 +2636,7 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                                 self.errors.push((
                                     e.span,
                                     format!(
-                                        "{} is uninitialized if the `for` loop runs 0 times",
+                                        "if the `for` loop runs 0 times, {} is not initialized ",
                                         self.name
                                     ),
                                 ));
@@ -2633,8 +2644,8 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                                 self.errors.push((
                                     arm.pat.span.to(guard.body().span),
                                     format!(
-                                        "{} is uninitialized if this pattern and condition are \
-                                         matched",
+                                        "if this pattern and condition are matched, {} is not \
+                                         initialized",
                                         self.name
                                     ),
                                 ));
@@ -2642,7 +2653,7 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                                 self.errors.push((
                                     arm.pat.span,
                                     format!(
-                                        "{} is uninitialized if this pattern is matched",
+                                        "if this pattern is matched, {} is not initialized",
                                         self.name
                                     ),
                                 ));
diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr
index b23e2da0e0920..12c15bf56ce22 100644
--- a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr
+++ b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr
@@ -1,13 +1,15 @@
-error[E0381]: used binding `y` isn't initialized in all conditions
+error[E0381]: used binding `y` is possibly-uninitialized
   --> $DIR/no-non-guaranteed-initialization.rs:9:5
    |
 LL |     let y;
    |         - binding declared here but left uninitialized
 LL |     if x > 5 {
-   |        ----- this `if` expression might be missing an `else` arm that initializes `y`
-...
+   |        ----- if this `if` condition is `false`, `y` is not initialized
+LL |         y = echo(10).await;
+LL |     }
+   |      - an `else` arm might be missing here, initializing `y`
 LL |     y
-   |     ^ `y` used here but it isn't initialized in all conditions
+   |     ^ `y` used here but it is possibly-uninitialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-and-init.stderr b/src/test/ui/borrowck/borrowck-and-init.stderr
index a78ac1e593a05..7f3d27d6091d8 100644
--- a/src/test/ui/borrowck/borrowck-and-init.stderr
+++ b/src/test/ui/borrowck/borrowck-and-init.stderr
@@ -1,4 +1,4 @@
-error[E0381]: used binding `i` isn't initialized in all conditions
+error[E0381]: used binding `i` is possibly-uninitialized
   --> $DIR/borrowck-and-init.rs:5:20
    |
 LL |     let i: isize;
@@ -7,7 +7,7 @@ LL |
 LL |     println!("{}", false && { i = 5; true });
    |                               ----- binding initialized here in some conditions
 LL |     println!("{}", i);
-   |                    ^ `i` used here but it isn't initialized in all conditions
+   |                    ^ `i` used here but it is possibly-uninitialized
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/borrowck-if-no-else.stderr b/src/test/ui/borrowck/borrowck-if-no-else.stderr
index 134e7d5df4b09..9eafc2c2a86e6 100644
--- a/src/test/ui/borrowck/borrowck-if-no-else.stderr
+++ b/src/test/ui/borrowck/borrowck-if-no-else.stderr
@@ -1,12 +1,13 @@
-error[E0381]: used binding `x` isn't initialized in all conditions
+error[E0381]: used binding `x` is possibly-uninitialized
   --> $DIR/borrowck-if-no-else.rs:5:9
    |
 LL |     let x: isize; if 1 > 2 { x = 10; }
-   |         -            ----- this `if` expression might be missing an `else` arm that initializes `x`
-   |         |
+   |         -            -----            - an `else` arm might be missing here, initializing `x`
+   |         |            |
+   |         |            if this `if` condition is `false`, `x` is not initialized
    |         binding declared here but left uninitialized
 LL |     foo(x);
-   |         ^ `x` used here but it isn't initialized in all conditions
+   |         ^ `x` used here but it is possibly-uninitialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-if-with-else.stderr b/src/test/ui/borrowck/borrowck-if-with-else.stderr
index f4b0c39307452..3f0fe291ca250 100644
--- a/src/test/ui/borrowck/borrowck-if-with-else.stderr
+++ b/src/test/ui/borrowck/borrowck-if-with-else.stderr
@@ -1,13 +1,13 @@
-error[E0381]: used binding `x` isn't initialized in all conditions
+error[E0381]: used binding `x` is possibly-uninitialized
   --> $DIR/borrowck-if-with-else.rs:10:9
    |
 LL |     let x: isize;
    |         - binding declared here but left uninitialized
 LL |     if 1 > 2 {
-   |        ----- `x` is uninitialized if this condition is met
+   |        ----- if this condition is `true`, `x` is not initialized
 ...
 LL |     foo(x);
-   |         ^ `x` used here but it isn't initialized in all conditions
+   |         ^ `x` used here but it is possibly-uninitialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-or-init.stderr b/src/test/ui/borrowck/borrowck-or-init.stderr
index 633c4017d16ac..0bc24f1b6932f 100644
--- a/src/test/ui/borrowck/borrowck-or-init.stderr
+++ b/src/test/ui/borrowck/borrowck-or-init.stderr
@@ -1,4 +1,4 @@
-error[E0381]: used binding `i` isn't initialized in all conditions
+error[E0381]: used binding `i` is possibly-uninitialized
   --> $DIR/borrowck-or-init.rs:5:20
    |
 LL |     let i: isize;
@@ -7,7 +7,7 @@ LL |
 LL |     println!("{}", false || { i = 5; true });
    |                               ----- binding initialized here in some conditions
 LL |     println!("{}", i);
-   |                    ^ `i` used here but it isn't initialized in all conditions
+   |                    ^ `i` used here but it is possibly-uninitialized
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/borrowck-while-break.stderr b/src/test/ui/borrowck/borrowck-while-break.stderr
index ab7d50b834a4e..44674febf4973 100644
--- a/src/test/ui/borrowck/borrowck-while-break.stderr
+++ b/src/test/ui/borrowck/borrowck-while-break.stderr
@@ -1,13 +1,13 @@
-error[E0381]: used binding `v` isn't initialized in all conditions
+error[E0381]: used binding `v` is possibly-uninitialized
   --> $DIR/borrowck-while-break.rs:7:20
    |
 LL |     let v;
    |         - binding declared here but left uninitialized
 LL |     while cond {
-   |           ---- `v` is uninitialized if this condition isn't met and the `while` loop runs 0 times
+   |           ---- if this condition isn't met and the `while` loop runs 0 times, `v` is not initialized
 ...
 LL |     println!("{}", v);
-   |                    ^ `v` used here but it isn't initialized in all conditions
+   |                    ^ `v` used here but it is possibly-uninitialized
    |
    = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/borrowck/borrowck-while.stderr b/src/test/ui/borrowck/borrowck-while.stderr
index 5bb86b11ba503..c45235990c383 100644
--- a/src/test/ui/borrowck/borrowck-while.stderr
+++ b/src/test/ui/borrowck/borrowck-while.stderr
@@ -1,12 +1,12 @@
-error[E0381]: used binding `x` isn't initialized in all conditions
+error[E0381]: used binding `x` is possibly-uninitialized
   --> $DIR/borrowck-while.rs:4:12
    |
 LL |     let mut x: isize;
    |         ----- binding declared here but left uninitialized
 LL |     while 1 == 1 { x = 10; }
-   |           ------ `x` is uninitialized if this condition isn't met and the `while` loop runs 0 times
+   |           ------ if this condition isn't met and the `while` loop runs 0 times, `x` is not initialized
 LL |     return x;
-   |            ^ `x` used here but it isn't initialized in all conditions
+   |            ^ `x` used here but it is possibly-uninitialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr
index 39933db364803..b7529389f0276 100644
--- a/src/test/ui/nll/match-cfg-fake-edges.stderr
+++ b/src/test/ui/nll/match-cfg-fake-edges.stderr
@@ -1,11 +1,11 @@
-error[E0381]: used binding `x` isn't initialized in all conditions
+error[E0381]: used binding `x` is possibly-uninitialized
   --> $DIR/match-cfg-fake-edges.rs:21:13
    |
 LL |     let x;
    |         - binding declared here but left uninitialized
 ...
 LL |             x;
-   |             ^ `x` used here but it isn't initialized in all conditions
+   |             ^ `x` used here but it is possibly-uninitialized
 
 error[E0382]: use of moved value: `x`
   --> $DIR/match-cfg-fake-edges.rs:35:13
diff --git a/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr b/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr
index a3d8c608f4b8b..30d5a6779fcd7 100644
--- a/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/chains-without-let.stderr
@@ -1,30 +1,30 @@
-error[E0381]: used binding `z` isn't initialized in all conditions
+error[E0381]: used binding `z` is possibly-uninitialized
   --> $DIR/chains-without-let.rs:3:34
    |
 LL |     let z;
    |         - binding declared here but left uninitialized
 LL |     if true && { z = 3; true} && z == 3 {}
-   |                  -----           ^ `z` used here but it isn't initialized in all conditions
+   |                  -----           ^ `z` used here but it is possibly-uninitialized
    |                  |
    |                  binding initialized here in some conditions
 
-error[E0381]: used binding `z` isn't initialized in all conditions
+error[E0381]: used binding `z` is possibly-uninitialized
   --> $DIR/chains-without-let.rs:9:31
    |
 LL |     let z;
    |         - binding declared here but left uninitialized
 LL |     true && { z = 3; true} && z == 3;
-   |               -----           ^ `z` used here but it isn't initialized in all conditions
+   |               -----           ^ `z` used here but it is possibly-uninitialized
    |               |
    |               binding initialized here in some conditions
 
-error[E0381]: used binding `z` isn't initialized in all conditions
+error[E0381]: used binding `z` is possibly-uninitialized
   --> $DIR/chains-without-let.rs:15:36
    |
 LL |     let z;
    |         - binding declared here but left uninitialized
 LL |     if false || { z = 3; false} || z == 3 {}
-   |                   -----            ^ `z` used here but it isn't initialized in all conditions
+   |                   -----            ^ `z` used here but it is possibly-uninitialized
    |                   |
    |                   binding initialized here in some conditions
 
diff --git a/src/test/ui/try-block/try-block-opt-init.stderr b/src/test/ui/try-block/try-block-opt-init.stderr
index 72e732599c00e..c397385017ff4 100644
--- a/src/test/ui/try-block/try-block-opt-init.stderr
+++ b/src/test/ui/try-block/try-block-opt-init.stderr
@@ -1,4 +1,4 @@
-error[E0381]: used binding `cfg_res` isn't initialized in all conditions
+error[E0381]: used binding `cfg_res` is possibly-uninitialized
   --> $DIR/try-block-opt-init.rs:15:5
    |
 LL |     let cfg_res;
@@ -8,7 +8,7 @@ LL |         cfg_res = 5;
    |         ----------- binding initialized here in some conditions
 ...
 LL |     assert_eq!(cfg_res, 5);
-   |     ^^^^^^^^^^^^^^^^^^^^^^ `cfg_res` used here but it isn't initialized in all conditions
+   |     ^^^^^^^^^^^^^^^^^^^^^^ `cfg_res` used here but it is possibly-uninitialized
    |
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 

From 0e69340c2a475b72b1a7261fa5aea06edd75dad7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Wed, 22 Jun 2022 11:26:08 -0700
Subject: [PATCH 08/20] Add test for `for` loop maybe initializing binding

---
 .../borrowck-for-loop-uninitialized-binding.rs      |  7 +++++++
 .../borrowck-for-loop-uninitialized-binding.stderr  | 13 +++++++++++++
 2 files changed, 20 insertions(+)
 create mode 100644 src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.rs
 create mode 100644 src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr

diff --git a/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.rs b/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.rs
new file mode 100644
index 0000000000000..f619c045b250f
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.rs
@@ -0,0 +1,7 @@
+fn f() -> isize {
+    let mut x: isize;
+    for _ in 0..0 { x = 10; }
+    return x; //~ ERROR E0381
+}
+
+fn main() { f(); }
diff --git a/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr b/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr
new file mode 100644
index 0000000000000..c08c93f361726
--- /dev/null
+++ b/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr
@@ -0,0 +1,13 @@
+error[E0381]: used binding `x` is possibly-uninitialized
+  --> $DIR/borrowck-for-loop-uninitialized-binding.rs:4:12
+   |
+LL |     let mut x: isize;
+   |         ----- binding declared here but left uninitialized
+LL |     for _ in 0..0 { x = 10; }
+   |              ---- if the `for` loop runs 0 times, `x` is not initialized 
+LL |     return x;
+   |            ^ `x` used here but it is possibly-uninitialized
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.

From 6eadf6ee6a3163288e8324ee53af11aba9f97659 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Wed, 22 Jun 2022 12:59:48 -0700
Subject: [PATCH 09/20] Avoid misleading message/label in
 `match-cfg-fake-edges.rs` test

---
 .../src/diagnostics/conflict_errors.rs        | 64 ++++++++++++-------
 src/test/ui/nll/match-cfg-fake-edges.stderr   |  7 +-
 2 files changed, 46 insertions(+), 25 deletions(-)

diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 54dff1b6c6b14..7598b9a265977 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -339,23 +339,48 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 Some(name) => (format!("`{name}`"), format!("`{name}`"), format!("`{name}` ")),
                 None => ("value".to_string(), "the variable".to_string(), String::new()),
             };
+
+        // We use the statements were the binding was initialized, and inspect the HIR to look
+        // for the branching codepaths that aren't covered, to point at them.
+        let hir_id = self.mir_hir_id();
+        let map = self.infcx.tcx.hir();
+        let body_id = map.body_owned_by(hir_id);
+        let body = map.body(body_id);
+
+        let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
+        visitor.visit_body(&body);
+
         let isnt_initialized =
             if let InitializationRequiringAction::PartialAssignment = desired_action {
                 // The same error is emitted for bindings that are *sometimes* initialized and the ones
                 // that are *partially* initialized by assigning to a field of an uninitialized
                 // binding. We differentiate between them for more accurate wording here.
                 "isn't fully initialized"
-            } else if spans.iter().filter(|i| !i.contains(span)).count() == 0 {
-                // We filter above to avoid misleading wording in cases like the following, where `x`
-                // has an `init`, but it is in the same place we're looking at:
-                // ```
-                // let x;
-                // x += 1;
-                // ```
+            } else if spans
+                .iter()
+                .filter(|i| {
+                    // We filter these to avoid misleading wording in cases like the following,
+                    // where `x` has an `init`, but it is in the same place we're looking at:
+                    // ```
+                    // let x;
+                    // x += 1;
+                    // ```
+                    !i.contains(span)
+                    // We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs`
+                        && !visitor
+                            .errors
+                            .iter()
+                            .map(|(sp, _)| *sp)
+                            .any(|sp| span < sp && !sp.contains(span))
+                })
+                .count()
+                == 0
+            {
                 "isn't initialized"
             } else {
                 "is possibly-uninitialized"
             };
+
         let used = desired_action.as_general_verb_in_past_tense();
         let mut err =
             struct_span_err!(self, span, E0381, "{used} binding {desc}{isnt_initialized}");
@@ -372,22 +397,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
         err.span_label(span, format!("{binding} {used} here but it {isnt_initialized}"));
 
-        // We use the statements were the binding was initialized, and inspect the HIR to look
-        // for the branching codepaths that aren't covered, to point at them.
-        let hir_id = self.mir_hir_id();
-        let map = self.infcx.tcx.hir();
-        let body_id = map.body_owned_by(hir_id);
-        let body = map.body(body_id);
-
-        let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
-        visitor.visit_body(&body);
-        if visitor.errors.is_empty() {
-            for sp in &spans {
-                if *sp < span && !sp.overlaps(span) {
-                    err.span_label(*sp, "binding initialized here in some conditions");
-                }
-            }
-        }
+        let mut shown = false;
         for (sp, label) in visitor.errors {
             if sp < span && !sp.overlaps(span) {
                 // When we have a case like `match-cfg-fake-edges.rs`, we don't want to mention
@@ -404,6 +414,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 // };
                 // ```
                 err.span_label(sp, &label);
+                shown = true;
+            }
+        }
+        if !shown {
+            for sp in &spans {
+                if *sp < span && !sp.overlaps(span) {
+                    err.span_label(*sp, "binding initialized here in some conditions");
+                }
             }
         }
         err.span_label(decl_span, "binding declared here but left uninitialized");
diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr
index b7529389f0276..250aa482e5c67 100644
--- a/src/test/ui/nll/match-cfg-fake-edges.stderr
+++ b/src/test/ui/nll/match-cfg-fake-edges.stderr
@@ -1,11 +1,14 @@
-error[E0381]: used binding `x` is possibly-uninitialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/match-cfg-fake-edges.rs:21:13
    |
 LL |     let x;
    |         - binding declared here but left uninitialized
 ...
+LL |         _ if { x = 2; true } => 1,
+   |                ----- binding initialized here in some conditions
+LL |         _ if {
 LL |             x;
-   |             ^ `x` used here but it is possibly-uninitialized
+   |             ^ `x` used here but it isn't initialized
 
 error[E0382]: use of moved value: `x`
   --> $DIR/match-cfg-fake-edges.rs:35:13

From cc4f804829ae56753acd2ef9c0f4bb741f5b3bae Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Mon, 20 Jun 2022 16:28:52 +0200
Subject: [PATCH 10/20] Move help popup into a pocket menu as well

---
 src/librustdoc/html/static/css/rustdoc.css    |  74 ++++----
 src/librustdoc/html/static/css/settings.css   |  21 ---
 src/librustdoc/html/static/css/themes/ayu.css |   9 +-
 .../html/static/css/themes/dark.css           |   9 +-
 .../html/static/css/themes/light.css          |   9 +-
 src/librustdoc/html/static/js/main.js         | 176 +++++++++++-------
 src/librustdoc/html/static/js/settings.js     |  30 +--
 src/librustdoc/html/templates/page.html       |   4 +-
 8 files changed, 173 insertions(+), 159 deletions(-)

diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index d0229bdb5f23c..77062770c189d 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -979,42 +979,51 @@ table,
 	font-weight: normal;
 }
 
-body.blur > :not(#help) {
-	filter: blur(8px);
-	-webkit-filter: blur(8px);
-	opacity: .7;
+.popover {
+	font-size: 1rem;
+	position: absolute;
+	right: 0;
+	z-index: 2;
+	display: block;
+	margin-top: 7px;
+	border-radius: 3px;
+	border: 1px solid;
+	font-size: 1rem;
 }
 
-#help {
-	width: 100%;
-	height: 100vh;
-	position: fixed;
-	top: 0;
-	left: 0;
-	display: flex;
-	justify-content: center;
-	align-items: center;
+/* This rule is to draw the little arrow connecting the settings menu to the gear icon. */
+.popover::before {
+	content: '';
+	position: absolute;
+	right: 11px;
+	border: solid;
+	border-width: 1px 1px 0 0;
+	display: inline-block;
+	padding: 4px;
+	transform: rotate(-45deg);
+	top: -5px;
 }
-#help > div {
-	flex: 0 0 auto;
-	box-shadow: 0 0 6px rgba(0,0,0,.2);
-	width: 550px;
-	height: auto;
-	border: 1px solid;
+
+#help-button .popover {
+	max-width: 600px;
 }
-#help dt {
+
+#help-button .popover::before {
+	right: 48px;
+}
+
+#help-button dt {
 	float: left;
 	clear: left;
 	display: block;
 	margin-right: 0.5rem;
 }
-#help span.top, #help span.bottom {
+#help-button span.top, #help-button span.bottom {
 	text-align: center;
 	display: block;
 	font-size: 1.125rem;
-
 }
-#help span.top {
+#help-button span.top {
 	text-align: center;
 	display: block;
 	margin: 10px 0;
@@ -1022,17 +1031,17 @@ body.blur > :not(#help) {
 	padding-bottom: 4px;
 	margin-bottom: 6px;
 }
-#help span.bottom {
+#help-button span.bottom {
 	clear: both;
 	border-top: 1px solid;
 }
-#help dd { margin: 5px 35px; }
-#help .infos { padding-left: 0; }
-#help h1, #help h2 { margin-top: 0; }
-#help > div div {
+.side-by-side {
+	text-align: initial;
+}
+.side-by-side > div {
 	width: 50%;
 	float: left;
-	padding: 0 20px 20px 17px;;
+	padding: 0 20px 20px 17px;
 }
 
 .item-info .stab {
@@ -1387,7 +1396,7 @@ pre.rust {
 #copy-path {
 	height: 34px;
 }
-#settings-menu > a, #help-button, #copy-path {
+#settings-menu > a, #help-button > button, #copy-path {
 	padding: 5px;
 	width: 33px;
 	border: 1px solid;
@@ -1397,9 +1406,8 @@ pre.rust {
 #settings-menu {
 	padding: 0;
 }
-#settings-menu > a {
+#settings-menu > a, #help-button > button {
 	padding: 5px;
-	width: 100%;
 	height: 100%;
 	display: block;
 }
@@ -1416,7 +1424,7 @@ pre.rust {
 	animation: rotating 2s linear infinite;
 }
 
-#help-button {
+#help-button > button {
 	font-family: "Fira Sans", Arial, sans-serif;
 	text-align: center;
 	/* Rare exception to specifying font sizes in rem. Since this is acting
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index 1cd8e39e03648..e531e6ce6bbde 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -86,27 +86,6 @@ input:checked + .slider:before {
 	display: block;
 }
 
-div#settings {
-	position: absolute;
-	right: 0;
-	z-index: 1;
-	display: block;
-	margin-top: 7px;
-	border-radius: 3px;
-	border: 1px solid;
-}
 #settings .setting-line {
 	margin: 1.2em 0.6em;
 }
-/* This rule is to draw the little arrow connecting the settings menu to the gear icon. */
-div#settings::before {
-	content: '';
-	position: absolute;
-	right: 11px;
-	border: solid;
-	border-width: 1px 1px 0 0;
-	display: inline-block;
-	padding: 4px;
-	transform: rotate(-45deg);
-	top: -5px;
-}
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 8e0521d9ad6a1..d27294657192c 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -5,7 +5,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 
 /* General structure and fonts */
 
-body, #settings-menu #settings, #settings-menu #settings::before {
+body, .popover, .popover::before {
 	background-color: #0f1419;
 	color: #c5c5c5;
 }
@@ -567,7 +567,7 @@ kbd {
 	box-shadow: inset 0 -1px 0 #5c6773;
 }
 
-#settings-menu > a, #help-button {
+#settings-menu > a, #help-button > button {
 	border-color: #5c6773;
 	background-color: #0f1419;
 	color: #fff;
@@ -577,7 +577,8 @@ kbd {
 	filter: invert(100);
 }
 
-#settings-menu #settings, #settings-menu #settings::before {
+.popover, .popover::before,
+#help-button span.top, #help-button span.bottom {
 	border-color: #5c6773;
 }
 
@@ -592,7 +593,7 @@ kbd {
 }
 
 #settings-menu > a:hover, #settings-menu > a:focus,
-#help-button:hover, #help-button:focus {
+#help-button > button:hover, #help-button > button:focus {
 	border-color: #e0e0e0;
 }
 
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 071ad006ed350..48079ea2f3041 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -1,4 +1,4 @@
-body, #settings-menu #settings, #settings-menu #settings::before {
+body, .popover, .popover::before {
 	background-color: #353535;
 	color: #ddd;
 }
@@ -442,18 +442,19 @@ kbd {
 	box-shadow: inset 0 -1px 0 #c6cbd1;
 }
 
-#settings-menu > a, #help-button {
+#settings-menu > a, #help-button > button {
 	border-color: #e0e0e0;
 	background: #f0f0f0;
 	color: #000;
 }
 
 #settings-menu > a:hover, #settings-menu > a:focus,
-#help-button:hover, #help-button:focus {
+#help-button > button:hover, #help-button > button:focus {
 	border-color: #ffb900;
 }
 
-#settings-menu #settings, #settings-menu #settings::before {
+.popover, .popover::before,
+#help-button span.top, #help-button span.bottom {
 	border-color: #d2d2d2;
 }
 
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 5c3789bf4630a..f4016be967963 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -1,6 +1,6 @@
 /* General structure and fonts */
 
-body, #settings-menu #settings, #settings-menu #settings::before {
+body, .popover, .popover::before {
 	background-color: white;
 	color: black;
 }
@@ -427,17 +427,18 @@ kbd {
 	box-shadow: inset 0 -1px 0 #c6cbd1;
 }
 
-#settings-menu > a, #help-button {
+#settings-menu > a, #help-button > button {
 	border-color: #e0e0e0;
 	background-color: #fff;
 }
 
 #settings-menu > a:hover, #settings-menu > a:focus,
-#help-button:hover, #help-button:focus {
+#help-button > button:hover, #help-button > button:focus {
 	border-color: #717171;
 }
 
-#settings-menu #settings, #settings-menu #settings::before {
+.popover, .popover::before,
+#help-button span.top, #help-button span.bottom {
 	border-color: #DDDDDD;
 }
 
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index b320db9104612..1ea645d3e6594 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -63,6 +63,24 @@ function showMain() {
     removeClass(document.getElementById(MAIN_ID), "hidden");
 }
 
+function elemIsInParent(elem, parent) {
+    while (elem && elem !== document.body) {
+        if (elem === parent) {
+            return true;
+        }
+        elem = elem.parentElement;
+    }
+    return false;
+}
+
+function blurHandler(event, parentElem, hideCallback) {
+    if (!elemIsInParent(document.activeElement, parentElem) &&
+        !elemIsInParent(event.relatedTarget, parentElem)
+    ) {
+        hideCallback();
+    }
+}
+
 (function() {
     window.rootPath = getVar("root-path");
     window.currentCrate = getVar("current-crate");
@@ -104,11 +122,16 @@ const MAIN_ID = "main-content";
 const SETTINGS_BUTTON_ID = "settings-menu";
 const ALTERNATIVE_DISPLAY_ID = "alternative-display";
 const NOT_DISPLAYED_ID = "not-displayed";
+const HELP_BUTTON_ID = "help-button";
 
 function getSettingsButton() {
     return document.getElementById(SETTINGS_BUTTON_ID);
 }
 
+function getHelpButton() {
+    return document.getElementById(HELP_BUTTON_ID);
+}
+
 // Returns the current URL without any query parameter or hash.
 function getNakedUrl() {
     return window.location.href.split("?")[0].split("#")[0];
@@ -381,55 +404,17 @@ function loadCss(cssFileName) {
         openParentDetails(document.getElementById(id));
     }
 
-    function getHelpElement(build) {
-        if (build) {
-            buildHelperPopup();
-        }
-        return document.getElementById("help");
-    }
-
-    /**
-     * Show the help popup.
-     *
-     * @param {boolean} display    - Whether to show or hide the popup
-     * @param {Event}   ev         - The event that triggered this call
-     * @param {Element} [help]     - The help element if it already exists
-     */
-    function displayHelp(display, ev, help) {
-        if (display) {
-            help = help ? help : getHelpElement(true);
-            if (hasClass(help, "hidden")) {
-                ev.preventDefault();
-                removeClass(help, "hidden");
-                addClass(document.body, "blur");
-            }
-        } else {
-            // No need to build the help popup if we want to hide it in case it hasn't been
-            // built yet...
-            help = help ? help : getHelpElement(false);
-            if (help && !hasClass(help, "hidden")) {
-                ev.preventDefault();
-                addClass(help, "hidden");
-                removeClass(document.body, "blur");
-            }
-        }
-    }
-
     function handleEscape(ev) {
         searchState.clearInputTimeout();
-        const help = getHelpElement(false);
-        if (help && !hasClass(help, "hidden")) {
-            displayHelp(false, ev, help);
-        } else {
-            switchDisplayedElement(null);
-            if (browserSupportsHistoryApi()) {
-                history.replaceState(null, window.currentCrate + " - Rust",
-                    getNakedUrl() + window.location.hash);
-            }
-            ev.preventDefault();
+        switchDisplayedElement(null);
+        if (browserSupportsHistoryApi()) {
+            history.replaceState(null, window.currentCrate + " - Rust",
+                getNakedUrl() + window.location.hash);
         }
+        ev.preventDefault();
         searchState.defocus();
         window.hideSettings();
+        hideHelp();
     }
 
     const disableShortcuts = getSettingValue("disable-shortcuts") === "true";
@@ -453,7 +438,6 @@ function loadCss(cssFileName) {
 
             case "s":
             case "S":
-                displayHelp(false, ev);
                 ev.preventDefault();
                 searchState.focus();
                 break;
@@ -465,7 +449,7 @@ function loadCss(cssFileName) {
                 break;
 
             case "?":
-                displayHelp(true, ev);
+                showHelp();
                 break;
 
             default:
@@ -796,9 +780,6 @@ function loadCss(cssFileName) {
             elem.addEventListener("click", f);
         }
     }
-    handleClick("help-button", ev => {
-        displayHelp(true, ev);
-    });
     handleClick(MAIN_ID, () => {
         hideSidebar();
     });
@@ -842,24 +823,16 @@ function loadCss(cssFileName) {
         });
     }
 
-    let buildHelperPopup = () => {
-        const popup = document.createElement("aside");
-        addClass(popup, "hidden");
-        popup.id = "help";
-
-        popup.addEventListener("click", ev => {
-            if (ev.target === popup) {
-                // Clicked the blurred zone outside the help popup; dismiss help.
-                displayHelp(false, ev);
-            }
-        });
+    function helpBlurHandler(event) {
+        blurHandler(event, getHelpButton(), hideHelp);
+    }
 
+    function buildHelpMenu() {
         const book_info = document.createElement("span");
         book_info.className = "top";
         book_info.innerHTML = "You can find more information in \
             <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
 
-        const container = document.createElement("div");
         const shortcuts = [
             ["?", "Show this help dialog"],
             ["S", "Focus the search field"],
@@ -895,23 +868,86 @@ function loadCss(cssFileName) {
         addClass(div_infos, "infos");
         div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos;
 
-        container.appendChild(book_info);
-        container.appendChild(div_shortcuts);
-        container.appendChild(div_infos);
-
         const rustdoc_version = document.createElement("span");
         rustdoc_version.className = "bottom";
         const rustdoc_version_code = document.createElement("code");
         rustdoc_version_code.innerText = "rustdoc " + getVar("rustdoc-version");
         rustdoc_version.appendChild(rustdoc_version_code);
 
+        const container = document.createElement("div");
+        container.className = "popover";
+        container.style.display = "none";
+
+        const side_by_side = document.createElement("div");
+        side_by_side.className = "side-by-side";
+        side_by_side.appendChild(div_shortcuts);
+        side_by_side.appendChild(div_infos);
+
+        container.appendChild(book_info);
+        container.appendChild(side_by_side);
         container.appendChild(rustdoc_version);
 
-        popup.appendChild(container);
-        insertAfter(popup, document.querySelector("main"));
-        // So that it's only built once and then it'll do nothing when called!
-        buildHelperPopup = () => {};
-    };
+        const help_button = getHelpButton();
+        help_button.appendChild(container);
+
+        container.onblur = helpBlurHandler;
+        container.onclick = event => {
+            event.preventDefault();
+        };
+        help_button.onblur = helpBlurHandler;
+        help_button.children[0].onblur = helpBlurHandler;
+
+        return container;
+    }
+
+    /**
+     * Returns the help menu element (not the button).
+     *
+     * @param {boolean} buildNeeded - If this argument is `false`, the help menu element won't be
+     *                                built if it doesn't exist.
+     *
+     * @return {HTMLElement}
+     */
+    function getHelpMenu(buildNeeded) {
+        let menu = getHelpButton().querySelector(".popover");
+        if (!menu && buildNeeded) {
+            menu = buildHelpMenu();
+        }
+        return menu;
+    }
+
+    /**
+     * Show the help popup menu.
+     */
+    function showHelp() {
+        const menu = getHelpMenu(true);
+        if (menu.style.display === "none") {
+            menu.style.display = "";
+        }
+    }
+
+    /**
+     * Hide the help popup menu.
+     */
+    function hideHelp() {
+        const menu = getHelpMenu(false);
+        if (menu && menu.style.display !== "none") {
+            menu.style.display = "none";
+        }
+    }
+
+    document.querySelector(`#${HELP_BUTTON_ID} > button`).addEventListener("click", event => {
+        const target = event.target;
+        if (target.tagName !== "BUTTON" || target.parentElement.id !== HELP_BUTTON_ID) {
+            return;
+        }
+        const menu = getHelpMenu(true);
+        if (menu.style.display !== "none") {
+            hideHelp();
+        } else {
+            showHelp();
+        }
+    });
 
     setMobileTopbar();
     addSidebarItems();
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 41bf0ec895580..2445773a96542 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -1,6 +1,6 @@
 // Local js definitions:
 /* global getSettingValue, getVirtualKey, updateLocalStorage, updateSystemTheme */
-/* global addClass, removeClass, onEach, onEachLazy */
+/* global addClass, removeClass, onEach, onEachLazy, blurHandler, elemIsInParent */
 /* global MAIN_ID, getVar, getSettingsButton */
 
 "use strict";
@@ -209,6 +209,7 @@
         const innerHTML = `<div class="settings">${buildSettingsPageSections(settings)}</div>`;
         const el = document.createElement(elementKind);
         el.id = "settings";
+        el.className = "popover";
         el.innerHTML = innerHTML;
 
         if (isSettingsPage) {
@@ -226,23 +227,8 @@
         settingsMenu.style.display = "";
     }
 
-    function elemIsInParent(elem, parent) {
-        while (elem && elem !== document.body) {
-            if (elem === parent) {
-                return true;
-            }
-            elem = elem.parentElement;
-        }
-        return false;
-    }
-
-    function blurHandler(event) {
-        const settingsButton = getSettingsButton();
-        if (!elemIsInParent(document.activeElement, settingsButton) &&
-            !elemIsInParent(event.relatedTarget, settingsButton)
-        ) {
-            window.hideSettings();
-        }
+    function settingsBlurHandler(event) {
+        blurHandler(event, getSettingsButton(), window.hideSettings);
     }
 
     if (isSettingsPage) {
@@ -268,12 +254,12 @@
                 displaySettings();
             }
         };
-        settingsButton.onblur = blurHandler;
-        settingsButton.querySelector("a").onblur = blurHandler;
+        settingsButton.onblur = settingsBlurHandler;
+        settingsButton.querySelector("a").onblur = settingsBlurHandler;
         onEachLazy(settingsMenu.querySelectorAll("input"), el => {
-            el.onblur = blurHandler;
+            el.onblur = settingsBlurHandler;
         });
-        settingsMenu.onblur = blurHandler;
+        settingsMenu.onblur = settingsBlurHandler;
     }
 
     // We now wait a bit for the web browser to end re-computing the DOM...
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index c4999e2c74fce..dfb3e4e6a2ccd 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -119,7 +119,9 @@ <h2 class="location"></h2>
                                 spellcheck="false" {# -#}
                                 placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {# -#}
                                 type="search"> {#- -#}
-                            <button type="button" id="help-button" title="help">?</button> {#- -#}
+                            <div id="help-button" title="help" tabindex="-1"> {#- -#}
+                                <button type="button">?</button> {#- -#}
+                            </div> {#- -#}
                             <div id="settings-menu" tabindex="-1">
                                 <a href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#}
                                     <img width="22" height="22" alt="Change settings" {# -#}

From 3eb9e1a7ae62ed074056928b7ae12ab5db713f07 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Mon, 20 Jun 2022 16:29:16 +0200
Subject: [PATCH 11/20] Add/update GUI tests for help pocket menu

---
 src/test/rustdoc-gui/escape-key.goml  | 12 -----
 src/test/rustdoc-gui/pocket-menu.goml | 72 +++++++++++++++++++++++++++
 src/test/rustdoc-gui/shortcuts.goml   |  5 +-
 3 files changed, 74 insertions(+), 15 deletions(-)
 create mode 100644 src/test/rustdoc-gui/pocket-menu.goml

diff --git a/src/test/rustdoc-gui/escape-key.goml b/src/test/rustdoc-gui/escape-key.goml
index 8713bf65c8432..d083b0ae0c931 100644
--- a/src/test/rustdoc-gui/escape-key.goml
+++ b/src/test/rustdoc-gui/escape-key.goml
@@ -21,17 +21,6 @@ wait-for: "#alternative-display #search"
 assert-attribute: ("#main-content", {"class": "content hidden"})
 assert-document-property: ({"URL": "index.html?search=test"}, ENDS_WITH)
 
-// Now let's check that when the help popup is displayed and we press Escape, it doesn't
-// hide the search results too.
-click: "#help-button"
-assert-document-property: ({"URL": "index.html?search=test"}, [ENDS_WITH])
-assert-attribute: ("#help", {"class": ""})
-press-key: "Escape"
-wait-for: "#alternative-display #search"
-assert-attribute: ("#help", {"class": "hidden"})
-assert-attribute: ("#main-content", {"class": "content hidden"})
-assert-document-property: ({"URL": "index.html?search=test"}, [ENDS_WITH])
-
 // Check that Escape hides the search results when a search result is focused.
 focus: ".search-input"
 assert: ".search-input:focus"
@@ -39,7 +28,6 @@ press-key: "ArrowDown"
 assert-false: ".search-input:focus"
 assert: "#results a:focus"
 press-key: "Escape"
-assert-attribute: ("#help", {"class": "hidden"})
 wait-for: "#not-displayed #search"
 assert-false: "#alternative-display #search"
 assert-attribute: ("#main-content", {"class": "content"})
diff --git a/src/test/rustdoc-gui/pocket-menu.goml b/src/test/rustdoc-gui/pocket-menu.goml
new file mode 100644
index 0000000000000..ba2986e969a35
--- /dev/null
+++ b/src/test/rustdoc-gui/pocket-menu.goml
@@ -0,0 +1,72 @@
+// This test ensures that the "pocket menus" are working as expected.
+goto: file://|DOC_PATH|/test_docs/index.html
+// First we check that the help menu doesn't exist yet.
+assert-false: "#help-button .popover"
+// Then we display the help menu.
+click: "#help-button"
+assert: "#help-button .popover"
+assert-css: ("#help-button .popover", {"display": "block"})
+
+// Now we click somewhere else on the page to ensure it is handling the blur event
+// correctly.
+click: ".sidebar"
+assert-css: ("#help-button .popover", {"display": "none"})
+
+// Now we will check that we cannot have two "pocket menus" displayed at the same time.
+click: "#help-button"
+assert-css: ("#help-button .popover", {"display": "block"})
+click: "#settings-menu"
+assert-css: ("#help-button .popover", {"display": "none"})
+assert-css: ("#settings-menu .popover", {"display": "block"})
+
+// Now the other way.
+click: "#help-button"
+assert-css: ("#help-button .popover", {"display": "block"})
+assert-css: ("#settings-menu .popover", {"display": "none"})
+
+// We check the borders color now:
+
+// Ayu theme
+local-storage: {
+    "rustdoc-theme": "ayu",
+    "rustdoc-use-system-theme": "false",
+}
+reload:
+
+click: "#help-button"
+assert-css: (
+    "#help-button .popover",
+    {"display": "block", "border-color": "rgb(92, 103, 115)"},
+)
+compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"])
+compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
+
+// Dark theme
+local-storage: {
+    "rustdoc-theme": "dark",
+    "rustdoc-use-system-theme": "false",
+}
+reload:
+
+click: "#help-button"
+assert-css: (
+    "#help-button .popover",
+    {"display": "block", "border-color": "rgb(210, 210, 210)"},
+)
+compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"])
+compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
+
+// Light theme
+local-storage: {
+    "rustdoc-theme": "light",
+    "rustdoc-use-system-theme": "false",
+}
+reload:
+
+click: "#help-button"
+assert-css: (
+    "#help-button .popover",
+    {"display": "block", "border-color": "rgb(221, 221, 221)"},
+)
+compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"])
+compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
diff --git a/src/test/rustdoc-gui/shortcuts.goml b/src/test/rustdoc-gui/shortcuts.goml
index 37a7c1662949d..1f20a0eaa9982 100644
--- a/src/test/rustdoc-gui/shortcuts.goml
+++ b/src/test/rustdoc-gui/shortcuts.goml
@@ -8,7 +8,6 @@ press-key: "Escape"
 assert-false: "input.search-input:focus"
 // We now check for the help popup.
 press-key: "?"
-assert-css: ("#help", {"display": "flex"})
-assert-false: "#help.hidden"
+assert-css: ("#help-button .popover", {"display": "block"})
 press-key: "Escape"
-assert-css: ("#help.hidden", {"display": "none"})
+assert-css: ("#help-button .popover", {"display": "none"})

From e4b2b41290f6b49441b5b9c8e013458bc23caeeb Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Wed, 22 Jun 2022 20:49:26 +0200
Subject: [PATCH 12/20] Merge all popover hide functions into one

---
 src/librustdoc/html/static/js/main.js     | 33 +++++++++--------------
 src/librustdoc/html/static/js/settings.js | 12 ++++-----
 2 files changed, 18 insertions(+), 27 deletions(-)

diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 1ea645d3e6594..70dbfd4442540 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -137,10 +137,6 @@ function getNakedUrl() {
     return window.location.href.split("?")[0].split("#")[0];
 }
 
-window.hideSettings = () => {
-    // Does nothing by default.
-};
-
 /**
  * This function inserts `newNode` after `referenceNode`. It doesn't work if `referenceNode`
  * doesn't have a parent node.
@@ -413,8 +409,7 @@ function loadCss(cssFileName) {
         }
         ev.preventDefault();
         searchState.defocus();
-        window.hideSettings();
-        hideHelp();
+        window.hidePopoverMenus();
     }
 
     const disableShortcuts = getSettingValue("disable-shortcuts") === "true";
@@ -824,7 +819,7 @@ function loadCss(cssFileName) {
     }
 
     function helpBlurHandler(event) {
-        blurHandler(event, getHelpButton(), hideHelp);
+        blurHandler(event, getHelpButton(), window.hidePopoverMenus);
     }
 
     function buildHelpMenu() {
@@ -900,6 +895,15 @@ function loadCss(cssFileName) {
         return container;
     }
 
+    /**
+     * Hide all the popover menus.
+     */
+    window.hidePopoverMenus = function() {
+        onEachLazy(document.querySelectorAll(".search-container .popover"), elem => {
+            elem.style.display = "none";
+        });
+    };
+
     /**
      * Returns the help menu element (not the button).
      *
@@ -926,25 +930,14 @@ function loadCss(cssFileName) {
         }
     }
 
-    /**
-     * Hide the help popup menu.
-     */
-    function hideHelp() {
-        const menu = getHelpMenu(false);
-        if (menu && menu.style.display !== "none") {
-            menu.style.display = "none";
-        }
-    }
-
     document.querySelector(`#${HELP_BUTTON_ID} > button`).addEventListener("click", event => {
         const target = event.target;
         if (target.tagName !== "BUTTON" || target.parentElement.id !== HELP_BUTTON_ID) {
             return;
         }
         const menu = getHelpMenu(true);
-        if (menu.style.display !== "none") {
-            hideHelp();
-        } else {
+        const shouldShowHelp = menu.style.display === "none";
+        if (shouldShowHelp) {
             showHelp();
         }
     });
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 2445773a96542..797b931afc643 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -228,7 +228,7 @@
     }
 
     function settingsBlurHandler(event) {
-        blurHandler(event, getSettingsButton(), window.hideSettings);
+        blurHandler(event, getSettingsButton(), window.hidePopoverMenus);
     }
 
     if (isSettingsPage) {
@@ -240,17 +240,15 @@
         // We replace the existing "onclick" callback.
         const settingsButton = getSettingsButton();
         const settingsMenu = document.getElementById("settings");
-        window.hideSettings = function() {
-            settingsMenu.style.display = "none";
-        };
         settingsButton.onclick = function(event) {
             if (elemIsInParent(event.target, settingsMenu)) {
                 return;
             }
             event.preventDefault();
-            if (settingsMenu.style.display !== "none") {
-                window.hideSettings();
-            } else {
+            const shouldDisplaySettings = settingsMenu.style.display === "none";
+
+            window.hidePopoverMenus();
+            if (shouldDisplaySettings) {
                 displaySettings();
             }
         };

From 8495c640bc8b263788422319dc3eee50fad23dbd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Wed, 22 Jun 2022 15:36:26 -0700
Subject: [PATCH 13/20] Fix label on uninit binding field assignment

---
 .../src/diagnostics/conflict_errors.rs        | 49 ++++++++++---------
 .../borrowck/borrowck-partial-reinit-4.stderr |  4 +-
 ...1232-partial-init-and-erroneous-use.stderr |  8 +--
 3 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 7598b9a265977..73baad614c8f1 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -350,36 +350,37 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
         visitor.visit_body(&body);
 
-        let isnt_initialized =
-            if let InitializationRequiringAction::PartialAssignment = desired_action {
-                // The same error is emitted for bindings that are *sometimes* initialized and the ones
-                // that are *partially* initialized by assigning to a field of an uninitialized
-                // binding. We differentiate between them for more accurate wording here.
-                "isn't fully initialized"
-            } else if spans
-                .iter()
-                .filter(|i| {
-                    // We filter these to avoid misleading wording in cases like the following,
-                    // where `x` has an `init`, but it is in the same place we're looking at:
-                    // ```
-                    // let x;
-                    // x += 1;
-                    // ```
-                    !i.contains(span)
+        let isnt_initialized = if let InitializationRequiringAction::PartialAssignment
+        | InitializationRequiringAction::Assignment = desired_action
+        {
+            // The same error is emitted for bindings that are *sometimes* initialized and the ones
+            // that are *partially* initialized by assigning to a field of an uninitialized
+            // binding. We differentiate between them for more accurate wording here.
+            "isn't fully initialized"
+        } else if spans
+            .iter()
+            .filter(|i| {
+                // We filter these to avoid misleading wording in cases like the following,
+                // where `x` has an `init`, but it is in the same place we're looking at:
+                // ```
+                // let x;
+                // x += 1;
+                // ```
+                !i.contains(span)
                     // We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs`
                         && !visitor
                             .errors
                             .iter()
                             .map(|(sp, _)| *sp)
                             .any(|sp| span < sp && !sp.contains(span))
-                })
-                .count()
-                == 0
-            {
-                "isn't initialized"
-            } else {
-                "is possibly-uninitialized"
-            };
+            })
+            .count()
+            == 0
+        {
+            "isn't initialized"
+        } else {
+            "is possibly-uninitialized"
+        };
 
         let used = desired_action.as_general_verb_in_past_tense();
         let mut err =
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
index 06351a943064b..7b5b64ff8cd23 100644
--- a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
@@ -1,10 +1,10 @@
-error[E0381]: assigned binding `x.0` isn't initialized
+error[E0381]: assigned binding `x.0` isn't fully initialized
   --> $DIR/borrowck-partial-reinit-4.rs:17:5
    |
 LL |     let mut x : (Test2, Test2);
    |         ----- binding declared here but left uninitialized
 LL |     (x.0).0 = Some(Test);
-   |     ^^^^^^^ `x.0` assigned here but it isn't initialized
+   |     ^^^^^^^ `x.0` assigned here but it isn't fully initialized
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
index f56b6294c2093..9ecfe2f754ac5 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
+++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
@@ -1,18 +1,18 @@
-error[E0381]: assigned binding `d` isn't initialized
+error[E0381]: assigned binding `d` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:28:5
    |
 LL |     let d: D;
    |         - binding declared here but left uninitialized
 LL |     d.x = 10;
-   |     ^^^^^^^^ `d` assigned here but it isn't initialized
+   |     ^^^^^^^^ `d` assigned here but it isn't fully initialized
 
-error[E0381]: assigned binding `d` isn't initialized
+error[E0381]: assigned binding `d` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:33:5
    |
 LL |     let mut d: D;
    |         ----- binding declared here but left uninitialized
 LL |     d.x = 10;
-   |     ^^^^^^^^ `d` assigned here but it isn't initialized
+   |     ^^^^^^^^ `d` assigned here but it isn't fully initialized
 
 error[E0382]: assign of moved value: `d`
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:39:5

From 6dd32f2742610d98fcf096a7f5141a70b17c6521 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Thu, 23 Jun 2022 10:42:17 -0700
Subject: [PATCH 14/20] Wording tweak

---
 .../src/diagnostics/conflict_errors.rs        | 29 ++++++++++++++-----
 .../ui/borrowck/borrowck-init-in-fru.stderr   |  2 +-
 .../borrowck/borrowck-partial-reinit-4.stderr |  2 ++
 .../borrowck-uninit-field-access.stderr       |  2 +-
 .../borrowck/borrowck-uninit-ref-chain.stderr |  6 ++--
 .../borrowck-use-in-index-lvalue.stderr       |  4 +--
 ...wck-use-uninitialized-in-cast-trait.stderr |  2 +-
 .../borrowck-use-uninitialized-in-cast.stderr |  2 +-
 ...const-generic-default-wont-borrowck.stderr |  2 +-
 ...1232-partial-init-and-erroneous-use.stderr |  8 +++--
 .../issue-21232-partial-init-and-use.stderr   | 12 ++++----
 11 files changed, 45 insertions(+), 26 deletions(-)

diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 73baad614c8f1..2820ac7401b28 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -98,8 +98,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 return;
             }
 
-            let err =
-                self.report_use_of_uninitialized(mpi, used_place, desired_action, span, use_spans);
+            let err = self.report_use_of_uninitialized(
+                mpi,
+                used_place,
+                moved_place,
+                desired_action,
+                span,
+                use_spans,
+            );
             self.buffer_error(err);
         } else {
             if let Some((reported_place, _)) = self.has_move_error(&move_out_indices) {
@@ -316,6 +322,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         &self,
         mpi: MovePathIndex,
         used_place: PlaceRef<'tcx>,
+        moved_place: PlaceRef<'tcx>,
         desired_action: InitializationRequiringAction,
         span: Span,
         use_spans: UseSpans<'tcx>,
@@ -334,11 +341,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
         }
 
-        let (binding, name, desc) =
-            match self.describe_place_with_options(used_place, IncludingDowncast(true)) {
-                Some(name) => (format!("`{name}`"), format!("`{name}`"), format!("`{name}` ")),
-                None => ("value".to_string(), "the variable".to_string(), String::new()),
+        let (name, desc) =
+            match self.describe_place_with_options(moved_place, IncludingDowncast(true)) {
+                Some(name) => (format!("`{name}`"), format!("`{name}` ")),
+                None => ("the variable".to_string(), String::new()),
             };
+        let path = match self.describe_place_with_options(used_place, IncludingDowncast(true)) {
+            Some(name) => format!("`{name}`"),
+            None => "value".to_string(),
+        };
 
         // We use the statements were the binding was initialized, and inspect the HIR to look
         // for the branching codepaths that aren't covered, to point at them.
@@ -390,13 +401,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()),
         );
 
-        if let InitializationRequiringAction::PartialAssignment = desired_action {
+        if let InitializationRequiringAction::PartialAssignment
+        | InitializationRequiringAction::Assignment = desired_action
+        {
             err.help(
                 "partial initialization isn't supported, fully initialize the binding with a \
                  default value and mutate it, or use `std::mem::MaybeUninit`",
             );
         }
-        err.span_label(span, format!("{binding} {used} here but it {isnt_initialized}"));
+        err.span_label(span, format!("{path} {used} here but it {isnt_initialized}"));
 
         let mut shown = false;
         for (sp, label) in visitor.errors {
diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.stderr
index 7a35a9a537cac..83a3e3e0e3ae0 100644
--- a/src/test/ui/borrowck/borrowck-init-in-fru.stderr
+++ b/src/test/ui/borrowck/borrowck-init-in-fru.stderr
@@ -1,4 +1,4 @@
-error[E0381]: used binding `origin.y` isn't initialized
+error[E0381]: used binding `origin` isn't initialized
   --> $DIR/borrowck-init-in-fru.rs:9:14
    |
 LL |     let mut origin: Point;
diff --git a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
index 7b5b64ff8cd23..d12a482cb69a9 100644
--- a/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
+++ b/src/test/ui/borrowck/borrowck-partial-reinit-4.stderr
@@ -5,6 +5,8 @@ LL |     let mut x : (Test2, Test2);
    |         ----- binding declared here but left uninitialized
 LL |     (x.0).0 = Some(Test);
    |     ^^^^^^^ `x.0` assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
index 3bc3a47778778..6a38a79891970 100644
--- a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
@@ -1,4 +1,4 @@
-error[E0381]: used binding `a.x` isn't initialized
+error[E0381]: used binding `a` isn't initialized
   --> $DIR/borrowck-uninit-field-access.rs:21:13
    |
 LL |     let mut a: Point;
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
index 9f33a163e084f..c486cb6dd0cd3 100644
--- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
@@ -1,4 +1,4 @@
-error[E0381]: used binding `**x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:8:14
    |
 LL |     let x: &&Box<i32>;
@@ -6,7 +6,7 @@ LL |     let x: &&Box<i32>;
 LL |     let _y = &**x;
    |              ^^^^ `**x` used here but it isn't initialized
 
-error[E0381]: used binding `**x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:11:14
    |
 LL |     let x: &&S<i32, i32>;
@@ -14,7 +14,7 @@ LL |     let x: &&S<i32, i32>;
 LL |     let _y = &**x;
    |              ^^^^ `**x` used here but it isn't initialized
 
-error[E0381]: used binding `**x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-uninit-ref-chain.rs:14:14
    |
 LL |     let x: &&i32;
diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
index 6372096caef02..459cf1398b750 100644
--- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
+++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
@@ -1,4 +1,4 @@
-error[E0381]: used binding `*w` isn't initialized
+error[E0381]: used binding `w` isn't initialized
   --> $DIR/borrowck-use-in-index-lvalue.rs:3:5
    |
 LL |     let w: &mut [isize];
@@ -6,7 +6,7 @@ LL |     let w: &mut [isize];
 LL |     w[5] = 0;
    |     ^^^^ `*w` used here but it isn't initialized
 
-error[E0381]: used binding `*w` isn't initialized
+error[E0381]: used binding `w` isn't initialized
   --> $DIR/borrowck-use-in-index-lvalue.rs:6:5
    |
 LL |     let mut w: &mut [isize];
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
index fea69c2e40d66..942ed4fc6cabf 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
@@ -1,4 +1,4 @@
-error[E0381]: used binding `*x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:9:13
    |
 LL |     let x: &i32;
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
index e75e033529607..f3289e239818a 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
@@ -1,4 +1,4 @@
-error[E0381]: used binding `*x` isn't initialized
+error[E0381]: used binding `x` isn't initialized
   --> $DIR/borrowck-use-uninitialized-in-cast.rs:7:13
    |
 LL |     let x: &i32;
diff --git a/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr
index 33f839c2866e9..c62f1d1d23061 100644
--- a/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr
+++ b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr
@@ -1,4 +1,4 @@
-error[E0381]: used binding `*s` isn't initialized
+error[E0381]: used binding `s` isn't initialized
   --> $DIR/const-generic-default-wont-borrowck.rs:2:26
    |
 LL |     let s: &'static str; s.len()
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
index 9ecfe2f754ac5..63f230be7d4b3 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
+++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.stderr
@@ -5,6 +5,8 @@ LL |     let d: D;
    |         - binding declared here but left uninitialized
 LL |     d.x = 10;
    |     ^^^^^^^^ `d` assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error[E0381]: assigned binding `d` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:33:5
@@ -13,6 +15,8 @@ LL |     let mut d: D;
    |         ----- binding declared here but left uninitialized
 LL |     d.x = 10;
    |     ^^^^^^^^ `d` assigned here but it isn't fully initialized
+   |
+   = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
 error[E0382]: assign of moved value: `d`
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:39:5
@@ -24,7 +28,7 @@ LL |     drop(d);
 LL |     d.x = 10;
    |     ^^^^^^^^ value assigned here after move
 
-error[E0381]: partially assigned binding `d.s` isn't fully initialized
+error[E0381]: partially assigned binding `d` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:45:5
    |
 LL |     let d: D;
@@ -34,7 +38,7 @@ LL |     d.s.y = 20;
    |
    = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: partially assigned binding `d.s` isn't fully initialized
+error[E0381]: partially assigned binding `d` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-erroneous-use.rs:50:5
    |
 LL |     let mut d: D;
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
index 2f5883b156300..947c9e29b4508 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
+++ b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr
@@ -98,7 +98,7 @@ LL |     t.0 = 10;
    |
    = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: partially assigned binding `q.r.f` isn't fully initialized
+error[E0381]: partially assigned binding `q` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:170:5
    |
 LL |     let q: Q<S<B>>;
@@ -108,7 +108,7 @@ LL |     q.r.f.x = 10; q.r.f.y = Box::new(20);
    |
    = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: partially assigned binding `q.r.f` isn't fully initialized
+error[E0381]: partially assigned binding `q` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:176:5
    |
 LL |     let q: Q<T>;
@@ -138,7 +138,7 @@ LL |     q.r.f.0 = 10; q.r.f.1 = Box::new(20);
    |
    = note: move occurs because `q.r` has type `R<(u32, Box<u32>)>`, which does not implement the `Copy` trait
 
-error[E0381]: partially assigned binding `q.r.f` isn't fully initialized
+error[E0381]: partially assigned binding `q` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:196:5
    |
 LL |     let q: Q<S<B>>;
@@ -148,7 +148,7 @@ LL |     q.r.f.x = 10;
    |
    = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: partially assigned binding `q.r.f` isn't fully initialized
+error[E0381]: partially assigned binding `q` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:202:5
    |
 LL |     let q: Q<T>;
@@ -178,7 +178,7 @@ LL |     q.r.f.0 = 10;
    |
    = note: move occurs because `q.r` has type `R<(u32, Box<u32>)>`, which does not implement the `Copy` trait
 
-error[E0381]: partially assigned binding `q.r.f` isn't fully initialized
+error[E0381]: partially assigned binding `q` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:222:5
    |
 LL |     let mut q: Q<S<Void>>;
@@ -188,7 +188,7 @@ LL |     q.r.f.x = 10;
    |
    = help: partial initialization isn't supported, fully initialize the binding with a default value and mutate it, or use `std::mem::MaybeUninit`
 
-error[E0381]: partially assigned binding `q.r.f` isn't fully initialized
+error[E0381]: partially assigned binding `q` isn't fully initialized
   --> $DIR/issue-21232-partial-init-and-use.rs:228:5
    |
 LL |     let mut q: Q<Tvoid>;

From 20cea3ebb468df74447ed3aa5e646f741208bea8 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Tue, 21 Jun 2022 21:27:15 -0700
Subject: [PATCH 15/20] Fix printing impl trait under binders

---
 compiler/rustc_middle/src/ty/print/pretty.rs  | 246 ++++++++++--------
 src/test/ui/impl-trait/printing-binder.rs     |  14 +
 src/test/ui/impl-trait/printing-binder.stderr |  31 +++
 3 files changed, 178 insertions(+), 113 deletions(-)
 create mode 100644 src/test/ui/impl-trait/printing-binder.rs
 create mode 100644 src/test/ui/impl-trait/printing-binder.stderr

diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 200253d575599..d0f53f8f74b26 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -226,7 +226,7 @@ pub trait PrettyPrinter<'tcx>:
         value.as_ref().skip_binder().print(self)
     }
 
-    fn wrap_binder<T, F: Fn(&T, Self) -> Result<Self, fmt::Error>>(
+    fn wrap_binder<T, F: FnOnce(&T, Self) -> Result<Self, fmt::Error>>(
         self,
         value: &ty::Binder<'tcx, T>,
         f: F,
@@ -773,18 +773,18 @@ pub trait PrettyPrinter<'tcx>:
         def_id: DefId,
         substs: &'tcx ty::List<ty::GenericArg<'tcx>>,
     ) -> Result<Self::Type, Self::Error> {
-        define_scoped_cx!(self);
+        let tcx = self.tcx();
 
         // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
         // by looking up the projections associated with the def_id.
-        let bounds = self.tcx().bound_explicit_item_bounds(def_id);
+        let bounds = tcx.bound_explicit_item_bounds(def_id);
 
         let mut traits = FxIndexMap::default();
         let mut fn_traits = FxIndexMap::default();
         let mut is_sized = false;
 
         for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
-            let predicate = predicate.subst(self.tcx(), substs);
+            let predicate = predicate.subst(tcx, substs);
             let bound_predicate = predicate.kind();
 
             match bound_predicate.skip_binder() {
@@ -792,7 +792,7 @@ pub trait PrettyPrinter<'tcx>:
                     let trait_ref = bound_predicate.rebind(pred.trait_ref);
 
                     // Don't print + Sized, but rather + ?Sized if absent.
-                    if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
+                    if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() {
                         is_sized = true;
                         continue;
                     }
@@ -801,7 +801,7 @@ pub trait PrettyPrinter<'tcx>:
                 }
                 ty::PredicateKind::Projection(pred) => {
                     let proj_ref = bound_predicate.rebind(pred);
-                    let trait_ref = proj_ref.required_poly_trait_ref(self.tcx());
+                    let trait_ref = proj_ref.required_poly_trait_ref(tcx);
 
                     // Projection type entry -- the def-id for naming, and the ty.
                     let proj_ty = (proj_ref.projection_def_id(), proj_ref.term());
@@ -817,148 +817,168 @@ pub trait PrettyPrinter<'tcx>:
             }
         }
 
+        {
+            define_scoped_cx!(self);
+            p!("impl ");
+        }
+
         let mut first = true;
         // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait
         let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !is_sized;
 
-        p!("impl");
-
         for (fn_once_trait_ref, entry) in fn_traits {
-            // Get the (single) generic ty (the args) of this FnOnce trait ref.
-            let generics = self.tcx().generics_of(fn_once_trait_ref.def_id());
-            let args =
-                generics.own_substs_no_defaults(self.tcx(), fn_once_trait_ref.skip_binder().substs);
-
-            match (entry.return_ty, args[0].expect_ty()) {
-                // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded
-                // a return type.
-                (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => {
-                    let name = if entry.fn_trait_ref.is_some() {
-                        "Fn"
-                    } else if entry.fn_mut_trait_ref.is_some() {
-                        "FnMut"
-                    } else {
-                        "FnOnce"
-                    };
+            {
+                define_scoped_cx!(self);
+                p!(
+                    write("{}", if first { "" } else { " + " }),
+                    write("{}", if paren_needed { "(" } else { "" })
+                );
+            }
+
+            self = self.wrap_binder(&fn_once_trait_ref, |trait_ref, mut self_| {
+                // Get the (single) generic ty (the args) of this FnOnce trait ref.
+                let generics = tcx.generics_of(trait_ref.def_id);
+                let args = generics.own_substs_no_defaults(tcx, trait_ref.substs);
+
+                match (entry.return_ty, args[0].expect_ty()) {
+                    // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded
+                    // a return type.
+                    (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => {
+                        let name = if entry.fn_trait_ref.is_some() {
+                            "Fn"
+                        } else if entry.fn_mut_trait_ref.is_some() {
+                            "FnMut"
+                        } else {
+                            "FnOnce"
+                        };
 
-                    p!(
-                        write("{}", if first { " " } else { " + " }),
-                        write("{}{}(", if paren_needed { "(" } else { "" }, name)
-                    );
+                        define_scoped_cx!(self_);
+                        p!(write("{}(", name));
 
-                    for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() {
-                        if idx > 0 {
-                            p!(", ");
+                        for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() {
+                            if idx > 0 {
+                                p!(", ");
+                            }
+                            p!(print(ty));
                         }
-                        p!(print(ty));
-                    }
 
-                    p!(")");
-                    if let Term::Ty(ty) = return_ty.skip_binder() {
-                        if !ty.is_unit() {
-                            p!(" -> ", print(return_ty));
+                        p!(")");
+                        if let Term::Ty(ty) = return_ty.skip_binder() {
+                            if !ty.is_unit() {
+                                p!(" -> ", print(return_ty));
+                            }
                         }
-                    }
-                    p!(write("{}", if paren_needed { ")" } else { "" }));
+                        p!(write("{}", if paren_needed { ")" } else { "" }));
 
-                    first = false;
-                }
-                // If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the
-                // trait_refs we collected in the OpaqueFnEntry as normal trait refs.
-                _ => {
-                    if entry.has_fn_once {
-                        traits.entry(fn_once_trait_ref).or_default().extend(
-                            // Group the return ty with its def id, if we had one.
-                            entry
-                                .return_ty
-                                .map(|ty| (self.tcx().lang_items().fn_once_output().unwrap(), ty)),
-                        );
-                    }
-                    if let Some(trait_ref) = entry.fn_mut_trait_ref {
-                        traits.entry(trait_ref).or_default();
+                        first = false;
                     }
-                    if let Some(trait_ref) = entry.fn_trait_ref {
-                        traits.entry(trait_ref).or_default();
+                    // If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the
+                    // trait_refs we collected in the OpaqueFnEntry as normal trait refs.
+                    _ => {
+                        if entry.has_fn_once {
+                            traits.entry(fn_once_trait_ref).or_default().extend(
+                                // Group the return ty with its def id, if we had one.
+                                entry
+                                    .return_ty
+                                    .map(|ty| (tcx.lang_items().fn_once_output().unwrap(), ty)),
+                            );
+                        }
+                        if let Some(trait_ref) = entry.fn_mut_trait_ref {
+                            traits.entry(trait_ref).or_default();
+                        }
+                        if let Some(trait_ref) = entry.fn_trait_ref {
+                            traits.entry(trait_ref).or_default();
+                        }
                     }
                 }
-            }
+
+                Ok(self_)
+            })?;
         }
 
         // Print the rest of the trait types (that aren't Fn* family of traits)
         for (trait_ref, assoc_items) in traits {
-            p!(
-                write("{}", if first { " " } else { " + " }),
-                print(trait_ref.skip_binder().print_only_trait_name())
-            );
+            {
+                define_scoped_cx!(self);
+                p!(write("{}", if first { "" } else { " + " }));
+            }
 
-            let generics = self.tcx().generics_of(trait_ref.def_id());
-            let args = generics.own_substs_no_defaults(self.tcx(), trait_ref.skip_binder().substs);
+            self = self.wrap_binder(&trait_ref, |trait_ref, mut self_| {
+                define_scoped_cx!(self_);
+                p!(print(trait_ref.print_only_trait_name()));
 
-            if !args.is_empty() || !assoc_items.is_empty() {
-                let mut first = true;
+                let generics = tcx.generics_of(trait_ref.def_id);
+                let args = generics.own_substs_no_defaults(tcx, trait_ref.substs);
 
-                for ty in args {
-                    if first {
-                        p!("<");
-                        first = false;
-                    } else {
-                        p!(", ");
+                if !args.is_empty() || !assoc_items.is_empty() {
+                    let mut first = true;
+
+                    for ty in args {
+                        if first {
+                            p!("<");
+                            first = false;
+                        } else {
+                            p!(", ");
+                        }
+                        p!(print(ty));
                     }
-                    p!(print(trait_ref.rebind(*ty)));
-                }
 
-                for (assoc_item_def_id, term) in assoc_items {
-                    // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks,
-                    // unless we can find out what generator return type it comes from.
-                    let term = if let Some(ty) = term.skip_binder().ty()
-                        && let ty::Projection(ty::ProjectionTy { item_def_id, substs }) = ty.kind()
-                        && Some(*item_def_id) == self.tcx().lang_items().generator_return()
-                    {
-                        if let ty::Generator(_, substs, _) = substs.type_at(0).kind() {
-                            let return_ty = substs.as_generator().return_ty();
-                            if !return_ty.is_ty_infer() {
-                                return_ty.into()
+                    for (assoc_item_def_id, term) in assoc_items {
+                        // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks,
+                        // unless we can find out what generator return type it comes from.
+                        let term = if let Some(ty) = term.skip_binder().ty()
+                            && let ty::Projection(ty::ProjectionTy { item_def_id, substs }) = ty.kind()
+                            && Some(*item_def_id) == tcx.lang_items().generator_return()
+                        {
+                            if let ty::Generator(_, substs, _) = substs.type_at(0).kind() {
+                                let return_ty = substs.as_generator().return_ty();
+                                if !return_ty.is_ty_infer() {
+                                    return_ty.into()
+                                } else {
+                                    continue;
+                                }
                             } else {
                                 continue;
                             }
                         } else {
-                            continue;
-                        }
-                    } else {
-                        term.skip_binder()
-                    };
+                            term.skip_binder()
+                        };
 
-                    if first {
-                        p!("<");
-                        first = false;
-                    } else {
-                        p!(", ");
-                    }
+                        if first {
+                            p!("<");
+                            first = false;
+                        } else {
+                            p!(", ");
+                        }
 
-                    p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).name));
+                        p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name));
 
-                    match term {
-                        Term::Ty(ty) => {
-                            p!(print(ty))
-                        }
-                        Term::Const(c) => {
-                            p!(print(c));
-                        }
-                    };
-                }
+                        match term {
+                            Term::Ty(ty) => {
+                                p!(print(ty))
+                            }
+                            Term::Const(c) => {
+                                p!(print(c));
+                            }
+                        };
+                    }
 
-                if !first {
-                    p!(">");
+                    if !first {
+                        p!(">");
+                    }
                 }
-            }
 
-            first = false;
+                first = false;
+                Ok(self_)
+            })?;
         }
 
+        define_scoped_cx!(self);
+
         if !is_sized {
-            p!(write("{}?Sized", if first { " " } else { " + " }));
+            p!(write("{}?Sized", if first { "" } else { " + " }));
         } else if first {
-            p!(" Sized");
+            p!("Sized");
         }
 
         Ok(self)
@@ -1869,7 +1889,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
         self.pretty_in_binder(value)
     }
 
-    fn wrap_binder<T, C: Fn(&T, Self) -> Result<Self, Self::Error>>(
+    fn wrap_binder<T, C: FnOnce(&T, Self) -> Result<Self, Self::Error>>(
         self,
         value: &ty::Binder<'tcx, T>,
         f: C,
@@ -2256,7 +2276,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
         Ok(inner)
     }
 
-    pub fn pretty_wrap_binder<T, C: Fn(&T, Self) -> Result<Self, fmt::Error>>(
+    pub fn pretty_wrap_binder<T, C: FnOnce(&T, Self) -> Result<Self, fmt::Error>>(
         self,
         value: &ty::Binder<'tcx, T>,
         f: C,
diff --git a/src/test/ui/impl-trait/printing-binder.rs b/src/test/ui/impl-trait/printing-binder.rs
new file mode 100644
index 0000000000000..273b5dcdb0985
--- /dev/null
+++ b/src/test/ui/impl-trait/printing-binder.rs
@@ -0,0 +1,14 @@
+trait Trait<'a> {}
+impl<T> Trait<'_> for T {}
+fn whatever() -> impl for<'a> Trait<'a> + for<'b> Trait<'b> {}
+
+fn whatever2() -> impl for<'c> Fn(&'c ()) {
+    |_: &()| {}
+}
+
+fn main() {
+    let x: u32 = whatever();
+    //~^ ERROR mismatched types
+    let x2: u32 = whatever2();
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/impl-trait/printing-binder.stderr b/src/test/ui/impl-trait/printing-binder.stderr
new file mode 100644
index 0000000000000..5ffec8af10289
--- /dev/null
+++ b/src/test/ui/impl-trait/printing-binder.stderr
@@ -0,0 +1,31 @@
+error[E0308]: mismatched types
+  --> $DIR/printing-binder.rs:10:18
+   |
+LL | fn whatever() -> impl for<'a> Trait<'a> + for<'b> Trait<'b> {}
+   |                  ------------------------------------------ the found opaque type
+...
+LL |     let x: u32 = whatever();
+   |            ---   ^^^^^^^^^^ expected `u32`, found opaque type
+   |            |
+   |            expected due to this
+   |
+   = note:     expected type `u32`
+           found opaque type `impl for<'a> Trait<'a> + for<'b> Trait<'b>`
+
+error[E0308]: mismatched types
+  --> $DIR/printing-binder.rs:12:19
+   |
+LL | fn whatever2() -> impl for<'c> Fn(&'c ()) {
+   |                   ----------------------- the found opaque type
+...
+LL |     let x2: u32 = whatever2();
+   |             ---   ^^^^^^^^^^^ expected `u32`, found opaque type
+   |             |
+   |             expected due to this
+   |
+   = note:     expected type `u32`
+           found opaque type `impl for<'c> Fn(&'c ())`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.

From e80ccedbaeeb5b97880d83ea95c79fc1d0dcf418 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 22 Jun 2022 10:21:24 -0700
Subject: [PATCH 16/20] Use write! instead of p! to avoid having to use weird
 scoping

---
 compiler/rustc_middle/src/ty/print/pretty.rs  | 37 ++++++-------------
 ...e-70935-complex-spans.drop_tracking.stderr |  2 +-
 2 files changed, 13 insertions(+), 26 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index d0f53f8f74b26..c56909ba18b14 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -817,25 +817,18 @@ pub trait PrettyPrinter<'tcx>:
             }
         }
 
-        {
-            define_scoped_cx!(self);
-            p!("impl ");
-        }
+        write!(self, "impl ")?;
 
         let mut first = true;
         // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait
         let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !is_sized;
 
         for (fn_once_trait_ref, entry) in fn_traits {
-            {
-                define_scoped_cx!(self);
-                p!(
-                    write("{}", if first { "" } else { " + " }),
-                    write("{}", if paren_needed { "(" } else { "" })
-                );
-            }
+            write!(self, "{}", if first { "" } else { " + " })?;
+            write!(self, "{}", if paren_needed { "(" } else { "" })?;
 
-            self = self.wrap_binder(&fn_once_trait_ref, |trait_ref, mut self_| {
+            self = self.wrap_binder(&fn_once_trait_ref, |trait_ref, mut cx| {
+                define_scoped_cx!(cx);
                 // Get the (single) generic ty (the args) of this FnOnce trait ref.
                 let generics = tcx.generics_of(trait_ref.def_id);
                 let args = generics.own_substs_no_defaults(tcx, trait_ref.substs);
@@ -852,7 +845,6 @@ pub trait PrettyPrinter<'tcx>:
                             "FnOnce"
                         };
 
-                        define_scoped_cx!(self_);
                         p!(write("{}(", name));
 
                         for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() {
@@ -892,19 +884,16 @@ pub trait PrettyPrinter<'tcx>:
                     }
                 }
 
-                Ok(self_)
+                Ok(cx)
             })?;
         }
 
         // Print the rest of the trait types (that aren't Fn* family of traits)
         for (trait_ref, assoc_items) in traits {
-            {
-                define_scoped_cx!(self);
-                p!(write("{}", if first { "" } else { " + " }));
-            }
+            write!(self, "{}", if first { "" } else { " + " })?;
 
-            self = self.wrap_binder(&trait_ref, |trait_ref, mut self_| {
-                define_scoped_cx!(self_);
+            self = self.wrap_binder(&trait_ref, |trait_ref, mut cx| {
+                define_scoped_cx!(cx);
                 p!(print(trait_ref.print_only_trait_name()));
 
                 let generics = tcx.generics_of(trait_ref.def_id);
@@ -969,16 +958,14 @@ pub trait PrettyPrinter<'tcx>:
                 }
 
                 first = false;
-                Ok(self_)
+                Ok(cx)
             })?;
         }
 
-        define_scoped_cx!(self);
-
         if !is_sized {
-            p!(write("{}?Sized", if first { "" } else { " + " }));
+            write!(self, "{}?Sized", if first { "" } else { " + " })?;
         } else if first {
-            p!("Sized");
+            write!(self, "Sized")?;
         }
 
         Ok(self)
diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
index 43b7cb8cece36..e9b76b19dc407 100644
--- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
+++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
@@ -22,7 +22,7 @@ LL |   async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
 LL | |
 LL | | }
    | |_^
-   = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = ()>`, `()`
+   = note: required because it captures the following types: `ResumeTy`, `impl for<'r, 's, 't0> Future<Output = ()>`, `()`
 note: required because it's used within this `async` block
   --> $DIR/issue-70935-complex-spans.rs:23:16
    |

From 9169905eb2d0e5df5c554396495df49283812abc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Fri, 24 Jun 2022 17:55:40 -0700
Subject: [PATCH 17/20] x.py: Support systems with only `python3` not `python`

---
 x.py | 29 +++++++++++++++++++++++++----
 1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/x.py b/x.py
index 4f64ea9fae8b8..0289056fdcb16 100755
--- a/x.py
+++ b/x.py
@@ -1,5 +1,25 @@
-#!/usr/bin/env python
+#!/usr/bin/env bash
 
+# Modern Linux and macOS systems commonly only have a thing called `python3` and
+# not `python`, while Windows commonly does not have `python3`, so we cannot
+# directly use python in the shebang and have it consistently work. Instead we
+# embed some bash to look for a python to run the rest of the script.
+#
+# On Windows, `py -3` sometimes works. We need to try it first because `python3`
+# sometimes tries to launch the app store on Windows.
+'''':
+for PYTHON in "py -3" python3 python python2; do
+    if command -v $PYTHON >/dev/null; then
+        exec $PYTHON "$0" "$@"
+        break
+    fi
+done
+echo "$0: error: did not find python installed" >&2
+exit 1
+'''
+
+# The rest of this file is Python.
+#
 # This file is only a "symlink" to bootstrap.py, all logic should go there.
 
 import os
@@ -7,11 +27,12 @@
 
 # If this is python2, check if python3 is available and re-execute with that
 # interpreter.
+#
+# `./x.py` would not normally benefit from this because the bash above tries
+# python3 before 2, but this matters if someone ran `python x.py` and their
+# system's `python` is python2.
 if sys.version_info.major < 3:
     try:
-        # On Windows, `py -3` sometimes works.
-        # Try this first, because 'python3' sometimes tries to launch the app
-        # store on Windows
         os.execvp("py", ["py", "-3"] + sys.argv)
     except OSError:
         try:

From 747586732b1bb21c1ef318428fe179a77db2d963 Mon Sep 17 00:00:00 2001
From: Caio <c410.f3r@gmail.com>
Date: Sat, 25 Jun 2022 08:08:38 -0300
Subject: [PATCH 18/20] [rustc_parse] Forbid lets in certain places

---
 compiler/rustc_parse/src/parser/expr.rs       |  30 +-
 compiler/rustc_parse/src/parser/mod.rs        |   6 +-
 src/test/ui/mir/issue-92893.rs                |   3 +-
 src/test/ui/mir/issue-92893.stderr            |   8 +-
 .../ui/rfc-2294-if-let-guard/feature-gate.rs  |   2 +
 .../rfc-2294-if-let-guard/feature-gate.stderr |  20 +-
 .../disallowed-positions.rs                   |  88 +++-
 .../disallowed-positions.stderr               | 442 ++++++++++++------
 ...-else-does-not-interact-with-let-chains.rs |   1 +
 ...e-does-not-interact-with-let-chains.stderr |  26 +-
 .../ui/rfc-2497-if-let-chains/feature-gate.rs |   3 +-
 .../feature-gate.stderr                       |  18 +-
 .../invalid-let-in-a-valid-let-context.rs     |  17 +
 13 files changed, 468 insertions(+), 196 deletions(-)
 create mode 100644 src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs

diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 81bab0e3513c9..2c43563b10474 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -7,6 +7,7 @@ use super::{
 };
 use crate::maybe_recover_from_interpolated_ty_qpath;
 
+use core::mem;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::Spacing;
@@ -26,7 +27,6 @@ use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_span::source_map::{self, Span, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Pos};
-use std::mem;
 
 /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
 /// dropped into the token stream, which happens while parsing the result of
@@ -2343,7 +2343,9 @@ impl<'a> Parser<'a> {
 
     /// Parses the condition of a `if` or `while` expression.
     fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
-        let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
+        let cond = self.with_let_management(true, |local_self| {
+            local_self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)
+        })?;
 
         if let ExprKind::Let(..) = cond.kind {
             // Remove the last feature gating of a `let` expression since it's stable.
@@ -2356,6 +2358,13 @@ impl<'a> Parser<'a> {
     /// Parses a `let $pat = $expr` pseudo-expression.
     /// The `let` token has already been eaten.
     fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
+        if !self.let_expr_allowed {
+            self.struct_span_err(
+                self.prev_token.span,
+                "expected expression, found `let` statement",
+            )
+            .emit();
+        }
         let lo = self.prev_token.span;
         let pat = self.parse_pat_allow_top_alt(
             None,
@@ -2672,6 +2681,8 @@ impl<'a> Parser<'a> {
     }
 
     pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
+        // Used to check the `let_chains` and `if_let_guard` features mostly by scaning
+        // `&&` tokens.
         fn check_let_expr(expr: &Expr) -> (bool, bool) {
             match expr.kind {
                 ExprKind::Binary(_, ref lhs, ref rhs) => {
@@ -2694,7 +2705,7 @@ impl<'a> Parser<'a> {
             )?;
             let guard = if this.eat_keyword(kw::If) {
                 let if_span = this.prev_token.span;
-                let cond = this.parse_expr()?;
+                let cond = this.with_let_management(true, |local_this| local_this.parse_expr())?;
                 let (has_let_expr, does_not_have_bin_op) = check_let_expr(&cond);
                 if has_let_expr {
                     if does_not_have_bin_op {
@@ -3256,4 +3267,17 @@ impl<'a> Parser<'a> {
             Ok((res, trailing))
         })
     }
+
+    // Calls `f` with the internal `let_expr_allowed` set to `let_expr_allowed` and then
+    // sets the internal `let_expr_allowed` back to its original value.
+    fn with_let_management<T>(
+        &mut self,
+        let_expr_allowed: bool,
+        f: impl FnOnce(&mut Self) -> T,
+    ) -> T {
+        let last_let_expr_allowed = mem::replace(&mut self.let_expr_allowed, let_expr_allowed);
+        let rslt = f(self);
+        self.let_expr_allowed = last_let_expr_allowed;
+        rslt
+    }
 }
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 6d6667717f0a3..acdf121522ad9 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -147,12 +147,15 @@ pub struct Parser<'a> {
     /// This allows us to recover when the user forget to add braces around
     /// multiple statements in the closure body.
     pub current_closure: Option<ClosureSpans>,
+    /// Used to track where `let`s are allowed. For example, `if true && let 1 = 1` is valid
+    /// but `[1, 2, 3][let _ = ()]` is not.
+    let_expr_allowed: bool,
 }
 
 // This type is used a lot, e.g. it's cloned when matching many declarative macro rules. Make sure
 // it doesn't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Parser<'_>, 328);
+rustc_data_structures::static_assert_size!(Parser<'_>, 336);
 
 /// Stores span information about a closure.
 #[derive(Clone)]
@@ -455,6 +458,7 @@ impl<'a> Parser<'a> {
                 inner_attr_ranges: Default::default(),
             },
             current_closure: None,
+            let_expr_allowed: false,
         };
 
         // Make parser point to the first token.
diff --git a/src/test/ui/mir/issue-92893.rs b/src/test/ui/mir/issue-92893.rs
index d2bbb4f110114..635050f376c8a 100644
--- a/src/test/ui/mir/issue-92893.rs
+++ b/src/test/ui/mir/issue-92893.rs
@@ -1,6 +1,7 @@
 struct Bug<A = [(); (let a = (), 1).1]> {
     //~^ `let` expressions are not supported here
-    //~^^ `let` expressions in this position are unstable [E0658]
+    //~| `let` expressions in this position are unstable [E0658]
+    //~| expected expression, found `let` statement
     a: A
 }
 
diff --git a/src/test/ui/mir/issue-92893.stderr b/src/test/ui/mir/issue-92893.stderr
index 063b5d66feb45..4a0fcce31d7c7 100644
--- a/src/test/ui/mir/issue-92893.stderr
+++ b/src/test/ui/mir/issue-92893.stderr
@@ -1,3 +1,9 @@
+error: expected expression, found `let` statement
+  --> $DIR/issue-92893.rs:1:22
+   |
+LL | struct Bug<A = [(); (let a = (), 1).1]> {
+   |                      ^^^
+
 error: `let` expressions are not supported here
   --> $DIR/issue-92893.rs:1:22
    |
@@ -15,6 +21,6 @@ LL | struct Bug<A = [(); (let a = (), 1).1]> {
    = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs b/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs
index 4a36515b99128..bb1aff70d8995 100644
--- a/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs
+++ b/src/test/ui/rfc-2294-if-let-guard/feature-gate.rs
@@ -58,8 +58,10 @@ fn _macros() {
     }
     use_expr!((let 0 = 1 && 0 == 0));
     //~^ ERROR `let` expressions in this position are unstable
+    //~| ERROR expected expression, found `let` statement
     use_expr!((let 0 = 1));
     //~^ ERROR `let` expressions in this position are unstable
+    //~| ERROR expected expression, found `let` statement
     match () {
         #[cfg(FALSE)]
         () if let 0 = 1 => {}
diff --git a/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr b/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr
index 8d93fb87f7ad1..370a57318fdd0 100644
--- a/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr
+++ b/src/test/ui/rfc-2294-if-let-guard/feature-gate.stderr
@@ -1,5 +1,17 @@
+error: expected expression, found `let` statement
+  --> $DIR/feature-gate.rs:59:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/feature-gate.rs:62:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^
+
 error: no rules expected the token `let`
-  --> $DIR/feature-gate.rs:69:15
+  --> $DIR/feature-gate.rs:71:15
    |
 LL |     macro_rules! use_expr {
    |     --------------------- when calling this macro
@@ -58,7 +70,7 @@ LL |         () if let Range { start: _, end: _ } = (true..true) && false => {}
    = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
 
 error[E0658]: `if let` guards are experimental
-  --> $DIR/feature-gate.rs:65:12
+  --> $DIR/feature-gate.rs:67:12
    |
 LL |         () if let 0 = 1 => {}
    |            ^^^^^^^^^^^^
@@ -203,7 +215,7 @@ LL |     use_expr!((let 0 = 1 && 0 == 0));
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:61:16
+  --> $DIR/feature-gate.rs:62:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
@@ -211,6 +223,6 @@ LL |     use_expr!((let 0 = 1));
    = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
-error: aborting due to 23 previous errors
+error: aborting due to 25 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs
index 1bd8b74240eac..36b730505c29e 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs
@@ -81,9 +81,11 @@ fn _macros() {
     use_expr!((let 0 = 1 && 0 == 0));
     //~^ ERROR `let` expressions are not supported here
     //~| ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
     use_expr!((let 0 = 1));
     //~^ ERROR `let` expressions are not supported here
     //~| ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
 }
 
 fn nested_within_if_expr() {
@@ -147,7 +149,8 @@ fn nested_within_if_expr() {
     //~| ERROR mismatched types
     //~| ERROR mismatched types
 
-    if let true = let true = true {} //~ ERROR `let` expressions are not supported here
+    if let true = let true = true {}
+    //~^ ERROR `let` expressions are not supported here
 }
 
 fn nested_within_while_expr() {
@@ -211,7 +214,8 @@ fn nested_within_while_expr() {
     //~| ERROR mismatched types
     //~| ERROR mismatched types
 
-    while let true = let true = true {} //~ ERROR `let` expressions are not supported here
+    while let true = let true = true {}
+    //~^ ERROR `let` expressions are not supported here
 }
 
 fn not_error_because_clarified_intent() {
@@ -225,45 +229,85 @@ fn not_error_because_clarified_intent() {
 }
 
 fn outside_if_and_while_expr() {
-    &let 0 = 0; //~ ERROR `let` expressions are not supported here
+    &let 0 = 0;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
 
-    !let 0 = 0; //~ ERROR `let` expressions are not supported here
-    *let 0 = 0; //~ ERROR `let` expressions are not supported here
-    //~^ ERROR type `bool` cannot be dereferenced
-    -let 0 = 0; //~ ERROR `let` expressions are not supported here
-    //~^ ERROR cannot apply unary operator `-` to type `bool`
+    !let 0 = 0;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
+    *let 0 = 0;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR type `bool` cannot be dereferenced
+    //~| ERROR expected expression, found `let` statement
+    -let 0 = 0;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR cannot apply unary operator `-` to type `bool`
+    //~| ERROR expected expression, found `let` statement
 
     fn _check_try_binds_tighter() -> Result<(), ()> {
         let 0 = 0?;
         //~^ ERROR the `?` operator can only be applied to values that implement `Try`
         Ok(())
     }
-    (let 0 = 0)?; //~ ERROR `let` expressions are not supported here
-    //~^ ERROR the `?` operator can only be used in a function that returns `Result`
+    (let 0 = 0)?;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR the `?` operator can only be used in a function that returns `Result`
     //~| ERROR the `?` operator can only be applied to values that implement `Try`
+    //~| ERROR expected expression, found `let` statement
 
-    true || let 0 = 0; //~ ERROR `let` expressions are not supported here
-    (true || let 0 = 0); //~ ERROR `let` expressions are not supported here
-    true && (true || let 0 = 0); //~ ERROR `let` expressions are not supported here
+    true || let 0 = 0;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
+    (true || let 0 = 0);
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
+    true && (true || let 0 = 0);
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
 
     let mut x = true;
-    x = let 0 = 0; //~ ERROR `let` expressions are not supported here
+    x = let 0 = 0;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
 
-    true..(let 0 = 0); //~ ERROR `let` expressions are not supported here
-    ..(let 0 = 0); //~ ERROR `let` expressions are not supported here
-    (let 0 = 0)..; //~ ERROR `let` expressions are not supported here
+    true..(let 0 = 0);
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
+    ..(let 0 = 0);
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
+    (let 0 = 0)..;
+    //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
 
     (let Range { start: _, end: _ } = true..true || false);
     //~^ ERROR `let` expressions are not supported here
     //~| ERROR mismatched types
+    //~| ERROR expected expression, found `let` statement
 
     (let true = let true = true);
     //~^ ERROR `let` expressions are not supported here
+    //~| ERROR expected expression, found `let` statement
+    //~| ERROR expected expression, found `let` statement
+
+    {
+        #[cfg(FALSE)]
+        let x = true && let y = 1;
+        //~^ ERROR expected expression, found `let` statement
+    }
+
+    #[cfg(FALSE)]
+    {
+        [1, 2, 3][let _ = ()]
+        //~^ ERROR expected expression, found `let` statement
+    }
 
     // Check function tail position.
     &let 0 = 0
     //~^ ERROR `let` expressions are not supported here
     //~| ERROR mismatched types
+    //~| ERROR expected expression, found `let` statement
 }
 
 // Let's make sure that `let` inside const generic arguments are considered.
@@ -335,4 +379,14 @@ fn with_parenthesis() {
     let fun = || true;
     if let true = (true && fun()) && (true) {
     }
+
+    #[cfg(FALSE)]
+    let x = (true && let y = 1);
+    //~^ ERROR expected expression, found `let` statement
+
+    #[cfg(FALSE)]
+    {
+        ([1, 2, 3][let _ = ()])
+        //~^ ERROR expected expression, found `let` statement
+    }
 }
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
index f7f39bd0b9a07..5cf06cf4b27cd 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -1,5 +1,113 @@
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:232:6
+   |
+LL |     &let 0 = 0;
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:236:6
+   |
+LL |     !let 0 = 0;
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:239:6
+   |
+LL |     *let 0 = 0;
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:243:6
+   |
+LL |     -let 0 = 0;
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:253:6
+   |
+LL |     (let 0 = 0)?;
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:259:13
+   |
+LL |     true || let 0 = 0;
+   |             ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:262:14
+   |
+LL |     (true || let 0 = 0);
+   |              ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:265:22
+   |
+LL |     true && (true || let 0 = 0);
+   |                      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:270:9
+   |
+LL |     x = let 0 = 0;
+   |         ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:274:12
+   |
+LL |     true..(let 0 = 0);
+   |            ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:277:8
+   |
+LL |     ..(let 0 = 0);
+   |        ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:280:6
+   |
+LL |     (let 0 = 0)..;
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:284:6
+   |
+LL |     (let Range { start: _, end: _ } = true..true || false);
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:289:6
+   |
+LL |     (let true = let true = true);
+   |      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:289:17
+   |
+LL |     (let true = let true = true);
+   |                 ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:296:25
+   |
+LL |         let x = true && let y = 1;
+   |                         ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:302:19
+   |
+LL |         [1, 2, 3][let _ = ()]
+   |                   ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:307:6
+   |
+LL |     &let 0 = 0
+   |      ^^^
+
 error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/disallowed-positions.rs:293:9
+  --> $DIR/disallowed-positions.rs:337:9
    |
 LL |         true && let 1 = 1
    |         ^^^^^^^^^^^^^^^^^
@@ -9,6 +117,30 @@ help: enclose the `const` expression in braces
 LL |         { true && let 1 = 1 }
    |         +                   +
 
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:384:22
+   |
+LL |     let x = (true && let y = 1);
+   |                      ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:389:20
+   |
+LL |         ([1, 2, 3][let _ = ()])
+   |                    ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:81:16
+   |
+LL |     use_expr!((let 0 = 1 && 0 == 0));
+   |                ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/disallowed-positions.rs:85:16
+   |
+LL |     use_expr!((let 0 = 1));
+   |                ^^^
+
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:29:9
    |
@@ -270,33 +402,33 @@ LL |     use_expr!((let 0 = 1 && 0 == 0));
    |                ^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:84:16
+  --> $DIR/disallowed-positions.rs:85:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:84:16
+  --> $DIR/disallowed-positions.rs:85:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:84:16
+  --> $DIR/disallowed-positions.rs:85:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:84:16
+  --> $DIR/disallowed-positions.rs:85:16
    |
 LL |     use_expr!((let 0 = 1));
    |                ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:90:9
+  --> $DIR/disallowed-positions.rs:92:9
    |
 LL |     if &let 0 = 0 {}
    |         ^^^^^^^^^
@@ -304,7 +436,7 @@ LL |     if &let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:93:9
+  --> $DIR/disallowed-positions.rs:95:9
    |
 LL |     if !let 0 = 0 {}
    |         ^^^^^^^^^
@@ -312,7 +444,7 @@ LL |     if !let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:94:9
+  --> $DIR/disallowed-positions.rs:96:9
    |
 LL |     if *let 0 = 0 {}
    |         ^^^^^^^^^
@@ -320,7 +452,7 @@ LL |     if *let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:96:9
+  --> $DIR/disallowed-positions.rs:98:9
    |
 LL |     if -let 0 = 0 {}
    |         ^^^^^^^^^
@@ -328,72 +460,72 @@ LL |     if -let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:104:9
+  --> $DIR/disallowed-positions.rs:106:9
    |
 LL |     if (let 0 = 0)? {}
    |         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:104:9
+  --> $DIR/disallowed-positions.rs:106:9
    |
 LL |     if (let 0 = 0)? {}
    |         ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:108:16
+  --> $DIR/disallowed-positions.rs:110:16
    |
 LL |     if true || let 0 = 0 {}
    |                ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:108:13
+  --> $DIR/disallowed-positions.rs:110:13
    |
 LL |     if true || let 0 = 0 {}
    |             ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:109:17
+  --> $DIR/disallowed-positions.rs:111:17
    |
 LL |     if (true || let 0 = 0) {}
    |                 ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:109:14
+  --> $DIR/disallowed-positions.rs:111:14
    |
 LL |     if (true || let 0 = 0) {}
    |              ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:110:25
+  --> $DIR/disallowed-positions.rs:112:25
    |
 LL |     if true && (true || let 0 = 0) {}
    |                         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:110:22
+  --> $DIR/disallowed-positions.rs:112:22
    |
 LL |     if true && (true || let 0 = 0) {}
    |                      ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:111:25
+  --> $DIR/disallowed-positions.rs:113:25
    |
 LL |     if true || (true && let 0 = 0) {}
    |                         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:111:17
+  --> $DIR/disallowed-positions.rs:113:17
    |
 LL |     if true || (true && let 0 = 0) {}
    |                 ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:114:12
+  --> $DIR/disallowed-positions.rs:116:12
    |
 LL |     if x = let 0 = 0 {}
    |            ^^^^^^^^^
@@ -401,46 +533,46 @@ LL |     if x = let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:117:15
+  --> $DIR/disallowed-positions.rs:119:15
    |
 LL |     if true..(let 0 = 0) {}
    |               ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:117:15
+  --> $DIR/disallowed-positions.rs:119:15
    |
 LL |     if true..(let 0 = 0) {}
    |               ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:119:11
+  --> $DIR/disallowed-positions.rs:121:11
    |
 LL |     if ..(let 0 = 0) {}
    |           ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:119:11
+  --> $DIR/disallowed-positions.rs:121:11
    |
 LL |     if ..(let 0 = 0) {}
    |           ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:121:9
+  --> $DIR/disallowed-positions.rs:123:9
    |
 LL |     if (let 0 = 0).. {}
    |         ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:121:9
+  --> $DIR/disallowed-positions.rs:123:9
    |
 LL |     if (let 0 = 0).. {}
    |         ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:125:8
+  --> $DIR/disallowed-positions.rs:127:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -448,7 +580,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:129:8
+  --> $DIR/disallowed-positions.rs:131:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -456,7 +588,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:136:8
+  --> $DIR/disallowed-positions.rs:138:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -464,7 +596,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:144:8
+  --> $DIR/disallowed-positions.rs:146:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -472,7 +604,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:150:19
+  --> $DIR/disallowed-positions.rs:152:19
    |
 LL |     if let true = let true = true {}
    |                   ^^^^^^^^^^^^^^^
@@ -480,7 +612,7 @@ LL |     if let true = let true = true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:154:12
+  --> $DIR/disallowed-positions.rs:157:12
    |
 LL |     while &let 0 = 0 {}
    |            ^^^^^^^^^
@@ -488,7 +620,7 @@ LL |     while &let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:157:12
+  --> $DIR/disallowed-positions.rs:160:12
    |
 LL |     while !let 0 = 0 {}
    |            ^^^^^^^^^
@@ -496,7 +628,7 @@ LL |     while !let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:158:12
+  --> $DIR/disallowed-positions.rs:161:12
    |
 LL |     while *let 0 = 0 {}
    |            ^^^^^^^^^
@@ -504,7 +636,7 @@ LL |     while *let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:160:12
+  --> $DIR/disallowed-positions.rs:163:12
    |
 LL |     while -let 0 = 0 {}
    |            ^^^^^^^^^
@@ -512,72 +644,72 @@ LL |     while -let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:168:12
+  --> $DIR/disallowed-positions.rs:171:12
    |
 LL |     while (let 0 = 0)? {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:168:12
+  --> $DIR/disallowed-positions.rs:171:12
    |
 LL |     while (let 0 = 0)? {}
    |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:172:19
+  --> $DIR/disallowed-positions.rs:175:19
    |
 LL |     while true || let 0 = 0 {}
    |                   ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:172:16
+  --> $DIR/disallowed-positions.rs:175:16
    |
 LL |     while true || let 0 = 0 {}
    |                ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:173:20
+  --> $DIR/disallowed-positions.rs:176:20
    |
 LL |     while (true || let 0 = 0) {}
    |                    ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:173:17
+  --> $DIR/disallowed-positions.rs:176:17
    |
 LL |     while (true || let 0 = 0) {}
    |                 ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:174:28
+  --> $DIR/disallowed-positions.rs:177:28
    |
 LL |     while true && (true || let 0 = 0) {}
    |                            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:174:25
+  --> $DIR/disallowed-positions.rs:177:25
    |
 LL |     while true && (true || let 0 = 0) {}
    |                         ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:175:28
+  --> $DIR/disallowed-positions.rs:178:28
    |
 LL |     while true || (true && let 0 = 0) {}
    |                            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:175:20
+  --> $DIR/disallowed-positions.rs:178:20
    |
 LL |     while true || (true && let 0 = 0) {}
    |                    ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:178:15
+  --> $DIR/disallowed-positions.rs:181:15
    |
 LL |     while x = let 0 = 0 {}
    |               ^^^^^^^^^
@@ -585,46 +717,46 @@ LL |     while x = let 0 = 0 {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:181:18
+  --> $DIR/disallowed-positions.rs:184:18
    |
 LL |     while true..(let 0 = 0) {}
    |                  ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:181:18
+  --> $DIR/disallowed-positions.rs:184:18
    |
 LL |     while true..(let 0 = 0) {}
    |                  ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:183:14
+  --> $DIR/disallowed-positions.rs:186:14
    |
 LL |     while ..(let 0 = 0) {}
    |              ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:183:14
+  --> $DIR/disallowed-positions.rs:186:14
    |
 LL |     while ..(let 0 = 0) {}
    |              ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:185:12
+  --> $DIR/disallowed-positions.rs:188:12
    |
 LL |     while (let 0 = 0).. {}
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:185:12
+  --> $DIR/disallowed-positions.rs:188:12
    |
 LL |     while (let 0 = 0).. {}
    |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:189:11
+  --> $DIR/disallowed-positions.rs:192:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -632,7 +764,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:193:11
+  --> $DIR/disallowed-positions.rs:196:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -640,7 +772,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:200:11
+  --> $DIR/disallowed-positions.rs:203:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -648,7 +780,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:208:11
+  --> $DIR/disallowed-positions.rs:211:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -656,7 +788,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:214:22
+  --> $DIR/disallowed-positions.rs:217:22
    |
 LL |     while let true = let true = true {}
    |                      ^^^^^^^^^^^^^^^
@@ -664,7 +796,7 @@ LL |     while let true = let true = true {}
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:228:6
+  --> $DIR/disallowed-positions.rs:232:6
    |
 LL |     &let 0 = 0;
    |      ^^^^^^^^^
@@ -672,7 +804,7 @@ LL |     &let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:230:6
+  --> $DIR/disallowed-positions.rs:236:6
    |
 LL |     !let 0 = 0;
    |      ^^^^^^^^^
@@ -680,7 +812,7 @@ LL |     !let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:231:6
+  --> $DIR/disallowed-positions.rs:239:6
    |
 LL |     *let 0 = 0;
    |      ^^^^^^^^^
@@ -688,7 +820,7 @@ LL |     *let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:233:6
+  --> $DIR/disallowed-positions.rs:243:6
    |
 LL |     -let 0 = 0;
    |      ^^^^^^^^^
@@ -696,59 +828,59 @@ LL |     -let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:241:6
+  --> $DIR/disallowed-positions.rs:253:6
    |
 LL |     (let 0 = 0)?;
    |      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:241:6
+  --> $DIR/disallowed-positions.rs:253:6
    |
 LL |     (let 0 = 0)?;
    |      ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:245:13
+  --> $DIR/disallowed-positions.rs:259:13
    |
 LL |     true || let 0 = 0;
    |             ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:245:10
+  --> $DIR/disallowed-positions.rs:259:10
    |
 LL |     true || let 0 = 0;
    |          ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:246:14
+  --> $DIR/disallowed-positions.rs:262:14
    |
 LL |     (true || let 0 = 0);
    |              ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:246:11
+  --> $DIR/disallowed-positions.rs:262:11
    |
 LL |     (true || let 0 = 0);
    |           ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:247:22
+  --> $DIR/disallowed-positions.rs:265:22
    |
 LL |     true && (true || let 0 = 0);
    |                      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `||` operators are not supported in let chain expressions
-  --> $DIR/disallowed-positions.rs:247:19
+  --> $DIR/disallowed-positions.rs:265:19
    |
 LL |     true && (true || let 0 = 0);
    |                   ^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:250:9
+  --> $DIR/disallowed-positions.rs:270:9
    |
 LL |     x = let 0 = 0;
    |         ^^^^^^^^^
@@ -756,46 +888,46 @@ LL |     x = let 0 = 0;
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:252:12
+  --> $DIR/disallowed-positions.rs:274:12
    |
 LL |     true..(let 0 = 0);
    |            ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:252:12
+  --> $DIR/disallowed-positions.rs:274:12
    |
 LL |     true..(let 0 = 0);
    |            ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:253:8
+  --> $DIR/disallowed-positions.rs:277:8
    |
 LL |     ..(let 0 = 0);
    |        ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:253:8
+  --> $DIR/disallowed-positions.rs:277:8
    |
 LL |     ..(let 0 = 0);
    |        ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:254:6
+  --> $DIR/disallowed-positions.rs:280:6
    |
 LL |     (let 0 = 0)..;
    |      ^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:254:6
+  --> $DIR/disallowed-positions.rs:280:6
    |
 LL |     (let 0 = 0)..;
    |      ^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:256:6
+  --> $DIR/disallowed-positions.rs:284:6
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -803,20 +935,20 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:260:6
+  --> $DIR/disallowed-positions.rs:289:6
    |
 LL |     (let true = let true = true);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:260:6
+  --> $DIR/disallowed-positions.rs:289:6
    |
 LL |     (let true = let true = true);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:264:6
+  --> $DIR/disallowed-positions.rs:307:6
    |
 LL |     &let 0 = 0
    |      ^^^^^^^^^
@@ -824,7 +956,7 @@ LL |     &let 0 = 0
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:275:17
+  --> $DIR/disallowed-positions.rs:319:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -832,7 +964,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:279:17
+  --> $DIR/disallowed-positions.rs:323:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -840,7 +972,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:283:17
+  --> $DIR/disallowed-positions.rs:327:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -848,7 +980,7 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:293:17
+  --> $DIR/disallowed-positions.rs:337:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -856,124 +988,124 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if` and `while` expressions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:302:9
+  --> $DIR/disallowed-positions.rs:346:9
    |
 LL |     if (let Some(a) = opt && true) {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:302:9
+  --> $DIR/disallowed-positions.rs:346:9
    |
 LL |     if (let Some(a) = opt && true) {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:306:9
+  --> $DIR/disallowed-positions.rs:350:9
    |
 LL |     if (let Some(a) = opt) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:306:9
+  --> $DIR/disallowed-positions.rs:350:9
    |
 LL |     if (let Some(a) = opt) && true {
    |         ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:309:9
+  --> $DIR/disallowed-positions.rs:353:9
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:309:9
+  --> $DIR/disallowed-positions.rs:353:9
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |         ^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:309:32
+  --> $DIR/disallowed-positions.rs:353:32
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |                                ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:309:32
+  --> $DIR/disallowed-positions.rs:353:32
    |
 LL |     if (let Some(a) = opt) && (let Some(b) = a) {
    |                                ^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:316:9
+  --> $DIR/disallowed-positions.rs:360:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:316:9
+  --> $DIR/disallowed-positions.rs:360:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:316:31
+  --> $DIR/disallowed-positions.rs:360:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |                               ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:316:31
+  --> $DIR/disallowed-positions.rs:360:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && b == 1 {
    |                               ^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:320:9
+  --> $DIR/disallowed-positions.rs:364:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:320:9
+  --> $DIR/disallowed-positions.rs:364:9
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:320:31
+  --> $DIR/disallowed-positions.rs:364:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |                               ^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:320:31
+  --> $DIR/disallowed-positions.rs:364:31
    |
 LL |     if (let Some(a) = opt && (let Some(b) = a)) && true {
    |                               ^^^^^^^^^^^^^^^
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:324:9
+  --> $DIR/disallowed-positions.rs:368:9
    |
 LL |     if (let Some(a) = opt && (true)) && true {
    |         ^^^^^^^^^^^^^^^^^
    |
    = note: only supported directly in conditions of `if` and `while` expressions
 note: `let`s wrapped in parentheses are not supported in a context with let chains
-  --> $DIR/disallowed-positions.rs:324:9
+  --> $DIR/disallowed-positions.rs:368:9
    |
 LL |     if (let Some(a) = opt && (true)) && true {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:90:8
+  --> $DIR/disallowed-positions.rs:92:8
    |
 LL |     if &let 0 = 0 {}
    |        ^^^^^^^^^^ expected `bool`, found `&bool`
@@ -985,19 +1117,19 @@ LL +     if let 0 = 0 {}
    |
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:94:8
+  --> $DIR/disallowed-positions.rs:96:8
    |
 LL |     if *let 0 = 0 {}
    |        ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:96:8
+  --> $DIR/disallowed-positions.rs:98:8
    |
 LL |     if -let 0 = 0 {}
    |        ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:104:8
+  --> $DIR/disallowed-positions.rs:106:8
    |
 LL |     if (let 0 = 0)? {}
    |        ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -1005,7 +1137,7 @@ LL |     if (let 0 = 0)? {}
    = help: the trait `Try` is not implemented for `bool`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:104:19
+  --> $DIR/disallowed-positions.rs:106:19
    |
 LL | / fn nested_within_if_expr() {
 LL | |     if &let 0 = 0 {}
@@ -1015,14 +1147,14 @@ LL | |
 LL | |     if (let 0 = 0)? {}
    | |                   ^ cannot use the `?` operator in a function that returns `()`
 ...  |
-LL | |     if let true = let true = true {}
+LL | |
 LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:114:8
+  --> $DIR/disallowed-positions.rs:116:8
    |
 LL |     if x = let 0 = 0 {}
    |        ^^^^^^^^^^^^^ expected `bool`, found `()`
@@ -1033,7 +1165,7 @@ LL |     if x == let 0 = 0 {}
    |          ~~
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:117:8
+  --> $DIR/disallowed-positions.rs:119:8
    |
 LL |     if true..(let 0 = 0) {}
    |        ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1042,7 +1174,7 @@ LL |     if true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:119:8
+  --> $DIR/disallowed-positions.rs:121:8
    |
 LL |     if ..(let 0 = 0) {}
    |        ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
@@ -1051,7 +1183,7 @@ LL |     if ..(let 0 = 0) {}
             found struct `RangeTo<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:121:8
+  --> $DIR/disallowed-positions.rs:123:8
    |
 LL |     if (let 0 = 0).. {}
    |        ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
@@ -1060,7 +1192,7 @@ LL |     if (let 0 = 0).. {}
             found struct `RangeFrom<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:125:12
+  --> $DIR/disallowed-positions.rs:127:12
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1071,7 +1203,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:125:8
+  --> $DIR/disallowed-positions.rs:127:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1080,7 +1212,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:129:12
+  --> $DIR/disallowed-positions.rs:131:12
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1091,7 +1223,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:129:8
+  --> $DIR/disallowed-positions.rs:131:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1100,7 +1232,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:136:12
+  --> $DIR/disallowed-positions.rs:138:12
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
@@ -1111,20 +1243,20 @@ LL |     if let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:136:41
+  --> $DIR/disallowed-positions.rs:138:41
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |                                         ^^^^^^^ expected `bool`, found closure
    |
    = note: expected type `bool`
-           found closure `[closure@$DIR/disallowed-positions.rs:136:41: 136:48]`
+           found closure `[closure@$DIR/disallowed-positions.rs:138:41: 138:48]`
 help: use parentheses to call this closure
    |
 LL |     if let Range { start: F, end } = F..(|| true)() {}
    |                                         +       +++
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:136:8
+  --> $DIR/disallowed-positions.rs:138:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1133,7 +1265,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:144:12
+  --> $DIR/disallowed-positions.rs:146:12
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -1144,7 +1276,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:144:44
+  --> $DIR/disallowed-positions.rs:146:44
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |                                            ^^^^^^^ expected `bool`, found `&&bool`
@@ -1156,7 +1288,7 @@ LL +     if let Range { start: true, end } = t..false {}
    |
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:144:8
+  --> $DIR/disallowed-positions.rs:146:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1165,7 +1297,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<bool>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:100:20
+  --> $DIR/disallowed-positions.rs:102:20
    |
 LL |         if let 0 = 0? {}
    |                    ^^ the `?` operator cannot be applied to type `{integer}`
@@ -1173,7 +1305,7 @@ LL |         if let 0 = 0? {}
    = help: the trait `Try` is not implemented for `{integer}`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:154:11
+  --> $DIR/disallowed-positions.rs:157:11
    |
 LL |     while &let 0 = 0 {}
    |           ^^^^^^^^^^ expected `bool`, found `&bool`
@@ -1185,19 +1317,19 @@ LL +     while let 0 = 0 {}
    |
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:158:11
+  --> $DIR/disallowed-positions.rs:161:11
    |
 LL |     while *let 0 = 0 {}
    |           ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:160:11
+  --> $DIR/disallowed-positions.rs:163:11
    |
 LL |     while -let 0 = 0 {}
    |           ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:168:11
+  --> $DIR/disallowed-positions.rs:171:11
    |
 LL |     while (let 0 = 0)? {}
    |           ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -1205,7 +1337,7 @@ LL |     while (let 0 = 0)? {}
    = help: the trait `Try` is not implemented for `bool`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:168:22
+  --> $DIR/disallowed-positions.rs:171:22
    |
 LL | / fn nested_within_while_expr() {
 LL | |     while &let 0 = 0 {}
@@ -1215,14 +1347,14 @@ LL | |
 LL | |     while (let 0 = 0)? {}
    | |                      ^ cannot use the `?` operator in a function that returns `()`
 ...  |
-LL | |     while let true = let true = true {}
+LL | |
 LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:178:11
+  --> $DIR/disallowed-positions.rs:181:11
    |
 LL |     while x = let 0 = 0 {}
    |           ^^^^^^^^^^^^^ expected `bool`, found `()`
@@ -1233,7 +1365,7 @@ LL |     while x == let 0 = 0 {}
    |             ~~
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:181:11
+  --> $DIR/disallowed-positions.rs:184:11
    |
 LL |     while true..(let 0 = 0) {}
    |           ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1242,7 +1374,7 @@ LL |     while true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:183:11
+  --> $DIR/disallowed-positions.rs:186:11
    |
 LL |     while ..(let 0 = 0) {}
    |           ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
@@ -1251,7 +1383,7 @@ LL |     while ..(let 0 = 0) {}
             found struct `RangeTo<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:185:11
+  --> $DIR/disallowed-positions.rs:188:11
    |
 LL |     while (let 0 = 0).. {}
    |           ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
@@ -1260,7 +1392,7 @@ LL |     while (let 0 = 0).. {}
             found struct `RangeFrom<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:189:15
+  --> $DIR/disallowed-positions.rs:192:15
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1271,7 +1403,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:189:11
+  --> $DIR/disallowed-positions.rs:192:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1280,7 +1412,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:193:15
+  --> $DIR/disallowed-positions.rs:196:15
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1291,7 +1423,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:193:11
+  --> $DIR/disallowed-positions.rs:196:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1300,7 +1432,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:200:15
+  --> $DIR/disallowed-positions.rs:203:15
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `fn() -> bool`
@@ -1311,20 +1443,20 @@ LL |     while let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:200:44
+  --> $DIR/disallowed-positions.rs:203:44
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |                                            ^^^^^^^ expected `bool`, found closure
    |
    = note: expected type `bool`
-           found closure `[closure@$DIR/disallowed-positions.rs:200:44: 200:51]`
+           found closure `[closure@$DIR/disallowed-positions.rs:203:44: 203:51]`
 help: use parentheses to call this closure
    |
 LL |     while let Range { start: F, end } = F..(|| true)() {}
    |                                            +       +++
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:200:11
+  --> $DIR/disallowed-positions.rs:203:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1333,7 +1465,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:208:15
+  --> $DIR/disallowed-positions.rs:211:15
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -1344,7 +1476,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:208:47
+  --> $DIR/disallowed-positions.rs:211:47
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |                                               ^^^^^^^ expected `bool`, found `&&bool`
@@ -1356,7 +1488,7 @@ LL +     while let Range { start: true, end } = t..false {}
    |
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:208:11
+  --> $DIR/disallowed-positions.rs:211:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -1365,7 +1497,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<bool>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:164:23
+  --> $DIR/disallowed-positions.rs:167:23
    |
 LL |         while let 0 = 0? {}
    |                       ^^ the `?` operator cannot be applied to type `{integer}`
@@ -1373,19 +1505,19 @@ LL |         while let 0 = 0? {}
    = help: the trait `Try` is not implemented for `{integer}`
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:231:5
+  --> $DIR/disallowed-positions.rs:239:5
    |
 LL |     *let 0 = 0;
    |     ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:233:5
+  --> $DIR/disallowed-positions.rs:243:5
    |
 LL |     -let 0 = 0;
    |     ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:241:5
+  --> $DIR/disallowed-positions.rs:253:5
    |
 LL |     (let 0 = 0)?;
    |     ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -1393,12 +1525,12 @@ LL |     (let 0 = 0)?;
    = help: the trait `Try` is not implemented for `bool`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:241:16
+  --> $DIR/disallowed-positions.rs:253:16
    |
 LL | / fn outside_if_and_while_expr() {
 LL | |     &let 0 = 0;
 LL | |
-LL | |     !let 0 = 0;
+LL | |
 ...  |
 LL | |     (let 0 = 0)?;
    | |                ^ cannot use the `?` operator in a function that returns `()`
@@ -1410,7 +1542,7 @@ LL | | }
    = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:256:10
+  --> $DIR/disallowed-positions.rs:284:10
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -1421,7 +1553,7 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:264:5
+  --> $DIR/disallowed-positions.rs:307:5
    |
 LL | fn outside_if_and_while_expr() {
    |                                - help: try adding a return type: `-> &bool`
@@ -1430,14 +1562,14 @@ LL |     &let 0 = 0
    |     ^^^^^^^^^^ expected `()`, found `&bool`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:237:17
+  --> $DIR/disallowed-positions.rs:249:17
    |
 LL |         let 0 = 0?;
    |                 ^^ the `?` operator cannot be applied to type `{integer}`
    |
    = help: the trait `Try` is not implemented for `{integer}`
 
-error: aborting due to 134 previous errors
+error: aborting due to 156 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0600, E0614.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
index e66caa19ec96b..12befc637c787 100644
--- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
@@ -17,6 +17,7 @@ fn main() {
     //~| ERROR `let` expressions are not supported here
     //~| ERROR mismatched types
     //~| ERROR mismatched types
+    //~| ERROR expected expression, found `let` statement
         return;
     };
 
diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
index eea8ed0c9633e..498a112fa9bb3 100644
--- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
@@ -9,6 +9,12 @@ help: wrap the expression in parentheses
 LL |     let Some(n) = (opt && n == 1) else {
    |                   +             +
 
+error: expected expression, found `let` statement
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:26
+   |
+LL |     let Some(n) = opt && let another = n else {
+   |                          ^^^
+
 error: a `&&` expression cannot be directly assigned in `let...else`
   --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19
    |
@@ -21,43 +27,43 @@ LL |     let Some(n) = (opt && let another = n) else {
    |                   +                      +
 
 error: this `if` expression is missing a block after the condition
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:5
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:24:5
    |
 LL |     if let Some(n) = opt else {
    |     ^^
    |
 help: add a block here
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:25
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:24:25
    |
 LL |     if let Some(n) = opt else {
    |                         ^
 
 error: this `if` expression is missing a block after the condition
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:5
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:28:5
    |
 LL |     if let Some(n) = opt && n == 1 else {
    |     ^^
    |
 help: add a block here
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:35
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:28:35
    |
 LL |     if let Some(n) = opt && n == 1 else {
    |                                   ^
 
 error: this `if` expression is missing a block after the condition
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:5
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:32:5
    |
 LL |     if let Some(n) = opt && let another = n else {
    |     ^^
    |
 help: add a block here
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:44
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:32:44
    |
 LL |     if let Some(n) = opt && let another = n else {
    |                                            ^
 
 error: expected `{`, found keyword `else`
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:37:33
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:38:33
    |
 LL |         while let Some(n) = opt else {
    |         ----- ----------------- ^^^^ expected `{`
@@ -66,7 +72,7 @@ LL |         while let Some(n) = opt else {
    |         while parsing the body of this `while` expression
 
 error: expected `{`, found keyword `else`
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:43:43
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:44:43
    |
 LL |         while let Some(n) = opt && n == 1 else {
    |         ----- --------------------------- ^^^^ expected `{`
@@ -75,7 +81,7 @@ LL |         while let Some(n) = opt && n == 1 else {
    |         while parsing the body of this `while` expression
 
 error: expected `{`, found keyword `else`
-  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:49:52
+  --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:50:52
    |
 LL |         while let Some(n) = opt && let another = n else {
    |         ----- ------------------------------------ ^^^^ expected `{`
@@ -131,6 +137,6 @@ LL |     let Some(n) = opt && let another = n else {
    = note: expected type `bool`
               found enum `Option<_>`
 
-error: aborting due to 13 previous errors
+error: aborting due to 14 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
index ac60bc7e57fd4..8771821130848 100644
--- a/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.rs
@@ -39,6 +39,7 @@ fn _macros() {
 
     noop_expr!((let 0 = 1));
     //~^ ERROR `let` expressions in this position are unstable [E0658]
+    //~| ERROR expected expression, found `let` statement
 
     macro_rules! use_expr {
         ($e:expr) => {
@@ -48,9 +49,9 @@ fn _macros() {
     }
     #[cfg(FALSE)] (let 0 = 1);
     //~^ ERROR `let` expressions in this position are unstable [E0658]
+    //~| ERROR expected expression, found `let` statement
     use_expr!(let 0 = 1);
     //~^ ERROR no rules expected the token `let`
-    // ^--- FIXME(53667): Consider whether `Let` can be added to `ident_can_begin_expr`.
 }
 
 fn main() {}
diff --git a/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
index 1eabee47c64ac..bcea8bbaa730b 100644
--- a/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/feature-gate.stderr
@@ -1,5 +1,17 @@
+error: expected expression, found `let` statement
+  --> $DIR/feature-gate.rs:50:20
+   |
+LL |     #[cfg(FALSE)] (let 0 = 1);
+   |                    ^^^
+
+error: expected expression, found `let` statement
+  --> $DIR/feature-gate.rs:40:17
+   |
+LL |     noop_expr!((let 0 = 1));
+   |                 ^^^
+
 error: no rules expected the token `let`
-  --> $DIR/feature-gate.rs:51:15
+  --> $DIR/feature-gate.rs:53:15
    |
 LL |     macro_rules! use_expr {
    |     --------------------- when calling this macro
@@ -62,7 +74,7 @@ LL |     while let Range { start: _, end: _ } = (true..true) && false {}
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
 error[E0658]: `let` expressions in this position are unstable
-  --> $DIR/feature-gate.rs:49:20
+  --> $DIR/feature-gate.rs:50:20
    |
 LL |     #[cfg(FALSE)] (let 0 = 1);
    |                    ^^^^^^^^^
@@ -79,6 +91,6 @@ LL |     noop_expr!((let 0 = 1));
    = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
    = help: add `#![feature(let_chains)]` to the crate attributes to enable
 
-error: aborting due to 9 previous errors
+error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs b/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs
new file mode 100644
index 0000000000000..6cc53a1935b95
--- /dev/null
+++ b/src/test/ui/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs
@@ -0,0 +1,17 @@
+// check-pass
+// known-bug
+
+#![feature(let_chains)]
+
+fn main() {
+    let _opt = Some(1i32);
+
+    #[cfg(FALSE)]
+    {
+        if let Some(elem) = _opt && {
+            [1, 2, 3][let _ = ()];
+            true
+        } {
+        }
+    }
+}

From 557793c2a4c5b4713d51c5c55e4f54c285bdc084 Mon Sep 17 00:00:00 2001
From: Mark Rousskov <mark.simulacrum@gmail.com>
Date: Sat, 25 Jun 2022 09:56:56 -0400
Subject: [PATCH 19/20] Bump RLS to latest master on rust-lang/rls

Of primary interest, this merges
rust-lang/rls@ece09b88c0365947af79c0ffdeea02bc6c1eec25 into rust-lang/rust,
which brings in the changes that fix RLS tests broken by #97853. #97853 already
introduced that commit's changes (under
27f4044df03d15c7c38a483c3e4635cf4f51807d) but without putting those changes on
rust-lang/rls as a branch, so we ended up with an orphan commit that caused
trouble when updating submodules in rust-lang/rust.

This commit, once merged into rust-lang/rust, should continue to let RLS tests
to pass on rust-lang/rust's side and move us back into a healthy state where tip
of the submodule points to a valid master commit in the rust-lang/rls
repository.
---
 Cargo.lock    | 3 +--
 src/tools/rls | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 1108c1f4d4c20..b6f17ad7838c3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3101,7 +3101,6 @@ name = "racer"
 version = "2.2.2"
 dependencies = [
  "bitflags",
- "clap 2.34.0",
  "derive_more",
  "env_logger 0.7.1",
  "humantime 2.0.1",
@@ -3325,7 +3324,7 @@ dependencies = [
  "difference",
  "env_logger 0.9.0",
  "futures 0.3.19",
- "heck 0.3.1",
+ "heck 0.4.0",
  "home",
  "itertools",
  "jsonrpc-core",
diff --git a/src/tools/rls b/src/tools/rls
index 27f4044df03d1..ece09b88c0365 160000
--- a/src/tools/rls
+++ b/src/tools/rls
@@ -1 +1 @@
-Subproject commit 27f4044df03d15c7c38a483c3e4635cf4f51807d
+Subproject commit ece09b88c0365947af79c0ffdeea02bc6c1eec25

From 50a46b92f6b09e5cab6e8b4f4683cf8518102115 Mon Sep 17 00:00:00 2001
From: Antoni Boucher <bouanto@zoho.com>
Date: Sat, 25 Jun 2022 11:48:26 -0400
Subject: [PATCH 20/20] Fix backtrace UI test when panic=abort is used

---
 src/test/ui/backtrace.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/test/ui/backtrace.rs b/src/test/ui/backtrace.rs
index c2d9e222b84a4..01b276d67ed87 100644
--- a/src/test/ui/backtrace.rs
+++ b/src/test/ui/backtrace.rs
@@ -43,6 +43,7 @@ fn expected(fn_name: &str) -> String {
     format!(" backtrace::{}", fn_name)
 }
 
+#[cfg(not(panic = "abort"))]
 fn contains_verbose_expected(s: &str, fn_name: &str) -> bool {
     // HACK(eddyb) work around the fact that verbosely demangled stack traces
     // (from `RUST_BACKTRACE=full`, or, as is the case here, panic-in-panic)