diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 6976999c0e4f7..809d64479084a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -453,7 +453,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         };
         for elem in place_ref.projection[base..].iter() {
             cg_base = match elem.clone() {
-                mir::ProjectionElem::Deref => bx.load_operand(cg_base).deref(bx.cx()),
+                mir::ProjectionElem::Deref => {
+                    // custom allocators can change box's abi, making it unable to be derefed directly
+                    if cg_base.layout.ty.is_box()
+                        && matches!(cg_base.layout.abi, Abi::Aggregate { .. } | Abi::Uninhabited)
+                    {
+                        let ptr = cg_base.project_field(bx, 0).project_field(bx, 0);
+
+                        bx.load_operand(ptr).deref(bx.cx())
+                    } else {
+                        bx.load_operand(cg_base).deref(bx.cx())
+                    }
+                }
                 mir::ProjectionElem::Field(ref field, _) => {
                     cg_base.project_field(bx, field.index())
                 }
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index a72681dbf4e7e..a185902123d8a 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -429,6 +429,7 @@ E0720: include_str!("./error_codes/E0720.md"),
 E0722: include_str!("./error_codes/E0722.md"),
 E0724: include_str!("./error_codes/E0724.md"),
 E0725: include_str!("./error_codes/E0725.md"),
+E0726: include_str!("./error_codes/E0726.md"),
 E0727: include_str!("./error_codes/E0727.md"),
 E0728: include_str!("./error_codes/E0728.md"),
 E0729: include_str!("./error_codes/E0729.md"),
@@ -641,6 +642,5 @@ E0787: include_str!("./error_codes/E0787.md"),
     E0717, // rustc_promotable without stability attribute
 //  E0721, // `await` keyword
 //  E0723, // unstable feature in `const` context
-    E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
 //  E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
 }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0726.md b/compiler/rustc_error_codes/src/error_codes/E0726.md
new file mode 100644
index 0000000000000..e3794327f2d4d
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0726.md
@@ -0,0 +1,46 @@
+An argument lifetime was elided in an async function.
+
+Erroneous code example:
+
+When a struct or a type is bound/declared with a lifetime it is important for
+the Rust compiler to know, on usage, the lifespan of the type. When the
+lifetime is not explicitly mentioned and the Rust Compiler cannot determine
+the lifetime of your type, the following error occurs.
+
+```compile_fail,E0726
+use futures::executor::block_on;
+struct Content<'a> {
+    title: &'a str,
+    body: &'a str,
+}
+async fn create(content: Content) { // error: implicit elided
+                                    // lifetime not allowed here
+    println!("title: {}", content.title);
+    println!("body: {}", content.body);
+}
+let content = Content { title: "Rust", body: "is great!" };
+let future = create(content);
+block_on(future);
+```
+
+Specify desired lifetime of parameter `content` or indicate the anonymous
+lifetime like `content: Content<'_>`. The anonymous lifetime tells the Rust
+compiler that `content` is only needed until create function is done with
+it's execution.
+
+The `implicit elision` meaning the omission of suggested lifetime that is
+`pub async fn create<'a>(content: Content<'a>) {}` is not allowed here as
+lifetime of the `content` can differ from current context:
+
+```ignore (needs futures dependency)
+async fn create(content: Content<'_>) { // ok!
+    println!("title: {}", content.title);
+    println!("body: {}", content.body);
+}
+```
+
+Know more about lifetime elision in this [chapter][lifetime-elision] and a
+chapter on lifetimes can be found [here][lifetimes].
+
+[lifetime-elision]: https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#lifetime-elision
+[lifetimes]: https://doc.rust-lang.org/rust-by-example/scope/lifetime.html
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index bdc9c064a6f9c..ab3951d768301 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -20,7 +20,7 @@ use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, PResult};
 use rustc_feature::Features;
 use rustc_parse::parser::{
-    AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma,
+    AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
 };
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
@@ -911,6 +911,7 @@ pub fn parse_ast_fragment<'a>(
             None,
             RecoverComma::No,
             RecoverColon::Yes,
