From 662024478deb04a8c71d779b66b4bedb0bf91dbe Mon Sep 17 00:00:00 2001
From: woppopo <woppopo@protonmail.com>
Date: Sun, 12 Dec 2021 04:19:23 +0900
Subject: [PATCH 1/8] Make some `Clone` impls `const`

---
 library/core/src/clone.rs        | 21 +++++++++++++++------
 library/core/src/convert/mod.rs  |  3 ++-
 library/core/src/lib.rs          |  1 +
 library/core/src/option.rs       |  6 +++++-
 library/core/src/ptr/non_null.rs |  3 ++-
 library/core/src/ptr/unique.rs   |  3 ++-
 library/core/src/result.rs       |  7 ++++++-
 7 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs
index 6f9579043c37d..1912694412b98 100644
--- a/library/core/src/clone.rs
+++ b/library/core/src/clone.rs
@@ -127,7 +127,11 @@ pub trait Clone: Sized {
     /// allocations.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn clone_from(&mut self, source: &Self) {
+    #[default_method_body_is_const]
+    fn clone_from(&mut self, source: &Self)
+    where
+        Self: ~const Drop,
+    {
         *self = source.clone()
     }
 }
@@ -178,7 +182,8 @@ mod impls {
         ($($t:ty)*) => {
             $(
                 #[stable(feature = "rust1", since = "1.0.0")]
-                impl Clone for $t {
+                #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
+                impl const Clone for $t {
                     #[inline]
                     fn clone(&self) -> Self {
                         *self
@@ -196,7 +201,8 @@ mod impls {
     }
 
     #[unstable(feature = "never_type", issue = "35121")]
-    impl Clone for ! {
+    #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
+    impl const Clone for ! {
         #[inline]
         fn clone(&self) -> Self {
             *self
@@ -204,7 +210,8 @@ mod impls {
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl<T: ?Sized> Clone for *const T {
+    #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
+    impl<T: ?Sized> const Clone for *const T {
         #[inline]
         fn clone(&self) -> Self {
             *self
@@ -212,7 +219,8 @@ mod impls {
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl<T: ?Sized> Clone for *mut T {
+    #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
+    impl<T: ?Sized> const Clone for *mut T {
         #[inline]
         fn clone(&self) -> Self {
             *self
@@ -221,7 +229,8 @@ mod impls {
 
     /// Shared references can be cloned, but mutable references *cannot*!
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl<T: ?Sized> Clone for &T {
+    #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
+    impl<T: ?Sized> const Clone for &T {
         #[inline]
         #[rustc_diagnostic_item = "noop_method_clone"]
         fn clone(&self) -> Self {
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 5aa53deee343d..a50b8904b593e 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -683,7 +683,8 @@ impl AsMut<str> for str {
 pub enum Infallible {}
 
 #[stable(feature = "convert_infallible", since = "1.34.0")]
-impl Clone for Infallible {
+#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
+impl const Clone for Infallible {
     fn clone(&self) -> Infallible {
         match *self {}
     }
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 78383b54c5d1e..4ef4740799a0b 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -106,6 +106,7 @@
 #![feature(const_caller_location)]
 #![feature(const_cell_into_inner)]
 #![feature(const_char_convert)]
+#![feature(const_clone)]
 #![feature(const_discriminant)]
 #![feature(const_eval_select)]
 #![feature(const_float_bits_conv)]
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 7b9c6e43960f7..941d7e0792628 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1668,7 +1668,11 @@ const fn expect_failed(msg: &str) -> ! {
 /////////////////////////////////////////////////////////////////////////////
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Clone> Clone for Option<T> {
+#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
+impl<T> const Clone for Option<T>
+where
+    T: ~const Clone + ~const Drop,
+{
     #[inline]
     fn clone(&self) -> Self {
         match self {
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 58110b0680943..cb268abc8eecd 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -635,7 +635,8 @@ impl<T> NonNull<[T]> {
 }
 
 #[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> Clone for NonNull<T> {
+#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
+impl<T: ?Sized> const Clone for NonNull<T> {
     #[inline]
     fn clone(&self) -> Self {
         *self
diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs
index d650a6f974b97..ee984b7b5a4f1 100644
--- a/library/core/src/ptr/unique.rs
+++ b/library/core/src/ptr/unique.rs
@@ -146,7 +146,8 @@ impl<T: ?Sized> Unique<T> {
 }
 
 #[unstable(feature = "ptr_internals", issue = "none")]
-impl<T: ?Sized> Clone for Unique<T> {
+#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
+impl<T: ?Sized> const Clone for Unique<T> {
     #[inline]
     fn clone(&self) -> Self {
         *self
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index e6b8c8ec3385a..d639c7188c15a 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1665,7 +1665,12 @@ fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! {
 /////////////////////////////////////////////////////////////////////////////
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Clone, E: Clone> Clone for Result<T, E> {
+#[rustc_const_unstable(feature = "const_clone", issue = "91805")]
+impl<T, E> const Clone for Result<T, E>
+where
+    T: ~const Clone + ~const Drop,
+    E: ~const Clone + ~const Drop,
+{
     #[inline]
     fn clone(&self) -> Self {
         match self {

From 9054fbb03ab2ebb048888f4963a364d800fba056 Mon Sep 17 00:00:00 2001
From: asquared31415 <34665709+asquared31415@users.noreply.github.com>
Date: Mon, 3 Jan 2022 17:12:59 -0500
Subject: [PATCH 2/8] mirror mention of intent of From

---
 library/core/src/convert/mod.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 1c2e673d60493..b6211900b47f4 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -300,7 +300,8 @@ pub trait Into<T>: Sized {
 /// that encapsulate multiple error types. See the "Examples" section and [the book][book] for more
 /// details.
 ///
-/// **Note: This trait must not fail**. If the conversion can fail, use [`TryFrom`].
+/// **Note: This trait must not fail**. The `From` trait is intended for perfect conversions.
+/// If the conversion can fail or is not perfect, use [`TryFrom`].
 ///
 /// # Generic Implementations
 ///

From b328688d23d56a7b95ddcd994c3967a193dd25ea Mon Sep 17 00:00:00 2001
From: Jon Gjengset <jongje@amazon.com>
Date: Mon, 7 Mar 2022 16:59:10 -0800
Subject: [PATCH 3/8] Statically compile libstdc++ everywhere if asked

PR #93918 made it so that `-static-libstdc++` was only set in one place,
and was only set during linking, but accidentally also made it so that
it is no longer passed when building LLD or sanitizers, only when
building LLVM itself. This moves the logic for setting
`-static-libstdc++` in the linker flags back to `configure_cmake` so
that it takes effect for all CMake invocations in `native.rs`.

As a side-effect, this also causes libstdc++ to be statically compiled
into sanitizers and LLD if `llvm-tools-enabled` is set but
`llvm-static-stdcpp` is not, even though previously it was only linked
statically if `llvm-static-stdcpp` was set explicitly. But that seems
more like the expected behavior anyway.
---
 src/bootstrap/native.rs | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index f00c5ce5aa6f0..0fe39defae85d 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -259,18 +259,6 @@ impl Step for Llvm {
             cfg.define("LLVM_LINK_LLVM_DYLIB", "ON");
         }
 
-        // For distribution we want the LLVM tools to be *statically* linked to libstdc++.
-        // We also do this if the user explicitly requested static libstdc++.
-        if builder.config.llvm_tools_enabled || builder.config.llvm_static_stdcpp {
-            if !target.contains("msvc") && !target.contains("netbsd") {
-                if target.contains("apple") {
-                    ldflags.push_all("-static-libstdc++");
-                } else {
-                    ldflags.push_all("-Wl,-Bsymbolic -static-libstdc++");
-                }
-            }
-        }
-
         if target.starts_with("riscv") && !target.contains("freebsd") {
             // RISC-V GCC erroneously requires linking against
             // `libatomic` when using 1-byte and 2-byte C++
@@ -576,6 +564,18 @@ fn configure_cmake(
         ldflags.push_all(&flags);
     }
 
+    // For distribution we want the LLVM tools to be *statically* linked to libstdc++.
+    // We also do this if the user explicitly requested static libstdc++.
+    if builder.config.llvm_tools_enabled || builder.config.llvm_static_stdcpp {
+        if !target.contains("msvc") && !target.contains("netbsd") {
+            if target.contains("apple") {
+                ldflags.push_all("-static-libstdc++");
+            } else {
+                ldflags.push_all("-Wl,-Bsymbolic -static-libstdc++");
+            }
+        }
+    }
+
     cfg.define("CMAKE_SHARED_LINKER_FLAGS", &ldflags.shared);
     cfg.define("CMAKE_MODULE_LINKER_FLAGS", &ldflags.module);
     cfg.define("CMAKE_EXE_LINKER_FLAGS", &ldflags.exe);

From 0d92752b8aac53e033541d04fc7d9677d8bca227 Mon Sep 17 00:00:00 2001
From: Esteban Kuber <esteban@kuber.com.ar>
Date: Tue, 8 Mar 2022 05:54:38 +0000
Subject: [PATCH 4/8] Suggest `if let`/`let_else` for refutable pat in `let`

---
 .../src/thir/pattern/check_match.rs           | 86 +++++++++++++++++--
 .../ui/consts/const-match-check.eval1.stderr  | 10 ++-
 .../ui/consts/const-match-check.eval2.stderr  | 10 ++-
 .../consts/const-match-check.matchck.stderr   | 40 ++++++---
 src/test/ui/empty/empty-never-array.stderr    |  6 +-
 src/test/ui/error-codes/E0005.stderr          |  8 +-
 .../feature-gate-exhaustive-patterns.stderr   |  8 +-
 ...een-expanded-earlier-non-exhaustive.stderr | 10 ++-
 .../ui/pattern/usefulness/issue-31561.stderr  |  8 +-
 .../non-exhaustive-defined-here.stderr        | 36 +++++---
 .../refutable-pattern-errors.stderr           |  8 +-
 ...recursive-types-are-not-uninhabited.stderr |  6 +-
 .../ui/uninhabited/uninhabited-irrefutable.rs |  6 +-
 .../uninhabited-irrefutable.stderr            | 12 ++-
 .../uninhabited-matches-feature-gated.stderr  |  6 +-
 15 files changed, 204 insertions(+), 56 deletions(-)

diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index b80d2e52ee709..dae313da8d993 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -7,7 +7,8 @@ use super::{PatCtxt, PatternError};
 use rustc_arena::TypedArena;
 use rustc_ast::Mutability;
 use rustc_errors::{
-    error_code, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
+    error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder,
+    ErrorGuaranteed,
 };
 use rustc_hir as hir;
 use rustc_hir::def::*;
@@ -20,7 +21,7 @@ use rustc_session::lint::builtin::{
 };
 use rustc_session::Session;
 use rustc_span::source_map::Spanned;
-use rustc_span::{DesugaringKind, ExpnKind, MultiSpan, Span};
+use rustc_span::{BytePos, DesugaringKind, ExpnKind, MultiSpan, Span};
 
 crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
     let body_id = match def_id.as_local() {
@@ -241,6 +242,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         }
 
         let joined_patterns = joined_uncovered_patterns(&cx, &witnesses);
+
+        let mut bindings = vec![];
+
         let mut err = struct_span_err!(
             self.tcx.sess,
             pat.span,
@@ -257,6 +261,16 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
                 false
             }
             _ => {
+                pat.walk(&mut |pat: &hir::Pat<'_>| {
+                    match pat.kind {
+                        hir::PatKind::Binding(_, _, ident, _) => {
+                            bindings.push(ident);
+                        }
+                        _ => {}
+                    }
+                    true
+                });
+
                 err.span_label(pat.span, pattern_not_covered_label(&witnesses, &joined_patterns));
                 true
             }
@@ -267,13 +281,71 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
                 "`let` bindings require an \"irrefutable pattern\", like a `struct` or \
                  an `enum` with only one variant",
             );
-            if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                err.span_suggestion(
-                    span,
-                    "you might want to use `if let` to ignore the variant that isn't matched",
-                    format!("if {} {{ /* */ }}", &snippet[..snippet.len() - 1]),
+            if self.tcx.sess.source_map().span_to_snippet(span).is_ok() {
+                let semi_span = span.shrink_to_hi().with_lo(span.hi() - BytePos(1));
+                let start_span = span.shrink_to_lo();
+                let end_span = semi_span.shrink_to_lo();
+                err.multipart_suggestion(
+                    &format!(
+                        "you might want to use `if let` to ignore the variant{} that {} matched",
+                        pluralize!(witnesses.len()),
+                        match witnesses.len() {
+                            1 => "isn't",
+                            _ => "aren't",
+                        },
+                    ),
+                    vec![
+                        match &bindings[..] {
+                            [] => (start_span, "if ".to_string()),
+                            [binding] => (start_span, format!("let {} = if ", binding)),
+                            bindings => (
+                                start_span,
+                                format!(
+                                    "let ({}) = if ",
+                                    bindings
+                                        .iter()
+                                        .map(|ident| ident.to_string())
+                                        .collect::<Vec<_>>()
+                                        .join(", ")
+                                ),
+                            ),
+                        },
+                        match &bindings[..] {
+                            [] => (semi_span, " { todo!() }".to_string()),
+                            [binding] => {
+                                (end_span, format!(" {{ {} }} else {{ todo!() }}", binding))
+                            }
+                            bindings => (
+                                end_span,
+                                format!(
+                                    " {{ ({}) }} else {{ todo!() }}",
+                                    bindings
+                                        .iter()
+                                        .map(|ident| ident.to_string())
+                                        .collect::<Vec<_>>()
+                                        .join(", ")
+                                ),
+                            ),
+                        },
+                    ],
                     Applicability::HasPlaceholders,
                 );
+                if cx.tcx.sess.is_nightly_build() {
+                    err.span_suggestion_verbose(
+                        semi_span.shrink_to_lo(),
+                        &format!(
+                            "alternatively, on nightly, you might want to use \
+                             `#![feature(let_else)]` to handle the variant{} that {} matched",
+                            pluralize!(witnesses.len()),
+                            match witnesses.len() {
+                                1 => "isn't",
+                                _ => "aren't",
+                            },
+                        ),
+                        " else { todo!() }".to_string(),
+                        Applicability::HasPlaceholders,
+                    );
+                }
             }
             err.note(
                 "for more information, visit \
diff --git a/src/test/ui/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr
index 4141cc4ab1a48..08ee800f138d2 100644
--- a/src/test/ui/consts/const-match-check.eval1.stderr
+++ b/src/test/ui/consts/const-match-check.eval1.stderr
@@ -7,10 +7,14 @@ LL |     A = { let 0 = 0; 0 },
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
-help: you might want to use `if let` to ignore the variant that isn't matched
+help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     A = { if let 0 = 0 { /* */ } 0 },
-   |           ~~~~~~~~~~~~~~~~~~~~~~
+LL |     A = { if let 0 = 0 { todo!() } 0 },
+   |           ++           ~~~~~~~~~~~
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
+   |
+LL |     A = { let 0 = 0 else { todo!() }; 0 },
+   |                     ++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-match-check.eval2.stderr b/src/test/ui/consts/const-match-check.eval2.stderr
index af86ba0cc82f8..579cb7e780007 100644
--- a/src/test/ui/consts/const-match-check.eval2.stderr
+++ b/src/test/ui/consts/const-match-check.eval2.stderr
@@ -7,10 +7,14 @@ LL |     let x: [i32; { let 0 = 0; 0 }] = [];
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
-help: you might want to use `if let` to ignore the variant that isn't matched
+help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     let x: [i32; { if let 0 = 0 { /* */ } 0 }] = [];
-   |                    ~~~~~~~~~~~~~~~~~~~~~~
+LL |     let x: [i32; { if let 0 = 0 { todo!() } 0 }] = [];
+   |                    ++           ~~~~~~~~~~~
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
+   |
+LL |     let x: [i32; { let 0 = 0 else { todo!() }; 0 }] = [];
+   |                              ++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-match-check.matchck.stderr b/src/test/ui/consts/const-match-check.matchck.stderr
index f71490eba6135..f89bbc0d42234 100644
--- a/src/test/ui/consts/const-match-check.matchck.stderr
+++ b/src/test/ui/consts/const-match-check.matchck.stderr
@@ -7,10 +7,14 @@ LL | const X: i32 = { let 0 = 0; 0 };
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
-help: you might want to use `if let` to ignore the variant that isn't matched
+help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL | const X: i32 = { if let 0 = 0 { /* */ } 0 };
-   |                  ~~~~~~~~~~~~~~~~~~~~~~
+LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
+   |                  ++           ~~~~~~~~~~~
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
+   |
+LL | const X: i32 = { let 0 = 0 else { todo!() }; 0 };
+   |                            ++++++++++++++++
 
 error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
   --> $DIR/const-match-check.rs:8:23
@@ -21,10 +25,14 @@ LL | static Y: i32 = { let 0 = 0; 0 };
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
-help: you might want to use `if let` to ignore the variant that isn't matched
+help: you might want to use `if let` to ignore the variants that aren't matched
+   |
+LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 };
+   |                   ++           ~~~~~~~~~~~
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
    |
-LL | static Y: i32 = { if let 0 = 0 { /* */ } 0 };
-   |                   ~~~~~~~~~~~~~~~~~~~~~~
+LL | static Y: i32 = { let 0 = 0 else { todo!() }; 0 };
+   |                             ++++++++++++++++
 
 error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
   --> $DIR/const-match-check.rs:13:26
@@ -35,10 +43,14 @@ LL |     const X: i32 = { let 0 = 0; 0 };
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
-help: you might want to use `if let` to ignore the variant that isn't matched
+help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     const X: i32 = { if let 0 = 0 { /* */ } 0 };
-   |                      ~~~~~~~~~~~~~~~~~~~~~~
+LL |     const X: i32 = { if let 0 = 0 { todo!() } 0 };
+   |                      ++           ~~~~~~~~~~~
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
+   |
+LL |     const X: i32 = { let 0 = 0 else { todo!() }; 0 };
+   |                                ++++++++++++++++
 
 error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
   --> $DIR/const-match-check.rs:19:26
@@ -49,10 +61,14 @@ LL |     const X: i32 = { let 0 = 0; 0 };
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
-help: you might want to use `if let` to ignore the variant that isn't matched
+help: you might want to use `if let` to ignore the variants that aren't matched
+   |
+LL |     const X: i32 = { if let 0 = 0 { todo!() } 0 };
+   |                      ++           ~~~~~~~~~~~
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
    |
-LL |     const X: i32 = { if let 0 = 0 { /* */ } 0 };
-   |                      ~~~~~~~~~~~~~~~~~~~~~~
+LL |     const X: i32 = { let 0 = 0 else { todo!() }; 0 };
+   |                                ++++++++++++++++
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr
index 8dd0f377533ce..909aa73a74a38 100644
--- a/src/test/ui/empty/empty-never-array.stderr
+++ b/src/test/ui/empty/empty-never-array.stderr
@@ -16,8 +16,12 @@ LL |     T(T, [!; 0]),
    = note: the matched value is of type `Helper<T, U>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
-LL |     if let Helper::U(u) = Helper::T(t, []) { /* */ }
+LL |     let u = if let Helper::U(u) = Helper::T(t, []) { u } else { todo!() };
+   |     ++++++++++                                     ++++++++++++++++++++++
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
    |
+LL |     let Helper::U(u) = Helper::T(t, []) else { todo!() };
+   |                                         ++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0005.stderr b/src/test/ui/error-codes/E0005.stderr
index 208c625a53e95..55b1112b5f8ec 100644
--- a/src/test/ui/error-codes/E0005.stderr
+++ b/src/test/ui/error-codes/E0005.stderr
@@ -22,8 +22,12 @@ LL | | }
    = note: the matched value is of type `Option<i32>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
-LL |     if let Some(y) = x { /* */ }
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     let y = if let Some(y) = x { y } else { todo!() };
+   |     ++++++++++                 ++++++++++++++++++++++
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
+   |
+LL |     let Some(y) = x else { todo!() };
+   |                     ++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
index c2ffda6bb72d2..21180f31bbd26 100644
--- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
+++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
@@ -21,8 +21,12 @@ LL | | }
    = note: the matched value is of type `Result<u32, !>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
-LL |     if let Ok(_x) = foo() { /* */ }
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     let _x = if let Ok(_x) = foo() { _x } else { todo!() };
+   |     +++++++++++                    +++++++++++++++++++++++
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
+   |
+LL |     let Ok(_x) = foo() else { todo!() };
+   |                        ++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
index 37a35700b36d5..aa1aa4434c3fa 100644
--- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
+++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
@@ -7,10 +7,14 @@ LL |     let (0 | (1 | 2)) = 0;
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
-help: you might want to use `if let` to ignore the variant that isn't matched
+help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     if let (0 | (1 | 2)) = 0 { /* */ }
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     if let (0 | (1 | 2)) = 0 { todo!() }
+   |     ++                       ~~~~~~~~~~~
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
+   |
+LL |     let (0 | (1 | 2)) = 0 else { todo!() };
+   |                           ++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered
   --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:3:11
diff --git a/src/test/ui/pattern/usefulness/issue-31561.stderr b/src/test/ui/pattern/usefulness/issue-31561.stderr
index dffcfc016072f..9da6b5eeead23 100644
--- a/src/test/ui/pattern/usefulness/issue-31561.stderr
+++ b/src/test/ui/pattern/usefulness/issue-31561.stderr
@@ -17,10 +17,14 @@ LL |     Bar,
 LL |     Baz
    |     ^^^ not covered
    = note: the matched value is of type `Thing`
-help: you might want to use `if let` to ignore the variant that isn't matched
+help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     if let Thing::Foo(y) = Thing::Foo(1) { /* */ }
+LL |     let y = if let Thing::Foo(y) = Thing::Foo(1) { y } else { todo!() };
+   |     ++++++++++                                   ++++++++++++++++++++++
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
    |
+LL |     let Thing::Foo(y) = Thing::Foo(1) else { todo!() };
+   |                                       ++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
index 8f5adccea806d..f7dc070f80248 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
@@ -42,10 +42,14 @@ LL |     B,
 LL |     C
    |     ^ not covered
    = note: the matched value is of type `E`
-help: you might want to use `if let` to ignore the variant that isn't matched
+help: you might want to use `if let` to ignore the variants that aren't matched
+   |
+LL |     if let E::A = e { todo!() }
+   |     ++              ~~~~~~~~~~~
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
    |
-LL |     if let E::A = e { /* */ }
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     let E::A = e else { todo!() };
+   |                  ++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered
   --> $DIR/non-exhaustive-defined-here.rs:52:11
@@ -91,10 +95,14 @@ LL |     B,
 LL |     C
    |     ^ not covered
    = note: the matched value is of type `&E`
-help: you might want to use `if let` to ignore the variant that isn't matched
+help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     if let E::A = e { /* */ }
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     if let E::A = e { todo!() }
+   |     ++              ~~~~~~~~~~~
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
+   |
+LL |     let E::A = e else { todo!() };
+   |                  ++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered
   --> $DIR/non-exhaustive-defined-here.rs:66:11
@@ -140,10 +148,14 @@ LL |     B,
 LL |     C
    |     ^ not covered
    = note: the matched value is of type `&&mut &E`
-help: you might want to use `if let` to ignore the variant that isn't matched
+help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     if let E::A = e { /* */ }
+LL |     if let E::A = e { todo!() }
+   |     ++              ~~~~~~~~~~~
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
    |
+LL |     let E::A = e else { todo!() };
+   |                  ++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `None` not covered
   --> $DIR/non-exhaustive-defined-here.rs:92:11
@@ -185,8 +197,12 @@ LL |     None,
    = note: the matched value is of type `Opt`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
-LL |     if let Opt::Some(ref _x) = e { /* */ }
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     let _x = if let Opt::Some(ref _x) = e { _x } else { todo!() };
+   |     +++++++++++                           +++++++++++++++++++++++
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
+   |
+LL |     let Opt::Some(ref _x) = e else { todo!() };
+   |                               ++++++++++++++++
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr
index 74ec646e31cca..e3ffc092327ac 100644
--- a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr
+++ b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr
@@ -15,10 +15,14 @@ LL |     let (1, (Some(1), 2..=3)) = (1, (None, 2));
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `(i32, (Option<i32>, i32))`
-help: you might want to use `if let` to ignore the variant that isn't matched
+help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { /* */ }
+LL |     if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { todo!() }
+   |     ++                                            ~~~~~~~~~~~
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
    |
+LL |     let (1, (Some(1), 2..=3)) = (1, (None, 2)) else { todo!() };
+   |                                                ++++++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
index ded3cf3ad1d44..a9159562d9d51 100644
--- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
+++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
@@ -21,8 +21,12 @@ LL | | }
    = note: the matched value is of type `Result<u32, &R>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
-LL |     if let Ok(x) = res { /* */ }
+LL |     let x = if let Ok(x) = res { x } else { todo!() };
+   |     ++++++++++                 ++++++++++++++++++++++
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
    |
+LL |     let Ok(x) = res else { todo!() };
+   |                     ++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.rs b/src/test/ui/uninhabited/uninhabited-irrefutable.rs
index 48cd92719b49a..661b5486adc12 100644
--- a/src/test/ui/uninhabited/uninhabited-irrefutable.rs
+++ b/src/test/ui/uninhabited/uninhabited-irrefutable.rs
@@ -19,10 +19,10 @@ enum Foo {
     A(foo::SecretlyEmpty),
     B(foo::NotSoSecretlyEmpty),
     C(NotSoSecretlyEmpty),
-    D(u32),
+    D(u32, u32),
 }
 
 fn main() {
-    let x: Foo = Foo::D(123);
-    let Foo::D(_y) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered
+    let x: Foo = Foo::D(123, 456);
+    let Foo::D(_y, _z) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered
 }
diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
index ad19c34a40a11..c571e17a7b372 100644
--- a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
+++ b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
@@ -1,8 +1,8 @@
 error[E0005]: refutable pattern in local binding: `A(_)` not covered
   --> $DIR/uninhabited-irrefutable.rs:27:9
    |
-LL |     let Foo::D(_y) = x;
-   |         ^^^^^^^^^^ pattern `A(_)` not covered
+LL |     let Foo::D(_y, _z) = x;
+   |         ^^^^^^^^^^^^^^ pattern `A(_)` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
@@ -16,8 +16,12 @@ LL |     A(foo::SecretlyEmpty),
    = note: the matched value is of type `Foo`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
-LL |     if let Foo::D(_y) = x { /* */ }
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     let (_y, _z) = if let Foo::D(_y, _z) = x { (_y, _z) } else { todo!() };
+   |     +++++++++++++++++                        +++++++++++++++++++++++++++++
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
+   |
+LL |     let Foo::D(_y, _z) = x else { todo!() };
+   |                            ++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
index d90075d82f47b..74216d265d034 100644
--- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -132,8 +132,12 @@ LL | | }
    = note: the matched value is of type `Result<u32, Void>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
-LL |     if let Ok(x) = x { /* */ }
+LL |     let x = if let Ok(x) = x { x } else { todo!() };
+   |     ++++++++++               ++++++++++++++++++++++
+help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
    |
+LL |     let Ok(x) = x else { todo!() };
+   |                   ++++++++++++++++
 
 error: aborting due to 7 previous errors
 

From c3a998e82a50b66e8f6f97170cd9117fadf03618 Mon Sep 17 00:00:00 2001
From: Esteban Kuber <esteban@kuber.com.ar>
Date: Tue, 8 Mar 2022 17:20:05 +0000
Subject: [PATCH 5/8] Do not suggest `let_else` if no bindings would be
 introduced

---
 .../src/thir/pattern/check_match.rs              |  2 +-
 .../ui/consts/const-match-check.eval1.stderr     |  4 ----
 .../ui/consts/const-match-check.eval2.stderr     |  4 ----
 .../ui/consts/const-match-check.matchck.stderr   | 16 ----------------
 ...e-been-expanded-earlier-non-exhaustive.stderr |  4 ----
 .../non-exhaustive-defined-here.stderr           | 12 ------------
 .../usefulness/refutable-pattern-errors.stderr   |  4 ----
 7 files changed, 1 insertion(+), 45 deletions(-)

diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index dae313da8d993..c94da838680e0 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -330,7 +330,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
                     ],
                     Applicability::HasPlaceholders,
                 );
-                if cx.tcx.sess.is_nightly_build() {
+                if !bindings.is_empty() && cx.tcx.sess.is_nightly_build() {
                     err.span_suggestion_verbose(
                         semi_span.shrink_to_lo(),
                         &format!(
diff --git a/src/test/ui/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr
index 08ee800f138d2..6e61dbbd8eee3 100644
--- a/src/test/ui/consts/const-match-check.eval1.stderr
+++ b/src/test/ui/consts/const-match-check.eval1.stderr
@@ -11,10 +11,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched
    |
 LL |     A = { if let 0 = 0 { todo!() } 0 },
    |           ++           ~~~~~~~~~~~
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
-   |
-LL |     A = { let 0 = 0 else { todo!() }; 0 },
-   |                     ++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-match-check.eval2.stderr b/src/test/ui/consts/const-match-check.eval2.stderr
index 579cb7e780007..1b3b6e06c3df6 100644
--- a/src/test/ui/consts/const-match-check.eval2.stderr
+++ b/src/test/ui/consts/const-match-check.eval2.stderr
@@ -11,10 +11,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched
    |
 LL |     let x: [i32; { if let 0 = 0 { todo!() } 0 }] = [];
    |                    ++           ~~~~~~~~~~~
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
-   |
-LL |     let x: [i32; { let 0 = 0 else { todo!() }; 0 }] = [];
-   |                              ++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-match-check.matchck.stderr b/src/test/ui/consts/const-match-check.matchck.stderr
index f89bbc0d42234..bc8edfa7af9f4 100644
--- a/src/test/ui/consts/const-match-check.matchck.stderr
+++ b/src/test/ui/consts/const-match-check.matchck.stderr
@@ -11,10 +11,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched
    |
 LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
    |                  ++           ~~~~~~~~~~~
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
-   |
-LL | const X: i32 = { let 0 = 0 else { todo!() }; 0 };
-   |                            ++++++++++++++++
 
 error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
   --> $DIR/const-match-check.rs:8:23
@@ -29,10 +25,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched
    |
 LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 };
    |                   ++           ~~~~~~~~~~~
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
-   |
-LL | static Y: i32 = { let 0 = 0 else { todo!() }; 0 };
-   |                             ++++++++++++++++
 
 error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
   --> $DIR/const-match-check.rs:13:26
@@ -47,10 +39,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched
    |
 LL |     const X: i32 = { if let 0 = 0 { todo!() } 0 };
    |                      ++           ~~~~~~~~~~~
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
-   |
-LL |     const X: i32 = { let 0 = 0 else { todo!() }; 0 };
-   |                                ++++++++++++++++
 
 error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
   --> $DIR/const-match-check.rs:19:26
@@ -65,10 +53,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched
    |
 LL |     const X: i32 = { if let 0 = 0 { todo!() } 0 };
    |                      ++           ~~~~~~~~~~~
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
-   |
-LL |     const X: i32 = { let 0 = 0 else { todo!() }; 0 };
-   |                                ++++++++++++++++
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
index aa1aa4434c3fa..95b22ac059482 100644
--- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
+++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
@@ -11,10 +11,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched
    |
 LL |     if let (0 | (1 | 2)) = 0 { todo!() }
    |     ++                       ~~~~~~~~~~~
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
-   |
-LL |     let (0 | (1 | 2)) = 0 else { todo!() };
-   |                           ++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered
   --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:3:11
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
index f7dc070f80248..0f06c31c468b1 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
@@ -46,10 +46,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched
    |
 LL |     if let E::A = e { todo!() }
    |     ++              ~~~~~~~~~~~
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
-   |
-LL |     let E::A = e else { todo!() };
-   |                  ++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered
   --> $DIR/non-exhaustive-defined-here.rs:52:11
@@ -99,10 +95,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched
    |
 LL |     if let E::A = e { todo!() }
    |     ++              ~~~~~~~~~~~
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
-   |
-LL |     let E::A = e else { todo!() };
-   |                  ++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered
   --> $DIR/non-exhaustive-defined-here.rs:66:11
@@ -152,10 +144,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched
    |
 LL |     if let E::A = e { todo!() }
    |     ++              ~~~~~~~~~~~
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
-   |
-LL |     let E::A = e else { todo!() };
-   |                  ++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `None` not covered
   --> $DIR/non-exhaustive-defined-here.rs:92:11
diff --git a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr
index e3ffc092327ac..d1dacc822e942 100644
--- a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr
+++ b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr
@@ -19,10 +19,6 @@ help: you might want to use `if let` to ignore the variants that aren't matched
    |
 LL |     if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { todo!() }
    |     ++                                            ~~~~~~~~~~~
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
-   |
-LL |     let (1, (Some(1), 2..=3)) = (1, (None, 2)) else { todo!() };
-   |                                                ++++++++++++++++
 
 error: aborting due to 2 previous errors
 

From e54d4ab189517efa1ef132b12443fc52de3faa8c Mon Sep 17 00:00:00 2001
From: JmPotato <ghzpotato@gmail.com>
Date: Tue, 1 Mar 2022 13:23:30 +0800
Subject: [PATCH 6/8] Use MaybeUninit in VecDeque to remove the undefined
 behavior of slice

Signed-off-by: JmPotato <ghzpotato@gmail.com>
---
 .../alloc/src/collections/vec_deque/iter.rs   | 59 +++++++++++++------
 .../alloc/src/collections/vec_deque/mod.rs    | 56 ++++++++++++++----
 2 files changed, 86 insertions(+), 29 deletions(-)

diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs
index edadd666edce6..253fa0b561e95 100644
--- a/library/alloc/src/collections/vec_deque/iter.rs
+++ b/library/alloc/src/collections/vec_deque/iter.rs
@@ -1,5 +1,6 @@
 use core::fmt;
 use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
+use core::mem::MaybeUninit;
 use core::ops::Try;
 
 use super::{count, wrap_index, RingSlices};
@@ -12,7 +13,7 @@ use super::{count, wrap_index, RingSlices};
 /// [`iter`]: super::VecDeque::iter
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
-    pub(crate) ring: &'a [T],
+    pub(crate) ring: &'a [MaybeUninit<T>],
     pub(crate) tail: usize,
     pub(crate) head: usize,
 }
@@ -44,7 +45,10 @@ impl<'a, T> Iterator for Iter<'a, T> {
         }
         let tail = self.tail;
         self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len());
-        unsafe { Some(self.ring.get_unchecked(tail)) }
+        // Safety:
+        // - `self.tail` in a ring buffer is always a valid index.
+        // - `self.head` and `self.tail` equality is checked above.
+        unsafe { Some(self.ring.get_unchecked(tail).assume_init_ref()) }
     }
 
     #[inline]
@@ -58,8 +62,13 @@ impl<'a, T> Iterator for Iter<'a, T> {
         F: FnMut(Acc, Self::Item) -> Acc,
     {
         let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
-        accum = front.iter().fold(accum, &mut f);
-        back.iter().fold(accum, &mut f)
+        // Safety:
+        // - `self.head` and `self.tail` in a ring buffer are always valid indices.
+        // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
+        unsafe {
+            accum = MaybeUninit::slice_assume_init_ref(front).iter().fold(accum, &mut f);
+            MaybeUninit::slice_assume_init_ref(back).iter().fold(accum, &mut f)
+        }
     }
 
     fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
@@ -70,17 +79,19 @@ impl<'a, T> Iterator for Iter<'a, T> {
     {
         let (mut iter, final_res);
         if self.tail <= self.head {
-            // single slice self.ring[self.tail..self.head]
-            iter = self.ring[self.tail..self.head].iter();
+            // Safety: single slice self.ring[self.tail..self.head] is initialized.
+            iter = unsafe { MaybeUninit::slice_assume_init_ref(&self.ring[self.tail..self.head]) }
+                .iter();
             final_res = iter.try_fold(init, &mut f);
         } else {
-            // two slices: self.ring[self.tail..], self.ring[..self.head]
+            // Safety: two slices: self.ring[self.tail..], self.ring[..self.head] both are initialized.
             let (front, back) = self.ring.split_at(self.tail);
-            let mut back_iter = back.iter();
+
+            let mut back_iter = unsafe { MaybeUninit::slice_assume_init_ref(back).iter() };
             let res = back_iter.try_fold(init, &mut f);
             let len = self.ring.len();
             self.tail = (self.ring.len() - back_iter.len()) & (len - 1);
-            iter = front[..self.head].iter();
+            iter = unsafe { MaybeUninit::slice_assume_init_ref(&front[..self.head]).iter() };
             final_res = iter.try_fold(res?, &mut f);
         }
         self.tail = self.head - iter.len();
@@ -109,7 +120,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
         // that is in bounds.
         unsafe {
             let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len());
-            self.ring.get_unchecked(idx)
+            self.ring.get_unchecked(idx).assume_init_ref()
         }
     }
 }
@@ -122,7 +133,10 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
             return None;
         }
         self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len());
-        unsafe { Some(self.ring.get_unchecked(self.head)) }
+        // Safety:
+        // - `self.head` in a ring buffer is always a valid index.
+        // - `self.head` and `self.tail` equality is checked above.
+        unsafe { Some(self.ring.get_unchecked(self.head).assume_init_ref()) }
     }
 
     fn rfold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
@@ -130,8 +144,13 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
         F: FnMut(Acc, Self::Item) -> Acc,
     {
         let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
-        accum = back.iter().rfold(accum, &mut f);
-        front.iter().rfold(accum, &mut f)
+        // Safety:
+        // - `self.head` and `self.tail` in a ring buffer are always valid indices.
+        // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
+        unsafe {
+            accum = MaybeUninit::slice_assume_init_ref(back).iter().rfold(accum, &mut f);
+            MaybeUninit::slice_assume_init_ref(front).iter().rfold(accum, &mut f)
+        }
     }
 
     fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
@@ -142,16 +161,20 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
     {
         let (mut iter, final_res);
         if self.tail <= self.head {
-            // single slice self.ring[self.tail..self.head]
-            iter = self.ring[self.tail..self.head].iter();
+            // Safety: single slice self.ring[self.tail..self.head] is initialized.
+            iter = unsafe {
+                MaybeUninit::slice_assume_init_ref(&self.ring[self.tail..self.head]).iter()
+            };
             final_res = iter.try_rfold(init, &mut f);
         } else {
-            // two slices: self.ring[self.tail..], self.ring[..self.head]
+            // Safety: two slices: self.ring[self.tail..], self.ring[..self.head] both are initialized.
             let (front, back) = self.ring.split_at(self.tail);
-            let mut front_iter = front[..self.head].iter();
+
+            let mut front_iter =
+                unsafe { MaybeUninit::slice_assume_init_ref(&front[..self.head]).iter() };
             let res = front_iter.try_rfold(init, &mut f);
             self.head = front_iter.len();
-            iter = back.iter();
+            iter = unsafe { MaybeUninit::slice_assume_init_ref(back).iter() };
             final_res = iter.try_rfold(res?, &mut f);
         }
         self.head = self.tail + iter.len();
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index 7139a0fb94d76..f27cd684067f9 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -12,7 +12,7 @@ use core::fmt;
 use core::hash::{Hash, Hasher};
 use core::iter::{repeat_with, FromIterator};
 use core::marker::PhantomData;
-use core::mem::{self, ManuallyDrop};
+use core::mem::{self, ManuallyDrop, MaybeUninit};
 use core::ops::{Index, IndexMut, Range, RangeBounds};
 use core::ptr::{self, NonNull};
 use core::slice;
@@ -181,16 +181,28 @@ impl<T, A: Allocator> VecDeque<T, A> {
         }
     }
 
-    /// Turn ptr into a slice
+    /// Turn ptr into a slice, since the elements of the backing buffer may be uninitialized,
+    /// we will return a slice of [`MaybeUninit<T>`].
+    ///
+    /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and
+    /// incorrect usage of this method.
+    ///
+    /// [zeroed]: mem::MaybeUninit::zeroed
     #[inline]
-    unsafe fn buffer_as_slice(&self) -> &[T] {
-        unsafe { slice::from_raw_parts(self.ptr(), self.cap()) }
+    unsafe fn buffer_as_slice(&self) -> &[MaybeUninit<T>] {
+        unsafe { slice::from_raw_parts(self.ptr() as *mut MaybeUninit<T>, self.cap()) }
     }
 
-    /// Turn ptr into a mut slice
+    /// Turn ptr into a mut slice, since the elements of the backing buffer may be uninitialized,
+    /// we will return a slice of [`MaybeUninit<T>`].
+    ///
+    /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and
+    /// incorrect usage of this method.
+    ///
+    /// [zeroed]: mem::MaybeUninit::zeroed
     #[inline]
-    unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] {
-        unsafe { slice::from_raw_parts_mut(self.ptr(), self.cap()) }
+    unsafe fn buffer_as_mut_slice(&mut self) -> &mut [MaybeUninit<T>] {
+        unsafe { slice::from_raw_parts_mut(self.ptr() as *mut MaybeUninit<T>, self.cap()) }
     }
 
     /// Moves an element out of the buffer
@@ -1055,9 +1067,13 @@ impl<T, A: Allocator> VecDeque<T, A> {
     #[inline]
     #[stable(feature = "deque_extras_15", since = "1.5.0")]
     pub fn as_slices(&self) -> (&[T], &[T]) {
+        // Safety:
+        // - `self.head` and `self.tail` in a ring buffer are always valid indices.
+        // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
         unsafe {
             let buf = self.buffer_as_slice();
-            RingSlices::ring_slices(buf, self.head, self.tail)
+            let (front, back) = RingSlices::ring_slices(buf, self.head, self.tail);
+            (MaybeUninit::slice_assume_init_ref(front), MaybeUninit::slice_assume_init_ref(back))
         }
     }
 
@@ -1089,11 +1105,15 @@ impl<T, A: Allocator> VecDeque<T, A> {
     #[inline]
     #[stable(feature = "deque_extras_15", since = "1.5.0")]
     pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
+        // Safety:
+        // - `self.head` and `self.tail` in a ring buffer are always valid indices.
+        // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
         unsafe {
             let head = self.head;
             let tail = self.tail;
             let buf = self.buffer_as_mut_slice();
-            RingSlices::ring_slices(buf, head, tail)
+            let (front, back) = RingSlices::ring_slices(buf, head, tail);
+            (MaybeUninit::slice_assume_init_mut(front), MaybeUninit::slice_assume_init_mut(back))
         }
     }
 
@@ -2327,7 +2347,14 @@ impl<T, A: Allocator> VecDeque<T, A> {
         if self.is_contiguous() {
             let tail = self.tail;
             let head = self.head;
-            return unsafe { RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0 };
+            // Safety:
+            // - `self.head` and `self.tail` in a ring buffer are always valid indices.
+            // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
+            return unsafe {
+                MaybeUninit::slice_assume_init_mut(
+                    RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0,
+                )
+            };
         }
 
         let buf = self.buf.ptr();
@@ -2413,7 +2440,14 @@ impl<T, A: Allocator> VecDeque<T, A> {
 
         let tail = self.tail;
         let head = self.head;
-        unsafe { RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0 }
+        // Safety:
+        // - `self.head` and `self.tail` in a ring buffer are always valid indices.
+        // - `RingSlices::ring_slices` guarantees that the slices split according to `self.head` and `self.tail` are initialized.
+        unsafe {
+            MaybeUninit::slice_assume_init_mut(
+                RingSlices::ring_slices(self.buffer_as_mut_slice(), head, tail).0,
+            )
+        }
     }
 
     /// Rotates the double-ended queue `mid` places to the left.

From 4d56c1563c5ae75acbcb8c163296561a6e17e47a Mon Sep 17 00:00:00 2001
From: Mara Bos <m-ou.se@m-ou.se>
Date: Wed, 9 Mar 2022 10:17:49 +0100
Subject: [PATCH 7/8] Add documentation about lifetimes to thread::scope.

---
 library/std/src/thread/scoped.rs | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs
index 4af58f1a38075..c4847b529a361 100644
--- a/library/std/src/thread/scoped.rs
+++ b/library/std/src/thread/scoped.rs
@@ -107,6 +107,24 @@ impl ScopeData {
 /// a.push(4);
 /// assert_eq!(x, a.len());
 /// ```
+///
+/// # Lifetimes
+///
+/// Scoped threads involve two lifetimes: `'scope` and `'env`.
+///
+/// The `'scope` lifetime represents the lifetime of the scope itself.
+/// That is: the time during which new scoped threads may be spawned,
+/// and also the time during which they might still be running.
+/// Once this lifetime ends, all scoped threads are joined.
+/// This lifetime starts within the `scope` function, before `f` (the argument to `scope`) starts.
+/// It ends after `f` returns and all scoped threads have been joined, but before `scope` returns.
+///
+/// The `'env` lifetime represents the lifetime of whatever is borrowed by the scoped threads.
+/// This lifetime must outlast the call to `scope`, and thus cannot be smaller than `'scope`.
+/// It can be as small as the call to `scope`, meaning that anything that outlives this call,
+/// such as local variables defined right before the scope, can be borrowed by the scoped threads.
+///
+/// The `'env: 'scope` bound is part of the definition of the `Scope` type.
 #[track_caller]
 pub fn scope<'env, F, T>(f: F) -> T
 where

From c7a5ad0e864dd790f31e7131b5f75d1d2a6220ca Mon Sep 17 00:00:00 2001
From: Caio <c410.f3r@gmail.com>
Date: Wed, 9 Mar 2022 12:43:42 -0300
Subject: [PATCH 8/8] Warn users about || in let chain expressions

---
 .../rustc_ast_passes/src/ast_validation.rs    | 108 +++++++-----
 compiler/rustc_ast_passes/src/lib.rs          |   6 +-
 .../disallowed-positions.stderr               | 165 ++++++++++++------
 3 files changed, 183 insertions(+), 96 deletions(-)

diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 0cf73178d679d..8664254c39372 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -64,8 +64,8 @@ struct AstValidator<'a> {
     /// certain positions.
     is_assoc_ty_bound_banned: bool,
 
-    /// Used to allow `let` expressions in certain syntactic locations.
-    is_let_allowed: bool,
+    /// See [ForbiddenLetReason]
+    forbidden_let_reason: Option<ForbiddenLetReason>,
 
     lint_buffer: &'a mut LintBuffer,
 }
@@ -103,20 +103,28 @@ impl<'a> AstValidator<'a> {
         self.is_tilde_const_allowed = old;
     }
 
-    fn with_let_allowed(&mut self, allowed: bool, f: impl FnOnce(&mut Self, bool)) {
-        let old = mem::replace(&mut self.is_let_allowed, allowed);
+    fn with_let_management(
+        &mut self,
+        forbidden_let_reason: Option<ForbiddenLetReason>,
+        f: impl FnOnce(&mut Self, Option<ForbiddenLetReason>),
+    ) {
+        let old = mem::replace(&mut self.forbidden_let_reason, forbidden_let_reason);
         f(self, old);
-        self.is_let_allowed = old;
+        self.forbidden_let_reason = old;
     }
 
     /// Emits an error banning the `let` expression provided in the given location.
-    fn ban_let_expr(&self, expr: &'a Expr) {
+    fn ban_let_expr(&self, expr: &'a Expr, or_span: Option<Span>) {
         let sess = &self.session;
         if sess.opts.unstable_features.is_nightly_build() {
-            sess.struct_span_err(expr.span, "`let` expressions are not supported here")
-                .note("only supported directly in conditions of `if`- and `while`-expressions")
-                .note("as well as when nested within `&&` and parentheses in those conditions")
-                .emit();
+            let err = "`let` expressions are not supported here";
+            let mut diag = sess.struct_span_err(expr.span, err);
+            diag.note("only supported directly in conditions of `if` and `while` expressions");
+            diag.note("as well as when nested within `&&` and parentheses in those conditions");
+            if let Some(elem) = or_span {
+                diag.span_note(elem, "`||` operators are not allowed in let chain expressions");
+            }
+            diag.emit();
         } else {
             sess.struct_span_err(expr.span, "expected expression, found statement (`let`)")
                 .note("variable declaration using `let` is a statement")
@@ -988,39 +996,52 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     }
 
     fn visit_expr(&mut self, expr: &'a Expr) {
-        self.with_let_allowed(false, |this, let_allowed| match &expr.kind {
-            ExprKind::If(cond, then, opt_else) => {
-                this.visit_block(then);
-                walk_list!(this, visit_expr, opt_else);
-                this.with_let_allowed(true, |this, _| this.visit_expr(cond));
-                return;
-            }
-            ExprKind::Let(..) if !let_allowed => this.ban_let_expr(expr),
-            ExprKind::Match(expr, arms) => {
-                this.visit_expr(expr);
-                for arm in arms {
-                    this.visit_expr(&arm.body);
-                    this.visit_pat(&arm.pat);
-                    walk_list!(this, visit_attribute, &arm.attrs);
-                    if let Some(ref guard) = arm.guard {
-                        if let ExprKind::Let(_, ref expr, _) = guard.kind {
-                            this.with_let_allowed(true, |this, _| this.visit_expr(expr));
+        self.with_let_management(Some(ForbiddenLetReason::GenericForbidden), |this, forbidden_let_reason| {
+            match &expr.kind {
+                ExprKind::Binary(Spanned { node: BinOpKind::Or, span }, lhs, rhs) => {
+                    let forbidden_let_reason = Some(ForbiddenLetReason::ForbiddenWithOr(*span));
+                    this.with_let_management(forbidden_let_reason, |this, _| this.visit_expr(lhs));
+                    this.with_let_management(forbidden_let_reason, |this, _| this.visit_expr(rhs));
+                }
+                ExprKind::If(cond, then, opt_else) => {
+                    this.visit_block(then);
+                    walk_list!(this, visit_expr, opt_else);
+                    this.with_let_management(None, |this, _| this.visit_expr(cond));
+                    return;
+                }
+                ExprKind::Let(..) if let Some(elem) = forbidden_let_reason => {
+                    let or_span = match elem {
+                        ForbiddenLetReason::ForbiddenWithOr(span) => Some(span),
+                        ForbiddenLetReason::GenericForbidden => None,
+                    };
+                    this.ban_let_expr(expr, or_span);
+                },
+                ExprKind::Match(scrutinee, arms) => {
+                    this.visit_expr(scrutinee);
+                    for arm in arms {
+                        this.visit_expr(&arm.body);
+                        this.visit_pat(&arm.pat);
+                        walk_list!(this, visit_attribute, &arm.attrs);
+                        if let Some(guard) = &arm.guard && let ExprKind::Let(_, guard_expr, _) = &guard.kind {
+                            this.with_let_management(None, |this, _| {
+                                this.visit_expr(guard_expr)
+                            });
                             return;
                         }
                     }
                 }
+                ExprKind::Paren(_) | ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => {
+                    this.with_let_management(forbidden_let_reason, |this, _| visit::walk_expr(this, expr));
+                    return;
+                }
+                ExprKind::While(cond, then, opt_label) => {
+                    walk_list!(this, visit_label, opt_label);
+                    this.visit_block(then);
+                    this.with_let_management(None, |this, _| this.visit_expr(cond));
+                    return;
+                }
+                _ => visit::walk_expr(this, expr),
             }
-            ExprKind::Paren(_) | ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => {
-                this.with_let_allowed(let_allowed, |this, _| visit::walk_expr(this, expr));
-                return;
-            }
-            ExprKind::While(cond, then, opt_label) => {
-                walk_list!(this, visit_label, opt_label);
-                this.visit_block(then);
-                this.with_let_allowed(true, |this, _| this.visit_expr(cond));
-                return;
-            }
-            _ => visit::walk_expr(this, expr),
         });
     }
 
@@ -1772,10 +1793,19 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
         is_tilde_const_allowed: false,
         is_impl_trait_banned: false,
         is_assoc_ty_bound_banned: false,
-        is_let_allowed: false,
+        forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
         lint_buffer: lints,
     };
     visit::walk_crate(&mut validator, krate);
 
     validator.has_proc_macro_decls
 }
+
+/// Used to forbid `let` expressions in certain syntactic locations.
+#[derive(Clone, Copy)]
+enum ForbiddenLetReason {
+    /// A let chain with the `||` operator
+    ForbiddenWithOr(Span),
+    /// `let` is not valid and the source environment is not important
+    GenericForbidden,
+}
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index 876dd7f757c5a..9d52c32885db0 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -4,11 +4,13 @@
 //!
 //! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`.
 
-#![feature(iter_is_partitioned)]
+#![allow(rustc::potential_query_instability)]
 #![feature(box_patterns)]
+#![feature(if_let_guard)]
+#![feature(iter_is_partitioned)]
+#![feature(let_chains)]
 #![feature(let_else)]
 #![recursion_limit = "256"]
-#![allow(rustc::potential_query_instability)]
 
 pub mod ast_validation;
 pub mod feature_gate;
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 897de54a7bf8c..dd090a3a5483d 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
@@ -15,7 +15,7 @@ error: `let` expressions are not supported here
 LL |     if &let 0 = 0 {}
    |         ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -24,7 +24,7 @@ error: `let` expressions are not supported here
 LL |     if !let 0 = 0 {}
    |         ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -33,7 +33,7 @@ error: `let` expressions are not supported here
 LL |     if *let 0 = 0 {}
    |         ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -42,7 +42,7 @@ error: `let` expressions are not supported here
 LL |     if -let 0 = 0 {}
    |         ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -51,7 +51,7 @@ error: `let` expressions are not supported here
 LL |     if (let 0 = 0)? {}
    |         ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -60,8 +60,13 @@ error: `let` expressions are not supported here
 LL |     if true || let 0 = 0 {}
    |                ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
+note: `||` operators are not allowed in let chain expressions
+  --> $DIR/disallowed-positions.rs:47:13
+   |
+LL |     if true || let 0 = 0 {}
+   |             ^^
 
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:48:17
@@ -69,8 +74,13 @@ error: `let` expressions are not supported here
 LL |     if (true || let 0 = 0) {}
    |                 ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
+note: `||` operators are not allowed in let chain expressions
+  --> $DIR/disallowed-positions.rs:48:14
+   |
+LL |     if (true || let 0 = 0) {}
+   |              ^^
 
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:49:25
@@ -78,8 +88,13 @@ error: `let` expressions are not supported here
 LL |     if true && (true || let 0 = 0) {}
    |                         ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
+note: `||` operators are not allowed in let chain expressions
+  --> $DIR/disallowed-positions.rs:49:22
+   |
+LL |     if true && (true || let 0 = 0) {}
+   |                      ^^
 
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:50:25
@@ -87,8 +102,13 @@ error: `let` expressions are not supported here
 LL |     if true || (true && let 0 = 0) {}
    |                         ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
+note: `||` operators are not allowed in let chain expressions
+  --> $DIR/disallowed-positions.rs:50:13
+   |
+LL |     if true || (true && let 0 = 0) {}
+   |             ^^
 
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:53:12
@@ -96,7 +116,7 @@ error: `let` expressions are not supported here
 LL |     if x = let 0 = 0 {}
    |            ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -105,7 +125,7 @@ error: `let` expressions are not supported here
 LL |     if true..(let 0 = 0) {}
    |               ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -114,7 +134,7 @@ error: `let` expressions are not supported here
 LL |     if ..(let 0 = 0) {}
    |           ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -123,7 +143,7 @@ error: `let` expressions are not supported here
 LL |     if (let 0 = 0).. {}
    |         ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -132,7 +152,7 @@ error: `let` expressions are not supported here
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -141,7 +161,7 @@ error: `let` expressions are not supported here
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -150,7 +170,7 @@ error: `let` expressions are not supported here
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -159,7 +179,7 @@ error: `let` expressions are not supported here
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -168,7 +188,7 @@ error: `let` expressions are not supported here
 LL |     if let true = let true = true {}
    |                   ^^^^^^^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -177,7 +197,7 @@ error: `let` expressions are not supported here
 LL |     while &let 0 = 0 {}
    |            ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -186,7 +206,7 @@ error: `let` expressions are not supported here
 LL |     while !let 0 = 0 {}
    |            ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -195,7 +215,7 @@ error: `let` expressions are not supported here
 LL |     while *let 0 = 0 {}
    |            ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -204,7 +224,7 @@ error: `let` expressions are not supported here
 LL |     while -let 0 = 0 {}
    |            ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -213,7 +233,7 @@ error: `let` expressions are not supported here
 LL |     while (let 0 = 0)? {}
    |            ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -222,8 +242,13 @@ error: `let` expressions are not supported here
 LL |     while true || let 0 = 0 {}
    |                   ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
+note: `||` operators are not allowed in let chain expressions
+  --> $DIR/disallowed-positions.rs:111:16
+   |
+LL |     while true || let 0 = 0 {}
+   |                ^^
 
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:112:20
@@ -231,8 +256,13 @@ error: `let` expressions are not supported here
 LL |     while (true || let 0 = 0) {}
    |                    ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
+note: `||` operators are not allowed in let chain expressions
+  --> $DIR/disallowed-positions.rs:112:17
+   |
+LL |     while (true || let 0 = 0) {}
+   |                 ^^
 
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:113:28
@@ -240,8 +270,13 @@ error: `let` expressions are not supported here
 LL |     while true && (true || let 0 = 0) {}
    |                            ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
+note: `||` operators are not allowed in let chain expressions
+  --> $DIR/disallowed-positions.rs:113:25
+   |
+LL |     while true && (true || let 0 = 0) {}
+   |                         ^^
 
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:114:28
@@ -249,8 +284,13 @@ error: `let` expressions are not supported here
 LL |     while true || (true && let 0 = 0) {}
    |                            ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
+note: `||` operators are not allowed in let chain expressions
+  --> $DIR/disallowed-positions.rs:114:16
+   |
+LL |     while true || (true && let 0 = 0) {}
+   |                ^^
 
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:117:15
@@ -258,7 +298,7 @@ error: `let` expressions are not supported here
 LL |     while x = let 0 = 0 {}
    |               ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -267,7 +307,7 @@ error: `let` expressions are not supported here
 LL |     while true..(let 0 = 0) {}
    |                  ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -276,7 +316,7 @@ error: `let` expressions are not supported here
 LL |     while ..(let 0 = 0) {}
    |              ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -285,7 +325,7 @@ error: `let` expressions are not supported here
 LL |     while (let 0 = 0).. {}
    |            ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -294,7 +334,7 @@ error: `let` expressions are not supported here
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -303,7 +343,7 @@ error: `let` expressions are not supported here
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -312,7 +352,7 @@ error: `let` expressions are not supported here
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -321,7 +361,7 @@ error: `let` expressions are not supported here
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -330,7 +370,7 @@ error: `let` expressions are not supported here
 LL |     while let true = let true = true {}
    |                      ^^^^^^^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -339,7 +379,7 @@ error: `let` expressions are not supported here
 LL |     &let 0 = 0;
    |      ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -348,7 +388,7 @@ error: `let` expressions are not supported here
 LL |     !let 0 = 0;
    |      ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -357,7 +397,7 @@ error: `let` expressions are not supported here
 LL |     *let 0 = 0;
    |      ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -366,7 +406,7 @@ error: `let` expressions are not supported here
 LL |     -let 0 = 0;
    |      ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -375,7 +415,7 @@ error: `let` expressions are not supported here
 LL |     (let 0 = 0)?;
    |      ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -384,8 +424,13 @@ error: `let` expressions are not supported here
 LL |     true || let 0 = 0;
    |             ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
+note: `||` operators are not allowed in let chain expressions
+  --> $DIR/disallowed-positions.rs:184:10
+   |
+LL |     true || let 0 = 0;
+   |          ^^
 
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:185:14
@@ -393,8 +438,13 @@ error: `let` expressions are not supported here
 LL |     (true || let 0 = 0);
    |              ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
+note: `||` operators are not allowed in let chain expressions
+  --> $DIR/disallowed-positions.rs:185:11
+   |
+LL |     (true || let 0 = 0);
+   |           ^^
 
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:186:22
@@ -402,8 +452,13 @@ error: `let` expressions are not supported here
 LL |     true && (true || let 0 = 0);
    |                      ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
+note: `||` operators are not allowed in let chain expressions
+  --> $DIR/disallowed-positions.rs:186:19
+   |
+LL |     true && (true || let 0 = 0);
+   |                   ^^
 
 error: `let` expressions are not supported here
   --> $DIR/disallowed-positions.rs:189:9
@@ -411,7 +466,7 @@ error: `let` expressions are not supported here
 LL |     x = let 0 = 0;
    |         ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -420,7 +475,7 @@ error: `let` expressions are not supported here
 LL |     true..(let 0 = 0);
    |            ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -429,7 +484,7 @@ error: `let` expressions are not supported here
 LL |     ..(let 0 = 0);
    |        ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -438,7 +493,7 @@ error: `let` expressions are not supported here
 LL |     (let 0 = 0)..;
    |      ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -447,7 +502,7 @@ error: `let` expressions are not supported here
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -456,7 +511,7 @@ error: `let` expressions are not supported here
 LL |     (let true = let true = true);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -465,7 +520,7 @@ error: `let` expressions are not supported here
 LL |     &let 0 = 0
    |      ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -474,7 +529,7 @@ error: `let` expressions are not supported here
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -483,7 +538,7 @@ error: `let` expressions are not supported here
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -492,7 +547,7 @@ error: `let` expressions are not supported here
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error: `let` expressions are not supported here
@@ -501,7 +556,7 @@ error: `let` expressions are not supported here
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
    |
-   = note: only supported directly in conditions of `if`- and `while`-expressions
+   = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
 
 error[E0308]: mismatched types