diff --git a/RELEASES.md b/RELEASES.md
index 9fd796fd775bf..8f04980e39036 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,131 @@
+Version 1.49.0 (2020-12-31)
+============================
+
+Language
+-----------------------
+
+- [Unions can now implement `Drop`, and you can now have a field in a union
+  with `ManuallyDrop<T>`.][77547]
+- [You can now cast uninhabited enums to integers.][76199]
+- [You can now bind by reference and by move in patterns.][76119] This
+  allows you to selectively borrow individual components of a type. E.g.
+  ```rust
+  #[derive(Debug)]
+  struct Person {
+      name: String,
+      age: u8,
+  }
+
+  let person = Person {
+      name: String::from("Alice"),
+      age: 20,
+  };
+
+  // `name` is moved out of person, but `age` is referenced.
+  let Person { name, ref age } = person;
+  println!("{} {}", name, age);
+  ```
+
+Compiler
+-----------------------
+
+- [Added tier 1\* support for `aarch64-unknown-linux-gnu`.][78228]
+- [Added tier 2 support for `aarch64-apple-darwin`.][75991]
+- [Added tier 2 support for `aarch64-pc-windows-msvc`.][75914]
+- [Added tier 3 support for `mipsel-unknown-none`.][78676]
+- [Raised the minimum supported LLVM version to LLVM 9.][78848]
+- [Output from threads spawned in tests is now captured.][78227]
+- [Change os and vendor values to "none" and "unknown" for some targets][78951]
+
+\* Refer to Rust's [platform support page][forge-platform-support] for more
+information on Rust's tiered platform support.
+
+Libraries
+-----------------------
+
+- [`RangeInclusive` now checks for exhaustion when calling `contains` and indexing.][78109]
+- [`ToString::to_string` now no longer shrinks the internal buffer in the default implementation.][77997]
+- [`ops::{Index, IndexMut}` are now implemented for fixed sized arrays of any length.][74989]
+
+Stabilized APIs
+---------------
+
+- [`slice::select_nth_unstable`]
+- [`slice::select_nth_unstable_by`]
+- [`slice::select_nth_unstable_by_key`]
+
+The following previously stable methods are now `const`.
+
+- [`Poll::is_ready`]
+- [`Poll::is_pending`]
+
+Cargo
+-----------------------
+- [Building a crate with `cargo-package` should now be independently reproducible.][cargo/8864]
+- [`cargo-tree` now marks proc-macro crates.][cargo/8765]
+- [Added `CARGO_PRIMARY_PACKAGE` build-time environment variable.][cargo/8758] This
+  variable will be set if the crate being built is one the user selected to build, either
+  with `-p` or through defaults.
+- [You can now use glob patterns when specifying packages & targets.][cargo/8752]
+
+
+Compatibility Notes
+-------------------
+
+- [Demoted `i686-unknown-freebsd` from host tier 2 to target tier 2 support.][78746]
+- [Macros that end with a semi-colon are now treated as statements even if they expand to nothing.][78376]
+- [Rustc will now check for the validity of some built-in attributes on enum variants.][77015]
+  Previously such invalid or unused attributes could be ignored.
+- Leading whitespace is stripped more uniformly in documentation comments, which may change behavior. You
+  read [this post about the changes][rustdoc-ws-post] for more details.
+- [Trait bounds are no longer inferred for associated types.][79904]
+
+Internal Only
+-------------
+These changes provide no direct user facing benefits, but represent significant
+improvements to the internals and overall performance of rustc and
+related tools.
+
+- [rustc's internal crates are now compiled using the `initial-exec` Thread
+  Local Storage model.][78201]
+- [Calculate visibilities once in resolve.][78077]
+- [Added `system` to the `llvm-libunwind` bootstrap config option.][77703]
+- [Added `--color` for configuring terminal color support to bootstrap.][79004]
+
+
+[75991]: https://github.com/rust-lang/rust/pull/75991
+[78951]: https://github.com/rust-lang/rust/pull/78951
+[78848]: https://github.com/rust-lang/rust/pull/78848
+[78746]: https://github.com/rust-lang/rust/pull/78746
+[78376]: https://github.com/rust-lang/rust/pull/78376
+[78228]: https://github.com/rust-lang/rust/pull/78228
+[78227]: https://github.com/rust-lang/rust/pull/78227
+[78201]: https://github.com/rust-lang/rust/pull/78201
+[78109]: https://github.com/rust-lang/rust/pull/78109
+[78077]: https://github.com/rust-lang/rust/pull/78077
+[77997]: https://github.com/rust-lang/rust/pull/77997
+[77703]: https://github.com/rust-lang/rust/pull/77703
+[77547]: https://github.com/rust-lang/rust/pull/77547
+[77015]: https://github.com/rust-lang/rust/pull/77015
+[76199]: https://github.com/rust-lang/rust/pull/76199
+[76119]: https://github.com/rust-lang/rust/pull/76119
+[75914]: https://github.com/rust-lang/rust/pull/75914
+[74989]: https://github.com/rust-lang/rust/pull/74989
+[79004]: https://github.com/rust-lang/rust/pull/79004
+[78676]: https://github.com/rust-lang/rust/pull/78676
+[79904]: https://github.com/rust-lang/rust/issues/79904
+[cargo/8864]: https://github.com/rust-lang/cargo/pull/8864
+[cargo/8765]: https://github.com/rust-lang/cargo/pull/8765
+[cargo/8758]: https://github.com/rust-lang/cargo/pull/8758
+[cargo/8752]: https://github.com/rust-lang/cargo/pull/8752
+[`slice::select_nth_unstable`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.select_nth_unstable
+[`slice::select_nth_unstable_by`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.select_nth_unstable_by
+[`slice::select_nth_unstable_by_key`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.select_nth_unstable_by_key
+[`hint::spin_loop`]: https://doc.rust-lang.org/stable/std/hint/fn.spin_loop.html
+[`Poll::is_ready`]: https://doc.rust-lang.org/stable/std/task/enum.Poll.html#method.is_ready
+[`Poll::is_pending`]: https://doc.rust-lang.org/stable/std/task/enum.Poll.html#method.is_pending
+[rustdoc-ws-post]: https://blog.guillaume-gomez.fr/articles/2020-11-11+New+doc+comment+handling+in+rustdoc
+
 Version 1.48.0 (2020-11-19)
 ==========================
 
@@ -10,7 +138,7 @@ Language
 Compiler
 --------
 - [Stabilised the `-C link-self-contained=<yes|no>` compiler flag.][76158] This tells
-  `rustc` whether to link its own C runtime and libraries or to rely on a external 
+  `rustc` whether to link its own C runtime and libraries or to rely on a external
   linker to find them. (Supported only on `windows-gnu`, `linux-musl`, and `wasi` platforms.)
 - [You can now use `-C target-feature=+crt-static` on `linux-gnu` targets.][77386]
   Note: If you're using cargo you must explicitly pass the `--target` flag.
@@ -82,7 +210,7 @@ Compatibility Notes
 - [Foreign exceptions are now caught by `catch_unwind` and will cause an abort.][70212]
   Note: This behaviour is not guaranteed and is still considered undefined behaviour,
   see the [`catch_unwind`] documentation for further information.
-  
+
 
 
 Internal Only
@@ -102,7 +230,7 @@ related tools.
 [76030]: https://github.com/rust-lang/rust/pull/76030/
 [70212]: https://github.com/rust-lang/rust/pull/70212/
 [27675]: https://github.com/rust-lang/rust/issues/27675/
-[54121]: https://github.com/rust-lang/rust/issues/54121/  
+[54121]: https://github.com/rust-lang/rust/issues/54121/
 [71274]: https://github.com/rust-lang/rust/pull/71274/
 [77386]: https://github.com/rust-lang/rust/pull/77386/
 [77153]: https://github.com/rust-lang/rust/pull/77153/
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 45cc6d894e9e8..b0d243985751a 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -167,10 +167,7 @@ pub enum GenericArgs {
 
 impl GenericArgs {
     pub fn is_angle_bracketed(&self) -> bool {
-        match *self {
-            AngleBracketed(..) => true,
-            _ => false,
-        }
+        matches!(self, AngleBracketed(..))
     }
 
     pub fn span(&self) -> Span {
@@ -629,10 +626,7 @@ impl Pat {
 
     /// Is this a `..` pattern?
     pub fn is_rest(&self) -> bool {
-        match self.kind {
-            PatKind::Rest => true,
-            _ => false,
-        }
+        matches!(self.kind, PatKind::Rest)
     }
 }
 
@@ -852,10 +846,7 @@ impl BinOpKind {
         }
     }
     pub fn lazy(&self) -> bool {
-        match *self {
-            BinOpKind::And | BinOpKind::Or => true,
-            _ => false,
-        }
+        matches!(self, BinOpKind::And | BinOpKind::Or)
     }
 
     pub fn is_comparison(&self) -> bool {
@@ -963,17 +954,11 @@ impl Stmt {
     }
 
     pub fn is_item(&self) -> bool {
-        match self.kind {
-            StmtKind::Item(_) => true,
-            _ => false,
-        }
+        matches!(self.kind, StmtKind::Item(_))
     }
 
     pub fn is_expr(&self) -> bool {
-        match self.kind {
-            StmtKind::Expr(_) => true,
-            _ => false,
-        }
+        matches!(self.kind, StmtKind::Expr(_))
     }
 }
 
@@ -1652,26 +1637,17 @@ pub enum LitKind {
 impl LitKind {
     /// Returns `true` if this literal is a string.
     pub fn is_str(&self) -> bool {
-        match *self {
-            LitKind::Str(..) => true,
-            _ => false,
-        }
+        matches!(self, LitKind::Str(..))
     }
 
     /// Returns `true` if this literal is byte literal string.
     pub fn is_bytestr(&self) -> bool {
-        match self {
-            LitKind::ByteStr(_) => true,
-            _ => false,
-        }
+        matches!(self, LitKind::ByteStr(_))
     }
 
     /// Returns `true` if this is a numeric literal.
     pub fn is_numeric(&self) -> bool {
-        match *self {
-            LitKind::Int(..) | LitKind::Float(..) => true,
-            _ => false,
-        }
+        matches!(self, LitKind::Int(..) | LitKind::Float(..))
     }
 
     /// Returns `true` if this literal has no suffix.
@@ -2237,10 +2213,7 @@ impl FnDecl {
         self.inputs.get(0).map_or(false, Param::is_self)
     }
     pub fn c_variadic(&self) -> bool {
-        self.inputs.last().map_or(false, |arg| match arg.ty.kind {
-            TyKind::CVarArgs => true,
-            _ => false,
-        })
+        self.inputs.last().map_or(false, |arg| matches!(arg.ty.kind, TyKind::CVarArgs))
     }
 }
 
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 19c7c479f0429..726ae5e51f7a6 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -234,10 +234,7 @@ impl MetaItem {
     }
 
     pub fn is_word(&self) -> bool {
-        match self.kind {
-            MetaItemKind::Word => true,
-            _ => false,
-        }
+        matches!(self.kind, MetaItemKind::Word)
     }
 
     pub fn has_name(&self, name: Symbol) -> bool {
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index a74464937c8b4..cd1e444bcf72a 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -130,10 +130,7 @@ impl LitKind {
     }
 
     crate fn may_have_suffix(self) -> bool {
-        match self {
-            Integer | Float | Err => true,
-            _ => false,
-        }
+        matches!(self, Integer | Float | Err)
     }
 }
 
@@ -305,10 +302,7 @@ impl TokenKind {
     }
 
     pub fn should_end_const_arg(&self) -> bool {
-        match self {
-            Gt | Ge | BinOp(Shr) | BinOpEq(Shr) => true,
-            _ => false,
-        }
+        matches!(self, Gt | Ge | BinOp(Shr) | BinOpEq(Shr))
     }
 }
 
@@ -346,18 +340,21 @@ impl Token {
     }
 
     pub fn is_op(&self) -> bool {
-        match self.kind {
-            OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
-            | Lifetime(..) | Interpolated(..) | Eof => false,
-            _ => true,
-        }
+        !matches!(
+            self.kind,
+            OpenDelim(..)
+                | CloseDelim(..)
+                | Literal(..)
+                | DocComment(..)
+                | Ident(..)
+                | Lifetime(..)
+                | Interpolated(..)
+                | Eof
+        )
     }
 
     pub fn is_like_plus(&self) -> bool {
-        match self.kind {
-            BinOp(Plus) | BinOpEq(Plus) => true,
-            _ => false,
-        }
+        matches!(self.kind, BinOp(Plus) | BinOpEq(Plus))
     }
 
     /// Returns `true` if the token can appear at the start of an expression.
@@ -379,13 +376,10 @@ impl Token {
             ModSep                            | // global path
             Lifetime(..)                      | // labeled loop
             Pound                             => true, // expression attributes
-            Interpolated(ref nt) => match **nt {
-                NtLiteral(..) |
+            Interpolated(ref nt) => matches!(**nt, NtLiteral(..) |
                 NtExpr(..)    |
                 NtBlock(..)   |
-                NtPath(..) => true,
-                _ => false,
-            },
+                NtPath(..)),
             _ => false,
         }
     }
@@ -405,10 +399,7 @@ impl Token {
             Lifetime(..)                | // lifetime bound in trait object
             Lt | BinOp(Shl)             | // associated path
             ModSep                      => true, // global path
-            Interpolated(ref nt) => match **nt {
-                NtTy(..) | NtPath(..) => true,
-                _ => false,
-            },
+            Interpolated(ref nt) => matches!(**nt, NtTy(..) | NtPath(..)),
             _ => false,
         }
     }
@@ -417,10 +408,7 @@ impl Token {
     pub fn can_begin_const_arg(&self) -> bool {
         match self.kind {
             OpenDelim(Brace) => true,
-            Interpolated(ref nt) => match **nt {
-                NtExpr(..) | NtBlock(..) | NtLiteral(..) => true,
-                _ => false,
-            },
+            Interpolated(ref nt) => matches!(**nt, NtExpr(..) | NtBlock(..) | NtLiteral(..)),
             _ => self.can_begin_literal_maybe_minus(),
         }
     }
@@ -436,10 +424,7 @@ impl Token {
 
     /// Returns `true` if the token is any literal.
     pub fn is_lit(&self) -> bool {
-        match self.kind {
-            Literal(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, Literal(..))
     }
 
     /// Returns `true` if the token is any literal, a minus (which can prefix a literal,
diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs
index 60422a2e57392..90786520fe802 100644
--- a/compiler/rustc_ast/src/util/classify.rs
+++ b/compiler/rustc_ast/src/util/classify.rs
@@ -12,14 +12,14 @@ use crate::ast;
 ///      |x| 5
 /// isn't parsed as (if true {...} else {...} | x) | 5
 pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
-    match e.kind {
+    !matches!(
+        e.kind,
         ast::ExprKind::If(..)
-        | ast::ExprKind::Match(..)
-        | ast::ExprKind::Block(..)
-        | ast::ExprKind::While(..)
-        | ast::ExprKind::Loop(..)
-        | ast::ExprKind::ForLoop(..)
-        | ast::ExprKind::TryBlock(..) => false,
-        _ => true,
-    }
+            | ast::ExprKind::Match(..)
+            | ast::ExprKind::Block(..)
+            | ast::ExprKind::While(..)
+            | ast::ExprKind::Loop(..)
+            | ast::ExprKind::ForLoop(..)
+            | ast::ExprKind::TryBlock(..)
+    )
 }
diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs
index 5d994c903795b..542a330a03141 100644
--- a/compiler/rustc_ast/src/util/comments.rs
+++ b/compiler/rustc_ast/src/util/comments.rs
@@ -180,10 +180,8 @@ pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comme
             }
             rustc_lexer::TokenKind::BlockComment { doc_style, .. } => {
                 if doc_style.is_none() {
-                    let code_to_the_right = match text[pos + token.len..].chars().next() {
-                        Some('\r' | '\n') => false,
-                        _ => true,
-                    };
+                    let code_to_the_right =
+                        !matches!(text[pos + token.len..].chars().next(), Some('\r' | '\n'));
                     let style = match (code_to_the_left, code_to_the_right) {
                         (_, true) => CommentStyle::Mixed,
                         (false, false) => CommentStyle::Isolated,
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index 957c8035399a2..ca1226b445d97 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -38,10 +38,9 @@ pub fn expand_deriving_clone(
             | ItemKind::Enum(_, Generics { ref params, .. }) => {
                 let container_id = cx.current_expansion.id.expn_data().parent;
                 if cx.resolver.has_derive_copy(container_id)
-                    && !params.iter().any(|param| match param.kind {
-                        ast::GenericParamKind::Type { .. } => true,
-                        _ => false,
-                    })
+                    && !params
+                        .iter()
+                        .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
                 {
                     bounds = vec![];
                     is_shallow = true;
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 6531e68be9cdc..e78d1368b357e 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -404,12 +404,10 @@ impl<'a> TraitDef<'a> {
                 let has_no_type_params = match item.kind {
                     ast::ItemKind::Struct(_, ref generics)
                     | ast::ItemKind::Enum(_, ref generics)
-                    | ast::ItemKind::Union(_, ref generics) => {
-                        !generics.params.iter().any(|param| match param.kind {
-                            ast::GenericParamKind::Type { .. } => true,
-                            _ => false,
-                        })
-                    }
+                    | ast::ItemKind::Union(_, ref generics) => !generics
+                        .params
+                        .iter()
+                        .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })),
                     _ => unreachable!(),
                 };
                 let container_id = cx.current_expansion.id.expn_data().parent;
@@ -868,7 +866,7 @@ impl<'a> MethodDef<'a> {
                 Self_ if nonstatic => {
                     self_args.push(arg_expr);
                 }
-                Ptr(ref ty, _) if (if let Self_ = **ty { true } else { false }) && nonstatic => {
+                Ptr(ref ty, _) if matches!(**ty, Self_) && nonstatic => {
                     self_args.push(cx.expr_deref(trait_.span, arg_expr))
                 }
                 _ => {
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 550524e652af7..85ca1da6f1daa 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1044,10 +1044,7 @@ pub fn expand_preparsed_format_args(
 
     let numbered_position_args = pieces.iter().any(|arg: &parse::Piece<'_>| match *arg {
         parse::String(_) => false,
-        parse::NextArgument(arg) => match arg.position {
-            parse::Position::ArgumentIs(_) => true,
-            _ => false,
-        },
+        parse::NextArgument(arg) => matches!(arg.position, parse::Position::ArgumentIs(_)),
     });
 
     cx.build_index_map();
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs
index f00dfd1241fbb..0496c72cb0050 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign.rs
@@ -580,10 +580,7 @@ pub mod printf {
     }
 
     fn is_flag(c: &char) -> bool {
-        match c {
-            '0' | '-' | '+' | ' ' | '#' | '\'' => true,
-            _ => false,
-        }
+        matches!(c, '0' | '-' | '+' | ' ' | '#' | '\'')
     }
 
     #[cfg(test)]
diff --git a/compiler/rustc_builtin_macros/src/llvm_asm.rs b/compiler/rustc_builtin_macros/src/llvm_asm.rs
index db73fdbe24ff5..d203b5bc5429e 100644
--- a/compiler/rustc_builtin_macros/src/llvm_asm.rs
+++ b/compiler/rustc_builtin_macros/src/llvm_asm.rs
@@ -87,9 +87,11 @@ fn parse_inline_asm<'a>(
     // parsed as `llvm_asm!(z)` with `z = "x": y` which is type ascription.
     let first_colon = tts
         .trees()
-        .position(|tt| match tt {
-            tokenstream::TokenTree::Token(Token { kind: token::Colon | token::ModSep, .. }) => true,
-            _ => false,
+        .position(|tt| {
+            matches!(
+                tt,
+                tokenstream::TokenTree::Token(Token { kind: token::Colon | token::ModSep, .. })
+            )
         })
         .unwrap_or(tts.len());
     let mut p = cx.new_parser_from_tts(tts.trees().skip(first_colon).collect());
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index 4e91436199a53..7582d9805390e 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -256,10 +256,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
         // we're just not interested in this item.
         //
         // If we find one, try to locate a `#[proc_macro_derive]` attribute on it.
-        let is_fn = match item.kind {
-            ast::ItemKind::Fn(..) => true,
-            _ => false,
-        };
+        let is_fn = matches!(item.kind, ast::ItemKind::Fn(..));
 
         let mut found_attr: Option<&'a ast::Attribute> = None;
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 44bb0deeae97f..57e49ba8d1a56 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -112,12 +112,12 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
             };
 
             // Allow uses of projections that are ZSTs or from scalar fields.
-            let is_consume = match context {
+            let is_consume = matches!(
+                context,
                 PlaceContext::NonMutatingUse(
                     NonMutatingUseContext::Copy | NonMutatingUseContext::Move,
-                ) => true,
-                _ => false,
-            };
+                )
+            );
             if is_consume {
                 let base_ty =
                     mir::Place::ty_from(place_ref.local, proj_base, self.fx.mir, cx.tcx());
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index 4d3217a9c0bd9..0958afa03082a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -132,10 +132,7 @@ impl Visitor<'tcx> for TypeParamSpanVisitor<'tcx> {
                 [segment]
                     if segment
                         .res
-                        .map(|res| match res {
-                            Res::SelfTy(_, _) | Res::Def(hir::def::DefKind::TyParam, _) => true,
-                            _ => false,
-                        })
+                        .map(|res| matches!(res, Res::SelfTy(_, _) | Res::Def(hir::def::DefKind::TyParam, _)))
                         .unwrap_or(false) =>
                 {
                     self.types.push(path.span);
diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs
index 32f73237dd410..728dc2de37031 100644
--- a/compiler/rustc_infer/src/infer/free_regions.rs
+++ b/compiler/rustc_infer/src/infer/free_regions.rs
@@ -93,10 +93,7 @@ impl<'tcx> FreeRegionMap<'tcx> {
 
     /// True for free regions other than `'static`.
     pub fn is_free(&self, r: Region<'_>) -> bool {
-        match *r {
-            ty::ReEarlyBound(_) | ty::ReFree(_) => true,
-            _ => false,
-        }
+        matches!(r, ty::ReEarlyBound(_) | ty::ReFree(_))
     }
 
     /// True if `r` is a free region or static of the sort that this
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index d7b2ce7ee2083..ab34cda8cc18f 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -393,10 +393,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                 if self.expand_node(a_region, b_vid, b_data) {
                     changes.push(b_vid);
                 }
-                match *b_data {
-                    VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
-                    _ => true,
-                }
+                !matches!(b_data, VarValue::Value(ReStatic) | VarValue::ErrorValue)
             });
         }
     }
@@ -972,11 +969,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
             }
 
             VerifyBound::IsEmpty => {
-                if let ty::ReEmpty(_) = min {
-                    true
-                } else {
-                    false
-                }
+                matches!(min, ty::ReEmpty(_))
             }
 
             VerifyBound::AnyBound(bs) => {
diff --git a/compiler/rustc_middle/src/hir/map/blocks.rs b/compiler/rustc_middle/src/hir/map/blocks.rs
index 6f572a4875f86..9d392c7b26bf7 100644
--- a/compiler/rustc_middle/src/hir/map/blocks.rs
+++ b/compiler/rustc_middle/src/hir/map/blocks.rs
@@ -42,37 +42,25 @@ trait MaybeFnLike {
 
 impl MaybeFnLike for hir::Item<'_> {
     fn is_fn_like(&self) -> bool {
-        match self.kind {
-            hir::ItemKind::Fn(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, hir::ItemKind::Fn(..))
     }
 }
 
 impl MaybeFnLike for hir::ImplItem<'_> {
     fn is_fn_like(&self) -> bool {
-        match self.kind {
-            hir::ImplItemKind::Fn(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, hir::ImplItemKind::Fn(..))
     }
 }
 
 impl MaybeFnLike for hir::TraitItem<'_> {
     fn is_fn_like(&self) -> bool {
-        match self.kind {
-            hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true,
-            _ => false,
-        }
+        matches!(self.kind, hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)))
     }
 }
 
 impl MaybeFnLike for hir::Expr<'_> {
     fn is_fn_like(&self) -> bool {
-        match self.kind {
-            hir::ExprKind::Closure(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, hir::ExprKind::Closure(..))
     }
 }
 
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index 8a6bf9dff7b6f..95096d0fb719c 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -118,17 +118,11 @@ impl CoverageKind {
     }
 
     pub fn is_counter(&self) -> bool {
-        match self {
-            Self::Counter { .. } => true,
-            _ => false,
-        }
+        matches!(self, Self::Counter { .. })
     }
 
     pub fn is_expression(&self) -> bool {
-        match self {
-            Self::Expression { .. } => true,
-            _ => false,
-        }
+        matches!(self, Self::Expression { .. })
     }
 
     pub fn is_unreachable(&self) -> bool {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 1b5f7a2c12e72..1e836d0a84253 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -576,11 +576,13 @@ rustc_queries! {
             desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) }
         }
 
-        query impl_trait_ref(key: DefId) -> Option<ty::TraitRef<'tcx>> {
-            desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(key) }
+        /// Given an `impl_id`, return the trait it implements.
+        /// Return `None` if this is an inherent impl.
+        query impl_trait_ref(impl_id: DefId) -> Option<ty::TraitRef<'tcx>> {
+            desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) }
         }
-        query impl_polarity(key: DefId) -> ty::ImplPolarity {
-            desc { |tcx| "computing implementation polarity of `{}`", tcx.def_path_str(key) }
+        query impl_polarity(impl_id: DefId) -> ty::ImplPolarity {
+            desc { |tcx| "computing implementation polarity of `{}`", tcx.def_path_str(impl_id) }
         }
 
         query issue33140_self_ty(key: DefId) -> Option<ty::Ty<'tcx>> {
@@ -917,8 +919,10 @@ rustc_queries! {
     }
 
     TypeChecking {
-        query trait_of_item(def_id: DefId) -> Option<DefId> {
-            desc { |tcx| "finding trait defining `{}`", tcx.def_path_str(def_id) }
+        /// Given an `associated_item`, find the trait it belongs to.
+        /// Return `None` if the `DefId` is not an associated item.
+        query trait_of_item(associated_item: DefId) -> Option<DefId> {
+            desc { |tcx| "finding trait defining `{}`", tcx.def_path_str(associated_item) }
         }
     }
 
@@ -948,20 +952,29 @@ rustc_queries! {
     }
 
     TypeChecking {
-        query all_local_trait_impls(key: CrateNum) -> &'tcx BTreeMap<DefId, Vec<hir::HirId>> {
+        /// Return all `impl` blocks in the current crate.
+        ///
+        /// To allow caching this between crates, you must pass in [`LOCAL_CRATE`] as the crate number.
+        /// Passing in any other crate will cause an ICE.
+        ///
+        /// [`LOCAL_CRATE`]: rustc_hir::def_id::LOCAL_CRATE
+        query all_local_trait_impls(local_crate: CrateNum) -> &'tcx BTreeMap<DefId, Vec<hir::HirId>> {
             desc { "local trait impls" }
         }
-        query trait_impls_of(key: DefId) -> ty::trait_def::TraitImpls {
+
+        /// Given a trait `trait_id`, return all known `impl` blocks.
+        query trait_impls_of(trait_id: DefId) -> ty::trait_def::TraitImpls {
             storage(ArenaCacheSelector<'tcx>)
-            desc { |tcx| "trait impls of `{}`", tcx.def_path_str(key) }
+            desc { |tcx| "trait impls of `{}`", tcx.def_path_str(trait_id) }
         }
-        query specialization_graph_of(key: DefId) -> specialization_graph::Graph {
+
+        query specialization_graph_of(trait_id: DefId) -> specialization_graph::Graph {
             storage(ArenaCacheSelector<'tcx>)
-            desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(key) }
+            desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) }
             cache_on_disk_if { true }
         }
-        query object_safety_violations(key: DefId) -> &'tcx [traits::ObjectSafetyViolation] {
-            desc { |tcx| "determine object safety of trait `{}`", tcx.def_path_str(key) }
+        query object_safety_violations(trait_id: DefId) -> &'tcx [traits::ObjectSafetyViolation] {
+            desc { |tcx| "determine object safety of trait `{}`", tcx.def_path_str(trait_id) }
         }
 
         /// Gets the ParameterEnvironment for a given item; this environment
@@ -969,6 +982,7 @@ rustc_queries! {
         /// type-checking etc, and it does not normalize specializable
         /// associated types. This is almost always what you want,
         /// unless you are doing MIR optimizations, in which case you
+        /// might want to use `reveal_all()` method to change modes.
         query param_env(def_id: DefId) -> ty::ParamEnv<'tcx> {
             desc { |tcx| "computing normalized predicates of `{}`", tcx.def_path_str(def_id) }
         }
@@ -1229,10 +1243,15 @@ rustc_queries! {
     }
 
     TypeChecking {
+        /// Given a crate and a trait, look up all impls of that trait in the crate.
+        /// Return `(impl_id, self_ty)`.
         query implementations_of_trait(_: (CrateNum, DefId))
             -> &'tcx [(DefId, Option<ty::fast_reject::SimplifiedType>)] {
             desc { "looking up implementations of a trait in a crate" }
         }
+
+        /// Given a crate, look up all trait impls in that crate.
+        /// Return `(impl_id, self_ty)`.
         query all_trait_implementations(_: CrateNum)
             -> &'tcx [(DefId, Option<ty::fast_reject::SimplifiedType>)] {
             desc { "looking up all (?) trait implementations" }
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index fc02e78b2fadf..fe20925b38798 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -647,14 +647,11 @@ impl<T> Trait<T> for X {
         let current_method_ident = body_owner.and_then(|n| n.ident()).map(|i| i.name);
 
         // We don't want to suggest calling an assoc fn in a scope where that isn't feasible.
-        let callable_scope = match body_owner {
-            Some(
+        let callable_scope = matches!(body_owner, Some(
                 hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })
                 | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. })
                 | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }),
-            ) => true,
-            _ => false,
-        };
+            ));
         let impl_comparison = matches!(
             cause_code,
             ObligationCauseCode::CompareImplMethodObligation { .. }
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 1f70fdb5ae30b..09281799041ee 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -40,11 +40,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let expr_span = expr.span;
         let source_info = this.source_info(expr_span);
 
-        let expr_is_block_or_scope = match expr.kind {
-            ExprKind::Block { .. } => true,
-            ExprKind::Scope { .. } => true,
-            _ => false,
-        };
+        let expr_is_block_or_scope = matches!(expr.kind, ExprKind::Block { .. } | ExprKind::Scope { .. });
 
         let schedule_drop = move |this: &mut Self| {
             if let Some(drop_scope) = scope {
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 4510e86e0341f..60a47ca12b868 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -501,10 +501,9 @@ impl<'a> Parser<'a> {
     pub(super) fn expr_is_valid_const_arg(&self, expr: &P<rustc_ast::Expr>) -> bool {
         match &expr.kind {
             ast::ExprKind::Block(_, _) | ast::ExprKind::Lit(_) => true,
-            ast::ExprKind::Unary(ast::UnOp::Neg, expr) => match &expr.kind {
-                ast::ExprKind::Lit(_) => true,
-                _ => false,
-            },
+            ast::ExprKind::Unary(ast::UnOp::Neg, expr) => {
+                matches!(expr.kind, ast::ExprKind::Lit(_))
+            }
             // We can only resolve single-segment paths at the moment, because multi-segment paths
             // require type-checking: see `visit_generic_arg` in `src/librustc_resolve/late.rs`.
             ast::ExprKind::Path(None, path)
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 00152878d6d9b..c4fb0cf5b28dc 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -23,18 +23,18 @@ use rustc_span::symbol::{sym, Symbol};
 // function, then we should explore its block to check for codes that
 // may need to be marked as live.
 fn should_explore(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
-    match tcx.hir().find(hir_id) {
+    matches!(
+        tcx.hir().find(hir_id),
         Some(
             Node::Item(..)
-            | Node::ImplItem(..)
-            | Node::ForeignItem(..)
-            | Node::TraitItem(..)
-            | Node::Variant(..)
-            | Node::AnonConst(..)
-            | Node::Pat(..),
-        ) => true,
-        _ => false,
-    }
+                | Node::ImplItem(..)
+                | Node::ForeignItem(..)
+                | Node::TraitItem(..)
+                | Node::Variant(..)
+                | Node::AnonConst(..)
+                | Node::Pat(..),
+        )
+    )
 }
 
 struct MarkSymbolVisitor<'tcx> {
@@ -500,16 +500,16 @@ struct DeadVisitor<'tcx> {
 
 impl DeadVisitor<'tcx> {
     fn should_warn_about_item(&mut self, item: &hir::Item<'_>) -> bool {
-        let should_warn = match item.kind {
+        let should_warn = matches!(
+            item.kind,
             hir::ItemKind::Static(..)
-            | hir::ItemKind::Const(..)
-            | hir::ItemKind::Fn(..)
-            | hir::ItemKind::TyAlias(..)
-            | hir::ItemKind::Enum(..)
-            | hir::ItemKind::Struct(..)
-            | hir::ItemKind::Union(..) => true,
-            _ => false,
-        };
+                | hir::ItemKind::Const(..)
+                | hir::ItemKind::Fn(..)
+                | hir::ItemKind::TyAlias(..)
+                | hir::ItemKind::Enum(..)
+                | hir::ItemKind::Struct(..)
+                | hir::ItemKind::Union(..)
+        );
         should_warn && !self.symbol_is_live(item.hir_id)
     }
 
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 86ce35c6d9909..54e3cc69aea9a 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -367,10 +367,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
     }
 
     fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
-        let is_shorthand = match param.pat.kind {
-            rustc_hir::PatKind::Struct(..) => true,
-            _ => false,
-        };
+        let is_shorthand = matches!(param.pat.kind, rustc_hir::PatKind::Struct(..));
         param.pat.each_binding(|_bm, hir_id, _x, ident| {
             let var = if is_shorthand {
                 Local(LocalInfo { id: hir_id, name: ident.name, is_shorthand: true })
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 3b4249a93e1fb..708563f2ee981 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -842,11 +842,9 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
         let macro_module_def_id =
             ty::DefIdTree::parent(self.tcx, self.tcx.hir().local_def_id(md.hir_id).to_def_id())
                 .unwrap();
-        // FIXME(#71104) Should really be using just `as_local_hir_id` but
-        // some `DefId` do not seem to have a corresponding HirId.
         let hir_id = macro_module_def_id
             .as_local()
-            .and_then(|def_id| self.tcx.hir().opt_local_def_id_to_hir_id(def_id));
+            .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
         let mut module_id = match hir_id {
             Some(module_id) if self.tcx.hir().is_hir_id_module(module_id) => module_id,
             // `module_id` doesn't correspond to a `mod`, return early (#63164, #65252).
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index d253a9dda861b..7d8f112af8a51 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1653,17 +1653,14 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
         for missing in &self.missing_named_lifetime_spots {
             match missing {
                 MissingLifetimeSpot::Generics(generics) => {
-                    let (span, sugg) = if let Some(param) =
-                        generics.params.iter().find(|p| match p.kind {
-                            hir::GenericParamKind::Type {
-                                synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
-                                ..
-                            } => false,
-                            hir::GenericParamKind::Lifetime {
-                                kind: hir::LifetimeParamKind::Elided,
-                            } => false,
-                            _ => true,
-                        }) {
+                    let (span, sugg) = if let Some(param) = generics.params.iter().find(|p| {
+                        !matches!(p.kind, hir::GenericParamKind::Type {
+                            synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
+                            ..
+                        } | hir::GenericParamKind::Lifetime {
+                            kind: hir::LifetimeParamKind::Elided,
+                        })
+                    }) {
                         (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref))
                     } else {
                         suggests_in_band = true;
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 6ab16886ed237..fc6a9a7f20972 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -35,10 +35,7 @@ pub enum AutoTraitResult<A> {
 #[allow(dead_code)]
 impl<A> AutoTraitResult<A> {
     fn is_auto(&self) -> bool {
-        match *self {
-            AutoTraitResult::PositiveImpl(_) | AutoTraitResult::NegativeImpl => true,
-            _ => false,
-        }
+        matches!(self, AutoTraitResult::PositiveImpl(_) | AutoTraitResult::NegativeImpl)
     }
 }
 
@@ -601,10 +598,7 @@ impl AutoTraitFinder<'tcx> {
     }
 
     fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool {
-        match *p.ty().skip_binder().kind() {
-            ty::Projection(proj) if proj == p.skip_binder().projection_ty => true,
-            _ => false,
-        }
+        matches!(*p.ty().skip_binder().kind(), ty::Projection(proj) if proj == p.skip_binder().projection_ty)
     }
 
     fn evaluate_nested_obligations(
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 9324d55ac1b2d..99b96f6096476 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -193,10 +193,8 @@ fn overlap_within_probe(
     let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes();
     debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes);
 
-    let involves_placeholder = match selcx.infcx().region_constraints_added_in_snapshot(snapshot) {
-        Some(true) => true,
-        _ => false,
-    };
+    let involves_placeholder =
+        matches!(selcx.infcx().region_constraints_added_in_snapshot(snapshot), Some(true));
 
     Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder })
 }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 9feba7bfc492f..1d82e732907ba 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -861,10 +861,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
         let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
             let arg_length = arguments.len();
-            let distinct = match &other[..] {
-                &[ArgKind::Tuple(..)] => true,
-                _ => false,
-            };
+            let distinct = matches!(other, &[ArgKind::Tuple(..)]);
             match (arg_length, arguments.get(0)) {
                 (1, Some(&ArgKind::Tuple(_, ref fields))) => {
                     format!("a single {}-tuple as argument", fields.len())
@@ -1201,12 +1198,9 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
                     normalized_ty, data.ty
                 );
 
-                let is_normalized_ty_expected = match &obligation.cause.code {
-                    ObligationCauseCode::ItemObligation(_)
+                let is_normalized_ty_expected = !matches!(obligation.cause.code, ObligationCauseCode::ItemObligation(_)
                     | ObligationCauseCode::BindingObligation(_, _)
-                    | ObligationCauseCode::ObjectCastObligation(_) => false,
-                    _ => true,
-                };
+                    | ObligationCauseCode::ObjectCastObligation(_));
 
                 if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
                     is_normalized_ty_expected,
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 2fb9b3cd5d305..9c894e99a389a 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -323,9 +323,8 @@ pub fn normalize_param_env_or_error<'tcx>(
     // This works fairly well because trait matching  does not actually care about param-env
     // TypeOutlives predicates - these are normally used by regionck.
     let outlives_predicates: Vec<_> = predicates
-        .drain_filter(|predicate| match predicate.skip_binders() {
-            ty::PredicateAtom::TypeOutlives(..) => true,
-            _ => false,
+        .drain_filter(|predicate| {
+            matches!(predicate.skip_binders(), ty::PredicateAtom::TypeOutlives(..))
         })
         .collect();
 
diff --git a/compiler/rustc_traits/src/chalk/mod.rs b/compiler/rustc_traits/src/chalk/mod.rs
index f3a55fec9e462..bd2f87f70a2f1 100644
--- a/compiler/rustc_traits/src/chalk/mod.rs
+++ b/compiler/rustc_traits/src/chalk/mod.rs
@@ -98,7 +98,7 @@ crate fn evaluate_goal<'tcx>(
     let mut solver = chalk_engine::solve::SLGSolver::new(32, None);
     let db = ChalkRustIrDatabase { interner, reempty_placeholder };
     let solution = solver.solve(&db, &lowered_goal);
-    debug!(?obligation, ?solution, "evaluatate goal");
+    debug!(?obligation, ?solution, "evaluate goal");
 
     // Ideally, the code to convert *back* to rustc types would live close to
     // the code to convert *from* rustc types. Right now though, we don't
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs
index b7e77f389f857..0feac036f0026 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -526,18 +526,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         generics: &ty::Generics,
     ) -> bool {
         let explicit = !seg.infer_args;
-        let impl_trait =
-            generics.params.iter().any(|param| match param.kind {
-                ty::GenericParamDefKind::Type {
-                    synthetic:
-                        Some(
-                            hir::SyntheticTyParamKind::ImplTrait
-                            | hir::SyntheticTyParamKind::FromAttr,
-                        ),
-                    ..
-                } => true,
-                _ => false,
-            });
+        let impl_trait = generics.params.iter().any(|param| {
+            matches!(param.kind, ty::GenericParamDefKind::Type {
+                synthetic:
+                    Some(
+                        hir::SyntheticTyParamKind::ImplTrait
+                        | hir::SyntheticTyParamKind::FromAttr,
+                    ),
+                ..
+            })
+        });
 
         if explicit && impl_trait {
             let spans = seg
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index ec7369fd3e8ee..9c60e8933d4db 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -543,10 +543,9 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
 
         if let Some(ty) = prohibit_opaque.break_value() {
             let is_async = match item.kind {
-                ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => match origin {
-                    hir::OpaqueTyOrigin::AsyncFn => true,
-                    _ => false,
-                },
+                ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
+                    matches!(origin, hir::OpaqueTyOrigin::AsyncFn)
+                }
                 _ => unreachable!(),
             };
 
@@ -1321,10 +1320,7 @@ pub fn check_enum<'tcx>(
     }
 
     if tcx.adt_def(def_id).repr.int.is_none() && tcx.features().arbitrary_enum_discriminant {
-        let is_unit = |var: &hir::Variant<'_>| match var.data {
-            hir::VariantData::Unit(..) => true,
-            _ => false,
-        };
+        let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..));
 
         let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
         let has_non_units = vs.iter().any(|var| !is_unit(var));
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 333bda00dbe81..3e60924d6fcf8 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -325,10 +325,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
                 }
 
-                let is_closure = match arg.kind {
-                    ExprKind::Closure(..) => true,
-                    _ => false,
-                };
+                let is_closure = matches!(arg.kind, ExprKind::Closure(..));
 
                 if is_closure != check_closures {
                     continue;
diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs
index b8b98cef7637a..eca6ce1ecdb63 100644
--- a/compiler/rustc_typeck/src/check/regionck.rs
+++ b/compiler/rustc_typeck/src/check/regionck.rs
@@ -354,10 +354,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> {
         hir_id: hir::HirId,
     ) {
         assert!(
-            match fk {
-                intravisit::FnKind::Closure(..) => true,
-                _ => false,
-            },
+            matches!(fk, intravisit::FnKind::Closure(..)),
             "visit_fn invoked for something other than a closure"
         );
 
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index dd4bfc7a75115..29b03d118e25a 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -156,10 +156,10 @@ crate fn placeholder_type_error(
         if let Some(span) = span {
             sugg.push((span, format!("<{}>", type_name)));
         }
-    } else if let Some(arg) = generics.iter().find(|arg| match arg.name {
-        hir::ParamName::Plain(Ident { name: kw::Underscore, .. }) => true,
-        _ => false,
-    }) {
+    } else if let Some(arg) = generics
+        .iter()
+        .find(|arg| matches!(arg.name, hir::ParamName::Plain(Ident { name: kw::Underscore, .. })))
+    {
         // Account for `_` already present in cases like `struct S<_>(_);` and suggest
         // `struct S<T>(T);` instead of `struct S<_, T>(T);`.
         sugg.push((arg.span, (*type_name).to_string()));
@@ -1544,12 +1544,27 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
                     let mut diag = bad_placeholder_type(tcx, visitor.0);
                     let ret_ty = fn_sig.output();
                     if ret_ty != tcx.ty_error() {
-                        diag.span_suggestion(
-                            ty.span,
-                            "replace with the correct return type",
-                            ret_ty.to_string(),
-                            Applicability::MaybeIncorrect,
-                        );
+                        if !ret_ty.is_closure() {
+                            let ret_ty_str = match ret_ty.kind() {
+                                // Suggest a function pointer return type instead of a unique function definition
+                                // (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid
+                                // syntax)
+                                ty::FnDef(..) => ret_ty.fn_sig(tcx).to_string(),
+                                _ => ret_ty.to_string(),
+                            };
+                            diag.span_suggestion(
+                                ty.span,
+                                "replace with the correct return type",
+                                ret_ty_str,
+                                Applicability::MaybeIncorrect,
+                            );
+                        } else {
+                            // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
+                            // to prevent the user from getting a papercut while trying to use the unique closure
+                            // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
+                            diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
+                            diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html");
+                        }
                     }
                     diag.emit();
                     ty::Binder::bind(fn_sig)
diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs
index ce9fd5575cf95..3ce244e11bf45 100644
--- a/compiler/rustc_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_typeck/src/expr_use_visitor.rs
@@ -595,10 +595,10 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
         let upvars = self.tcx().upvars_mentioned(self.body_owner);
 
         // For purposes of this function, generator and closures are equivalent.
-        let body_owner_is_closure = match self.tcx().type_of(self.body_owner.to_def_id()).kind() {
-            ty::Closure(..) | ty::Generator(..) => true,
-            _ => false,
-        };
+        let body_owner_is_closure = matches!(
+            self.tcx().type_of(self.body_owner.to_def_id()).kind(),
+            ty::Closure(..) | ty::Generator(..)
+        );
 
         if let Some(min_captures) = self.mc.typeck_results.closure_min_captures.get(&closure_def_id)
         {
diff --git a/library/alloc/src/collections/btree/append.rs b/library/alloc/src/collections/btree/append.rs
index 9c53c84f5b2fb..1d6488dd2dfe3 100644
--- a/library/alloc/src/collections/btree/append.rs
+++ b/library/alloc/src/collections/btree/append.rs
@@ -81,15 +81,18 @@ impl<K, V> Root<K, V> {
             // the appended elements even if advancing the iterator panicks.
             *length += 1;
         }
-        self.fix_right_edge();
+        self.fix_right_border_of_plentiful();
     }
 
-    fn fix_right_edge(&mut self) {
-        // Handle underfull nodes, start from the top.
+    /// Stock up any underfull nodes on the right border of the tree.
+    /// The other nodes, those that are not the root nor a rightmost edge,
+    /// must have MIN_LEN elements to spare.
+    fn fix_right_border_of_plentiful(&mut self) {
         let mut cur_node = self.borrow_mut();
         while let Internal(internal) = cur_node.force() {
             // Check if right-most child is underfull.
             let mut last_kv = internal.last_kv().consider_for_balancing();
+            debug_assert!(last_kv.left_child_len() >= MIN_LEN * 2);
             let right_child_len = last_kv.right_child_len();
             if right_child_len < MIN_LEN {
                 // We need to steal.
diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs
index 26f8f9da7ec82..f92aed8ce15bf 100644
--- a/library/alloc/src/collections/btree/map/tests.rs
+++ b/library/alloc/src/collections/btree/map/tests.rs
@@ -1821,7 +1821,6 @@ fn test_append_ord_chaos() {
 }
 
 fn rand_data(len: usize) -> Vec<(u32, u32)> {
-    assert!(len * 2 <= 70029); // from that point on numbers repeat
     let mut rng = DeterministicRng::new();
     Vec::from_iter((0..len).map(|_| (rng.next(), rng.next())))
 }
@@ -1886,6 +1885,25 @@ fn test_split_off_tiny_right_height_2() {
     assert_eq!(*right.last_key_value().unwrap().0, last);
 }
 
+#[test]
+fn test_split_off_halfway() {
+    let mut rng = DeterministicRng::new();
+    for &len in &[NODE_CAPACITY, 25, 50, 75, 100] {
+        let mut data = Vec::from_iter((0..len).map(|_| (rng.next(), ())));
+        // Insertion in non-ascending order creates some variation in node length.
+        let mut map = BTreeMap::from_iter(data.iter().copied());
+        data.sort();
+        let small_keys = data.iter().take(len / 2).map(|kv| kv.0);
+        let large_keys = data.iter().skip(len / 2).map(|kv| kv.0);
+        let split_key = large_keys.clone().next().unwrap();
+        let right = map.split_off(&split_key);
+        map.check();
+        right.check();
+        assert!(map.keys().copied().eq(small_keys));
+        assert!(right.keys().copied().eq(large_keys));
+    }
+}
+
 #[test]
 fn test_split_off_large_random_sorted() {
     // Miri is too slow
diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs
index ebcbb0e467c46..cdb39104047f0 100644
--- a/library/alloc/src/collections/btree/mod.rs
+++ b/library/alloc/src/collections/btree/mod.rs
@@ -38,6 +38,7 @@ pub unsafe fn unwrap_unchecked<T>(val: Option<T>) -> T {
 #[cfg(test)]
 /// XorShiftRng
 struct DeterministicRng {
+    count: usize,
     x: u32,
     y: u32,
     z: u32,
@@ -47,11 +48,13 @@ struct DeterministicRng {
 #[cfg(test)]
 impl DeterministicRng {
     fn new() -> Self {
-        DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb }
+        DeterministicRng { count: 0, x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb }
     }
 
-    /// Guarantees that the first 70029 results are unique.
+    /// Guarantees that each returned number is unique.
     fn next(&mut self) -> u32 {
+        self.count += 1;
+        assert!(self.count <= 70029);
         let x = self.x;
         let t = x ^ (x << 11);
         self.x = self.y;
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs
index 16b4b1091eff7..b3641a7a0c697 100644
--- a/library/alloc/src/collections/btree/node.rs
+++ b/library/alloc/src/collections/btree/node.rs
@@ -489,7 +489,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
     ///
     /// # Safety
     /// `index` is in bounds of 0..CAPACITY
-    unsafe fn key_area_mut_at<I, Output: ?Sized>(&mut self, index: I) -> &mut Output
+    unsafe fn key_area_mut<I, Output: ?Sized>(&mut self, index: I) -> &mut Output
     where
         I: SliceIndex<[MaybeUninit<K>], Output = Output>,
     {
@@ -503,7 +503,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
     ///
     /// # Safety
     /// `index` is in bounds of 0..CAPACITY
-    unsafe fn val_area_mut_at<I, Output: ?Sized>(&mut self, index: I) -> &mut Output
+    unsafe fn val_area_mut<I, Output: ?Sized>(&mut self, index: I) -> &mut Output
     where
         I: SliceIndex<[MaybeUninit<V>], Output = Output>,
     {
@@ -519,7 +519,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
     ///
     /// # Safety
     /// `index` is in bounds of 0..CAPACITY + 1
-    unsafe fn edge_area_mut_at<I, Output: ?Sized>(&mut self, index: I) -> &mut Output
+    unsafe fn edge_area_mut<I, Output: ?Sized>(&mut self, index: I) -> &mut Output
     where
         I: SliceIndex<[MaybeUninit<BoxedNode<K, V>>], Output = Output>,
     {
@@ -583,8 +583,8 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
         assert!(idx < CAPACITY);
         *len += 1;
         unsafe {
-            self.key_area_mut_at(idx).write(key);
-            self.val_area_mut_at(idx).write(val);
+            self.key_area_mut(idx).write(key);
+            self.val_area_mut(idx).write(val);
         }
     }
 
@@ -593,8 +593,8 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
         let new_len = self.len() + 1;
         assert!(new_len <= CAPACITY);
         unsafe {
-            slice_insert(self.key_area_mut_at(..new_len), 0, key);
-            slice_insert(self.val_area_mut_at(..new_len), 0, val);
+            slice_insert(self.key_area_mut(..new_len), 0, key);
+            slice_insert(self.val_area_mut(..new_len), 0, val);
             *self.len_mut() = new_len as u16;
         }
     }
@@ -627,9 +627,9 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
         assert!(idx < CAPACITY);
         *len += 1;
         unsafe {
-            self.key_area_mut_at(idx).write(key);
-            self.val_area_mut_at(idx).write(val);
-            self.edge_area_mut_at(idx + 1).write(edge.node);
+            self.key_area_mut(idx).write(key);
+            self.val_area_mut(idx).write(val);
+            self.edge_area_mut(idx + 1).write(edge.node);
             Handle::new_edge(self.reborrow_mut(), idx + 1).correct_parent_link();
         }
     }
@@ -642,9 +642,9 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
         assert!(new_len <= CAPACITY);
 
         unsafe {
-            slice_insert(self.key_area_mut_at(..new_len), 0, key);
-            slice_insert(self.val_area_mut_at(..new_len), 0, val);
-            slice_insert(self.edge_area_mut_at(..new_len + 1), 0, edge.node);
+            slice_insert(self.key_area_mut(..new_len), 0, key);
+            slice_insert(self.val_area_mut(..new_len), 0, val);
+            slice_insert(self.edge_area_mut(..new_len + 1), 0, edge.node);
             *self.len_mut() = new_len as u16;
         }
 
@@ -662,12 +662,12 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
         let idx = self.len() - 1;
 
         unsafe {
-            let key = self.key_area_mut_at(idx).assume_init_read();
-            let val = self.val_area_mut_at(idx).assume_init_read();
+            let key = self.key_area_mut(idx).assume_init_read();
+            let val = self.val_area_mut(idx).assume_init_read();
             let edge = match self.reborrow_mut().force() {
                 ForceResult::Leaf(_) => None,
                 ForceResult::Internal(mut internal) => {
-                    let node = internal.edge_area_mut_at(idx + 1).assume_init_read();
+                    let node = internal.edge_area_mut(idx + 1).assume_init_read();
                     let mut edge = Root { node, height: internal.height - 1, _marker: PhantomData };
                     // Currently, clearing the parent link is superfluous, because we will
                     // insert the node elsewhere and set its parent link again.
@@ -690,12 +690,12 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
         let old_len = self.len();
 
         unsafe {
-            let key = slice_remove(self.key_area_mut_at(..old_len), 0);
-            let val = slice_remove(self.val_area_mut_at(..old_len), 0);
+            let key = slice_remove(self.key_area_mut(..old_len), 0);
+            let val = slice_remove(self.val_area_mut(..old_len), 0);
             let edge = match self.reborrow_mut().force() {
                 ForceResult::Leaf(_) => None,
                 ForceResult::Internal(mut internal) => {
-                    let node = slice_remove(internal.edge_area_mut_at(..old_len + 1), 0);
+                    let node = slice_remove(internal.edge_area_mut(..old_len + 1), 0);
                     let mut edge = Root { node, height: internal.height - 1, _marker: PhantomData };
                     // Currently, clearing the parent link is superfluous, because we will
                     // insert the node elsewhere and set its parent link again.
@@ -919,11 +919,11 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
         let new_len = self.node.len() + 1;
 
         unsafe {
-            slice_insert(self.node.key_area_mut_at(..new_len), self.idx, key);
-            slice_insert(self.node.val_area_mut_at(..new_len), self.idx, val);
+            slice_insert(self.node.key_area_mut(..new_len), self.idx, key);
+            slice_insert(self.node.val_area_mut(..new_len), self.idx, val);
             *self.node.len_mut() = new_len as u16;
 
-            self.node.val_area_mut_at(self.idx).assume_init_mut()
+            self.node.val_area_mut(self.idx).assume_init_mut()
         }
     }
 }
@@ -978,9 +978,9 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
         let new_len = self.node.len() + 1;
 
         unsafe {
-            slice_insert(self.node.key_area_mut_at(..new_len), self.idx, key);
-            slice_insert(self.node.val_area_mut_at(..new_len), self.idx, val);
-            slice_insert(self.node.edge_area_mut_at(..new_len + 1), self.idx + 1, edge.node);
+            slice_insert(self.node.key_area_mut(..new_len), self.idx, key);
+            slice_insert(self.node.val_area_mut(..new_len), self.idx, val);
+            slice_insert(self.node.edge_area_mut(..new_len + 1), self.idx + 1, edge.node);
             *self.node.len_mut() = new_len as u16;
 
             self.node.correct_childrens_parent_links(self.idx + 1..new_len + 1);
@@ -1085,7 +1085,7 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Immut<'a>, K, V, NodeTyp
 
 impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> {
     pub fn key_mut(&mut self) -> &mut K {
-        unsafe { self.node.key_area_mut_at(self.idx).assume_init_mut() }
+        unsafe { self.node.key_area_mut(self.idx).assume_init_mut() }
     }
 
     pub fn into_val_mut(self) -> &'a mut V {
@@ -1127,16 +1127,16 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>
         let new_len = self.node.len() - self.idx - 1;
         new_node.len = new_len as u16;
         unsafe {
-            let k = self.node.key_area_mut_at(self.idx).assume_init_read();
-            let v = self.node.val_area_mut_at(self.idx).assume_init_read();
+            let k = self.node.key_area_mut(self.idx).assume_init_read();
+            let v = self.node.val_area_mut(self.idx).assume_init_read();
 
             ptr::copy_nonoverlapping(
-                self.node.key_area_mut_at(self.idx + 1..).as_ptr(),
+                self.node.key_area_mut(self.idx + 1..).as_ptr(),
                 new_node.keys.as_mut_ptr(),
                 new_len,
             );
             ptr::copy_nonoverlapping(
-                self.node.val_area_mut_at(self.idx + 1..).as_ptr(),
+                self.node.val_area_mut(self.idx + 1..).as_ptr(),
                 new_node.vals.as_mut_ptr(),
                 new_len,
             );
@@ -1173,8 +1173,8 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
     ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) {
         let old_len = self.node.len();
         unsafe {
-            let k = slice_remove(self.node.key_area_mut_at(..old_len), self.idx);
-            let v = slice_remove(self.node.val_area_mut_at(..old_len), self.idx);
+            let k = slice_remove(self.node.key_area_mut(..old_len), self.idx);
+            let v = slice_remove(self.node.val_area_mut(..old_len), self.idx);
             *self.node.len_mut() = (old_len - 1) as u16;
             ((k, v), self.left_edge())
         }
@@ -1195,7 +1195,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
             let kv = self.split_leaf_data(&mut new_node.data);
             let new_len = usize::from(new_node.data.len);
             ptr::copy_nonoverlapping(
-                self.node.edge_area_mut_at(self.idx + 1..).as_ptr(),
+                self.node.edge_area_mut(self.idx + 1..).as_ptr(),
                 new_node.edges.as_mut_ptr(),
                 new_len + 1,
             );
@@ -1321,25 +1321,23 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> {
         unsafe {
             *left_node.len_mut() = new_left_len as u16;
 
-            let parent_key =
-                slice_remove(parent_node.key_area_mut_at(..old_parent_len), parent_idx);
-            left_node.key_area_mut_at(old_left_len).write(parent_key);
+            let parent_key = slice_remove(parent_node.key_area_mut(..old_parent_len), parent_idx);
+            left_node.key_area_mut(old_left_len).write(parent_key);
             ptr::copy_nonoverlapping(
-                right_node.key_area_mut_at(..).as_ptr(),
-                left_node.key_area_mut_at(old_left_len + 1..).as_mut_ptr(),
+                right_node.key_area_mut(..).as_ptr(),
+                left_node.key_area_mut(old_left_len + 1..).as_mut_ptr(),
                 right_len,
             );
 
-            let parent_val =
-                slice_remove(parent_node.val_area_mut_at(..old_parent_len), parent_idx);
-            left_node.val_area_mut_at(old_left_len).write(parent_val);
+            let parent_val = slice_remove(parent_node.val_area_mut(..old_parent_len), parent_idx);
+            left_node.val_area_mut(old_left_len).write(parent_val);
             ptr::copy_nonoverlapping(
-                right_node.val_area_mut_at(..).as_ptr(),
-                left_node.val_area_mut_at(old_left_len + 1..).as_mut_ptr(),
+                right_node.val_area_mut(..).as_ptr(),
+                left_node.val_area_mut(old_left_len + 1..).as_mut_ptr(),
                 right_len,
             );
 
-            slice_remove(&mut parent_node.edge_area_mut_at(..old_parent_len + 1), parent_idx + 1);
+            slice_remove(&mut parent_node.edge_area_mut(..old_parent_len + 1), parent_idx + 1);
             parent_node.correct_childrens_parent_links(parent_idx + 1..old_parent_len);
             *parent_node.len_mut() -= 1;
 
@@ -1349,8 +1347,8 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> {
                 let mut left_node = left_node.reborrow_mut().cast_to_internal_unchecked();
                 let mut right_node = right_node.cast_to_internal_unchecked();
                 ptr::copy_nonoverlapping(
-                    right_node.edge_area_mut_at(..).as_ptr(),
-                    left_node.edge_area_mut_at(old_left_len + 1..).as_mut_ptr(),
+                    right_node.edge_area_mut(..).as_ptr(),
+                    left_node.edge_area_mut(old_left_len + 1..).as_mut_ptr(),
                     right_len + 1,
                 );
 
@@ -1458,7 +1456,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> {
             match (left_node.reborrow_mut().force(), right_node.reborrow_mut().force()) {
                 (ForceResult::Internal(left), ForceResult::Internal(mut right)) => {
                     // Make room for stolen edges.
-                    let right_edges = right.edge_area_mut_at(..).as_mut_ptr();
+                    let right_edges = right.edge_area_mut(..).as_mut_ptr();
                     ptr::copy(right_edges, right_edges.add(count), old_right_len + 1);
                     right.correct_childrens_parent_links(count..new_right_len + 1);
 
@@ -1518,7 +1516,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> {
                     move_edges(right.reborrow_mut(), 0, left, old_left_len + 1, count);
 
                     // Fill gap where stolen edges used to be.
-                    let right_edges = right.edge_area_mut_at(..).as_mut_ptr();
+                    let right_edges = right.edge_area_mut(..).as_mut_ptr();
                     ptr::copy(right_edges.add(count), right_edges, new_right_len + 1);
                     right.correct_childrens_parent_links(0..=new_right_len);
                 }
@@ -1551,8 +1549,8 @@ unsafe fn move_edges<'a, K: 'a, V: 'a>(
     count: usize,
 ) {
     unsafe {
-        let source_ptr = source.edge_area_mut_at(..).as_ptr();
-        let dest_ptr = dest.edge_area_mut_at(dest_offset..).as_mut_ptr();
+        let source_ptr = source.edge_area_mut(..).as_ptr();
+        let dest_ptr = dest.edge_area_mut(dest_offset..).as_mut_ptr();
         ptr::copy_nonoverlapping(source_ptr.add(source_offset), dest_ptr, count);
         dest.correct_childrens_parent_links(dest_offset..dest_offset + count);
     }
diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs
index 4d05bc4ebfa1e..fd19c0078a748 100644
--- a/library/alloc/src/collections/btree/set/tests.rs
+++ b/library/alloc/src/collections/btree/set/tests.rs
@@ -696,8 +696,10 @@ fn test_first_last() {
     assert_eq!(a.pop_last(), None);
 }
 
+// Unlike the function with the same name in map/tests, returns no values.
+// Which also means it returns different predetermined pseudo-random keys,
+// and the test cases using this function explore slightly different trees.
 fn rand_data(len: usize) -> Vec<u32> {
-    assert!(len <= 70029); // from that point on numbers repeat
     let mut rng = DeterministicRng::new();
     Vec::from_iter((0..len).map(|_| rng.next()))
 }
diff --git a/library/alloc/src/collections/btree/split.rs b/library/alloc/src/collections/btree/split.rs
index 6108c139bb3a6..4561c8eaf47fb 100644
--- a/library/alloc/src/collections/btree/split.rs
+++ b/library/alloc/src/collections/btree/split.rs
@@ -53,6 +53,9 @@ impl<K, V> Root<K, V> {
         }
     }
 
+    /// Stock up or merge away any underfull nodes on the right border of the
+    /// tree. The other nodes, those that are not the root nor a rightmost edge,
+    /// must already have at least MIN_LEN elements.
     fn fix_right_border(&mut self) {
         self.fix_top();
 
@@ -72,6 +75,7 @@ impl<K, V> Root<K, V> {
                     }
                     cur_node = last_kv.into_right_child();
                 }
+                debug_assert!(cur_node.len() > MIN_LEN);
             }
         }
 
@@ -98,6 +102,7 @@ impl<K, V> Root<K, V> {
                     }
                     cur_node = first_kv.into_left_child();
                 }
+                debug_assert!(cur_node.len() > MIN_LEN);
             }
         }
 
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 8fd9ff768c4f4..38519f759ae05 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -232,23 +232,27 @@ impl<T: ?Sized> *const T {
     ///
     /// # Safety
     ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
+    /// This operation itself is always safe, but using the resulting pointer is not.
     ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
+    /// The resulting pointer remains attached to the same allocated object that `self` points to.
+    /// It may *not* be used to access a different allocated object. Note that in Rust, every
+    /// (stack-allocated) variable is considered a separate allocated object.
     ///
-    /// In other words, `x.wrapping_offset((y as usize).wrapping_sub(x as usize) / size_of::<T>())`
-    /// is *not* the same as `y`, and dereferencing it is undefined behavior
-    /// unless `x` and `y` point into the same allocated object.
+    /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z`
+    /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
+    /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
+    /// `x` and `y` point into the same allocated object.
     ///
-    /// Compared to [`offset`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`offset`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized
-    /// better and is thus preferable in performance-sensitive code.
+    /// Compared to [`offset`], this method basically delays the requirement of staying within the
+    /// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object
+    /// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a
+    /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`]
+    /// can be optimized better and is thus preferable in performance-sensitive code.
+    ///
+    /// The delayed check only considers the value of the pointer that was dereferenced, not the
+    /// intermediate values used during the computation of the final result. For example,
+    /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other
+    /// words, leaving the allocated object and then re-entering it later is permitted.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
@@ -571,19 +575,27 @@ impl<T: ?Sized> *const T {
     ///
     /// # Safety
     ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
+    /// This operation itself is always safe, but using the resulting pointer is not.
+    ///
+    /// The resulting pointer remains attached to the same allocated object that `self` points to.
+    /// It may *not* be used to access a different allocated object. Note that in Rust, every
+    /// (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z`
+    /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
+    /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
+    /// `x` and `y` point into the same allocated object.
     ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
+    /// Compared to [`add`], this method basically delays the requirement of staying within the
+    /// same allocated object: [`add`] is immediate Undefined Behavior when crossing object
+    /// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a
+    /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`]
+    /// can be optimized better and is thus preferable in performance-sensitive code.
     ///
-    /// Compared to [`add`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`add`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_add` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized
-    /// better and is thus preferable in performance-sensitive code.
+    /// The delayed check only considers the value of the pointer that was dereferenced, not the
+    /// intermediate values used during the computation of the final result. For example,
+    /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
+    /// allocated object and then re-entering it later is permitted.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
@@ -628,19 +640,27 @@ impl<T: ?Sized> *const T {
     ///
     /// # Safety
     ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
+    /// This operation itself is always safe, but using the resulting pointer is not.
+    ///
+    /// The resulting pointer remains attached to the same allocated object that `self` points to.
+    /// It may *not* be used to access a different allocated object. Note that in Rust, every
+    /// (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z`
+    /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
+    /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
+    /// `x` and `y` point into the same allocated object.
     ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
+    /// Compared to [`sub`], this method basically delays the requirement of staying within the
+    /// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object
+    /// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a
+    /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`]
+    /// can be optimized better and is thus preferable in performance-sensitive code.
     ///
-    /// Compared to [`sub`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`sub`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized
-    /// better and is thus preferable in performance-sensitive code.
+    /// The delayed check only considers the value of the pointer that was dereferenced, not the
+    /// intermediate values used during the computation of the final result. For example,
+    /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
+    /// allocated object and then re-entering it later is permitted.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 5f94c2393aef3..92f4e431de499 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -238,23 +238,27 @@ impl<T: ?Sized> *mut T {
     ///
     /// # Safety
     ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
+    /// This operation itself is always safe, but using the resulting pointer is not.
     ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
+    /// The resulting pointer remains attached to the same allocated object that `self` points to.
+    /// It may *not* be used to access a different allocated object. Note that in Rust, every
+    /// (stack-allocated) variable is considered a separate allocated object.
     ///
-    /// In other words, `x.wrapping_offset((y as usize).wrapping_sub(x as usize) / size_of::<T>())`
-    /// is *not* the same as `y`, and dereferencing it is undefined behavior
-    /// unless `x` and `y` point into the same allocated object.
+    /// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z`
+    /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
+    /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
+    /// `x` and `y` point into the same allocated object.
     ///
-    /// Compared to [`offset`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`offset`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized
-    /// better and is thus preferable in performance-sensitive code.
+    /// Compared to [`offset`], this method basically delays the requirement of staying within the
+    /// same allocated object: [`offset`] is immediate Undefined Behavior when crossing object
+    /// boundaries; `wrapping_offset` produces a pointer but still leads to Undefined Behavior if a
+    /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`offset`]
+    /// can be optimized better and is thus preferable in performance-sensitive code.
+    ///
+    /// The delayed check only considers the value of the pointer that was dereferenced, not the
+    /// intermediate values used during the computation of the final result. For example,
+    /// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other
+    /// words, leaving the allocated object and then re-entering it later is permitted.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
@@ -678,19 +682,27 @@ impl<T: ?Sized> *mut T {
     ///
     /// # Safety
     ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
+    /// This operation itself is always safe, but using the resulting pointer is not.
+    ///
+    /// The resulting pointer remains attached to the same allocated object that `self` points to.
+    /// It may *not* be used to access a different allocated object. Note that in Rust, every
+    /// (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z`
+    /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
+    /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
+    /// `x` and `y` point into the same allocated object.
     ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
+    /// Compared to [`add`], this method basically delays the requirement of staying within the
+    /// same allocated object: [`add`] is immediate Undefined Behavior when crossing object
+    /// boundaries; `wrapping_add` produces a pointer but still leads to Undefined Behavior if a
+    /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`add`]
+    /// can be optimized better and is thus preferable in performance-sensitive code.
     ///
-    /// Compared to [`add`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`add`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_add` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized
-    /// better and is thus preferable in performance-sensitive code.
+    /// The delayed check only considers the value of the pointer that was dereferenced, not the
+    /// intermediate values used during the computation of the final result. For example,
+    /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
+    /// allocated object and then re-entering it later is permitted.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
@@ -735,19 +747,27 @@ impl<T: ?Sized> *mut T {
     ///
     /// # Safety
     ///
-    /// The resulting pointer does not need to be in bounds, but it is
-    /// potentially hazardous to dereference (which requires `unsafe`).
+    /// This operation itself is always safe, but using the resulting pointer is not.
+    ///
+    /// The resulting pointer remains attached to the same allocated object that `self` points to.
+    /// It may *not* be used to access a different allocated object. Note that in Rust, every
+    /// (stack-allocated) variable is considered a separate allocated object.
+    ///
+    /// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z`
+    /// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
+    /// attached to the object `x` is attached to, and dereferencing it is Undefined Behavior unless
+    /// `x` and `y` point into the same allocated object.
     ///
-    /// In particular, the resulting pointer remains attached to the same allocated
-    /// object that `self` points to. It may *not* be used to access a
-    /// different allocated object. Note that in Rust,
-    /// every (stack-allocated) variable is considered a separate allocated object.
+    /// Compared to [`sub`], this method basically delays the requirement of staying within the
+    /// same allocated object: [`sub`] is immediate Undefined Behavior when crossing object
+    /// boundaries; `wrapping_sub` produces a pointer but still leads to Undefined Behavior if a
+    /// pointer is dereferenced when it is out-of-bounds of the object it is attached to. [`sub`]
+    /// can be optimized better and is thus preferable in performance-sensitive code.
     ///
-    /// Compared to [`sub`], this method basically delays the requirement of staying
-    /// within the same allocated object: [`sub`] is immediate Undefined Behavior when
-    /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads
-    /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized
-    /// better and is thus preferable in performance-sensitive code.
+    /// The delayed check only considers the value of the pointer that was dereferenced, not the
+    /// intermediate values used during the computation of the final result. For example,
+    /// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
+    /// allocated object and then re-entering it later is permitted.
     ///
     /// If you need to cross object boundaries, cast the pointer to an integer and
     /// do the arithmetic there.
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 30a8229036fd8..2d60bb0a4bde2 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -500,18 +500,17 @@ impl Step for Rustc {
         let target = self.target;
         builder.info(&format!("Documenting stage{} compiler ({})", stage, target));
 
-        // This is the intended out directory for compiler documentation.
-        let out = builder.compiler_doc_out(target);
-        t!(fs::create_dir_all(&out));
-
-        let compiler = builder.compiler(stage, builder.config.build);
-
         if !builder.config.compiler_docs {
             builder.info("\tskipping - compiler/librustdoc docs disabled");
             return;
         }
 
+        // This is the intended out directory for compiler documentation.
+        let out = builder.compiler_doc_out(target);
+        t!(fs::create_dir_all(&out));
+
         // Build rustc.
+        let compiler = builder.compiler(stage, builder.config.build);
         builder.ensure(compile::Rustc { compiler, target });
 
         // This uses a shared directory so that librustdoc documentation gets
@@ -521,6 +520,10 @@ impl Step for Rustc {
         // merging the search index, or generating local (relative) links.
         let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target.triple).join("doc");
         t!(symlink_dir_force(&builder.config, &out, &out_dir));
+        // Cargo puts proc macros in `target/doc` even if you pass `--target`
+        // explicitly (https://github.com/rust-lang/cargo/issues/7677).
+        let proc_macro_out_dir = builder.stage_out(compiler, Mode::Rustc).join("doc");
+        t!(symlink_dir_force(&builder.config, &out, &proc_macro_out_dir));
 
         // Build cargo command.
         let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "doc");
diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml
index 8adc05c513720..21d127c39c904 100644
--- a/src/doc/rustc/book.toml
+++ b/src/doc/rustc/book.toml
@@ -3,3 +3,6 @@ authors = ["The Rust Project Developers"]
 multilingual = false
 src = "src"
 title = "The rustc book"
+
+[output.html]
+git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustc"
diff --git a/src/doc/rustdoc/book.toml b/src/doc/rustdoc/book.toml
index ba30c107667ed..c2e7ff589066b 100644
--- a/src/doc/rustdoc/book.toml
+++ b/src/doc/rustdoc/book.toml
@@ -2,3 +2,6 @@
 authors = ["The Rust Project Developers"]
 src = "src"
 title = "The rustdoc book"
+
+[output.html]
+git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustdoc"
diff --git a/src/doc/rustdoc/src/what-is-rustdoc.md b/src/doc/rustdoc/src/what-is-rustdoc.md
index 1f6dced180b96..32dc1e02bb3db 100644
--- a/src/doc/rustdoc/src/what-is-rustdoc.md
+++ b/src/doc/rustdoc/src/what-is-rustdoc.md
@@ -10,7 +10,7 @@ CSS, and JavaScript.
 Let's give it a try! Create a new project with Cargo:
 
 ```bash
-$ cargo new docs
+$ cargo new docs --lib
 $ cd docs
 ```
 
diff --git a/src/test/ui/const-generics/issues/issue-80375.rs b/src/test/ui/const-generics/issues/issue-80375.rs
new file mode 100644
index 0000000000000..c906bb2c4d9b4
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-80375.rs
@@ -0,0 +1,4 @@
+struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
+//~^ ERROR generic parameters may not be used in const operations
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-80375.stderr b/src/test/ui/const-generics/issues/issue-80375.stderr
new file mode 100644
index 0000000000000..9765a639a48d0
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-80375.stderr
@@ -0,0 +1,11 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-80375.rs:1:41
+   |
+LL | struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
+   |                                         ^^^^^ cannot perform const operation using `COUNT`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/fn/issue-80179.rs b/src/test/ui/fn/issue-80179.rs
new file mode 100644
index 0000000000000..7609b1525cc90
--- /dev/null
+++ b/src/test/ui/fn/issue-80179.rs
@@ -0,0 +1,27 @@
+// Functions with a type placeholder `_` as the return type should
+// show a function pointer suggestion when given a function item
+// and suggest how to return closures correctly from a function.
+// This is a regression test of #80179
+
+fn returns_i32() -> i32 {
+    0
+}
+
+fn returns_fn_ptr() -> _ {
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures [E0121]
+//~| NOTE not allowed in type signatures
+//~| HELP replace with the correct return type
+//~| SUGGESTION fn() -> i32
+    returns_i32
+}
+
+fn returns_closure() -> _ {
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures [E0121]
+//~| NOTE not allowed in type signatures
+//~| HELP consider using an `Fn`, `FnMut`, or `FnOnce` trait bound
+//~| NOTE for more information on `Fn` traits and closure types, see
+//        https://doc.rust-lang.org/book/ch13-01-closures.html
+    || 0
+}
+
+fn main() {}
diff --git a/src/test/ui/fn/issue-80179.stderr b/src/test/ui/fn/issue-80179.stderr
new file mode 100644
index 0000000000000..63571e71b34f4
--- /dev/null
+++ b/src/test/ui/fn/issue-80179.stderr
@@ -0,0 +1,21 @@
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/issue-80179.rs:10:24
+   |
+LL | fn returns_fn_ptr() -> _ {
+   |                        ^
+   |                        |
+   |                        not allowed in type signatures
+   |                        help: replace with the correct return type: `fn() -> i32`
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/issue-80179.rs:18:25
+   |
+LL | fn returns_closure() -> _ {
+   |                         ^ not allowed in type signatures
+   |
+   = help: consider using an `Fn`, `FnMut`, or `FnOnce` trait bound
+   = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0121`.