about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs104
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs86
-rw-r--r--compiler/rustc_session/src/config.rs15
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/core/src/clone.rs21
-rw-r--r--library/core/src/convert/mod.rs6
-rw-r--r--library/core/src/iter/traits/iterator.rs71
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/option.rs6
-rw-r--r--library/core/src/ptr/non_null.rs3
-rw-r--r--library/core/src/ptr/unique.rs3
-rw-r--r--library/core/src/result.rs7
-rw-r--r--library/core/tests/iter/traits/iterator.rs8
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/std/src/net/tcp/tests.rs1
-rw-r--r--library/std/src/thread/scoped.rs18
-rw-r--r--src/bootstrap/lib.rs1
-rw-r--r--src/test/ui/check-cfg/well-known-names.rs6
-rw-r--r--src/test/ui/check-cfg/well-known-values.rs14
-rw-r--r--src/test/ui/check-cfg/well-known-values.stderr22
-rw-r--r--src/test/ui/consts/const-match-check.eval1.stderr6
-rw-r--r--src/test/ui/consts/const-match-check.eval2.stderr6
-rw-r--r--src/test/ui/consts/const-match-check.matchck.stderr24
-rw-r--r--src/test/ui/empty/empty-never-array.stderr6
-rw-r--r--src/test/ui/error-codes/E0005.stderr8
-rw-r--r--src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr8
-rw-r--r--src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr6
-rw-r--r--src/test/ui/pattern/usefulness/issue-31561.stderr8
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr26
-rw-r--r--src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr6
-rw-r--r--src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr6
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr165
-rw-r--r--src/test/ui/uninhabited/uninhabited-irrefutable.rs6
-rw-r--r--src/test/ui/uninhabited/uninhabited-irrefutable.stderr12
-rw-r--r--src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr6
36 files changed, 527 insertions, 173 deletions
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 0cf73178d67..8f0b12cb4fe 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, forbidden_let_reason: ForbiddenLetReason) {
         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 ForbiddenLetReason::ForbiddenWithOr(span) = forbidden_let_reason {
+                diag.span_note(span, "`||` 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,48 @@ 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 => {
+                    this.ban_let_expr(expr, elem);
+                },
+                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 +1789,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 876dd7f757c..9d52c32885d 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/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index b80d2e52ee7..c94da838680 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 !bindings.is_empty() && 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/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 221dc86c1d4..1d36ff059de 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1072,6 +1072,7 @@ impl CrateCheckConfig {
         // NOTE: This should be kept in sync with `default_configuration` and
         // `fill_well_known_values`
         const WELL_KNOWN_NAMES: &[Symbol] = &[
+            // rustc
             sym::unix,
             sym::windows,
             sym::target_os,
@@ -1091,9 +1092,12 @@ impl CrateCheckConfig {
             sym::debug_assertions,
             sym::proc_macro,
             sym::test,
+            sym::feature,
+            // rustdoc
             sym::doc,
             sym::doctest,
-            sym::feature,
+            // miri
+            sym::miri,
         ];
 
         // We only insert well-known names if `names()` was activated
@@ -1128,13 +1132,14 @@ impl CrateCheckConfig {
 
         // No-values
         for name in [
+            sym::doc,
+            sym::miri,
             sym::unix,
-            sym::windows,
-            sym::debug_assertions,
-            sym::proc_macro,
             sym::test,
-            sym::doc,
             sym::doctest,
+            sym::windows,
+            sym::proc_macro,
+            sym::debug_assertions,
             sym::target_thread_local,
         ] {
             self.values_valid.entry(name).or_default();
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 3f44292e034..3884578f5d4 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -891,6 +891,7 @@ symbols! {
         minnumf32,
         minnumf64,
         mips_target_feature,
+        miri,
         misc,
         mmx_reg,
         modifiers,
diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs
index 6f9579043c3..1912694412b 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 0ceedf93633..f5ea5f5ba50 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
 ///
@@ -690,7 +691,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/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index f5c0a3b5cd8..b38df1c2d02 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -1859,6 +1859,77 @@ pub trait Iterator {
         try_process(self, |i| i.collect())
     }
 
+    /// Collects all the items from an iterator into a collection.
+    ///
+    /// This method consumes the iterator and adds all its items to the
+    /// passed collection. The collection is then returned, so the call chain
+    /// can be continued.
+    ///
+    /// This is useful when you already have a collection and wants to add
+    /// the iterator items to it.
+    ///
+    /// This method is a convenience method to call [Extend::extend](trait.Extend.html),
+    /// but instead of being called on a collection, it's called on an iterator.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(iter_collect_into)]
+    ///
+    /// let a = [1, 2, 3];
+    /// let mut vec: Vec::<i32> = vec![0, 1];
+    ///
+    /// a.iter().map(|&x| x * 2).collect_into(&mut vec);
+    /// a.iter().map(|&x| x * 10).collect_into(&mut vec);
+    ///
+    /// assert_eq!(vec![0, 1, 2, 4, 6, 10, 20, 30], vec);
+    /// ```
+    ///
+    /// `Vec` can have a manual set capacity to avoid reallocating it:
+    ///
+    /// ```
+    /// #![feature(iter_collect_into)]
+    ///
+    /// let a = [1, 2, 3];
+    /// let mut vec: Vec::<i32> = Vec::with_capacity(6);
+    ///
+    /// a.iter().map(|&x| x * 2).collect_into(&mut vec);
+    /// a.iter().map(|&x| x * 10).collect_into(&mut vec);
+    ///
+    /// assert_eq!(6, vec.capacity());
+    /// println!("{:?}", vec);
+    /// ```
+    ///
+    /// The returned mutable reference can be used to continue the call chain:
+    ///
+    /// ```
+    /// #![feature(iter_collect_into)]
+    ///
+    /// let a = [1, 2, 3];
+    /// let mut vec: Vec::<i32> = Vec::with_capacity(6);
+    ///
+    /// let count = a.iter().collect_into(&mut vec).iter().count();
+    ///
+    /// assert_eq!(count, vec.len());
+    /// println!("Vec len is {}", count);
+    ///
+    /// let count = a.iter().collect_into(&mut vec).iter().count();
+    ///
+    /// assert_eq!(count, vec.len());
+    /// println!("Vec len now is {}", count);
+    /// ```
+    #[inline]
+    #[unstable(feature = "iter_collect_into", reason = "new API", issue = "94780")]
+    fn collect_into<E: Extend<Self::Item>>(self, collection: &mut E) -> &mut E
+    where
+        Self: Sized,
+    {
+        collection.extend(self);
+        collection
+    }
+
     /// Consumes an iterator, creating two collections from it.
     ///
     /// The predicate passed to `partition()` can return `true`, or `false`.
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index f436afbee44..ddd8ae0c02c 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -104,6 +104,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 508837f63c3..a6286f8d8d1 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1857,7 +1857,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 0aa8e9960a8..77b93e0c24c 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -642,7 +642,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 661d111c99d..cff68f64f78 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 1827860a390..5a189f2b098 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1801,7 +1801,12 @@ fn unwrap_failed<T>(_msg: &str, _error: &T) -> ! {
 /////////////////////////////////////////////////////////////////////////////
 
 #[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 {
diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs
index cf69f0a7a4d..32bd68e3d25 100644
--- a/library/core/tests/iter/traits/iterator.rs
+++ b/library/core/tests/iter/traits/iterator.rs
@@ -543,6 +543,14 @@ fn test_try_collect() {
     assert_eq!(v, Continue(vec![4, 5]));
 }
 
+#[test]
+fn test_collect_into() {
+    let a = vec![1, 2, 3, 4, 5];
+    let mut b = Vec::new();
+    a.iter().cloned().collect_into(&mut b);
+    assert!(a == b);
+}
+
 // just tests by whether or not this compiles
 fn _empty_impl_all_auto_traits<T>() {
     use std::panic::{RefUnwindSafe, UnwindSafe};
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 2437f4afdeb..dc374022827 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -62,6 +62,7 @@
 #![feature(slice_partition_dedup)]
 #![feature(int_log)]
 #![feature(iter_advance_by)]
+#![feature(iter_collect_into)]
 #![feature(iter_partition_in_place)]
 #![feature(iter_intersperse)]
 #![feature(iter_is_partitioned)]
diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs
index 959fe6943f6..4d5cf658def 100644
--- a/library/std/src/net/tcp/tests.rs
+++ b/library/std/src/net/tcp/tests.rs
@@ -508,6 +508,7 @@ fn close_readwrite_smoke() {
 }
 
 #[test]
+#[cfg_attr(target_env = "sgx", ignore)]
 fn close_read_wakes_up() {
     each_ip(&mut |addr| {
         let a = t!(TcpListener::bind(&addr));
diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs
index 4af58f1a380..c4847b529a3 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
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 2ae63858ff6..2ee67d623ee 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -193,7 +193,6 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
     (None, "bootstrap", None),
     (Some(Mode::Rustc), "parallel_compiler", None),
     (Some(Mode::ToolRustc), "parallel_compiler", None),
-    (Some(Mode::Std), "miri", None),
     (Some(Mode::Std), "stdarch_intel_sde", None),
     (Some(Mode::Std), "no_fp_fmt_parse", None),
     (Some(Mode::Std), "no_global_oom_handling", None),
diff --git a/src/test/ui/check-cfg/well-known-names.rs b/src/test/ui/check-cfg/well-known-names.rs
index a66568a2ffd..e57fb69a1e0 100644
--- a/src/test/ui/check-cfg/well-known-names.rs
+++ b/src/test/ui/check-cfg/well-known-names.rs
@@ -24,4 +24,10 @@ fn unix_misspell() {}
 #[cfg(unix)]
 fn unix() {}
 
+#[cfg(miri)]
+fn miri() {}
+
+#[cfg(doc)]
+fn doc() {}
+
 fn main() {}
diff --git a/src/test/ui/check-cfg/well-known-values.rs b/src/test/ui/check-cfg/well-known-values.rs
index 46004be43d8..96375dc8d31 100644
--- a/src/test/ui/check-cfg/well-known-values.rs
+++ b/src/test/ui/check-cfg/well-known-values.rs
@@ -25,4 +25,18 @@ fn unix_with_value() {}
 #[cfg(unix)]
 fn unix() {}
 
+#[cfg(miri = "miri")]
+//~^ WARNING unexpected `cfg` condition value
+fn miri_with_value() {}
+
+#[cfg(miri)]
+fn miri() {}
+
+#[cfg(doc = "linux")]
+//~^ WARNING unexpected `cfg` condition value
+fn doc_with_value() {}
+
+#[cfg(doc)]
+fn doc() {}
+
 fn main() {}
diff --git a/src/test/ui/check-cfg/well-known-values.stderr b/src/test/ui/check-cfg/well-known-values.stderr
index 8eefd6aaf35..8b04c770fb5 100644
--- a/src/test/ui/check-cfg/well-known-values.stderr
+++ b/src/test/ui/check-cfg/well-known-values.stderr
@@ -29,5 +29,25 @@ LL | #[cfg(unix = "aa")]
    |
    = note: no expected value for `unix`
 
-warning: 3 warnings emitted
+warning: unexpected `cfg` condition value
+  --> $DIR/well-known-values.rs:28:7
+   |
+LL | #[cfg(miri = "miri")]
+   |       ^^^^---------
+   |           |
+   |           help: remove the value
+   |
+   = note: no expected value for `miri`
+
+warning: unexpected `cfg` condition value
+  --> $DIR/well-known-values.rs:35:7
+   |
+LL | #[cfg(doc = "linux")]
+   |       ^^^----------
+   |          |
+   |          help: remove the value
+   |
+   = note: no expected value for `doc`
+
+warning: 5 warnings emitted
 
diff --git a/src/test/ui/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr
index 4141cc4ab1a..6e61dbbd8ee 100644
--- a/src/test/ui/consts/const-match-check.eval1.stderr
+++ b/src/test/ui/consts/const-match-check.eval1.stderr
@@ -7,10 +7,10 @@ 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 },
+   |           ++           ~~~~~~~~~~~
 
 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 af86ba0cc82..1b3b6e06c3d 100644
--- a/src/test/ui/consts/const-match-check.eval2.stderr
+++ b/src/test/ui/consts/const-match-check.eval2.stderr
@@ -7,10 +7,10 @@ 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 }] = [];
+   |                    ++           ~~~~~~~~~~~
 
 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 f71490eba61..bc8edfa7af9 100644
--- a/src/test/ui/consts/const-match-check.matchck.stderr
+++ b/src/test/ui/consts/const-match-check.matchck.stderr
@@ -7,10 +7,10 @@ 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 };
+   |                  ++           ~~~~~~~~~~~
 
 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 +21,10 @@ 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 { /* */ } 0 };
-   |                   ~~~~~~~~~~~~~~~~~~~~~~
+LL | static Y: i32 = { if let 0 = 0 { 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 +35,10 @@ 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 };
+   |                      ++           ~~~~~~~~~~~
 
 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 +49,10 @@ 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 };
+   |                      ++           ~~~~~~~~~~~
 
 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 8dd0f377533..909aa73a74a 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 208c625a53e..55b1112b5f8 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 c2ffda6bb72..21180f31bbd 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 37a35700b36..95b22ac0594 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,10 @@ 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!() }
+   |     ++                       ~~~~~~~~~~~
 
 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 dffcfc01607..9da6b5eeead 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 8f5adccea80..0f06c31c468 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,10 @@ 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!() }
+   |     ++              ~~~~~~~~~~~
 
 error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered
   --> $DIR/non-exhaustive-defined-here.rs:52:11
@@ -91,10 +91,10 @@ 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!() }
+   |     ++              ~~~~~~~~~~~
 
 error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered
   --> $DIR/non-exhaustive-defined-here.rs:66:11
@@ -140,10 +140,10 @@ 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
-   |
-LL |     if let E::A = e { /* */ }
+help: you might want to use `if let` to ignore the variants that aren't matched
    |
+LL |     if let E::A = e { todo!() }
+   |     ++              ~~~~~~~~~~~
 
 error[E0004]: non-exhaustive patterns: `None` not covered
   --> $DIR/non-exhaustive-defined-here.rs:92:11
@@ -185,8 +185,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 74ec646e31c..d1dacc822e9 100644
--- a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr
+++ b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr
@@ -15,10 +15,10 @@ 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
-   |
-LL |     if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { /* */ }
+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!() }
+   |     ++                                            ~~~~~~~~~~~
 
 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 ded3cf3ad1d..a9159562d9d 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/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
index 897de54a7bf..dd090a3a548 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
diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.rs b/src/test/ui/uninhabited/uninhabited-irrefutable.rs
index 48cd92719b4..661b5486adc 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 ad19c34a40a..c571e17a7b3 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 d90075d82f4..74216d265d0 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