+            CommaRecoveryMode::LikelyTuple,
         )?),
         AstFragmentKind::Crate => AstFragment::Crate(this.parse_crate_mod()?),
         AstFragmentKind::Arms
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index 6233549dc8579..8318aec8726dc 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -282,14 +282,13 @@ struct TokenStreamBuilder {
 
 impl TokenStreamBuilder {
     fn push(&mut self, (tree, joint): TreeAndSpacing) {
-        if let Some((TokenTree::Token(prev_token), Joint)) = self.buf.last() {
-            if let TokenTree::Token(token) = &tree {
-                if let Some(glued) = prev_token.glue(token) {
-                    self.buf.pop();
-                    self.buf.push((TokenTree::Token(glued), joint));
-                    return;
-                }
-            }
+        if let Some((TokenTree::Token(prev_token), Joint)) = self.buf.last()
+            && let TokenTree::Token(token) = &tree
+            && let Some(glued) = prev_token.glue(token)
+        {
+            self.buf.pop();
+            self.buf.push((TokenTree::Token(glued), joint));
+            return;
         }
         self.buf.push((tree, joint))
     }
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index eb0d1a12c778f..5c95a9e7bb616 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -1,9 +1,10 @@
 //! The main parser interface.
 
 #![feature(array_windows)]
+#![feature(box_patterns)]
 #![feature(crate_visibility_modifier)]
 #![feature(if_let_guard)]
-#![feature(box_patterns)]
+#![feature(let_chains)]
 #![feature(let_else)]
 #![recursion_limit = "256"]
 
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 50310b28f9a73..c92785bd9afeb 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1,8 +1,8 @@
 use super::pat::Expected;
 use super::ty::{AllowPlus, IsAsCast};
 use super::{
-    BlockMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, SemiColonMode, SeqSep,
-    TokenExpectType, TokenType,
+    BlockMode, CommaRecoveryMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions,
+    SemiColonMode, SeqSep, TokenExpectType, TokenType,
 };
 
 use rustc_ast as ast;
@@ -732,43 +732,42 @@ impl<'a> Parser<'a> {
         mut e: DiagnosticBuilder<'a, ErrorReported>,
         expr: &mut P<Expr>,
     ) -> PResult<'a, ()> {
-        if let ExprKind::Binary(binop, _, _) = &expr.kind {
-            if let ast::BinOpKind::Lt = binop.node {
-                if self.eat(&token::Comma) {
-                    let x = self.parse_seq_to_before_end(
-                        &token::Gt,
-                        SeqSep::trailing_allowed(token::Comma),
-                        |p| p.parse_generic_arg(None),
-                    );
-                    match x {
-                        Ok((_, _, false)) => {
-                            if self.eat(&token::Gt) {
-                                e.span_suggestion_verbose(
-                                    binop.span.shrink_to_lo(),
-                                    TURBOFISH_SUGGESTION_STR,
-                                    "::".to_string(),
-                                    Applicability::MaybeIncorrect,
-                                )
-                                .emit();
-                                match self.parse_expr() {
-                                    Ok(_) => {
-                                        *expr =
-                                            self.mk_expr_err(expr.span.to(self.prev_token.span));
-                                        return Ok(());
-                                    }
-                                    Err(err) => {
-                                        *expr = self.mk_expr_err(expr.span);
-                                        err.cancel();
-                                    }
-                                }
+        if let ExprKind::Binary(binop, _, _) = &expr.kind
+            && let ast::BinOpKind::Lt = binop.node
+            && self.eat(&token::Comma)
+        {
+            let x = self.parse_seq_to_before_end(
+                &token::Gt,
+                SeqSep::trailing_allowed(token::Comma),
+                |p| p.parse_generic_arg(None),
+            );
+            match x {
+                Ok((_, _, false)) => {
+                    if self.eat(&token::Gt) {
+                        e.span_suggestion_verbose(
+                            binop.span.shrink_to_lo(),
+                            TURBOFISH_SUGGESTION_STR,
+                            "::".to_string(),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
+                        match self.parse_expr() {
+                            Ok(_) => {
+                                *expr =
+                                    self.mk_expr_err(expr.span.to(self.prev_token.span));
+                                return Ok(());
+                            }
+                            Err(err) => {
+                                *expr = self.mk_expr_err(expr.span);
+                                err.cancel();
                             }
                         }
-                        Err(err) => {
-                            err.cancel();
-                        }
-                        _ => {}
                     }
                 }
+                Err(err) => {
+                    err.cancel();
+                }
+                _ => {}
             }
         }
         Err(e)
@@ -784,12 +783,13 @@ impl<'a> Parser<'a> {
         outer_op: &Spanned<AssocOp>,
     ) -> bool /* advanced the cursor */ {
         if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind {
-            if let ExprKind::Field(_, ident) = l1.kind {
-                if ident.as_str().parse::<i32>().is_err() && !matches!(r1.kind, ExprKind::Lit(_)) {
-                    // The parser has encountered `foo.bar<baz`, the likelihood of the turbofish
-                    // suggestion being the only one to apply is high.
-                    return false;
-                }
+            if let ExprKind::Field(_, ident) = l1.kind
+                && ident.as_str().parse::<i32>().is_err()
+                && !matches!(r1.kind, ExprKind::Lit(_))
+            {
+                // The parser has encountered `foo.bar<baz`, the likelihood of the turbofish
+                // suggestion being the only one to apply is high.
+                return false;
             }
             let mut enclose = |left: Span, right: Span| {
                 err.multipart_suggestion(
@@ -2245,12 +2245,32 @@ impl<'a> Parser<'a> {
         first_pat
     }
 
+    crate fn maybe_recover_unexpected_block_label(&mut self) -> bool {
+        let Some(label) = self.eat_label().filter(|_| {
+            self.eat(&token::Colon) && self.token.kind == token::OpenDelim(token::Brace)
+        }) else {
+            return false;
+        };
+        let span = label.ident.span.to(self.prev_token.span);
+        let mut err = self.struct_span_err(span, "block label not supported here");
+        err.span_label(span, "not supported here");
+        err.tool_only_span_suggestion(
+            label.ident.span.until(self.token.span),
+            "remove this block label",
+            String::new(),
+            Applicability::MachineApplicable,
+        );
+        err.emit();
+        true
+    }
+
     /// Some special error handling for the "top-level" patterns in a match arm,
     /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
     crate fn maybe_recover_unexpected_comma(
         &mut self,
         lo: Span,
         rc: RecoverComma,
+        rt: CommaRecoveryMode,
     ) -> PResult<'a, ()> {
         if rc == RecoverComma::No || self.token != token::Comma {
             return Ok(());
@@ -2270,20 +2290,25 @@ impl<'a> Parser<'a> {
         let seq_span = lo.to(self.prev_token.span);
         let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
         if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
-            const MSG: &str = "try adding parentheses to match on a tuple...";
-
-            err.span_suggestion(
-                seq_span,
-                MSG,
-                format!("({})", seq_snippet),
-                Applicability::MachineApplicable,
-            );
-            err.span_suggestion(
-                seq_span,
-                "...or a vertical bar to match on multiple alternatives",
-                seq_snippet.replace(',', " |"),
+            err.multipart_suggestion(
+                &format!(
+                    "try adding parentheses to match on a tuple{}",
+                    if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
+                ),
+                vec![
+                    (seq_span.shrink_to_lo(), "(".to_string()),
+                    (seq_span.shrink_to_hi(), ")".to_string()),
+                ],
                 Applicability::MachineApplicable,
             );
+            if let CommaRecoveryMode::EitherTupleOrPipe = rt {
+                err.span_suggestion(
+                    seq_span,
+                    "...or a vertical bar to match on multiple alternatives",
+                    seq_snippet.replace(',', " |"),
+                    Applicability::MachineApplicable,
+                );
+            }
         }
         Err(err)
     }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index a11cb3f5677c6..a54ab4a92e1b8 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1,4 +1,4 @@
-use super::pat::{RecoverColon, RecoverComma, PARAM_EXPECTED};
+use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{
     AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, TokenType,
@@ -1286,18 +1286,27 @@ impl<'a> Parser<'a> {
         } else if let Some(label) = self.eat_label() {
             self.parse_labeled_expr(label, attrs, true)
         } else if self.eat_keyword(kw::Loop) {
-            self.parse_loop_expr(None, self.prev_token.span, attrs)
+            let sp = self.prev_token.span;
+            self.parse_loop_expr(None, self.prev_token.span, attrs).map_err(|mut err| {
+                err.span_label(sp, "while parsing this `loop` expression");
+                err
+            })
         } else if self.eat_keyword(kw::Continue) {
             let kind = ExprKind::Continue(self.eat_label());
             Ok(self.mk_expr(lo.to(self.prev_token.span), kind, attrs))
         } else if self.eat_keyword(kw::Match) {
             let match_sp = self.prev_token.span;
             self.parse_match_expr(attrs).map_err(|mut err| {
-                err.span_label(match_sp, "while parsing this match expression");
+                err.span_label(match_sp, "while parsing this `match` expression");
                 err
             })
         } else if self.eat_keyword(kw::Unsafe) {
+            let sp = self.prev_token.span;
             self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided), attrs)
+                .map_err(|mut err| {
+                    err.span_label(sp, "while parsing this `unsafe` expression");
+                    err
+                })
         } else if self.check_inline_const(0) {
             self.parse_const_block(lo.to(self.token.span), false)
         } else if self.is_do_catch_block() {
@@ -2160,7 +2169,12 @@ impl<'a> Parser<'a> {
     /// The `let` token has already been eaten.
     fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let lo = self.prev_token.span;
-        let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes, RecoverColon::Yes)?;
+        let pat = self.parse_pat_allow_top_alt(
+            None,
+            RecoverComma::Yes,
+            RecoverColon::Yes,
+            CommaRecoveryMode::LikelyTuple,
+        )?;
         self.expect(&token::Eq)?;
         let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| {
             this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
@@ -2223,7 +2237,12 @@ impl<'a> Parser<'a> {
             _ => None,
         };
 
-        let pat = self.parse_pat_allow_top_alt(None, RecoverComma::Yes, RecoverColon::Yes)?;
+        let pat = self.parse_pat_allow_top_alt(
+            None,
+            RecoverComma::Yes,
+            RecoverColon::Yes,
+            CommaRecoveryMode::LikelyTuple,
+        )?;
         if !self.eat_keyword(kw::In) {
             self.error_missing_in_for_loop();
         }
@@ -2266,8 +2285,15 @@ impl<'a> Parser<'a> {
         lo: Span,
         mut attrs: AttrVec,
     ) -> PResult<'a, P<Expr>> {
-        let cond = self.parse_cond_expr()?;
-        let (iattrs, body) = self.parse_inner_attrs_and_block()?;
+        let cond = self.parse_cond_expr().map_err(|mut err| {
+            err.span_label(lo, "while parsing the condition of this `while` expression");
+            err
+        })?;
+        let (iattrs, body) = self.parse_inner_attrs_and_block().map_err(|mut err| {
+            err.span_label(lo, "while parsing the body of this `while` expression");
+            err.span_label(cond.span, "this `while` condition successfully parsed");
+            err
+        })?;
         attrs.extend(iattrs);
         Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::While(cond, body, opt_label), attrs))
     }
@@ -2284,7 +2310,7 @@ impl<'a> Parser<'a> {
         Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::Loop(body, opt_label), attrs))
     }
 
-    fn eat_label(&mut self) -> Option<Label> {
+    crate fn eat_label(&mut self) -> Option<Label> {
         self.token.lifetime().map(|ident| {
             self.bump();
             Label { ident }
@@ -2305,7 +2331,12 @@ impl<'a> Parser<'a> {
                     Applicability::MaybeIncorrect, // speculative
                 );
             }
-            return Err(e);
+            if self.maybe_recover_unexpected_block_label() {
+                e.cancel();
+                self.bump();
+            } else {
+                return Err(e);
+            }
         }
         attrs.extend(self.parse_inner_attributes()?);
 
@@ -2441,7 +2472,12 @@ impl<'a> Parser<'a> {
         let attrs = self.parse_outer_attributes()?;
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
             let lo = this.token.span;
-            let pat = this.parse_pat_allow_top_alt(None, RecoverComma::Yes, RecoverColon::Yes)?;
+            let pat = this.parse_pat_allow_top_alt(
+                None,
+                RecoverComma::Yes,
+                RecoverColon::Yes,
+                CommaRecoveryMode::EitherTupleOrPipe,
+            )?;
             let guard = if this.eat_keyword(kw::If) {
                 let if_span = this.prev_token.span;
                 let cond = this.parse_expr()?;
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index bd349e89482ef..af5cc0e094868 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -102,14 +102,12 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, Option<Item>> {
         // Don't use `maybe_whole` so that we have precise control
         // over when we bump the parser
-        if let token::Interpolated(nt) = &self.token.kind {
-            if let token::NtItem(item) = &**nt {
-                let mut item = item.clone();
-                self.bump();
+        if let token::Interpolated(nt) = &self.token.kind && let token::NtItem(item) = &**nt {
+            let mut item = item.clone();
+            self.bump();
 
-                attrs.prepend_to_nt_inner(&mut item.attrs);
-                return Ok(Some(item.into_inner()));
-            }
+            attrs.prepend_to_nt_inner(&mut item.attrs);
+            return Ok(Some(item.into_inner()));
         };
 
         let mut unclosed_delims = vec![];
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index d8e6d5037bbd8..9d85be93b1dd7 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -15,7 +15,7 @@ pub use attr_wrapper::AttrWrapper;
 pub use diagnostics::AttemptLocalParseRecovery;
 use diagnostics::Error;
 pub(crate) use item::FnParseMode;
-pub use pat::{RecoverColon, RecoverComma};
+pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
 pub use path::PathStyle;
 
 use rustc_ast::ptr::P;
@@ -97,15 +97,15 @@ macro_rules! maybe_whole {
 #[macro_export]
 macro_rules! maybe_recover_from_interpolated_ty_qpath {
     ($self: expr, $allow_qpath_recovery: expr) => {
-        if $allow_qpath_recovery && $self.look_ahead(1, |t| t == &token::ModSep) {
-            if let token::Interpolated(nt) = &$self.token.kind {
-                if let token::NtTy(ty) = &**nt {
+        if $allow_qpath_recovery
+                    && $self.look_ahead(1, |t| t == &token::ModSep)
+                    && let token::Interpolated(nt) = &$self.token.kind
+                    && let token::NtTy(ty) = &**nt
+                {
                     let ty = ty.clone();
                     $self.bump();
                     return $self.maybe_recover_from_bad_qpath_stage_2($self.prev_token.span, ty);
                 }
-            }
-        }
     };
 }
 
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 72e6f8a1bc857..83e0a4997ad85 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -5,7 +5,7 @@ use rustc_ast_pretty::pprust;
 use rustc_errors::PResult;
 use rustc_span::symbol::{kw, Ident};
 
-use crate::parser::pat::{RecoverColon, RecoverComma};
+use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
 use crate::parser::{FollowedByType, ForceCollect, Parser, PathStyle};
 
 impl<'a> Parser<'a> {
@@ -125,7 +125,7 @@ impl<'a> Parser<'a> {
                 token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
                     NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None),
                     NonterminalKind::PatWithOr { .. } => {
-                        this.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No)
+                        this.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No, CommaRecoveryMode::EitherTupleOrPipe)
                     }
                     _ => unreachable!(),
                 })?)
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index d41298711459f..ff536d15cbfca 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -33,6 +33,13 @@ pub enum RecoverColon {
     No,
 }
 
+/// Whether or not to recover a `a, b` when parsing patterns as `(a, b)` or that *and* `a | b`.
+#[derive(PartialEq, Copy, Clone)]
+pub enum CommaRecoveryMode {
+    LikelyTuple,
+    EitherTupleOrPipe,
+}
+
 /// The result of `eat_or_separator`. We want to distinguish which case we are in to avoid
 /// emitting duplicate diagnostics.
 #[derive(Debug, Clone, Copy)]
@@ -68,8 +75,9 @@ impl<'a> Parser<'a> {
         expected: Expected,
         rc: RecoverComma,
         ra: RecoverColon,
+        rt: CommaRecoveryMode,
     ) -> PResult<'a, P<Pat>> {
-        self.parse_pat_allow_top_alt_inner(expected, rc, ra).map(|(pat, _)| pat)
+        self.parse_pat_allow_top_alt_inner(expected, rc, ra, rt).map(|(pat, _)| pat)
     }
 
     /// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true =
@@ -79,6 +87,7 @@ impl<'a> Parser<'a> {
         expected: Expected,
         rc: RecoverComma,
         ra: RecoverColon,
+        rt: CommaRecoveryMode,
     ) -> PResult<'a, (P<Pat>, bool)> {
         // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
         // suggestions (which bothers rustfix).
@@ -92,7 +101,7 @@ impl<'a> Parser<'a> {
 
         // Parse the first pattern (`p_0`).
         let first_pat = self.parse_pat_no_top_alt(expected)?;
-        self.maybe_recover_unexpected_comma(first_pat.span, rc)?;
+        self.maybe_recover_unexpected_comma(first_pat.span, rc, rt)?;
 
         // If the next token is not a `|`,
         // this is not an or-pattern and we should exit here.
@@ -130,7 +139,7 @@ impl<'a> Parser<'a> {
                 err.span_label(lo, WHILE_PARSING_OR_MSG);
                 err
             })?;
-            self.maybe_recover_unexpected_comma(pat.span, rc)?;
+            self.maybe_recover_unexpected_comma(pat.span, rc, rt)?;
             pats.push(pat);
         }
         let or_pattern_span = lo.to(self.prev_token.span);
@@ -155,8 +164,12 @@ impl<'a> Parser<'a> {
         // We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level
         // or-patterns so that we can detect when a user tries to use it. This allows us to print a
         // better error message.
-        let (pat, trailing_vert) =
-            self.parse_pat_allow_top_alt_inner(expected, rc, RecoverColon::No)?;
+        let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner(
+            expected,
+            rc,
+            RecoverColon::No,
+            CommaRecoveryMode::LikelyTuple,
+        )?;
         let colon = self.eat(&token::Colon);
 
         if let PatKind::Or(pats) = &pat.kind {
@@ -315,7 +328,12 @@ impl<'a> Parser<'a> {
         } else if self.check(&token::OpenDelim(token::Bracket)) {
             // Parse `[pat, pat,...]` as a slice pattern.
             let (pats, _) = self.parse_delim_comma_seq(token::Bracket, |p| {
-                p.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No)
+                p.parse_pat_allow_top_alt(
+                    None,
+                    RecoverComma::No,
+                    RecoverColon::No,
+                    CommaRecoveryMode::EitherTupleOrPipe,
+                )
             })?;
             PatKind::Slice(pats)
         } else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) {
@@ -529,7 +547,12 @@ impl<'a> Parser<'a> {
     /// Parse a tuple or parenthesis pattern.
     fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
         let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| {
-            p.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No)
+            p.parse_pat_allow_top_alt(
+                None,
+                RecoverComma::No,
+                RecoverColon::No,
+                CommaRecoveryMode::LikelyTuple,
+            )
         })?;
 
         // Here, `(pat,)` is a tuple pattern.
@@ -873,7 +896,12 @@ impl<'a> Parser<'a> {
     /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
     fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
         let (fields, _) = self.parse_paren_comma_seq(|p| {
-            p.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No)
+            p.parse_pat_allow_top_alt(
+                None,
+                RecoverComma::No,
+                RecoverColon::No,
+                CommaRecoveryMode::EitherTupleOrPipe,
+            )
         })?;
         if qself.is_some() {
             self.sess.gated_spans.gate(sym::more_qualified_paths, path.span);
@@ -1033,7 +1061,12 @@ impl<'a> Parser<'a> {
             // Parsing a pattern of the form `fieldname: pat`.
             let fieldname = self.parse_field_name()?;
             self.bump();
-            let pat = self.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No)?;
+            let pat = self.parse_pat_allow_top_alt(
+                None,
+                RecoverComma::No,
+                RecoverColon::No,
+                CommaRecoveryMode::EitherTupleOrPipe,
+            )?;
             hi = pat.span;
             (pat, fieldname, false)
         } else {
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 0ffc9d0935524..5e537d7b95c4a 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -658,13 +658,13 @@ impl<'a> Parser<'a> {
         &self,
         gen_arg: GenericArg,
     ) -> Result<(Ident, Option<GenericArgs>), GenericArg> {
-        if let GenericArg::Type(ty) = &gen_arg {
-            if let ast::TyKind::Path(qself, path) = &ty.kind {
-                if qself.is_none() && path.segments.len() == 1 {
-                    let seg = &path.segments[0];
-                    return Ok((seg.ident, seg.args.as_deref().cloned()));
-                }
-            }
+        if let GenericArg::Type(ty) = &gen_arg
+            && let ast::TyKind::Path(qself, path) = &ty.kind
+            && qself.is_none()
+            && path.segments.len() == 1
+        {
+            let seg = &path.segments[0];
+            return Ok((seg.ident, seg.args.as_deref().cloned()));
         }
         Err(gen_arg)
     }
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 6b195285243fd..e39e32ff364fa 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -48,15 +48,13 @@ impl<'a> Parser<'a> {
 
         // Don't use `maybe_whole` so that we have precise control
         // over when we bump the parser
-        if let token::Interpolated(nt) = &self.token.kind {
-            if let token::NtStmt(stmt) = &**nt {
-                let mut stmt = stmt.clone();
-                self.bump();
-                stmt.visit_attrs(|stmt_attrs| {
-                    attrs.prepend_to_nt_inner(stmt_attrs);
-                });
-                return Ok(Some(stmt));
-            }
+        if let token::Interpolated(nt) = &self.token.kind && let token::NtStmt(stmt) = &**nt {
+            let mut stmt = stmt.clone();
+            self.bump();
+            stmt.visit_attrs(|stmt_attrs| {
+                attrs.prepend_to_nt_inner(stmt_attrs);
+            });
+            return Ok(Some(stmt));
         }
 
         Ok(Some(if self.token.is_keyword(kw::Let) {
@@ -434,6 +432,8 @@ impl<'a> Parser<'a> {
             Ok(Some(_))
                 if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
                     || do_not_suggest_help => {}
+            // Do not suggest `if foo println!("") {;}` (as would be seen in test for #46836).
+            Ok(Some(Stmt { kind: StmtKind::Empty, .. })) => {}
             Ok(Some(stmt)) => {
                 let stmt_own_line = self.sess.source_map().is_line_before_span_empty(sp);
                 let stmt_span = if stmt_own_line && self.eat(&token::Semi) {
@@ -442,15 +442,15 @@ impl<'a> Parser<'a> {
                 } else {
                     stmt.span
                 };
-                if let Ok(snippet) = self.span_to_snippet(stmt_span) {
-                    e.span_suggestion(
-                        stmt_span,
-                        "try placing this code inside a block",
-                        format!("{{ {} }}", snippet),
-                        // Speculative; has been misleading in the past (#46836).
-                        Applicability::MaybeIncorrect,
-                    );
-                }
+                e.multipart_suggestion(
+                    "try placing this code inside a block",
+                    vec![
+                        (stmt_span.shrink_to_lo(), "{ ".to_string()),
+                        (stmt_span.shrink_to_hi(), " }".to_string()),
+                    ],
+                    // Speculative; has been misleading in the past (#46836).
+                    Applicability::MaybeIncorrect,
+                );
             }
             Err(e) => {
                 self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore);
@@ -483,15 +483,15 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
         maybe_whole!(self, NtBlock, |x| (Vec::new(), x));
 
+        self.maybe_recover_unexpected_block_label();
         if !self.eat(&token::OpenDelim(token::Brace)) {
             return self.error_block_no_opening_brace();
         }
 
         let attrs = self.parse_inner_attributes()?;
-        let tail = if let Some(tail) = self.maybe_suggest_struct_literal(lo, blk_mode) {
-            tail?
-        } else {
-            self.parse_block_tail(lo, blk_mode, AttemptLocalParseRecovery::Yes)?
+        let tail = match self.maybe_suggest_struct_literal(lo, blk_mode) {
+            Some(tail) => tail?,
+            None => self.parse_block_tail(lo, blk_mode, AttemptLocalParseRecovery::Yes)?,
         };
         Ok((attrs, tail))
     }
@@ -587,11 +587,11 @@ impl<'a> Parser<'a> {
                 // We might be at the `,` in `let x = foo<bar, baz>;`. Try to recover.
                 match &mut local.kind {
                     LocalKind::Init(expr) | LocalKind::InitElse(expr, _) => {
-                            self.check_mistyped_turbofish_with_multiple_type_params(e, expr)?;
-                            // We found `foo<bar, baz>`, have we fully recovered?
-                            self.expect_semi()?;
-                        }
-                        LocalKind::Decl => return Err(e),
+                        self.check_mistyped_turbofish_with_multiple_type_params(e, expr)?;
+                        // We found `foo<bar, baz>`, have we fully recovered?
+                        self.expect_semi()?;
+                    }
+                    LocalKind::Decl => return Err(e),
                 }
                 eat_semi = false;
             }
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 14a1318517a19..f3aa40b9ad11e 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -840,7 +840,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         );
         err.span_label(lhs.span, "cannot assign to this expression");
 
-        let mut parent = self.tcx.hir().get_parent_node(lhs.hir_id);
+        self.comes_from_while_condition(lhs.hir_id, |expr| {
+            err.span_suggestion_verbose(
+                expr.span.shrink_to_lo(),
+                "you might have meant to use pattern destructuring",
+                "let ".to_string(),
+                Applicability::MachineApplicable,
+            );
+        });
+
+        err.emit();
+    }
+
+    // Check if an expression `original_expr_id` comes from the condition of a while loop,
+    // as opposed from the body of a while loop, which we can naively check by iterating
+    // parents until we find a loop...
+    pub(super) fn comes_from_while_condition(
+        &self,
+        original_expr_id: HirId,
+        then: impl FnOnce(&hir::Expr<'_>),
+    ) {
+        let mut parent = self.tcx.hir().get_parent_node(original_expr_id);
         while let Some(node) = self.tcx.hir().find(parent) {
             match node {
                 hir::Node::Expr(hir::Expr {
@@ -861,8 +881,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ),
                     ..
                 }) => {
-                    // Check if our lhs is a child of the condition of a while loop
-                    let expr_is_ancestor = std::iter::successors(Some(lhs.hir_id), |id| {
+                    // Check if our original expression is a child of the condition of a while loop
+                    let expr_is_ancestor = std::iter::successors(Some(original_expr_id), |id| {
                         self.tcx.hir().find_parent_node(*id)
                     })
                     .take_while(|id| *id != parent)
@@ -870,12 +890,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // if it is, then we have a situation like `while Some(0) = value.get(0) {`,
                     // where `while let` was more likely intended.
                     if expr_is_ancestor {
-                        err.span_suggestion_verbose(
-                            expr.span.shrink_to_lo(),
-                            "you might have meant to use pattern destructuring",
-                            "let ".to_string(),
-                            Applicability::MachineApplicable,
-                        );
+                        then(expr);
                     }
                     break;
                 }
@@ -888,8 +903,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
         }
-
-        err.emit();
     }
 
     // A generic function for checking the 'then' and 'else' clauses in an 'if'
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 76339998a2fbb..f5d110903e6e3 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -768,55 +768,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let prev_diverges = self.diverges.get();
         let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
 
-        let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
-            for (pos, s) in blk.stmts.iter().enumerate() {
-                self.check_stmt(s, blk.stmts.len() - 1 == pos);
-            }
+        let (ctxt, ()) =
+            self.with_breakable_ctxt(blk.hir_id, ctxt, || {
+                for (pos, s) in blk.stmts.iter().enumerate() {
+                    self.check_stmt(s, blk.stmts.len() - 1 == pos);
+                }
 
-            // check the tail expression **without** holding the
-            // `enclosing_breakables` lock below.
-            let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
-
-            let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
-            let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
-            let coerce = ctxt.coerce.as_mut().unwrap();
-            if let Some(tail_expr_ty) = tail_expr_ty {
-                let tail_expr = tail_expr.unwrap();
-                let span = self.get_expr_coercion_span(tail_expr);
-                let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
-                coerce.coerce(self, &cause, tail_expr, tail_expr_ty);
-            } else {
-                // Subtle: if there is no explicit tail expression,
-                // that is typically equivalent to a tail expression
-                // of `()` -- except if the block diverges. In that
-                // case, there is no value supplied from the tail
-                // expression (assuming there are no other breaks,
-                // this implies that the type of the block will be
-                // `!`).
-                //
-                // #41425 -- label the implicit `()` as being the
-                // "found type" here, rather than the "expected type".
-                if !self.diverges.get().is_always() {
-                    // #50009 -- Do not point at the entire fn block span, point at the return type
-                    // span, as it is the cause of the requirement, and
-                    // `consider_hint_about_removing_semicolon` will point at the last expression
-                    // if it were a relevant part of the error. This improves usability in editors
-                    // that highlight errors inline.
-                    let mut sp = blk.span;
-                    let mut fn_span = None;
-                    if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) {
-                        let ret_sp = decl.output.span();
-                        if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
-                            // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
-                            // output would otherwise be incorrect and even misleading. Make sure
-                            // the span we're aiming at correspond to a `fn` body.
-                            if block_sp == blk.span {
-                                sp = ret_sp;
-                                fn_span = Some(ident.span);
+                // check the tail expression **without** holding the
+                // `enclosing_breakables` lock below.
+                let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
+
+                let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
+                let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
+                let coerce = ctxt.coerce.as_mut().unwrap();
+                if let Some(tail_expr_ty) = tail_expr_ty {
+                    let tail_expr = tail_expr.unwrap();
+                    let span = self.get_expr_coercion_span(tail_expr);
+                    let cause =
+                        self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
+                    coerce.coerce(self, &cause, tail_expr, tail_expr_ty);
+                } else {
+                    // Subtle: if there is no explicit tail expression,
+                    // that is typically equivalent to a tail expression
+                    // of `()` -- except if the block diverges. In that
+                    // case, there is no value supplied from the tail
+                    // expression (assuming there are no other breaks,
+                    // this implies that the type of the block will be
+                    // `!`).
+                    //
+                    // #41425 -- label the implicit `()` as being the
+                    // "found type" here, rather than the "expected type".
+                    if !self.diverges.get().is_always() {
+                        // #50009 -- Do not point at the entire fn block span, point at the return type
+                        // span, as it is the cause of the requirement, and
+                        // `consider_hint_about_removing_semicolon` will point at the last expression
+                        // if it were a relevant part of the error. This improves usability in editors
+                        // that highlight errors inline.
+                        let mut sp = blk.span;
+                        let mut fn_span = None;
+                        if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) {
+                            let ret_sp = decl.output.span();
+                            if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
+                                // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
+                                // output would otherwise be incorrect and even misleading. Make sure
+                                // the span we're aiming at correspond to a `fn` body.
+                                if block_sp == blk.span {
+                                    sp = ret_sp;
+                                    fn_span = Some(ident.span);
+                                }
                             }
                         }
-                    }
-                    coerce.coerce_forced_unit(
+                        coerce.coerce_forced_unit(
                         self,
                         &self.misc(sp),
                         &mut |err| {
@@ -825,19 +827,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 if expected_ty == self.tcx.types.bool {
                                     // If this is caused by a missing `let` in a `while let`,
                                     // silence this redundant error, as we already emit E0070.
-                                    let parent = self.tcx.hir().get_parent_node(blk.hir_id);
-                                    let parent = self.tcx.hir().get_parent_node(parent);
-                                    let parent = self.tcx.hir().get_parent_node(parent);
-                                    let parent = self.tcx.hir().get_parent_node(parent);
-                                    let parent = self.tcx.hir().get_parent_node(parent);
-                                    match self.tcx.hir().find(parent) {
-                                        Some(hir::Node::Expr(hir::Expr {
-                                            kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _),
-                                            ..
-                                        })) => {
+
+                                    // Our block must be a `assign desugar local; assignment`
+                                    if let Some(hir::Node::Block(hir::Block {
+                                        stmts:
+                                            [hir::Stmt {
+                                                kind:
+                                                    hir::StmtKind::Local(hir::Local {
+                                                        source: hir::LocalSource::AssignDesugar(_),
+                                                        ..
+                                                    }),
+                                                ..
+                                            }, hir::Stmt {
+                                                kind:
+                                                    hir::StmtKind::Expr(hir::Expr {
+                                                        kind: hir::ExprKind::Assign(..),
+                                                        ..
+                                                    }),
+                                                ..
+                                            }],
+                                        ..
+                                    })) = self.tcx.hir().find(blk.hir_id)
+                                    {
+                                        self.comes_from_while_condition(blk.hir_id, |_| {
                                             err.downgrade_to_delayed_bug();
-                                        }
-                                        _ => {}
+                                        })
                                     }
                                 }
                             }
@@ -851,9 +865,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         },
                         false,
                     );
+                    }
                 }
-            }
-        });
+            });
 
         if ctxt.may_break {
             // If we can break from the block, then the block's exit is always reachable
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 67f5b386ecd7f..7890c1040f0a1 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -986,7 +986,7 @@ impl<K, V> BTreeMap<K, V> {
         self.drain_filter(|k, v| !f(k, v));
     }
 
-    /// Moves all elements from `other` into `Self`, leaving `other` empty.
+    /// Moves all elements from `other` into `self`, leaving `other` empty.
     ///
     /// # Examples
     ///
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index 3031bf86a7be1..bab6af8269864 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -895,7 +895,7 @@ impl<T> BTreeSet<T> {
         self.drain_filter(|v| !f(v));
     }
 
-    /// Moves all elements from `other` into `Self`, leaving `other` empty.
+    /// Moves all elements from `other` into `self`, leaving `other` empty.
     ///
     /// # Examples
     ///
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index c29aa0fec5b87..c4c393f55eee9 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1763,7 +1763,7 @@ impl<T, A: Allocator> Vec<T, A> {
         }
     }
 
-    /// Moves all the elements of `other` into `Self`, leaving `other` empty.
+    /// Moves all the elements of `other` into `self`, leaving `other` empty.
     ///
     /// # Panics
     ///
@@ -1788,7 +1788,7 @@ impl<T, A: Allocator> Vec<T, A> {
         }
     }
 
-    /// Appends elements to `Self` from other buffer.
+    /// Appends elements to `self` from other buffer.
     #[cfg(not(no_global_oom_handling))]
     #[inline]
     unsafe fn append_elements(&mut self, other: *const [T]) {
diff --git a/src/test/ui/async-await/async-fn-path-elision.stderr b/src/test/ui/async-await/async-fn-path-elision.stderr
index 36fb73a8dde24..3d18d9c412596 100644
--- a/src/test/ui/async-await/async-fn-path-elision.stderr
+++ b/src/test/ui/async-await/async-fn-path-elision.stderr
@@ -8,3 +8,4 @@ LL | async fn error(lt: HasLifetime) {
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0726`.
diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr
index b4323c314badc..b30f2883732b4 100644
--- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr
+++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr
@@ -132,7 +132,7 @@ error: expected one of `.`, `?`, `{`, or an operator, found `}`
 LL |     match await { await => () }
    |     -----                      - expected one of `.`, `?`, `{`, or an operator
    |     |
-   |     while parsing this match expression
+   |     while parsing this `match` expression
 ...
 LL | }
    | ^ unexpected token
diff --git a/src/test/ui/box/issue-78459-ice.rs b/src/test/ui/box/issue-78459-ice.rs
deleted file mode 100644
index 89f75fea15b1d..0000000000000
--- a/src/test/ui/box/issue-78459-ice.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// check-pass
-#![feature(allocator_api)]
-
-fn main() {
-    Box::new_in((), &std::alloc::Global);
-}
diff --git a/src/test/ui/box/large-allocator-ice.rs b/src/test/ui/box/large-allocator-ice.rs
new file mode 100644
index 0000000000000..3ef1171ff50d9
--- /dev/null
+++ b/src/test/ui/box/large-allocator-ice.rs
@@ -0,0 +1,23 @@
+// build-pass
+#![feature(allocator_api)]
+
+use std::alloc::Allocator;
+
+struct BigAllocator([usize; 2]);
+
+unsafe impl Allocator for BigAllocator {
+    fn allocate(
+        &self,
+        _: std::alloc::Layout,
+    ) -> Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError> {
+        todo!()
+    }
+    unsafe fn deallocate(&self, _: std::ptr::NonNull<u8>, _: std::alloc::Layout) {
+        todo!()
+    }
+}
+
+fn main() {
+    Box::new_in((), &std::alloc::Global);
+    Box::new_in((), BigAllocator([0; 2]));
+}
diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
index 8025886a9eb46..609a5efd46fee 100644
--- a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
+++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
@@ -28,10 +28,7 @@ error: expected `{`, found `;`
 LL |     if not  // lack of braces is [sic]
    |     -- this `if` expression has a condition, but no block
 LL |         println!("Then when?");
-   |                               ^
-   |                               |
-   |                               expected `{`
-   |                               help: try placing this code inside a block: `{ ; }`
+   |                               ^ expected `{`
 
 error: unexpected `2` after identifier
   --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:26:24
diff --git a/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr b/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
index c2e3ead7ec7c6..a3c607b59037f 100644
--- a/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
+++ b/src/test/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr
@@ -2,16 +2,14 @@ error: unexpected `,` in pattern
   --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:38:17
    |
 LL |     while let b1, b2, b3 = reading_frame.next().expect("there should be a start codon") {
-   |                 ^
+   |     -----       ^
+   |     |
+   |     while parsing the condition of this `while` expression
    |
-help: try adding parentheses to match on a tuple...
+help: try adding parentheses to match on a tuple
    |
 LL |     while let (b1, b2, b3) = reading_frame.next().expect("there should be a start codon") {
-   |               ~~~~~~~~~~~~
-help: ...or a vertical bar to match on multiple alternatives
-   |
-LL |     while let b1 | b2 | b3 = reading_frame.next().expect("there should be a start codon") {
-   |               ~~~~~~~~~~~~
+   |               +          +
 
 error: unexpected `,` in pattern
   --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:49:14
@@ -19,14 +17,10 @@ error: unexpected `,` in pattern
 LL |     if let b1, b2, b3 = reading_frame.next().unwrap() {
    |              ^
    |
-help: try adding parentheses to match on a tuple...
+help: try adding parentheses to match on a tuple
    |
 LL |     if let (b1, b2, b3) = reading_frame.next().unwrap() {
-   |            ~~~~~~~~~~~~
-help: ...or a vertical bar to match on multiple alternatives
-   |
-LL |     if let b1 | b2 | b3 = reading_frame.next().unwrap() {
-   |            ~~~~~~~~~~~~
+   |            +          +
 
 error: unexpected `,` in pattern
   --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:59:28
@@ -37,7 +31,7 @@ LL |         Nucleotide::Adenine, Nucleotide::Cytosine, _ => true
 help: try adding parentheses to match on a tuple...
    |
 LL |         (Nucleotide::Adenine, Nucleotide::Cytosine, _) => true
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |         +                                            +
 help: ...or a vertical bar to match on multiple alternatives
    |
 LL |         Nucleotide::Adenine | Nucleotide::Cytosine | _ => true
@@ -49,14 +43,10 @@ error: unexpected `,` in pattern
 LL |     for x, _barr_body in women.iter().map(|woman| woman.allosomes.clone()) {
    |          ^
    |
-help: try adding parentheses to match on a tuple...
+help: try adding parentheses to match on a tuple
    |
 LL |     for (x, _barr_body) in women.iter().map(|woman| woman.allosomes.clone()) {
-   |         ~~~~~~~~~~~~~~~
-help: ...or a vertical bar to match on multiple alternatives
-   |
-LL |     for x | _barr_body in women.iter().map(|woman| woman.allosomes.clone()) {
-   |         ~~~~~~~~~~~~~~
+   |         +             +
 
 error: unexpected `,` in pattern
   --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:75:10
@@ -64,14 +54,10 @@ error: unexpected `,` in pattern
 LL |     for x, y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) {
    |          ^
    |
-help: try adding parentheses to match on a tuple...
+help: try adding parentheses to match on a tuple
    |
 LL |     for (x, y @ Allosome::Y(_)) in men.iter().map(|man| man.allosomes.clone()) {
-   |         ~~~~~~~~~~~~~~~~~~~~~~~
-help: ...or a vertical bar to match on multiple alternatives
-   |
-LL |     for x | y @ Allosome::Y(_) in men.iter().map(|man| man.allosomes.clone()) {
-   |         ~~~~~~~~~~~~~~~~~~~~~~
+   |         +                     +
 
 error: unexpected `,` in pattern
   --> $DIR/issue-48492-tuple-destructure-missing-parens.rs:84:14
@@ -79,14 +65,10 @@ error: unexpected `,` in pattern
 LL |     let women, men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
    |              ^
    |
-help: try adding parentheses to match on a tuple...
+help: try adding parentheses to match on a tuple
    |
 LL |     let (women, men): (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
-   |         ~~~~~~~~~~~~
-help: ...or a vertical bar to match on multiple alternatives
-   |
-LL |     let women | men: (Vec<Genome>, Vec<Genome>) = genomes.iter().cloned()
-   |         ~~~~~~~~~~~
+   |         +          +
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/impl-header-lifetime-elision/path-elided.stderr b/src/test/ui/impl-header-lifetime-elision/path-elided.stderr
index 1c81c69620165..90522a885ab90 100644
--- a/src/test/ui/impl-header-lifetime-elision/path-elided.stderr
+++ b/src/test/ui/impl-header-lifetime-elision/path-elided.stderr
@@ -8,3 +8,4 @@ LL | impl MyTrait for Foo {
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0726`.
diff --git a/src/test/ui/impl-header-lifetime-elision/trait-elided.stderr b/src/test/ui/impl-header-lifetime-elision/trait-elided.stderr
index 735f01379f09f..15bc3f106b9c4 100644
--- a/src/test/ui/impl-header-lifetime-elision/trait-elided.stderr
+++ b/src/test/ui/impl-header-lifetime-elision/trait-elided.stderr
@@ -8,3 +8,4 @@ LL | impl MyTrait for u32 {
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0726`.
diff --git a/src/test/ui/issues/issue-10412.stderr b/src/test/ui/issues/issue-10412.stderr
index 053a93e6cd8c7..a91b3c90ebb25 100644
--- a/src/test/ui/issues/issue-10412.stderr
+++ b/src/test/ui/issues/issue-10412.stderr
@@ -67,4 +67,5 @@ LL | trait Serializable<'self, T: ?Sized> {
 
 error: aborting due to 9 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0726.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-39848.stderr b/src/test/ui/issues/issue-39848.stderr
index 08faed24bc745..feabe3814dcf9 100644
--- a/src/test/ui/issues/issue-39848.stderr
+++ b/src/test/ui/issues/issue-39848.stderr
@@ -2,16 +2,18 @@ error: expected `{`, found `foo`
   --> $DIR/issue-39848.rs:3:21
    |
 LL |         if $tgt.has_$field() {}
-   |         --          ^^^^^^--
-   |         |           |
-   |         |           expected `{`
-   |         |           help: try placing this code inside a block: `{ $field() }`
+   |         --          ^^^^^^ expected `{`
+   |         |
    |         this `if` expression has a condition, but no block
 ...
 LL |     get_opt!(bar, foo);
    |     ------------------ in this macro invocation
    |
    = note: this error originates in the macro `get_opt` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: try placing this code inside a block
+   |
+LL |         if $tgt.has_{ $field() } {}
+   |                     +          +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/label/label_break_value_illegal_uses.fixed b/src/test/ui/label/label_break_value_illegal_uses.fixed
new file mode 100644
index 0000000000000..c1d2023a21629
--- /dev/null
+++ b/src/test/ui/label/label_break_value_illegal_uses.fixed
@@ -0,0 +1,30 @@
+// run-rustfix
+#![feature(label_break_value)]
+
+// These are forbidden occurrences of label-break-value
+
+#[allow(unused_unsafe)]
+fn labeled_unsafe() {
+    unsafe {} //~ ERROR block label not supported here
+}
+
+fn labeled_if() {
+    if true {} //~ ERROR block label not supported here
+}
+
+fn labeled_else() {
+    if true {} else {} //~ ERROR block label not supported here
+}
+
+fn labeled_match() {
+    match false { //~ ERROR block label not supported here
+        _ => {}
+    }
+}
+
+fn main() {
+    labeled_unsafe();
+    labeled_if();
+    labeled_else();
+    labeled_match();
+}
diff --git a/src/test/ui/label/label_break_value_illegal_uses.rs b/src/test/ui/label/label_break_value_illegal_uses.rs
index 9d4c72410a6d1..5b20c95e581e5 100644
--- a/src/test/ui/label/label_break_value_illegal_uses.rs
+++ b/src/test/ui/label/label_break_value_illegal_uses.rs
@@ -1,21 +1,30 @@
+// run-rustfix
 #![feature(label_break_value)]
 
 // These are forbidden occurrences of label-break-value
 
+#[allow(unused_unsafe)]
 fn labeled_unsafe() {
-    unsafe 'b: {} //~ ERROR expected `{`, found `'b`
+    unsafe 'b: {} //~ ERROR block label not supported here
 }
 
 fn labeled_if() {
-    if true 'b: {} //~ ERROR expected `{`, found `'b`
+    if true 'b: {} //~ ERROR block label not supported here
 }
 
 fn labeled_else() {
-    if true {} else 'b: {} //~ ERROR expected `{`, found `'b`
+    if true {} else 'b: {} //~ ERROR block label not supported here
 }
 
 fn labeled_match() {
-    match false 'b: {} //~ ERROR expected one of `.`, `?`, `{`, or an operator
+    match false 'b: { //~ ERROR block label not supported here
+        _ => {}
+    }
 }
 
-pub fn main() {}
+fn main() {
+    labeled_unsafe();
+    labeled_if();
+    labeled_else();
+    labeled_match();
+}
diff --git a/src/test/ui/label/label_break_value_illegal_uses.stderr b/src/test/ui/label/label_break_value_illegal_uses.stderr
index a2c75882be0ca..24b733fec5301 100644
--- a/src/test/ui/label/label_break_value_illegal_uses.stderr
+++ b/src/test/ui/label/label_break_value_illegal_uses.stderr
@@ -1,38 +1,26 @@
-error: expected `{`, found `'b`
-  --> $DIR/label_break_value_illegal_uses.rs:6:12
+error: block label not supported here
+  --> $DIR/label_break_value_illegal_uses.rs:8:12
    |
 LL |     unsafe 'b: {}
-   |            ^^----
-   |            |
-   |            expected `{`
-   |            help: try placing this code inside a block: `{ 'b: {} }`
+   |            ^^^ not supported here
 
-error: expected `{`, found `'b`
-  --> $DIR/label_break_value_illegal_uses.rs:10:13
+error: block label not supported here
+  --> $DIR/label_break_value_illegal_uses.rs:12:13
    |
 LL |     if true 'b: {}
-   |     --      ^^----
-   |     |       |
-   |     |       expected `{`
-   |     |       help: try placing this code inside a block: `{ 'b: {} }`
-   |     this `if` expression has a condition, but no block
+   |             ^^^ not supported here
 
-error: expected `{`, found `'b`
-  --> $DIR/label_break_value_illegal_uses.rs:14:21
+error: block label not supported here
+  --> $DIR/label_break_value_illegal_uses.rs:16:21
    |
 LL |     if true {} else 'b: {}
-   |                     ^^----
-   |                     |
-   |                     expected `{`
-   |                     help: try placing this code inside a block: `{ 'b: {} }`
+   |                     ^^^ not supported here
 
-error: expected one of `.`, `?`, `{`, or an operator, found `'b`
-  --> $DIR/label_break_value_illegal_uses.rs:18:17
+error: block label not supported here
+  --> $DIR/label_break_value_illegal_uses.rs:20:17
    |
-LL |     match false 'b: {}
-   |     -----       ^^ expected one of `.`, `?`, `{`, or an operator
-   |     |
-   |     while parsing this match expression
+LL |     match false 'b: {
+   |                 ^^^ not supported here
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/let-else/let-else-if.stderr b/src/test/ui/let-else/let-else-if.stderr
index 38c739fd85072..a0324565673da 100644
--- a/src/test/ui/let-else/let-else-if.stderr
+++ b/src/test/ui/let-else/let-else-if.stderr
@@ -7,10 +7,10 @@ LL |     let Some(_) = Some(()) else if true {
 help: try placing this code inside a block
    |
 LL ~     let Some(_) = Some(()) else { if true {
-LL +
-LL +         return;
-LL +     } else {
-LL +         return;
+LL |
+LL |         return;
+LL |     } else {
+LL |         return;
 LL ~     } };
    |
 
diff --git a/src/test/ui/missing/missing-block-hint.stderr b/src/test/ui/missing/missing-block-hint.stderr
index 0f635817bf462..148e214e58ec1 100644
--- a/src/test/ui/missing/missing-block-hint.stderr
+++ b/src/test/ui/missing/missing-block-hint.stderr
@@ -12,10 +12,12 @@ error: expected `{`, found `bar`
 LL |         if (foo)
    |         -- this `if` expression has a condition, but no block
 LL |             bar;
-   |             ^^^-
-   |             |
-   |             expected `{`
-   |             help: try placing this code inside a block: `{ bar; }`
+   |             ^^^ expected `{`
+   |
+help: try placing this code inside a block
+   |
+LL |             { bar; }
+   |             +      +
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/block-no-opening-brace.stderr b/src/test/ui/parser/block-no-opening-brace.stderr
index e32c8bdc73acc..f232f480ce9c2 100644
--- a/src/test/ui/parser/block-no-opening-brace.stderr
+++ b/src/test/ui/parser/block-no-opening-brace.stderr
@@ -1,29 +1,41 @@
 error: expected `{`, found keyword `let`
   --> $DIR/block-no-opening-brace.rs:9:9
    |
+LL |     loop
+   |     ---- while parsing this `loop` expression
 LL |         let x = 0;
-   |         ^^^-------
-   |         |
-   |         expected `{`
-   |         help: try placing this code inside a block: `{ let x = 0; }`
+   |         ^^^ expected `{`
+   |
+help: try placing this code inside a block
+   |
+LL |         { let x = 0; }
+   |         +            +
 
 error: expected `{`, found keyword `let`
   --> $DIR/block-no-opening-brace.rs:15:9
    |
+LL |     while true
+   |     ----- ---- this `while` condition successfully parsed
+   |     |
+   |     while parsing the body of this `while` expression
 LL |         let x = 0;
-   |         ^^^-------
-   |         |
-   |         expected `{`
-   |         help: try placing this code inside a block: `{ let x = 0; }`
+   |         ^^^ expected `{`
+   |
+help: try placing this code inside a block
+   |
+LL |         { let x = 0; }
+   |         +            +
 
 error: expected `{`, found keyword `let`
   --> $DIR/block-no-opening-brace.rs:20:9
    |
 LL |         let x = 0;
-   |         ^^^-------
-   |         |
-   |         expected `{`
-   |         help: try placing this code inside a block: `{ let x = 0; }`
+   |         ^^^ expected `{`
+   |
+help: try placing this code inside a block
+   |
+LL |         { let x = 0; }
+   |         +            +
 
 error: expected expression, found reserved keyword `try`
   --> $DIR/block-no-opening-brace.rs:24:5
diff --git a/src/test/ui/parser/closure-return-syntax.stderr b/src/test/ui/parser/closure-return-syntax.stderr
index 1ccdd97730555..3d16a2067ccae 100644
--- a/src/test/ui/parser/closure-return-syntax.stderr
+++ b/src/test/ui/parser/closure-return-syntax.stderr
@@ -2,10 +2,12 @@ error: expected `{`, found `22`
   --> $DIR/closure-return-syntax.rs:5:23
    |
 LL |     let x = || -> i32 22;
-   |                       ^^
-   |                       |
-   |                       expected `{`
-   |                       help: try placing this code inside a block: `{ 22 }`
+   |                       ^^ expected `{`
+   |
+help: try placing this code inside a block
+   |
+LL |     let x = || -> i32 { 22 };
+   |                       +    +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issues/issue-62554.stderr b/src/test/ui/parser/issues/issue-62554.stderr
index 5dc9a9675bc21..3589016e1dc83 100644
--- a/src/test/ui/parser/issues/issue-62554.stderr
+++ b/src/test/ui/parser/issues/issue-62554.stderr
@@ -63,9 +63,8 @@ LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s
    |
 help: try placing this code inside a block
    |
-LL ~ fn foo(u: u8) { if u8 { macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-LL +  }
-   |
+LL | fn foo(u: u8) { if u8 { macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { }
+   |                       +                                                                    +
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/parser/issues/issue-62973.stderr b/src/test/ui/parser/issues/issue-62973.stderr
index 51d835e732988..871b5d5965134 100644
--- a/src/test/ui/parser/issues/issue-62973.stderr
+++ b/src/test/ui/parser/issues/issue-62973.stderr
@@ -50,7 +50,7 @@ error: expected one of `.`, `?`, `{`, or an operator, found `}`
   --> $DIR/issue-62973.rs:8:2
    |
 LL | fn p() { match s { v, E { [) {) }
-   |          ----- while parsing this match expression
+   |          ----- while parsing this `match` expression
 LL | 
 LL | 
    |  ^ expected one of `.`, `?`, `{`, or an operator
diff --git a/src/test/ui/parser/match-refactor-to-expr.fixed b/src/test/ui/parser/match-refactor-to-expr.fixed
index f21024235a591..423147b27aa0b 100644
--- a/src/test/ui/parser/match-refactor-to-expr.fixed
+++ b/src/test/ui/parser/match-refactor-to-expr.fixed
@@ -2,7 +2,7 @@
 
 fn main() {
     let foo =
-         //~ NOTE while parsing this match expression
+         //~ NOTE while parsing this `match` expression
         Some(4).unwrap_or(5)
         //~^ NOTE expected one of `.`, `?`, `{`, or an operator
         ; //~ NOTE unexpected token
diff --git a/src/test/ui/parser/match-refactor-to-expr.rs b/src/test/ui/parser/match-refactor-to-expr.rs
index e02d74e2f7eac..fcba5d0447e0d 100644
--- a/src/test/ui/parser/match-refactor-to-expr.rs
+++ b/src/test/ui/parser/match-refactor-to-expr.rs
@@ -2,7 +2,7 @@
 
 fn main() {
     let foo =
-        match //~ NOTE while parsing this match expression
+        match //~ NOTE while parsing this `match` expression
         Some(4).unwrap_or(5)
         //~^ NOTE expected one of `.`, `?`, `{`, or an operator
         ; //~ NOTE unexpected token
diff --git a/src/test/ui/parser/match-refactor-to-expr.stderr b/src/test/ui/parser/match-refactor-to-expr.stderr
index 15107ab9a258b..851bef8f2c7e8 100644
--- a/src/test/ui/parser/match-refactor-to-expr.stderr
+++ b/src/test/ui/parser/match-refactor-to-expr.stderr
@@ -4,7 +4,7 @@ error: expected one of `.`, `?`, `{`, or an operator, found `;`
 LL |         match
    |         -----
    |         |
-   |         while parsing this match expression
+   |         while parsing this `match` expression
    |         help: try removing this `match`
 LL |         Some(4).unwrap_or(5)
    |                             - expected one of `.`, `?`, `{`, or an operator
diff --git a/src/test/ui/parser/while-if-let-without-body.rs b/src/test/ui/parser/while-if-let-without-body.rs
new file mode 100644
index 0000000000000..063c0145c85c6
--- /dev/null
+++ b/src/test/ui/parser/while-if-let-without-body.rs
@@ -0,0 +1,13 @@
+fn main() {
+    let container = vec![Some(1), Some(2), None];
+
+    let mut i = 0;
+    while if let Some(thing) = container.get(i) {
+        //~^ NOTE while parsing the body of this `while` expression
+        //~| NOTE this `while` condition successfully parsed
+        println!("{:?}", thing);
+        i += 1;
+    }
+}
+//~^ ERROR expected `{`, found `}`
+//~| NOTE expected `{`
diff --git a/src/test/ui/parser/while-if-let-without-body.stderr b/src/test/ui/parser/while-if-let-without-body.stderr
new file mode 100644
index 0000000000000..2dac45c115d11
--- /dev/null
+++ b/src/test/ui/parser/while-if-let-without-body.stderr
@@ -0,0 +1,18 @@
+error: expected `{`, found `}`
+  --> $DIR/while-if-let-without-body.rs:11:1
+   |
+LL |       while if let Some(thing) = container.get(i) {
+   |  _____-----_-
+   | |     |
+   | |     while parsing the body of this `while` expression
+LL | |
+LL | |
+LL | |         println!("{:?}", thing);
+LL | |         i += 1;
+LL | |     }
+   | |_____- this `while` condition successfully parsed
+LL |   }
+   |   ^ expected `{`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/typeck/while-loop-block-cond.rs b/src/test/ui/typeck/while-loop-block-cond.rs
new file mode 100644
index 0000000000000..929759766f279
--- /dev/null
+++ b/src/test/ui/typeck/while-loop-block-cond.rs
@@ -0,0 +1,4 @@
+fn main() {
+    while {} {}
+    //~^ ERROR mismatched types [E0308]
+}
diff --git a/src/test/ui/typeck/while-loop-block-cond.stderr b/src/test/ui/typeck/while-loop-block-cond.stderr
new file mode 100644
index 0000000000000..598273af9cfc4
--- /dev/null
+++ b/src/test/ui/typeck/while-loop-block-cond.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/while-loop-block-cond.rs:2:11
+   |
+LL |     while {} {}
+   |           ^^ expected `bool`, found `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/unsafe/unsafe-block-without-braces.stderr b/src/test/ui/unsafe/unsafe-block-without-braces.stderr
index 895f33638f95a..44f77b99c561c 100644
--- a/src/test/ui/unsafe/unsafe-block-without-braces.stderr
+++ b/src/test/ui/unsafe/unsafe-block-without-braces.stderr
@@ -1,11 +1,15 @@
 error: expected `{`, found `std`
   --> $DIR/unsafe-block-without-braces.rs:3:9
    |
+LL |     unsafe //{
+   |     ------ while parsing this `unsafe` expression
 LL |         std::mem::transmute::<f32, u32>(1.0);
-   |         ^^^----------------------------------
-   |         |
-   |         expected `{`
-   |         help: try placing this code inside a block: `{ std::mem::transmute::<f32, u32>(1.0); }`
+   |         ^^^ expected `{`
+   |
+help: try placing this code inside a block
+   |
+LL |         { std::mem::transmute::<f32, u32>(1.0); }
+   |         +                                       +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr
index d3593d8c1eb67..ba624507c21f0 100644
--- a/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr
+++ b/src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr
@@ -30,3 +30,4 @@ LL | impl Trait for Ref {}
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0726`.