about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs21
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs27
-rw-r--r--compiler/rustc_errors/src/lib.rs261
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs63
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/lint.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs45
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs31
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs76
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs98
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs4
-rw-r--r--compiler/rustc_infer/src/infer/at.rs1
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs15
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs10
-rw-r--r--compiler/rustc_lint/src/array_into_iter.rs14
-rw-r--r--compiler/rustc_middle/src/thir.rs18
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs16
-rw-r--r--compiler/rustc_middle/src/ty/region.rs4
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs52
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs6
-rw-r--r--compiler/rustc_parse/src/errors.rs8
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs10
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs29
-rw-r--r--compiler/rustc_passes/messages.ftl2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs20
-rw-r--r--compiler/rustc_pattern_analysis/src/constructor.rs14
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs10
-rw-r--r--compiler/rustc_pattern_analysis/src/pat.rs19
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs124
-rw-r--r--compiler/rustc_pattern_analysis/src/usefulness.rs27
-rw-r--r--compiler/rustc_privacy/src/lib.rs5
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs3
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs5
-rw-r--r--compiler/rustc_resolve/src/errors.rs39
-rw-r--r--compiler/rustc_session/src/parse.rs3
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs17
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs201
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs81
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs22
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/string.rs102
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/env.rs18
-rw-r--r--library/std/src/f32.rs184
-rw-r--r--library/std/src/f64.rs184
-rw-r--r--library/std/src/io/stdio.rs45
-rw-r--r--library/std/src/panic.rs6
-rw-r--r--library/std/src/sync/mod.rs5
-rw-r--r--library/std/src/sync/mpmc/list.rs3
-rw-r--r--library/std/src/sync/reentrant_lock.rs320
-rw-r--r--library/std/src/sync/reentrant_lock/tests.rs (renamed from library/std/src/sync/remutex/tests.rs)34
-rw-r--r--library/std/src/sync/remutex.rs178
-rw-r--r--library/std/src/sys/pal/hermit/os.rs10
-rw-r--r--library/std/src/sys/pal/windows/thread_local_key.rs35
-rw-r--r--src/bootstrap/src/core/build_steps/format.rs4
-rw-r--r--src/bootstrap/src/core/builder.rs10
-rw-r--r--src/bootstrap/src/core/config/flags.rs28
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/platform-support.md4
-rw-r--r--src/doc/rustc/src/platform-support/hexagon-unknown-linux-musl.md102
-rw-r--r--src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md19
-rw-r--r--src/librustdoc/html/highlight.rs1
-rw-r--r--src/librustdoc/html/highlight/fixtures/sample.html2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10912.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10912.stderr11
-rw-r--r--src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.rs8
-rw-r--r--src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.stderr9
-rw-r--r--src/tools/miri/src/bin/miri.rs2
-rw-r--r--src/tools/rustfmt/src/formatting.rs21
-rw-r--r--src/tools/rustfmt/src/parse/session.rs8
-rw-r--r--tests/codegen/sanitizer/cfi-emit-type-metadata-attr-cfi-encoding.rs25
-rw-r--r--tests/codegen/sse42-implies-crc32.rs2
-rw-r--r--tests/rustdoc-ui/lints/doc_cfg_hide.stderr4
-rw-r--r--tests/rustdoc/source-code-highlight.rs29
-rw-r--r--tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs10
-rw-r--r--tests/ui/async-await/async-closures/is-fn.rs24
-rw-r--r--tests/ui/async-await/async-closures/move-is-async-fn.rs10
-rw-r--r--tests/ui/async-await/async-closures/once.rs6
-rw-r--r--tests/ui/async-await/async-closures/refd.rs13
-rw-r--r--tests/ui/async-await/async-fn/higher-ranked-async-fn.rs31
-rw-r--r--tests/ui/async-await/async-fn/project.rs12
-rw-r--r--tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs1
-rw-r--r--tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr21
-rw-r--r--tests/ui/foreign/stashed-issue-121451.rs4
-rw-r--r--tests/ui/foreign/stashed-issue-121451.stderr9
-rw-r--r--tests/ui/impl-trait/in-trait/refine-normalize.rs20
-rw-r--r--tests/ui/impl-trait/stashed-diag-issue-121504.rs13
-rw-r--r--tests/ui/impl-trait/stashed-diag-issue-121504.stderr9
-rw-r--r--tests/ui/implied-bounds/impl-implied-bounds-compatibility.rs2
-rw-r--r--tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr20
-rw-r--r--tests/ui/lowering/issue-121108.rs2
-rw-r--r--tests/ui/lowering/issue-121108.stderr10
-rw-r--r--tests/ui/parser/float-field.rs71
-rw-r--r--tests/ui/parser/float-field.stderr226
-rw-r--r--tests/ui/resolve/issue-111312.rs4
-rw-r--r--tests/ui/resolve/issue-111312.stderr16
-rw-r--r--tests/ui/resolve/issue-111727.rs4
-rw-r--r--tests/ui/resolve/issue-111727.stderr16
-rw-r--r--tests/ui/suggestions/silenced-binding-typo.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr14
-rw-r--r--triagebot.toml8
116 files changed, 2293 insertions, 1249 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e37e8614af2..0b74d71fd89 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1640,9 +1640,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 
 [[package]]
 name = "hermit-abi"
-version = "0.3.6"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-alloc",
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index 23d2da128e5..6546a35734c 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -137,27 +137,6 @@ pub(crate) struct BenchSig {
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_test_arg_non_lifetime)]
-pub(crate) struct TestArgNonLifetime {
-    #[primary_span]
-    pub(crate) span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(builtin_macros_should_panic)]
-pub(crate) struct ShouldPanic {
-    #[primary_span]
-    pub(crate) span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(builtin_macros_test_args)]
-pub(crate) struct TestArgs {
-    #[primary_span]
-    pub(crate) span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(builtin_macros_alloc_must_statics)]
 pub(crate) struct AllocMustStatics {
     #[primary_span]
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 01f36ad6a78..1c820bfd01f 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -108,6 +108,25 @@ impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
 
 /// Trait implemented by error types. This is rarely implemented manually. Instead, use
 /// `#[derive(Diagnostic)]` -- see [rustc_macros::Diagnostic].
+///
+/// When implemented manually, it should be generic over the emission
+/// guarantee, i.e.:
+/// ```ignore (fragment)
+/// impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for Foo { ... }
+/// ```
+/// rather than being specific:
+/// ```ignore (fragment)
+/// impl<'a> IntoDiagnostic<'a> for Bar { ... }  // the default type param is `ErrorGuaranteed`
+/// impl<'a> IntoDiagnostic<'a, ()> for Baz { ... }
+/// ```
+/// There are two reasons for this.
+/// - A diagnostic like `Foo` *could* be emitted at any level -- `level` is
+///   passed in to `into_diagnostic` from outside. Even if in practice it is
+///   always emitted at a single level, we let the diagnostic creation/emission
+///   site determine the level (by using `create_err`, `emit_warn`, etc.)
+///   rather than the `IntoDiagnostic` impl.
+/// - Derived impls are always generic, and it's good for the hand-written
+///   impls to be consistent with them.
 #[rustc_diagnostic_item = "IntoDiagnostic"]
 pub trait IntoDiagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> {
     /// Write out as a diagnostic out of `DiagCtxt`.
@@ -1289,11 +1308,9 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         drop(self);
     }
 
-    /// Stashes diagnostic for possible later improvement in a different,
-    /// later stage of the compiler. The diagnostic can be accessed with
-    /// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`].
-    pub fn stash(mut self, span: Span, key: StashKey) {
-        self.dcx.stash_diagnostic(span, key, self.take_diag());
+    /// See `DiagCtxt::stash_diagnostic` for details.
+    pub fn stash(mut self, span: Span, key: StashKey) -> Option<ErrorGuaranteed> {
+        self.dcx.stash_diagnostic(span, key, self.take_diag())
     }
 
     /// Delay emission of this diagnostic as a bug.
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index a5e6aed13eb..0a533833e64 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -434,10 +434,6 @@ struct DiagCtxtInner {
     /// The delayed bugs and their error guarantees.
     delayed_bugs: Vec<(DelayedDiagInner, ErrorGuaranteed)>,
 
-    /// The number of stashed errors. Unlike the other counts, this can go up
-    /// and down, so it doesn't guarantee anything.
-    stashed_err_count: usize,
-
     /// The error count shown to the user at the end.
     deduplicated_err_count: usize,
     /// The warning count shown to the user at the end.
@@ -475,7 +471,7 @@ struct DiagCtxtInner {
     /// add more information). All stashed diagnostics must be emitted with
     /// `emit_stashed_diagnostics` by the time the `DiagCtxtInner` is dropped,
     /// otherwise an assertion failure will occur.
-    stashed_diagnostics: FxIndexMap<(Span, StashKey), DiagInner>,
+    stashed_diagnostics: FxIndexMap<(Span, StashKey), (DiagInner, Option<ErrorGuaranteed>)>,
 
     future_breakage_diagnostics: Vec<DiagInner>,
 
@@ -559,10 +555,18 @@ pub struct DiagCtxtFlags {
 
 impl Drop for DiagCtxtInner {
     fn drop(&mut self) {
-        // Any stashed diagnostics should have been handled by
-        // `emit_stashed_diagnostics` by now.
-        assert!(self.stashed_diagnostics.is_empty());
+        // For tools using `interface::run_compiler` (e.g. rustc, rustdoc)
+        // stashed diagnostics will have already been emitted. But for others
+        // that don't use `interface::run_compiler` (e.g. rustfmt, some clippy
+        // lints) this fallback is necessary.
+        //
+        // Important: it is sound to produce an `ErrorGuaranteed` when stashing
+        // errors because they are guaranteed to be emitted here or earlier.
+        self.emit_stashed_diagnostics();
 
+        // Important: it is sound to produce an `ErrorGuaranteed` when emitting
+        // delayed bugs because they are guaranteed to be emitted here if
+        // necessary.
         if self.err_guars.is_empty() {
             self.flush_delayed()
         }
@@ -608,7 +612,6 @@ impl DiagCtxt {
                 err_guars: Vec::new(),
                 lint_err_guars: Vec::new(),
                 delayed_bugs: Vec::new(),
-                stashed_err_count: 0,
                 deduplicated_err_count: 0,
                 deduplicated_warn_count: 0,
                 emitter,
@@ -669,7 +672,6 @@ impl DiagCtxt {
             err_guars,
             lint_err_guars,
             delayed_bugs,
-            stashed_err_count,
             deduplicated_err_count,
             deduplicated_warn_count,
             emitter: _,
@@ -692,7 +694,6 @@ impl DiagCtxt {
         *err_guars = Default::default();
         *lint_err_guars = Default::default();
         *delayed_bugs = Default::default();
-        *stashed_err_count = 0;
         *deduplicated_err_count = 0;
         *deduplicated_warn_count = 0;
         *must_produce_diag = false;
@@ -708,39 +709,111 @@ impl DiagCtxt {
         *fulfilled_expectations = Default::default();
     }
 
-    /// Stash a given diagnostic with the given `Span` and [`StashKey`] as the key.
-    /// Retrieve a stashed diagnostic with `steal_diagnostic`.
-    pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: DiagInner) {
-        let mut inner = self.inner.borrow_mut();
-
-        let key = (span.with_parent(None), key);
-
-        if diag.is_error() {
-            if diag.is_lint.is_none() {
-                inner.stashed_err_count += 1;
-            }
-        }
+    /// Stashes a diagnostic for possible later improvement in a different,
+    /// later stage of the compiler. Possible actions depend on the diagnostic
+    /// level:
+    /// - Level::Error: immediately counted as an error that has occurred, because it
+    ///   is guaranteed to be emitted eventually. Can be later accessed with the
+    ///   provided `span` and `key` through
+    ///   [`DiagCtxt::try_steal_modify_and_emit_err`] or
+    ///   [`DiagCtxt::try_steal_replace_and_emit_err`]. These do not allow
+    ///   cancellation or downgrading of the error. Returns
+    ///   `Some(ErrorGuaranteed)`.
+    /// - Level::Warning and lower (i.e. !is_error()): can be accessed with the
+    ///   provided `span` and `key` through [`DiagCtxt::steal_non_err()`]. This
+    ///   allows cancelling and downgrading of the diagnostic. Returns `None`.
+    /// - Others: not allowed, will trigger a panic.
+    pub fn stash_diagnostic(
+        &self,
+        span: Span,
+        key: StashKey,
+        diag: DiagInner,
+    ) -> Option<ErrorGuaranteed> {
+        let guar = if diag.level() == Level::Error {
+            // This `unchecked_error_guaranteed` is valid. It is where the
+            // `ErrorGuaranteed` for stashed errors originates. See
+            // `DiagCtxtInner::drop`.
+            #[allow(deprecated)]
+            Some(ErrorGuaranteed::unchecked_error_guaranteed())
+        } else if !diag.is_error() {
+            None
+        } else {
+            self.span_bug(span, format!("invalid level in `stash_diagnostic`: {}", diag.level));
+        };
 
         // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
         // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key.
         // See the PR for a discussion.
-        inner.stashed_diagnostics.insert(key, diag);
+        let key = (span.with_parent(None), key);
+        self.inner.borrow_mut().stashed_diagnostics.insert(key, (diag, guar));
+
+        guar
     }
 
-    /// Steal a previously stashed diagnostic with the given `Span` and [`StashKey`] as the key.
-    pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option<Diag<'_, ()>> {
-        let mut inner = self.inner.borrow_mut();
+    /// Steal a previously stashed non-error diagnostic with the given `Span`
+    /// and [`StashKey`] as the key. Panics if the found diagnostic is an
+    /// error.
+    pub fn steal_non_err(&self, span: Span, key: StashKey) -> Option<Diag<'_, ()>> {
         let key = (span.with_parent(None), key);
         // FIXME(#120456) - is `swap_remove` correct?
-        let diag = inner.stashed_diagnostics.swap_remove(&key)?;
-        if diag.is_error() {
-            if diag.is_lint.is_none() {
-                inner.stashed_err_count -= 1;
-            }
-        }
+        let (diag, guar) = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key)?;
+        assert!(!diag.is_error());
+        assert!(guar.is_none());
         Some(Diag::new_diagnostic(self, diag))
     }
 
+    /// Steals a previously stashed error with the given `Span` and
+    /// [`StashKey`] as the key, modifies it, and emits it. Returns `None` if
+    /// no matching diagnostic is found. Panics if the found diagnostic's level
+    /// isn't `Level::Error`.
+    pub fn try_steal_modify_and_emit_err<F>(
+        &self,
+        span: Span,
+        key: StashKey,
+        mut modify_err: F,
+    ) -> Option<ErrorGuaranteed>
+    where
+        F: FnMut(&mut Diag<'_>),
+    {
+        let key = (span.with_parent(None), key);
+        // FIXME(#120456) - is `swap_remove` correct?
+        let err = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key);
+        err.map(|(err, guar)| {
+            // The use of `::<ErrorGuaranteed>` is safe because level is `Level::Error`.
+            assert_eq!(err.level, Level::Error);
+            assert!(guar.is_some());
+            let mut err = Diag::<ErrorGuaranteed>::new_diagnostic(self, err);
+            modify_err(&mut err);
+            assert_eq!(err.level, Level::Error);
+            err.emit()
+        })
+    }
+
+    /// Steals a previously stashed error with the given `Span` and
+    /// [`StashKey`] as the key, cancels it if found, and emits `new_err`.
+    /// Panics if the found diagnostic's level isn't `Level::Error`.
+    pub fn try_steal_replace_and_emit_err(
+        &self,
+        span: Span,
+        key: StashKey,
+        new_err: Diag<'_>,
+    ) -> ErrorGuaranteed {
+        let key = (span.with_parent(None), key);
+        // FIXME(#120456) - is `swap_remove` correct?
+        let old_err = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key);
+        match old_err {
+            Some((old_err, guar)) => {
+                assert_eq!(old_err.level, Level::Error);
+                assert!(guar.is_some());
+                // Because `old_err` has already been counted, it can only be
+                // safely cancelled because the `new_err` supplants it.
+                Diag::<ErrorGuaranteed>::new_diagnostic(self, old_err).cancel();
+            }
+            None => {}
+        };
+        new_err.emit()
+    }
+
     pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool {
         self.inner.borrow().stashed_diagnostics.get(&(span.with_parent(None), key)).is_some()
     }
@@ -750,41 +823,40 @@ impl DiagCtxt {
         self.inner.borrow_mut().emit_stashed_diagnostics()
     }
 
-    /// This excludes lint errors, delayed bugs and stashed errors.
+    /// This excludes lint errors, and delayed bugs.
     #[inline]
     pub fn err_count_excluding_lint_errs(&self) -> usize {
-        self.inner.borrow().err_guars.len()
+        let inner = self.inner.borrow();
+        inner.err_guars.len()
+            + inner
+                .stashed_diagnostics
+                .values()
+                .filter(|(diag, guar)| guar.is_some() && diag.is_lint.is_none())
+                .count()
     }
 
-    /// This excludes delayed bugs and stashed errors.
+    /// This excludes delayed bugs.
     #[inline]
     pub fn err_count(&self) -> usize {
         let inner = self.inner.borrow();
-        inner.err_guars.len() + inner.lint_err_guars.len()
-    }
-
-    /// This excludes normal errors, lint errors, and delayed bugs. Unless
-    /// absolutely necessary, avoid using this. It's dubious because stashed
-    /// errors can later be cancelled, so the presence of a stashed error at
-    /// some point of time doesn't guarantee anything -- there are no
-    /// `ErrorGuaranteed`s here.
-    pub fn stashed_err_count(&self) -> usize {
-        self.inner.borrow().stashed_err_count
+        inner.err_guars.len()
+            + inner.lint_err_guars.len()
+            + inner.stashed_diagnostics.values().filter(|(_diag, guar)| guar.is_some()).count()
     }
 
-    /// This excludes lint errors, delayed bugs, and stashed errors. Unless
-    /// absolutely necessary, prefer `has_errors` to this method.
+    /// This excludes lint errors and delayed bugs. Unless absolutely
+    /// necessary, prefer `has_errors` to this method.
     pub fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
         self.inner.borrow().has_errors_excluding_lint_errors()
     }
 
-    /// This excludes delayed bugs and stashed errors.
+    /// This excludes delayed bugs.
     pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
         self.inner.borrow().has_errors()
     }
 
-    /// This excludes stashed errors. Unless absolutely necessary, prefer
-    /// `has_errors` to this method.
+    /// This excludes nothing. Unless absolutely necessary, prefer `has_errors`
+    /// to this method.
     pub fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
         self.inner.borrow().has_errors_or_delayed_bugs()
     }
@@ -869,10 +941,10 @@ impl DiagCtxt {
         }
     }
 
-    /// This excludes delayed bugs and stashed errors. Used for early aborts
-    /// after errors occurred -- e.g. because continuing in the face of errors is
-    /// likely to lead to bad results, such as spurious/uninteresting
-    /// additional errors -- when returning an error `Result` is difficult.
+    /// This excludes delayed bugs. Used for early aborts after errors occurred
+    /// -- e.g. because continuing in the face of errors is likely to lead to
+    /// bad results, such as spurious/uninteresting additional errors -- when
+    /// returning an error `Result` is difficult.
     pub fn abort_if_errors(&self) {
         if self.has_errors().is_some() {
             FatalError.raise();
@@ -956,7 +1028,7 @@ impl DiagCtxt {
         inner
             .stashed_diagnostics
             .values_mut()
-            .for_each(|diag| diag.update_unstable_expectation_id(unstable_to_stable));
+            .for_each(|(diag, _guar)| diag.update_unstable_expectation_id(unstable_to_stable));
         inner
             .future_breakage_diagnostics
             .iter_mut()
@@ -1263,12 +1335,8 @@ impl DiagCtxtInner {
     fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
         let mut guar = None;
         let has_errors = !self.err_guars.is_empty();
-        for (_, diag) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
-            if diag.is_error() {
-                if diag.is_lint.is_none() {
-                    self.stashed_err_count -= 1;
-                }
-            } else {
+        for (_, (diag, _guar)) in std::mem::take(&mut self.stashed_diagnostics).into_iter() {
+            if !diag.is_error() {
                 // Unless they're forced, don't flush stashed warnings when
                 // there are errors, to avoid causing warning overload. The
                 // stash would've been stolen already if it were important.
@@ -1327,7 +1395,8 @@ impl DiagCtxtInner {
                 } else {
                     let backtrace = std::backtrace::Backtrace::capture();
                     // This `unchecked_error_guaranteed` is valid. It is where the
-                    // `ErrorGuaranteed` for delayed bugs originates.
+                    // `ErrorGuaranteed` for delayed bugs originates. See
+                    // `DiagCtxtInner::drop`.
                     #[allow(deprecated)]
                     let guar = ErrorGuaranteed::unchecked_error_guaranteed();
                     self.delayed_bugs
@@ -1439,11 +1508,31 @@ impl DiagCtxtInner {
     }
 
     fn has_errors_excluding_lint_errors(&self) -> Option<ErrorGuaranteed> {
-        self.err_guars.get(0).copied()
+        self.err_guars.get(0).copied().or_else(|| {
+            if let Some((_diag, guar)) = self
+                .stashed_diagnostics
+                .values()
+                .find(|(diag, guar)| guar.is_some() && diag.is_lint.is_none())
+            {
+                *guar
+            } else {
+                None
+            }
+        })
     }
 
     fn has_errors(&self) -> Option<ErrorGuaranteed> {
-        self.has_errors_excluding_lint_errors().or_else(|| self.lint_err_guars.get(0).copied())
+        self.err_guars.get(0).copied().or_else(|| self.lint_err_guars.get(0).copied()).or_else(
+            || {
+                if let Some((_diag, guar)) =
+                    self.stashed_diagnostics.values().find(|(_diag, guar)| guar.is_some())
+                {
+                    *guar
+                } else {
+                    None
+                }
+            },
+        )
     }
 
     fn has_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> {
@@ -1491,14 +1580,26 @@ impl DiagCtxtInner {
         let bugs: Vec<_> =
             std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect();
 
-        // If backtraces are enabled, also print the query stack
         let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0");
-        for (i, bug) in bugs.into_iter().enumerate() {
-            if let Some(file) = self.ice_file.as_ref()
-                && let Ok(mut out) = std::fs::File::options().create(true).append(true).open(file)
-            {
-                let _ = write!(
-                    &mut out,
+        let decorate = backtrace || self.ice_file.is_none();
+        let mut out = self
+            .ice_file
+            .as_ref()
+            .and_then(|file| std::fs::File::options().create(true).append(true).open(file).ok());
+
+        // Put the overall explanation before the `DelayedBug`s, to frame them
+        // better (e.g. separate warnings from them). Also, use notes, which
+        // don't count as errors, to avoid possibly triggering
+        // `-Ztreat-err-as-bug`, which we don't want.
+        let note1 = "no errors encountered even though delayed bugs were created";
+        let note2 = "those delayed bugs will now be shown as internal compiler errors";
+        self.emit_diagnostic(DiagInner::new(Note, note1));
+        self.emit_diagnostic(DiagInner::new(Note, note2));
+
+        for bug in bugs {
+            if let Some(out) = &mut out {
+                _ = write!(
+                    out,
                     "delayed bug: {}\n{}\n",
                     bug.inner
                         .messages
@@ -1509,21 +1610,9 @@ impl DiagCtxtInner {
                 );
             }
 
-            if i == 0 {
-                // Put the overall explanation before the `DelayedBug`s, to
-                // frame them better (e.g. separate warnings from them). Also,
-                // make it a note so it doesn't count as an error, because that
-                // could trigger `-Ztreat-err-as-bug`, which we don't want.
-                let note1 = "no errors encountered even though delayed bugs were created";
-                let note2 = "those delayed bugs will now be shown as internal compiler errors";
-                self.emit_diagnostic(DiagInner::new(Note, note1));
-                self.emit_diagnostic(DiagInner::new(Note, note2));
-            }
-
-            let mut bug =
-                if backtrace || self.ice_file.is_none() { bug.decorate(self) } else { bug.inner };
+            let mut bug = if decorate { bug.decorate(self) } else { bug.inner };
 
-            // "Undelay" the delayed bugs (into plain `Bug`s).
+            // "Undelay" the delayed bugs into plain bugs.
             if bug.level != DelayedBug {
                 // NOTE(eddyb) not panicking here because we're already producing
                 // an ICE, and the more information the merrier.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 1fb061f9114..327c70ede28 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -555,16 +555,19 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     gated!(
         rustc_allow_const_fn_unstable, Normal,
-        template!(Word, List: "feat1, feat2, ..."), DuplicatesOk,
+        template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, @only_local: true,
         "rustc_allow_const_fn_unstable side-steps feature gating and stability checks"
     ),
     gated!(
         allow_internal_unsafe, Normal, template!(Word), WarnFollowing,
-        "allow_internal_unsafe side-steps the unsafe_code lint",
+        @only_local: true, "allow_internal_unsafe side-steps the unsafe_code lint",
+    ),
+    rustc_attr!(
+        rustc_allowed_through_unstable_modules, Normal, template!(Word),
+        WarnFollowing, @only_local: true,
+        "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \
+        through unstable paths"
     ),
-    rustc_attr!(rustc_allowed_through_unstable_modules, Normal, template!(Word), WarnFollowing,
-    "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \
-    through unstable paths"),
 
     // ==========================================================================
     // Internal attributes: Type system related:
@@ -572,7 +575,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
 
     gated!(fundamental, Normal, template!(Word), WarnFollowing, experimental!(fundamental)),
     gated!(
-        may_dangle, Normal, template!(Word), WarnFollowing, dropck_eyepatch,
+        may_dangle, Normal, template!(Word), WarnFollowing,
+        @only_local: true, dropck_eyepatch,
         "`may_dangle` has unstable semantics and may be removed in the future",
     ),
 
@@ -580,31 +584,51 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // Internal attributes: Runtime related:
     // ==========================================================================
 
-    rustc_attr!(rustc_allocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
-    rustc_attr!(rustc_nounwind, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
-    rustc_attr!(rustc_reallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
-    rustc_attr!(rustc_deallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
-    rustc_attr!(rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
+    rustc_attr!(
+        rustc_allocator, Normal, template!(Word), WarnFollowing,
+        @only_local: true, IMPL_DETAIL
+    ),
+    rustc_attr!(
+        rustc_nounwind, Normal, template!(Word), WarnFollowing,
+        @only_local: true, IMPL_DETAIL
+    ),
+    rustc_attr!(
+        rustc_reallocator, Normal, template!(Word), WarnFollowing,
+        @only_local: true, IMPL_DETAIL
+    ),
+    rustc_attr!(
+        rustc_deallocator, Normal, template!(Word), WarnFollowing,
+        @only_local: true, IMPL_DETAIL
+    ),
+    rustc_attr!(
+        rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing,
+        @only_local: true, IMPL_DETAIL
+    ),
+    gated!(
+        default_lib_allocator, Normal, template!(Word), WarnFollowing,
+        @only_local: true, allocator_internals, experimental!(default_lib_allocator),
+    ),
     gated!(
-        default_lib_allocator, Normal, template!(Word), WarnFollowing, allocator_internals,
-        experimental!(default_lib_allocator),
+        needs_allocator, Normal, template!(Word), WarnFollowing,
+        @only_local: true, allocator_internals, experimental!(needs_allocator),
     ),
     gated!(
-        needs_allocator, Normal, template!(Word), WarnFollowing, allocator_internals,
-        experimental!(needs_allocator),
+        panic_runtime, Normal, template!(Word), WarnFollowing,
+        @only_local: true, experimental!(panic_runtime)
     ),
-    gated!(panic_runtime, Normal, template!(Word), WarnFollowing, experimental!(panic_runtime)),
     gated!(
         needs_panic_runtime, Normal, template!(Word), WarnFollowing,
-        experimental!(needs_panic_runtime)
+        @only_local: true, experimental!(needs_panic_runtime)
     ),
     gated!(
         compiler_builtins, Normal, template!(Word), WarnFollowing,
+        @only_local: true,
         "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \
         which contains compiler-rt intrinsics and will never be stable",
     ),
     gated!(
         profiler_runtime, Normal, template!(Word), WarnFollowing,
+        @only_local: true,
         "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \
         which contains the profiler runtime and will never be stable",
     ),
@@ -630,7 +654,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing,
         IMPL_DETAIL,
     ),
-    rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
+    rustc_attr!(
+        rustc_proc_macro_decls, Normal, template!(Word), WarnFollowing,
+        @only_local: true, INTERNAL_UNSTABLE
+    ),
     rustc_attr!(
         rustc_macro_transparency, Normal,
         template!(NameValueStr: "transparent|semitransparent|opaque"), ErrorFollowing,
diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs
index fb5f3426cea..227254b4cc8 100644
--- a/compiler/rustc_hir_analysis/src/astconv/lint.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs
@@ -1,5 +1,5 @@
 use rustc_ast::TraitObjectSyntax;
-use rustc_errors::{codes::*, Diag, EmissionGuarantee, StashKey};
+use rustc_errors::{codes::*, Diag, EmissionGuarantee, Level, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability};
@@ -237,7 +237,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 }
                 // check if the impl trait that we are considering is a impl of a local trait
                 self.maybe_lint_blanket_trait_impl(self_ty, &mut diag);
-                diag.stash(self_ty.span, StashKey::TraitMissingMethod);
+                match diag.level() {
+                    Level::Error => {
+                        diag.stash(self_ty.span, StashKey::TraitMissingMethod);
+                    }
+                    Level::DelayedBug => {
+                        diag.emit();
+                    }
+                    _ => unreachable!(),
+                }
             } else {
                 let msg = "trait objects without an explicit `dyn` are deprecated";
                 tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| {
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 81e84860b82..96bebda5828 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1350,8 +1350,7 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
     let ty = tcx.type_of(def_id).instantiate_identity();
     if ty.references_error() {
         // If there is already another error, do not emit an error for not using a type parameter.
-        // Without the `stashed_err_count` part this can fail (#120856).
-        assert!(tcx.dcx().has_errors().is_some() || tcx.dcx().stashed_err_count() > 0);
+        assert!(tcx.dcx().has_errors().is_some());
         return;
     }
 
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index b5e69b8e376..29dc434ab45 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -136,11 +136,15 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
     // 1. Project the RPITIT projections from the trait to the opaques on the impl,
     //    which means that they don't need to be mapped manually.
     //
-    // 2. Project any other projections that show up in the bound. That makes sure that
-    //    we don't consider `tests/ui/async-await/in-trait/async-associated-types.rs`
-    //    to be refining.
-    let (trait_bounds, impl_bounds) =
-        ocx.normalize(&ObligationCause::dummy(), param_env, (trait_bounds, impl_bounds));
+    // 2. Deeply normalize any other projections that show up in the bound. That makes sure
+    //    that we don't consider `tests/ui/async-await/in-trait/async-associated-types.rs`
+    //    or `tests/ui/impl-trait/in-trait/refine-normalize.rs` to be refining.
+    let Ok((trait_bounds, impl_bounds)) =
+        ocx.deeply_normalize(&ObligationCause::dummy(), param_env, (trait_bounds, impl_bounds))
+    else {
+        tcx.dcx().delayed_bug("encountered errors when checking RPITIT refinement (selection)");
+        return;
+    };
 
     // Since we've normalized things, we need to resolve regions, since we'll
     // possibly have introduced region vars during projection. We don't expect
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index c0128afe2bf..417f0fceaa8 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -596,10 +596,11 @@ fn infer_placeholder_type<'a>(
     // then the user may have written e.g. `const A = 42;`.
     // In this case, the parser has stashed a diagnostic for
     // us to improve in typeck so we do that now.
-    match tcx.dcx().steal_diagnostic(span, StashKey::ItemNoType) {
-        Some(mut err) => {
+    let guar = tcx
+        .dcx()
+        .try_steal_modify_and_emit_err(span, StashKey::ItemNoType, |err| {
             if !ty.references_error() {
-                // Only suggest adding `:` if it was missing (and suggested by parsing diagnostic)
+                // Only suggest adding `:` if it was missing (and suggested by parsing diagnostic).
                 let colon = if span == item_ident.span.shrink_to_hi() { ":" } else { "" };
 
                 // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type.
@@ -622,12 +623,8 @@ fn infer_placeholder_type<'a>(
                     ));
                 }
             }
-
-            err.emit();
-            // diagnostic stashing loses the information of whether something is a hard error.
-            Ty::new_error_with_message(tcx, span, "ItemNoType is a hard error")
-        }
-        None => {
+        })
+        .unwrap_or_else(|| {
             let mut diag = bad_placeholder(tcx, vec![span], kind);
 
             if !ty.references_error() {
@@ -645,10 +642,9 @@ fn infer_placeholder_type<'a>(
                     ));
                 }
             }
-
-            Ty::new_error(tcx, diag.emit())
-        }
-    }
+            diag.emit()
+        });
+    Ty::new_error(tcx, guar)
 }
 
 fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index ccad3b66d6b..5330260fbf5 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1005,13 +1005,6 @@ pub(crate) struct StaticSpecialize {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_missing_tilde_const)]
-pub(crate) struct MissingTildeConst {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 pub(crate) enum DropImplPolarity {
     #[diag(hir_analysis_drop_impl_negative)]
     Negative {
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index bb6d1ecae02..b87d71e3533 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -484,12 +484,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &callee_expr.kind
                     && let [segment] = path.segments
-                    && let Some(mut diag) =
-                        self.dcx().steal_diagnostic(segment.ident.span, StashKey::CallIntoMethod)
                 {
-                    // Try suggesting `foo(a)` -> `a.foo()` if possible.
-                    self.suggest_call_as_method(&mut diag, segment, arg_exprs, call_expr, expected);
-                    diag.emit();
+                    self.dcx().try_steal_modify_and_emit_err(
+                        segment.ident.span,
+                        StashKey::CallIntoMethod,
+                        |err| {
+                            // Try suggesting `foo(a)` -> `a.foo()` if possible.
+                            self.suggest_call_as_method(
+                                err, segment, arg_exprs, call_expr, expected,
+                            );
+                        },
+                    );
                 }
 
                 let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
@@ -601,7 +606,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// and suggesting the fix if the method probe is successful.
     fn suggest_call_as_method(
         &self,
-        diag: &mut Diag<'_, ()>,
+        diag: &mut Diag<'_>,
         segment: &'tcx hir::PathSegment<'tcx>,
         arg_exprs: &'tcx [hir::Expr<'tcx>],
         call_expr: &'tcx hir::Expr<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 2b7bce3f485..054be89a7c4 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1460,18 +1460,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
         {
             let span = self.tcx.hir().span(hir_id);
-            match self.dcx().steal_diagnostic(span, StashKey::UnderscoreForArrayLengths) {
-                Some(mut err) => {
+            self.dcx().try_steal_modify_and_emit_err(
+                span,
+                StashKey::UnderscoreForArrayLengths,
+                |err| {
                     err.span_suggestion(
                         span,
                         "consider specifying the array length",
                         array_len,
                         Applicability::MaybeIncorrect,
                     );
-                    err.emit();
-                }
-                None => (),
-            }
+                },
+            );
         }
     }
 
@@ -1751,11 +1751,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let (_, diag) =
                 self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);
 
-            if let Some(mut diag) = diag {
+            if let Some(diag) = diag {
                 if idx == ast_fields.len() - 1 {
                     if remaining_fields.is_empty() {
-                        self.suggest_fru_from_range(field, variant, args, &mut diag);
-                        diag.emit();
+                        self.suggest_fru_from_range_and_emit(field, variant, args, diag);
                     } else {
                         diag.stash(field.span, StashKey::MaybeFruTypo);
                     }
@@ -1986,20 +1985,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err.span_label(span, format!("missing {remaining_fields_names}{truncated_fields_error}"));
 
         if let Some(last) = ast_fields.last() {
-            self.suggest_fru_from_range(last, variant, args, &mut err);
+            self.suggest_fru_from_range_and_emit(last, variant, args, err);
+        } else {
+            err.emit();
         }
-
-        err.emit();
     }
 
     /// If the last field is a range literal, but it isn't supposed to be, then they probably
     /// meant to use functional update syntax.
-    fn suggest_fru_from_range(
+    fn suggest_fru_from_range_and_emit(
         &self,
         last_expr_field: &hir::ExprField<'tcx>,
         variant: &ty::VariantDef,
         args: GenericArgsRef<'tcx>,
-        err: &mut Diag<'_>,
+        mut err: Diag<'_>,
     ) {
         // I don't use 'is_range_literal' because only double-sided, half-open ranges count.
         if let ExprKind::Struct(QPath::LangItem(LangItem::Range, ..), [range_start, range_end], _) =
@@ -2012,16 +2011,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .map(|adt| adt.did())
                 != range_def_id
         {
-            // Suppress any range expr type mismatches
-            if let Some(diag) =
-                self.dcx().steal_diagnostic(last_expr_field.span, StashKey::MaybeFruTypo)
-            {
-                diag.delay_as_bug();
-            }
-
             // Use a (somewhat arbitrary) filtering heuristic to avoid printing
             // expressions that are either too long, or have control character
-            //such as newlines in them.
+            // such as newlines in them.
             let expr = self
                 .tcx
                 .sess
@@ -2043,6 +2035,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.dcx(),
                 TypeMismatchFruTypo { expr_span: range_start.span, fru_span, expr },
             );
+
+            // Suppress any range expr type mismatches
+            self.dcx().try_steal_replace_and_emit_err(
+                last_expr_field.span,
+                StashKey::MaybeFruTypo,
+                err,
+            );
+        } else {
+            err.emit();
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index a5892dea1a5..dd44fdd8893 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -848,11 +848,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
             .map(|r| {
                 // lint bare trait if the method is found in the trait
-                if span.edition().at_least_rust_2021()
-                    && let Some(diag) =
-                        self.dcx().steal_diagnostic(qself.span, StashKey::TraitMissingMethod)
-                {
-                    diag.emit();
+                if span.edition().at_least_rust_2021() {
+                    self.dcx().try_steal_modify_and_emit_err(
+                        qself.span,
+                        StashKey::TraitMissingMethod,
+                        |_err| {},
+                    );
                 }
                 r
             })
@@ -879,17 +880,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     );
                 }
 
-                // emit or cancel the diagnostic for bare traits
-                if span.edition().at_least_rust_2021()
-                    && let Some(diag) =
-                        self.dcx().steal_diagnostic(qself.span, StashKey::TraitMissingMethod)
-                {
-                    if trait_missing_method {
-                        // cancel the diag for bare traits when meeting `MyTrait::missing_method`
-                        diag.cancel();
-                    } else {
-                        diag.emit();
-                    }
+                // Emit the diagnostic for bare traits. (We used to cancel for slightly better
+                // error messages, but cancelling stashed diagnostics is no longer allowed because
+                // it causes problems when tracking whether errors have actually occurred.)
+                if span.edition().at_least_rust_2021() {
+                    self.dcx().try_steal_modify_and_emit_err(
+                        qself.span,
+                        StashKey::TraitMissingMethod,
+                        |_err| {},
+                    );
                 }
 
                 if item_name.name != kw::Empty {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 61c52422d19..1311cc8968a 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1941,53 +1941,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         errors_causecode: Vec<(Span, ObligationCauseCode<'tcx>)>,
     ) {
         for (span, code) in errors_causecode {
-            let Some(mut diag) = self.dcx().steal_diagnostic(span, StashKey::MaybeForgetReturn)
-            else {
-                continue;
-            };
-
-            if let Some(fn_sig) = self.body_fn_sig()
-                && let ExprBindingObligation(_, _, hir_id, ..) = code
-                && !fn_sig.output().is_unit()
-            {
-                let mut block_num = 0;
-                let mut found_semi = false;
-                for (_, node) in self.tcx.hir().parent_iter(hir_id) {
-                    match node {
-                        hir::Node::Stmt(stmt) => {
-                            if let hir::StmtKind::Semi(expr) = stmt.kind {
-                                let expr_ty = self.typeck_results.borrow().expr_ty(expr);
-                                let return_ty = fn_sig.output();
-                                if !matches!(expr.kind, hir::ExprKind::Ret(..))
-                                    && self.can_coerce(expr_ty, return_ty)
-                                {
-                                    found_semi = true;
+            self.dcx().try_steal_modify_and_emit_err(span, StashKey::MaybeForgetReturn, |err| {
+                if let Some(fn_sig) = self.body_fn_sig()
+                    && let ExprBindingObligation(_, _, hir_id, ..) = code
+                    && !fn_sig.output().is_unit()
+                {
+                    let mut block_num = 0;
+                    let mut found_semi = false;
+                    for (_, node) in self.tcx.hir().parent_iter(hir_id) {
+                        match node {
+                            hir::Node::Stmt(stmt) => {
+                                if let hir::StmtKind::Semi(expr) = stmt.kind {
+                                    let expr_ty = self.typeck_results.borrow().expr_ty(expr);
+                                    let return_ty = fn_sig.output();
+                                    if !matches!(expr.kind, hir::ExprKind::Ret(..))
+                                        && self.can_coerce(expr_ty, return_ty)
+                                    {
+                                        found_semi = true;
+                                    }
                                 }
                             }
-                        }
-                        hir::Node::Block(_block) => {
-                            if found_semi {
-                                block_num += 1;
+                            hir::Node::Block(_block) => {
+                                if found_semi {
+                                    block_num += 1;
+                                }
                             }
-                        }
-                        hir::Node::Item(item) => {
-                            if let hir::ItemKind::Fn(..) = item.kind {
-                                break;
+                            hir::Node::Item(item) => {
+                                if let hir::ItemKind::Fn(..) = item.kind {
+                                    break;
+                                }
                             }
+                            _ => {}
                         }
-                        _ => {}
+                    }
+                    if block_num > 1 && found_semi {
+                        err.span_suggestion_verbose(
+                            span.shrink_to_lo(),
+                            "you might have meant to return this to infer its type parameters",
+                            "return ",
+                            Applicability::MaybeIncorrect,
+                        );
                     }
                 }
-                if block_num > 1 && found_semi {
-                    diag.span_suggestion_verbose(
-                        span.shrink_to_lo(),
-                        "you might have meant to return this to infer its type parameters",
-                        "return ",
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-            }
-            diag.emit();
+            });
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 28771ae40f5..e5b0d0ae0da 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2194,59 +2194,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let [seg1, seg2] = segs else {
             return;
         };
-        let Some(mut diag) =
-            self.dcx().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
-        else {
-            return;
-        };
-
-        let map = self.infcx.tcx.hir();
-        let body_id = self.tcx.hir().body_owned_by(self.body_id);
-        let body = map.body(body_id);
-        struct LetVisitor<'a> {
-            result: Option<&'a hir::Expr<'a>>,
-            ident_name: Symbol,
-        }
+        self.dcx().try_steal_modify_and_emit_err(
+            seg1.ident.span,
+            StashKey::CallAssocMethod,
+            |err| {
+                let map = self.infcx.tcx.hir();
+                let body_id = self.tcx.hir().body_owned_by(self.body_id);
+                let body = map.body(body_id);
+                struct LetVisitor<'a> {
+                    result: Option<&'a hir::Expr<'a>>,
+                    ident_name: Symbol,
+                }
 
-        // FIXME: This really should be taking scoping, etc into account.
-        impl<'v> Visitor<'v> for LetVisitor<'v> {
-            fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
-                if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
-                    && let Binding(_, _, ident, ..) = pat.kind
-                    && ident.name == self.ident_name
-                {
-                    self.result = *init;
-                } else {
-                    hir::intravisit::walk_stmt(self, ex);
+                // FIXME: This really should be taking scoping, etc into account.
+                impl<'v> Visitor<'v> for LetVisitor<'v> {
+                    fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
+                        if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
+                            && let Binding(_, _, ident, ..) = pat.kind
+                            && ident.name == self.ident_name
+                        {
+                            self.result = *init;
+                        } else {
+                            hir::intravisit::walk_stmt(self, ex);
+                        }
+                    }
                 }
-            }
-        }
 
-        let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
-        visitor.visit_body(body);
+                let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
+                visitor.visit_body(body);
 
-        if let Node::Expr(call_expr) = self.tcx.parent_hir_node(seg1.hir_id)
-            && let Some(expr) = visitor.result
-            && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
-        {
-            let probe = self.lookup_probe_for_diagnostic(
-                seg2.ident,
-                self_ty,
-                call_expr,
-                ProbeScope::TraitsInScope,
-                None,
-            );
-            if probe.is_ok() {
-                let sm = self.infcx.tcx.sess.source_map();
-                diag.span_suggestion_verbose(
-                    sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(),
-                    "you may have meant to call an instance method",
-                    ".",
-                    Applicability::MaybeIncorrect,
-                );
-            }
-        }
-        diag.emit();
+                if let Node::Expr(call_expr) = self.tcx.parent_hir_node(seg1.hir_id)
+                    && let Some(expr) = visitor.result
+                    && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
+                {
+                    let probe = self.lookup_probe_for_diagnostic(
+                        seg2.ident,
+                        self_ty,
+                        call_expr,
+                        ProbeScope::TraitsInScope,
+                        None,
+                    );
+                    if probe.is_ok() {
+                        let sm = self.infcx.tcx.sess.source_map();
+                        err.span_suggestion_verbose(
+                            sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':')
+                                .unwrap(),
+                            "you may have meant to call an instance method",
+                            ".",
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                }
+            },
+        );
     }
 
     /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index ed102a7fac0..0740a3fd3e9 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -772,10 +772,6 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
     fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
         if let Some(guar) = self.fcx.dcx().has_errors() {
             guar
-        } else if self.fcx.dcx().stashed_err_count() > 0 {
-            // Without this case we sometimes get uninteresting and extraneous
-            // "type annotations needed" errors.
-            self.fcx.dcx().delayed_bug("error in Resolver")
         } else {
             self.fcx
                 .err_ctxt()
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index cc09a094688..a086d89b933 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -87,7 +87,6 @@ impl<'tcx> InferCtxt<'tcx> {
             reported_signature_mismatch: self.reported_signature_mismatch.clone(),
             tainted_by_errors: self.tainted_by_errors.clone(),
             err_count_on_creation: self.err_count_on_creation,
-            stashed_err_count_on_creation: self.stashed_err_count_on_creation,
             universe: self.universe.clone(),
             intercrate,
             next_trait_solver: self.next_trait_solver,
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index d7e16488508..6f52ded3551 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -306,12 +306,6 @@ pub struct InferCtxt<'tcx> {
     // FIXME(matthewjasper) Merge into `tainted_by_errors`
     err_count_on_creation: usize,
 
-    /// Track how many errors were stashed when this infcx is created.
-    /// Used for the same purpose as `err_count_on_creation`, even
-    /// though it's weaker because the count can go up and down.
-    // FIXME(matthewjasper) Merge into `tainted_by_errors`
-    stashed_err_count_on_creation: usize,
-
     /// What is the innermost universe we have created? Starts out as
     /// `UniverseIndex::root()` but grows from there as we enter
     /// universal quantifiers.
@@ -717,7 +711,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
             reported_signature_mismatch: Default::default(),
             tainted_by_errors: Cell::new(None),
             err_count_on_creation: tcx.dcx().err_count_excluding_lint_errs(),
-            stashed_err_count_on_creation: tcx.dcx().stashed_err_count(),
             universe: Cell::new(ty::UniverseIndex::ROOT),
             intercrate,
             next_trait_solver,
@@ -1274,14 +1267,6 @@ impl<'tcx> InferCtxt<'tcx> {
             let guar = self.dcx().has_errors().unwrap();
             self.set_tainted_by_errors(guar);
             Some(guar)
-        } else if self.dcx().stashed_err_count() > self.stashed_err_count_on_creation {
-            // Errors stashed since this infcx was made. Not entirely reliable
-            // because the count of stashed errors can go down. But without
-            // this case we get a moderate number of uninteresting and
-            // extraneous "type annotations needed" errors.
-            let guar = self.dcx().delayed_bug("tainted_by_errors: stashed bug awaiting emission");
-            self.set_tainted_by_errors(guar);
-            Some(guar)
         } else {
             None
         }
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index c0a99e5cc41..8dd3a1f40cc 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -62,6 +62,7 @@
 use crate::infer::outlives::components::{push_outlives_components, Component};
 use crate::infer::outlives::env::RegionBoundPairs;
 use crate::infer::outlives::verify::VerifyBoundCx;
+use crate::infer::resolve::OpportunisticRegionResolver;
 use crate::infer::{
     self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound,
 };
@@ -69,7 +70,9 @@ use crate::traits::{ObligationCause, ObligationCauseCode};
 use rustc_data_structures::undo_log::UndoLogs;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::traits::query::NoSolution;
-use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{
+    self, GenericArgsRef, Region, Ty, TyCtxt, TypeFoldable as _, TypeVisitableExt,
+};
 use rustc_middle::ty::{GenericArgKind, PolyTypeOutlivesPredicate};
 use rustc_span::DUMMY_SP;
 use smallvec::smallvec;
@@ -176,6 +179,11 @@ impl<'tcx> InferCtxt<'tcx> {
                         .map_err(|NoSolution| (outlives, origin.clone()))?
                         .no_bound_vars()
                         .expect("started with no bound vars, should end with no bound vars");
+                // `TypeOutlives` is structural, so we should try to opportunistically resolve all
+                // region vids before processing regions, so we have a better chance to match clauses
+                // in our param-env.
+                let (sup_type, sub_region) =
+                    (sup_type, sub_region).fold_with(&mut OpportunisticRegionResolver::new(self));
 
                 debug!(?sup_type, ?sub_region, ?origin);
 
diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs
index 993b1d739a1..3a5c585366a 100644
--- a/compiler/rustc_lint/src/array_into_iter.rs
+++ b/compiler/rustc_lint/src/array_into_iter.rs
@@ -70,15 +70,11 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
 
             // Check if the method call actually calls the libcore
             // `IntoIterator::into_iter`.
-            let trait_id = cx
-                .typeck_results()
-                .type_dependent_def_id(expr.hir_id)
-                .and_then(|did| cx.tcx.trait_of_item(did));
-            if trait_id.is_none()
-                || !cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_id.unwrap())
-            {
-                return;
-            }
+            let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
+            match cx.tcx.trait_of_item(def_id) {
+                Some(trait_id) if cx.tcx.is_diagnostic_item(sym::IntoIterator, trait_id) => {}
+                _ => return,
+            };
 
             // As this is a method call expression, we have at least one argument.
             let receiver_ty = cx.typeck_results().expr_ty(receiver_arg);
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 2ad592174f1..65875ff3f9a 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -815,7 +815,9 @@ pub enum PatKind<'tcx> {
 /// The boundaries must be of the same type and that type must be numeric.
 #[derive(Clone, Debug, PartialEq, HashStable, TypeVisitable)]
 pub struct PatRange<'tcx> {
+    /// Must not be `PosInfinity`.
     pub lo: PatRangeBoundary<'tcx>,
+    /// Must not be `NegInfinity`.
     pub hi: PatRangeBoundary<'tcx>,
     #[type_visitable(ignore)]
     pub end: RangeEnd,
@@ -958,22 +960,6 @@ impl<'tcx> PatRangeBoundary<'tcx> {
             Self::NegInfinity | Self::PosInfinity => None,
         }
     }
-    #[inline]
-    pub fn to_const(self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> mir::Const<'tcx> {
-        match self {
-            Self::Finite(value) => value,
-            Self::NegInfinity => {
-                // Unwrap is ok because the type is known to be numeric.
-                let c = ty.numeric_min_val(tcx).unwrap();
-                mir::Const::from_ty_const(c, tcx)
-            }
-            Self::PosInfinity => {
-                // Unwrap is ok because the type is known to be numeric.
-                let c = ty.numeric_max_val(tcx).unwrap();
-                mir::Const::from_ty_const(c, tcx)
-            }
-        }
-    }
     pub fn eval_bits(self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 {
         match self {
             Self::Finite(value) => value.eval_bits(tcx, param_env),
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index d97f0e4c321..6fdb03c0bab 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -847,13 +847,15 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
         opaque_def_id: LocalDefId,
         tcx: TyCtxt<'tcx>,
     ) -> Result<Diag<'tcx>, ErrorGuaranteed> {
-        if let Some(diag) = tcx
-            .sess
-            .dcx()
-            .steal_diagnostic(tcx.def_span(opaque_def_id), StashKey::OpaqueHiddenTypeMismatch)
-        {
-            diag.cancel();
-        }
+        // We used to cancel here for slightly better error messages, but
+        // cancelling stashed diagnostics is no longer allowed because it
+        // causes problems when tracking whether errors have actually
+        // occurred.
+        tcx.sess.dcx().try_steal_modify_and_emit_err(
+            tcx.def_span(opaque_def_id),
+            StashKey::OpaqueHiddenTypeMismatch,
+            |_err| {},
+        );
         (self.ty, other.ty).error_reported()?;
         // Found different concrete types for the opaque type.
         let sub_diag = if self.span == other.span {
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index b206727f051..51a4a9f411c 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -91,8 +91,8 @@ impl<'tcx> Region<'tcx> {
 
     /// Constructs a `RegionKind::ReError` region.
     #[track_caller]
-    pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Region<'tcx> {
-        tcx.intern_region(ty::ReError(reported))
+    pub fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Region<'tcx> {
+        tcx.intern_region(ty::ReError(guar))
     }
 
     /// Constructs a `RegionKind::ReError` region and registers a delayed bug to ensure it gets
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 27c78d18d19..06be8191dc4 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1528,8 +1528,8 @@ impl<'tcx> Ty<'tcx> {
     }
 
     /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
-    pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Ty<'tcx> {
-        Ty::new(tcx, Error(reported))
+    pub fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Ty<'tcx> {
+        Ty::new(tcx, Error(guar))
     }
 
     /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` to ensure it gets used.
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 1c97de58863..1b6994966d1 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -291,33 +291,41 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
 
             TestKind::Range(ref range) => {
-                let lower_bound_success = self.cfg.start_new_block();
-
+                let [success, fail] = *target_blocks else {
+                    bug!("`TestKind::Range` should have two target blocks");
+                };
                 // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
-                // FIXME: skip useless comparison when the range is half-open.
-                let lo = range.lo.to_const(range.ty, self.tcx);
-                let hi = range.hi.to_const(range.ty, self.tcx);
-                let lo = self.literal_operand(test.span, lo);
-                let hi = self.literal_operand(test.span, hi);
                 let val = Operand::Copy(place);
 
-                let [success, fail] = *target_blocks else {
-                    bug!("`TestKind::Range` should have two target blocks");
+                let intermediate_block = if !range.lo.is_finite() {
+                    block
+                } else if !range.hi.is_finite() {
+                    success
+                } else {
+                    self.cfg.start_new_block()
                 };
-                self.compare(
-                    block,
-                    lower_bound_success,
-                    fail,
-                    source_info,
-                    BinOp::Le,
-                    lo,
-                    val.clone(),
-                );
-                let op = match range.end {
-                    RangeEnd::Included => BinOp::Le,
-                    RangeEnd::Excluded => BinOp::Lt,
+
+                if let Some(lo) = range.lo.as_finite() {
+                    let lo = self.literal_operand(test.span, lo);
+                    self.compare(
+                        block,
+                        intermediate_block,
+                        fail,
+                        source_info,
+                        BinOp::Le,
+                        lo,
+                        val.clone(),
+                    );
                 };
-                self.compare(lower_bound_success, success, fail, source_info, op, val, hi);
+
+                if let Some(hi) = range.hi.as_finite() {
+                    let hi = self.literal_operand(test.span, hi);
+                    let op = match range.end {
+                        RangeEnd::Included => BinOp::Le,
+                        RangeEnd::Excluded => BinOp::Lt,
+                    };
+                    self.compare(intermediate_block, success, fail, source_info, op, val, hi);
+                }
             }
 
             TestKind::Len { len, op } => {
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 75613a2c555..733e2f93b25 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -37,7 +37,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
         }
         ty::InstanceDef::FnPtrShim(def_id, ty) => {
             let trait_ = tcx.trait_of_item(def_id).unwrap();
-            let adjustment = match tcx.fn_trait_kind_from_def_id(trait_) {
+            // Supports `Fn` or `async Fn` traits.
+            let adjustment = match tcx
+                .fn_trait_kind_from_def_id(trait_)
+                .or_else(|| tcx.async_fn_trait_kind_from_def_id(trait_))
+            {
                 Some(ty::ClosureKind::FnOnce) => Adjustment::Identity,
                 Some(ty::ClosureKind::Fn) => Adjustment::Deref { source: DerefSource::ImmRef },
                 Some(ty::ClosureKind::FnMut) => Adjustment::Deref { source: DerefSource::MutRef },
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 6c506a8efe0..91dbf0321d2 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -558,14 +558,6 @@ pub(crate) struct CatchAfterTry {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_gen_fn)]
-#[help]
-pub(crate) struct GenFn {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(parse_comma_after_base_struct)]
 #[note]
 pub(crate) struct CommaAfterBaseStruct {
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index e728575ab2d..4cfd061ebd9 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -501,9 +501,11 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                 (kind, self.symbol_from_to(start, end))
             }
             rustc_lexer::LiteralKind::Float { base, empty_exponent } => {
+                let mut kind = token::Float;
                 if empty_exponent {
                     let span = self.mk_sp(start, self.pos);
-                    self.dcx().emit_err(errors::EmptyExponentFloat { span });
+                    let guar = self.dcx().emit_err(errors::EmptyExponentFloat { span });
+                    kind = token::Err(guar);
                 }
                 let base = match base {
                     Base::Hexadecimal => Some("hexadecimal"),
@@ -513,9 +515,11 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                 };
                 if let Some(base) = base {
                     let span = self.mk_sp(start, end);
-                    self.dcx().emit_err(errors::FloatLiteralUnsupportedBase { span, base });
+                    let guar =
+                        self.dcx().emit_err(errors::FloatLiteralUnsupportedBase { span, base });
+                    kind = token::Err(guar)
                 }
-                (token::Float, self.symbol_from_to(start, end))
+                (kind, self.symbol_from_to(start, end))
             }
         }
     }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index f5a7bfd42ff..316a9c4f8df 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1762,24 +1762,25 @@ impl<'a> Parser<'a> {
         err: impl FnOnce(&Self) -> Diag<'a>,
     ) -> L {
         assert!(could_be_unclosed_char_literal(ident));
-        if let Some(diag) = self.dcx().steal_diagnostic(ident.span, StashKey::LifetimeIsChar) {
-            diag.with_span_suggestion_verbose(
-                ident.span.shrink_to_hi(),
-                "add `'` to close the char literal",
-                "'",
-                Applicability::MaybeIncorrect,
-            )
-            .emit();
-        } else {
-            err(self)
-                .with_span_suggestion_verbose(
+        self.dcx()
+            .try_steal_modify_and_emit_err(ident.span, StashKey::LifetimeIsChar, |err| {
+                err.span_suggestion_verbose(
                     ident.span.shrink_to_hi(),
                     "add `'` to close the char literal",
                     "'",
                     Applicability::MaybeIncorrect,
-                )
-                .emit();
-        }
+                );
+            })
+            .unwrap_or_else(|| {
+                err(self)
+                    .with_span_suggestion_verbose(
+                        ident.span.shrink_to_hi(),
+                        "add `'` to close the char literal",
+                        "'",
+                        Applicability::MaybeIncorrect,
+                    )
+                    .emit()
+            });
         let name = ident.without_first_quote().name;
         mk_lit_char(name, ident.span)
     }
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 648ef9d51de..c223b847528 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -187,7 +187,7 @@ passes_doc_attr_not_crate_level =
     `#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute
 
 passes_doc_cfg_hide_takes_list =
-    `#[doc(cfg_hide(...)]` takes a list of attributes
+    `#[doc(cfg_hide(...))]` takes a list of attributes
 
 passes_doc_expect_str =
     doc {$attr_name} attribute expects a string: #[doc({$attr_name} = "a")]
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index c12d35ec73c..04c0cf7436e 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -2520,14 +2520,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
         if attr.style == AttrStyle::Inner {
             for attr_to_check in ATTRS_TO_CHECK {
                 if attr.has_name(*attr_to_check) {
-                    if let AttrKind::Normal(ref p) = attr.kind
-                        && let Some(diag) = tcx.dcx().steal_diagnostic(
-                            p.item.path.span,
-                            StashKey::UndeterminedMacroResolution,
-                        )
-                    {
-                        diag.cancel();
-                    }
                     let item = tcx
                         .hir()
                         .items()
@@ -2537,7 +2529,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
                             span: item.ident.span,
                             kind: item.kind.descr(),
                         });
-                    tcx.dcx().emit_err(errors::InvalidAttrAtCrateLevel {
+                    let err = tcx.dcx().create_err(errors::InvalidAttrAtCrateLevel {
                         span: attr.span,
                         sugg_span: tcx
                             .sess
@@ -2553,6 +2545,16 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
                         name: *attr_to_check,
                         item,
                     });
+
+                    if let AttrKind::Normal(ref p) = attr.kind {
+                        tcx.dcx().try_steal_replace_and_emit_err(
+                            p.item.path.span,
+                            StashKey::UndeterminedMacroResolution,
+                            err,
+                        );
+                    } else {
+                        err.emit();
+                    }
                 }
             }
         }
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs
index 483986969d1..767227619b0 100644
--- a/compiler/rustc_pattern_analysis/src/constructor.rs
+++ b/compiler/rustc_pattern_analysis/src/constructor.rs
@@ -688,6 +688,9 @@ pub enum Constructor<Cx: TypeCx> {
     /// Fake extra constructor for constructors that are not seen in the matrix, as explained at the
     /// top of the file.
     Missing,
+    /// Fake extra constructor that indicates and empty field that is private. When we encounter one
+    /// we skip the column entirely so we don't observe its emptiness. Only used for specialization.
+    PrivateUninhabited,
 }
 
 impl<Cx: TypeCx> Clone for Constructor<Cx> {
@@ -709,6 +712,7 @@ impl<Cx: TypeCx> Clone for Constructor<Cx> {
             Constructor::NonExhaustive => Constructor::NonExhaustive,
             Constructor::Hidden => Constructor::Hidden,
             Constructor::Missing => Constructor::Missing,
+            Constructor::PrivateUninhabited => Constructor::PrivateUninhabited,
         }
     }
 }
@@ -763,6 +767,8 @@ impl<Cx: TypeCx> Constructor<Cx> {
             }
             // Wildcards cover anything
             (_, Wildcard) => true,
+            // `PrivateUninhabited` skips everything.
+            (PrivateUninhabited, _) => true,
             // Only a wildcard pattern can match these special constructors.
             (Missing { .. } | NonExhaustive | Hidden, _) => false,
 
@@ -940,7 +946,7 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
             }
             ConstructorSet::Variants { variants, non_exhaustive } => {
                 let mut seen_set = index::IdxSet::new_empty(variants.len());
-                for idx in seen.iter().map(|c| c.as_variant().unwrap()) {
+                for idx in seen.iter().filter_map(|c| c.as_variant()) {
                     seen_set.insert(idx);
                 }
                 let mut skipped_a_hidden_variant = false;
@@ -969,7 +975,7 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
             ConstructorSet::Bool => {
                 let mut seen_false = false;
                 let mut seen_true = false;
-                for b in seen.iter().map(|ctor| ctor.as_bool().unwrap()) {
+                for b in seen.iter().filter_map(|ctor| ctor.as_bool()) {
                     if b {
                         seen_true = true;
                     } else {
@@ -989,7 +995,7 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
             }
             ConstructorSet::Integers { range_1, range_2 } => {
                 let seen_ranges: Vec<_> =
-                    seen.iter().map(|ctor| *ctor.as_int_range().unwrap()).collect();
+                    seen.iter().filter_map(|ctor| ctor.as_int_range()).copied().collect();
                 for (seen, splitted_range) in range_1.split(seen_ranges.iter().cloned()) {
                     match seen {
                         Presence::Unseen => missing.push(IntRange(splitted_range)),
@@ -1006,7 +1012,7 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
                 }
             }
             ConstructorSet::Slice { array_len, subtype_is_empty } => {
-                let seen_slices = seen.iter().map(|c| c.as_slice().unwrap());
+                let seen_slices = seen.iter().filter_map(|c| c.as_slice());
                 let base_slice = Slice::new(*array_len, VarLen(0, 0));
                 for (seen, splitted_slice) in base_slice.split(seen_slices) {
                     let ctor = Slice(splitted_slice);
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index 164dc36b679..d4b38d260e7 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -82,6 +82,11 @@ use crate::usefulness::{compute_match_usefulness, ValidityConstraint};
 pub trait Captures<'a> {}
 impl<'a, T: ?Sized> Captures<'a> for T {}
 
+/// `bool` newtype that indicates whether this is a privately uninhabited field that we should skip
+/// during analysis.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub struct PrivateUninhabitedField(pub bool);
+
 /// Context that provides type information about constructors.
 ///
 /// Most of the crate is parameterized on a type that implements this trait.
@@ -105,13 +110,12 @@ pub trait TypeCx: Sized + fmt::Debug {
     /// The number of fields for this constructor.
     fn ctor_arity(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> usize;
 
-    /// The types of the fields for this constructor. The result must have a length of
-    /// `ctor_arity()`.
+    /// The types of the fields for this constructor. The result must contain `ctor_arity()` fields.
     fn ctor_sub_tys<'a>(
         &'a self,
         ctor: &'a Constructor<Self>,
         ty: &'a Self::Ty,
-    ) -> impl Iterator<Item = Self::Ty> + ExactSizeIterator + Captures<'a>;
+    ) -> impl Iterator<Item = (Self::Ty, PrivateUninhabitedField)> + ExactSizeIterator + Captures<'a>;
 
     /// The set of all the constructors for `ty`.
     ///
diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs
index d9b2b31643d..decbfa5c0cf 100644
--- a/compiler/rustc_pattern_analysis/src/pat.rs
+++ b/compiler/rustc_pattern_analysis/src/pat.rs
@@ -5,7 +5,7 @@ use std::fmt;
 use smallvec::{smallvec, SmallVec};
 
 use crate::constructor::{Constructor, Slice, SliceKind};
-use crate::TypeCx;
+use crate::{PrivateUninhabitedField, TypeCx};
 
 use self::Constructor::*;
 
@@ -23,11 +23,6 @@ impl PatId {
 /// Values and patterns can be represented as a constructor applied to some fields. This represents
 /// a pattern in this form. A `DeconstructedPat` will almost always come from user input; the only
 /// exception are some `Wildcard`s introduced during pattern lowering.
-///
-/// Note that the number of fields may not match the fields declared in the original struct/variant.
-/// This happens if a private or `non_exhaustive` field is uninhabited, because the code mustn't
-/// observe that it is uninhabited. In that case that field is not included in `fields`. Care must
-/// be taken when converting to/from `thir::Pat`.
 pub struct DeconstructedPat<Cx: TypeCx> {
     ctor: Constructor<Cx>,
     fields: Vec<DeconstructedPat<Cx>>,
@@ -84,6 +79,8 @@ impl<Cx: TypeCx> DeconstructedPat<Cx> {
         match (&self.ctor, other_ctor) {
             // Return a wildcard for each field of `other_ctor`.
             (Wildcard, _) => wildcard_sub_tys(),
+            // Skip this column.
+            (_, PrivateUninhabited) => smallvec![],
             // The only non-trivial case: two slices of different arity. `other_slice` is
             // guaranteed to have a larger arity, so we fill the middle part with enough
             // wildcards to reach the length of the new, larger slice.
@@ -192,7 +189,9 @@ impl<Cx: TypeCx> fmt::Debug for DeconstructedPat<Cx> {
                 }
                 Ok(())
             }
-            Wildcard | Missing { .. } | NonExhaustive | Hidden => write!(f, "_ : {:?}", pat.ty()),
+            Wildcard | Missing | NonExhaustive | Hidden | PrivateUninhabited => {
+                write!(f, "_ : {:?}", pat.ty())
+            }
         }
     }
 }
@@ -300,7 +299,11 @@ impl<Cx: TypeCx> WitnessPat<Cx> {
     /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
     /// `Some(_)`.
     pub(crate) fn wild_from_ctor(cx: &Cx, ctor: Constructor<Cx>, ty: Cx::Ty) -> Self {
-        let fields = cx.ctor_sub_tys(&ctor, &ty).map(|ty| Self::wildcard(ty)).collect();
+        let fields = cx
+            .ctor_sub_tys(&ctor, &ty)
+            .filter(|(_, PrivateUninhabitedField(skip))| !skip)
+            .map(|(ty, _)| Self::wildcard(ty))
+            .collect();
         Self::new(ctor, fields, ty)
     }
 
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 5b62731e202..7a0562e12f1 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -10,7 +10,7 @@ use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::{self, Const};
 use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange, PatRangeBoundary};
 use rustc_middle::ty::layout::IntegerExt;
-use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeVisitableExt, VariantDef};
+use rustc_middle::ty::{self, FieldDef, OpaqueTypeKey, Ty, TyCtxt, TypeVisitableExt, VariantDef};
 use rustc_session::lint;
 use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT};
@@ -18,7 +18,7 @@ use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT};
 use crate::constructor::{
     IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility,
 };
-use crate::{errors, Captures, TypeCx};
+use crate::{errors, Captures, PrivateUninhabitedField, TypeCx};
 
 use crate::constructor::Constructor::*;
 
@@ -158,34 +158,19 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
         }
     }
 
-    // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
-    // uninhabited fields in order not to reveal the uninhabitedness of the whole variant.
-    // This lists the fields we keep along with their types.
-    pub(crate) fn list_variant_nonhidden_fields(
+    pub(crate) fn variant_sub_tys(
         &self,
         ty: RevealedTy<'tcx>,
         variant: &'tcx VariantDef,
-    ) -> impl Iterator<Item = (FieldIdx, RevealedTy<'tcx>)> + Captures<'p> + Captures<'_> {
-        let cx = self;
-        let ty::Adt(adt, args) = ty.kind() else { bug!() };
-        // Whether we must not match the fields of this variant exhaustively.
-        let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did().is_local();
-
-        variant.fields.iter().enumerate().filter_map(move |(i, field)| {
-            let ty = field.ty(cx.tcx, args);
+    ) -> impl Iterator<Item = (&'tcx FieldDef, RevealedTy<'tcx>)> + Captures<'p> + Captures<'_>
+    {
+        let ty::Adt(_, args) = ty.kind() else { bug!() };
+        variant.fields.iter().map(move |field| {
+            let ty = field.ty(self.tcx, args);
             // `field.ty()` doesn't normalize after instantiating.
-            let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
-            let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
-            let is_uninhabited = (cx.tcx.features().exhaustive_patterns
-                || cx.tcx.features().min_exhaustive_patterns)
-                && cx.is_uninhabited(ty);
-
-            if is_uninhabited && (!is_visible || is_non_exhaustive) {
-                None
-            } else {
-                let ty = cx.reveal_opaque_ty(ty);
-                Some((FieldIdx::new(i), ty))
-            }
+            let ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
+            let ty = self.reveal_opaque_ty(ty);
+            (field, ty)
         })
     }
 
@@ -210,12 +195,17 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
         &'a self,
         ctor: &'a Constructor<'p, 'tcx>,
         ty: RevealedTy<'tcx>,
-    ) -> impl Iterator<Item = RevealedTy<'tcx>> + ExactSizeIterator + Captures<'a> {
+    ) -> impl Iterator<Item = (RevealedTy<'tcx>, PrivateUninhabitedField)>
+    + ExactSizeIterator
+    + Captures<'a> {
         fn reveal_and_alloc<'a, 'tcx>(
             cx: &'a RustcMatchCheckCtxt<'_, 'tcx>,
             iter: impl Iterator<Item = Ty<'tcx>>,
-        ) -> &'a [RevealedTy<'tcx>] {
-            cx.dropless_arena.alloc_from_iter(iter.map(|ty| cx.reveal_opaque_ty(ty)))
+        ) -> &'a [(RevealedTy<'tcx>, PrivateUninhabitedField)] {
+            cx.dropless_arena.alloc_from_iter(
+                iter.map(|ty| cx.reveal_opaque_ty(ty))
+                    .map(|ty| (ty, PrivateUninhabitedField(false))),
+            )
         }
         let cx = self;
         let slice = match ctor {
@@ -229,7 +219,21 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
                     } else {
                         let variant =
                             &adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt));
-                        let tys = cx.list_variant_nonhidden_fields(ty, variant).map(|(_, ty)| ty);
+
+                        // In the cases of either a `#[non_exhaustive]` field list or a non-public
+                        // field, we skip uninhabited fields in order not to reveal the
+                        // uninhabitedness of the whole variant.
+                        let is_non_exhaustive =
+                            variant.is_field_list_non_exhaustive() && !adt.did().is_local();
+                        let tys = cx.variant_sub_tys(ty, variant).map(|(field, ty)| {
+                            let is_visible =
+                                adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
+                            let is_uninhabited = (cx.tcx.features().exhaustive_patterns
+                                || cx.tcx.features().min_exhaustive_patterns)
+                                && cx.is_uninhabited(*ty);
+                            let skip = is_uninhabited && (!is_visible || is_non_exhaustive);
+                            (ty, PrivateUninhabitedField(skip))
+                        });
                         cx.dropless_arena.alloc_from_iter(tys)
                     }
                 }
@@ -246,16 +250,8 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
                 }
                 _ => bug!("bad slice pattern {:?} {:?}", ctor, ty),
             },
-            Bool(..)
-            | IntRange(..)
-            | F32Range(..)
-            | F64Range(..)
-            | Str(..)
-            | Opaque(..)
-            | NonExhaustive
-            | Hidden
-            | Missing { .. }
-            | Wildcard => &[],
+            Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
+            | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => &[],
             Or => {
                 bug!("called `Fields::wildcards` on an `Or` ctor")
             }
@@ -274,25 +270,16 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
                         // patterns. If we're here we can assume this is a box pattern.
                         1
                     } else {
-                        let variant =
-                            &adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt));
-                        self.list_variant_nonhidden_fields(ty, variant).count()
+                        let variant_idx = RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt);
+                        adt.variant(variant_idx).fields.len()
                     }
                 }
                 _ => bug!("Unexpected type for constructor `{ctor:?}`: {ty:?}"),
             },
             Ref => 1,
             Slice(slice) => slice.arity(),
-            Bool(..)
-            | IntRange(..)
-            | F32Range(..)
-            | F64Range(..)
-            | Str(..)
-            | Opaque(..)
-            | NonExhaustive
-            | Hidden
-            | Missing { .. }
-            | Wildcard => 0,
+            Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
+            | NonExhaustive | Hidden | Missing | PrivateUninhabited | Wildcard => 0,
             Or => bug!("The `Or` constructor doesn't have a fixed arity"),
         }
     }
@@ -520,20 +507,12 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
                         };
                         let variant =
                             &adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt));
-                        // For each field in the variant, we store the relevant index into `self.fields` if any.
-                        let mut field_id_to_id: Vec<Option<usize>> =
-                            (0..variant.fields.len()).map(|_| None).collect();
-                        let tys = cx.list_variant_nonhidden_fields(ty, variant).enumerate().map(
-                            |(i, (field, ty))| {
-                                field_id_to_id[field.index()] = Some(i);
-                                ty
-                            },
-                        );
-                        fields = tys.map(|ty| DeconstructedPat::wildcard(ty)).collect();
+                        fields = cx
+                            .variant_sub_tys(ty, variant)
+                            .map(|(_, ty)| DeconstructedPat::wildcard(ty))
+                            .collect();
                         for pat in subpatterns {
-                            if let Some(i) = field_id_to_id[pat.field.index()] {
-                                fields[i] = self.lower_pat(&pat.pattern);
-                            }
+                            fields[pat.field.index()] = self.lower_pat(&pat.pattern);
                         }
                     }
                     _ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, ty),
@@ -775,11 +754,9 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
                 ty::Adt(adt_def, args) => {
                     let variant_index =
                         RustcMatchCheckCtxt::variant_index_for_adt(&pat.ctor(), *adt_def);
-                    let variant = &adt_def.variant(variant_index);
-                    let subpatterns = cx
-                        .list_variant_nonhidden_fields(*pat.ty(), variant)
-                        .zip(subpatterns)
-                        .map(|((field, _ty), pattern)| FieldPat { field, pattern })
+                    let subpatterns = subpatterns
+                        .enumerate()
+                        .map(|(i, pattern)| FieldPat { field: FieldIdx::new(i), pattern })
                         .collect();
 
                     if adt_def.is_enum() {
@@ -830,7 +807,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
                 }
             }
             &Str(value) => PatKind::Constant { value },
-            Wildcard | NonExhaustive | Hidden => PatKind::Wild,
+            Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind::Wild,
             Missing { .. } => bug!(
                 "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
                 `Missing` should have been processed in `apply_constructors`"
@@ -866,7 +843,8 @@ impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
         &'a self,
         ctor: &'a crate::constructor::Constructor<Self>,
         ty: &'a Self::Ty,
-    ) -> impl Iterator<Item = Self::Ty> + ExactSizeIterator + Captures<'a> {
+    ) -> impl Iterator<Item = (Self::Ty, PrivateUninhabitedField)> + ExactSizeIterator + Captures<'a>
+    {
         self.ctor_sub_tys(ctor, *ty)
     }
     fn ctors_for_ty(
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index f672051be5a..bbe02f94c0a 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -716,7 +716,7 @@ use std::fmt;
 
 use crate::constructor::{Constructor, ConstructorSet, IntRange};
 use crate::pat::{DeconstructedPat, PatId, PatOrWild, WitnessPat};
-use crate::{Captures, MatchArm, TypeCx};
+use crate::{Captures, MatchArm, PrivateUninhabitedField, TypeCx};
 
 use self::ValidityConstraint::*;
 
@@ -817,6 +817,9 @@ impl fmt::Display for ValidityConstraint {
 struct PlaceInfo<Cx: TypeCx> {
     /// The type of the place.
     ty: Cx::Ty,
+    /// Whether the place is a private uninhabited field. If so we skip this field during analysis
+    /// so that we don't observe its emptiness.
+    private_uninhabited: bool,
     /// Whether the place is known to contain valid data.
     validity: ValidityConstraint,
     /// Whether the place is the scrutinee itself or a subplace of it.
@@ -833,8 +836,9 @@ impl<Cx: TypeCx> PlaceInfo<Cx> {
     ) -> impl Iterator<Item = Self> + ExactSizeIterator + Captures<'a> {
         let ctor_sub_tys = cx.ctor_sub_tys(ctor, &self.ty);
         let ctor_sub_validity = self.validity.specialize(ctor);
-        ctor_sub_tys.map(move |ty| PlaceInfo {
+        ctor_sub_tys.map(move |(ty, PrivateUninhabitedField(private_uninhabited))| PlaceInfo {
             ty,
+            private_uninhabited,
             validity: ctor_sub_validity,
             is_scrutinee: false,
         })
@@ -856,6 +860,11 @@ impl<Cx: TypeCx> PlaceInfo<Cx> {
     where
         Cx: 'a,
     {
+        if self.private_uninhabited {
+            // Skip the whole column
+            return Ok((smallvec![Constructor::PrivateUninhabited], vec![]));
+        }
+
         let ctors_for_ty = cx.ctors_for_ty(&self.ty)?;
 
         // We treat match scrutinees of type `!` or `EmptyEnum` differently.
@@ -914,7 +923,12 @@ impl<Cx: TypeCx> PlaceInfo<Cx> {
 
 impl<Cx: TypeCx> Clone for PlaceInfo<Cx> {
     fn clone(&self) -> Self {
-        Self { ty: self.ty.clone(), validity: self.validity, is_scrutinee: self.is_scrutinee }
+        Self {
+            ty: self.ty.clone(),
+            private_uninhabited: self.private_uninhabited,
+            validity: self.validity,
+            is_scrutinee: self.is_scrutinee,
+        }
     }
 }
 
@@ -1121,7 +1135,12 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
         scrut_ty: Cx::Ty,
         scrut_validity: ValidityConstraint,
     ) -> Self {
-        let place_info = PlaceInfo { ty: scrut_ty, validity: scrut_validity, is_scrutinee: true };
+        let place_info = PlaceInfo {
+            ty: scrut_ty,
+            private_uninhabited: false,
+            validity: scrut_validity,
+            is_scrutinee: true,
+        };
         let mut matrix = Matrix {
             rows: Vec::with_capacity(arms.len()),
             place_info: smallvec![place_info],
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 1c6bd887128..9d8a9f5fce3 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -988,10 +988,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
         if let hir::ExprKind::Struct(qpath, fields, ref base) = expr.kind {
             let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
-            let Some(adt) = self.typeck_results().expr_ty(expr).ty_adt_def() else {
-                self.tcx.dcx().span_delayed_bug(expr.span, "no adt_def for expression");
-                return;
-            };
+            let adt = self.typeck_results().expr_ty(expr).ty_adt_def().unwrap();
             let variant = adt.variant_of_res(res);
             if let Some(base) = *base {
                 // If the expression uses FRU we need to make sure all the unmentioned fields
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index e4c596b10b8..40517407ee6 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -149,8 +149,7 @@ where
             let guar = if let Some(root) = cycle_error.cycle.first()
                 && let Some(span) = root.query.span
             {
-                error.stash(span, StashKey::Cycle);
-                qcx.dep_context().sess().dcx().span_delayed_bug(span, "delayed cycle error")
+                error.stash(span, StashKey::Cycle).unwrap()
             } else {
                 error.emit()
             };
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index e4298a98129..6b45db7ba83 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1585,9 +1585,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         {
             // When the suggested binding change would be from `x` to `_x`, suggest changing the
             // original binding definition instead. (#60164)
-            (span, snippet, ", consider changing it")
+            let post = format!(", consider renaming `{}` into `{snippet}`", suggestion.candidate);
+            (span, snippet, post)
         } else {
-            (span, suggestion.candidate.to_string(), "")
+            (span, suggestion.candidate.to_string(), String::new())
         };
         let msg = match suggestion.target {
             SuggestionTarget::SimilarlyNamed => format!(
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index adc4cd911a7..6f23f531996 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -8,32 +8,6 @@ use rustc_span::{
 use crate::{late::PatternSource, Res};
 
 #[derive(Diagnostic)]
-#[diag(resolve_parent_module_reset_for_binding, code = E0637)]
-pub(crate) struct ParentModuleResetForBinding;
-
-#[derive(Diagnostic)]
-#[diag(resolve_ampersand_used_without_explicit_lifetime_name, code = E0637)]
-#[note]
-pub(crate) struct AmpersandUsedWithoutExplicitLifetimeName(#[primary_span] pub(crate) Span);
-
-#[derive(Diagnostic)]
-#[diag(resolve_underscore_lifetime_name_cannot_be_used_here, code = E0637)]
-#[note]
-pub(crate) struct UnderscoreLifetimeNameCannotBeUsedHere(#[primary_span] pub(crate) Span);
-
-#[derive(Diagnostic)]
-#[diag(resolve_crate_may_not_be_imported)]
-pub(crate) struct CrateMayNotBeImported(#[primary_span] pub(crate) Span);
-
-#[derive(Diagnostic)]
-#[diag(resolve_crate_root_imports_must_be_named_explicitly)]
-pub(crate) struct CrateRootNamesMustBeNamedExplicitly(#[primary_span] pub(crate) Span);
-
-#[derive(Diagnostic)]
-#[diag(resolve_crate_root_imports_must_be_named_explicitly)]
-pub(crate) struct ResolutionError(#[primary_span] pub(crate) Span);
-
-#[derive(Diagnostic)]
 #[diag(resolve_generic_params_from_outer_item, code = E0401)]
 pub(crate) struct GenericParamsFromOuterItem {
     #[primary_span]
@@ -468,19 +442,6 @@ pub(crate) struct UnreachableLabelSubLabelUnreachable {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_trait_impl_mismatch)]
-pub(crate) struct TraitImplMismatch {
-    #[primary_span]
-    #[label]
-    pub(crate) span: Span,
-    pub(crate) name: Symbol,
-    pub(crate) kind: String,
-    #[label(resolve_label_trait_item)]
-    pub(crate) trait_item_span: Span,
-    pub(crate) trait_path: String,
-}
-
-#[derive(Diagnostic)]
 #[diag(resolve_invalid_asm_sym)]
 #[help]
 pub(crate) struct InvalidAsmSym {
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 18c8652aaf2..9170b265748 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -106,8 +106,7 @@ pub fn feature_err_issue(
 
     // Cancel an earlier warning for this same error, if it exists.
     if let Some(span) = span.primary_span() {
-        if let Some(err) = sess.parse_sess.dcx.steal_diagnostic(span, StashKey::EarlySyntaxWarning)
-        {
+        if let Some(err) = sess.parse_sess.dcx.steal_non_err(span, StashKey::EarlySyntaxWarning) {
             err.cancel()
         }
     }
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 0d7b9afab5e..42d9b519c14 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -546,8 +546,20 @@ fn encode_ty<'tcx>(
             if let Some(cfi_encoding) = tcx.get_attr(def_id, sym::cfi_encoding) {
                 // Use user-defined CFI encoding for type
                 if let Some(value_str) = cfi_encoding.value_str() {
-                    if !value_str.to_string().trim().is_empty() {
-                        s.push_str(value_str.to_string().trim());
+                    let value_str = value_str.to_string();
+                    let str = value_str.trim();
+                    if !str.is_empty() {
+                        s.push_str(str);
+                        // Don't compress user-defined builtin types (see
+                        // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-builtin and
+                        // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-compression).
+                        let builtin_types = [
+                            "v", "w", "b", "c", "a", "h", "s", "t", "i", "j", "l", "m", "x", "y",
+                            "n", "o", "f", "d", "e", "g", "z",
+                        ];
+                        if !builtin_types.contains(&str) {
+                            compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
+                        }
                     } else {
                         #[allow(
                             rustc::diagnostic_outside_of_impl,
@@ -563,7 +575,6 @@ fn encode_ty<'tcx>(
                 } else {
                     bug!("encode_ty: invalid `cfi_encoding` for `{:?}`", ty.kind());
                 }
-                compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
             } else if options.contains(EncodeTyOptions::GENERALIZE_REPR_C) && adt_def.repr().c() {
                 // For cross-language LLVM CFI support, the encoding must be compatible at the FFI
                 // boundary. For instance:
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
index 9e964d248bf..d6b44e7cfd4 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target};
 pub fn target() -> Target {
     let mut base = base::windows_gnu::opts();
     base.cpu = "x86-64".into();
+    base.features = "+cx16,+sse3,+sahf".into();
     base.plt_by_default = false;
     // Use high-entropy 64 bit address space for ASLR
     base.add_pre_link_args(
@@ -10,7 +11,7 @@ pub fn target() -> Target {
         &["-m", "i386pep", "--high-entropy-va"],
     );
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64", "-Wl,--high-entropy-va"]);
-    base.max_atomic_width = Some(64);
+    base.max_atomic_width = Some(128);
     base.linker = Some("x86_64-w64-mingw32-gcc".into());
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
index 1facf9450cd..b84a9a5a8a1 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
@@ -3,9 +3,10 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target};
 pub fn target() -> Target {
     let mut base = base::windows_gnullvm::opts();
     base.cpu = "x86-64".into();
+    base.features = "+cx16,+sse3,+sahf".into();
     base.plt_by_default = false;
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
-    base.max_atomic_width = Some(64);
+    base.max_atomic_width = Some(128);
     base.linker = Some("x86_64-w64-mingw32-clang".into());
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
index 357261073a8..51807bdba5d 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
@@ -3,8 +3,9 @@ use crate::spec::{base, SanitizerSet, Target};
 pub fn target() -> Target {
     let mut base = base::windows_msvc::opts();
     base.cpu = "x86-64".into();
+    base.features = "+cx16,+sse3,+sahf".into();
     base.plt_by_default = false;
-    base.max_atomic_width = Some(64);
+    base.max_atomic_width = Some(128);
     base.supported_sanitizers = SanitizerSet::ADDRESS;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
index c2981ddbad6..b37d33601e6 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
@@ -3,6 +3,7 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target};
 pub fn target() -> Target {
     let mut base = base::windows_uwp_gnu::opts();
     base.cpu = "x86-64".into();
+    base.features = "+cx16,+sse3,+sahf".into();
     base.plt_by_default = false;
     // Use high-entropy 64 bit address space for ASLR
     base.add_pre_link_args(
@@ -10,7 +11,7 @@ pub fn target() -> Target {
         &["-m", "i386pep", "--high-entropy-va"],
     );
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64", "-Wl,--high-entropy-va"]);
-    base.max_atomic_width = Some(64);
+    base.max_atomic_width = Some(128);
 
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
index 3f0702c7ad6..fe2b4c8e92d 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
@@ -3,8 +3,9 @@ use crate::spec::{base, Target};
 pub fn target() -> Target {
     let mut base = base::windows_uwp_msvc::opts();
     base.cpu = "x86-64".into();
+    base.features = "+cx16,+sse3,+sahf".into();
     base.plt_by_default = false;
-    base.max_atomic_width = Some(64);
+    base.max_atomic_width = Some(128);
 
     Target {
         llvm_target: "x86_64-pc-windows-msvc".into(),
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index 3b902dd80f5..af533d8db71 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -281,7 +281,58 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
         }
 
         // Coroutine-closures don't implement `Fn` traits the normal way.
-        ty::CoroutineClosure(..) => Err(NoSolution),
+        // Instead, they always implement `FnOnce`, but only implement
+        // `FnMut`/`Fn` if they capture no upvars, since those may borrow
+        // from the closure.
+        ty::CoroutineClosure(def_id, args) => {
+            let args = args.as_coroutine_closure();
+            let kind_ty = args.kind_ty();
+            let sig = args.coroutine_closure_sig().skip_binder();
+
+            let coroutine_ty = if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
+                if !closure_kind.extends(goal_kind) {
+                    return Err(NoSolution);
+                }
+
+                // If `Fn`/`FnMut`, we only implement this goal if we
+                // have no captures.
+                let no_borrows = match args.tupled_upvars_ty().kind() {
+                    ty::Tuple(tys) => tys.is_empty(),
+                    ty::Error(_) => false,
+                    _ => bug!("tuple_fields called on non-tuple"),
+                };
+                if closure_kind != ty::ClosureKind::FnOnce && !no_borrows {
+                    return Err(NoSolution);
+                }
+
+                coroutine_closure_to_certain_coroutine(
+                    tcx,
+                    goal_kind,
+                    // No captures by ref, so this doesn't matter.
+                    tcx.lifetimes.re_static,
+                    def_id,
+                    args,
+                    sig,
+                )
+            } else {
+                // Closure kind is not yet determined, so we return ambiguity unless
+                // the expected kind is `FnOnce` as that is always implemented.
+                if goal_kind != ty::ClosureKind::FnOnce {
+                    return Ok(None);
+                }
+
+                coroutine_closure_to_ambiguous_coroutine(
+                    tcx,
+                    goal_kind, // No captures by ref, so this doesn't matter.
+                    tcx.lifetimes.re_static,
+                    def_id,
+                    args,
+                    sig,
+                )
+            };
+
+            Ok(Some(args.coroutine_closure_sig().rebind((sig.tupled_inputs_ty, coroutine_ty))))
+        }
 
         ty::Bool
         | ty::Char
@@ -313,6 +364,19 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
     }
 }
 
+/// Relevant types for an async callable, including its inputs, output,
+/// and the return type you get from awaiting the output.
+#[derive(Copy, Clone, Debug, TypeVisitable, TypeFoldable)]
+pub(in crate::solve) struct AsyncCallableRelevantTypes<'tcx> {
+    pub tupled_inputs_ty: Ty<'tcx>,
+    /// Type returned by calling the closure
+    /// i.e. `f()`.
+    pub output_coroutine_ty: Ty<'tcx>,
+    /// Type returned by `await`ing the output
+    /// i.e. `f().await`.
+    pub coroutine_return_ty: Ty<'tcx>,
+}
+
 // Returns a binder of the tupled inputs types, output type, and coroutine type
 // from a builtin coroutine-closure type. If we don't yet know the closure kind of
 // the coroutine-closure, emit an additional trait predicate for `AsyncFnKindHelper`
@@ -323,8 +387,10 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
     self_ty: Ty<'tcx>,
     goal_kind: ty::ClosureKind,
     env_region: ty::Region<'tcx>,
-) -> Result<(ty::Binder<'tcx, (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>)>, Vec<ty::Predicate<'tcx>>), NoSolution>
-{
+) -> Result<
+    (ty::Binder<'tcx, AsyncCallableRelevantTypes<'tcx>>, Vec<ty::Predicate<'tcx>>),
+    NoSolution,
+> {
     match *self_ty.kind() {
         ty::CoroutineClosure(def_id, args) => {
             let args = args.as_coroutine_closure();
@@ -335,24 +401,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                 if !closure_kind.extends(goal_kind) {
                     return Err(NoSolution);
                 }
-                sig.to_coroutine_given_kind_and_upvars(
-                    tcx,
-                    args.parent_args(),
-                    tcx.coroutine_for_closure(def_id),
-                    goal_kind,
-                    env_region,
-                    args.tupled_upvars_ty(),
-                    args.coroutine_captures_by_ref_ty(),
+
+                coroutine_closure_to_certain_coroutine(
+                    tcx, goal_kind, env_region, def_id, args, sig,
                 )
             } else {
-                let async_fn_kind_trait_def_id =
-                    tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
-                let upvars_projection_def_id = tcx
-                    .associated_items(async_fn_kind_trait_def_id)
-                    .filter_by_name_unhygienic(sym::Upvars)
-                    .next()
-                    .unwrap()
-                    .def_id;
                 // When we don't know the closure kind (and therefore also the closure's upvars,
                 // which are computed at the same time), we must delay the computation of the
                 // generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
@@ -363,38 +416,23 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                 nested.push(
                     ty::TraitRef::new(
                         tcx,
-                        async_fn_kind_trait_def_id,
+                        tcx.require_lang_item(LangItem::AsyncFnKindHelper, None),
                         [kind_ty, Ty::from_closure_kind(tcx, goal_kind)],
                     )
                     .to_predicate(tcx),
                 );
-                let tupled_upvars_ty = Ty::new_projection(
-                    tcx,
-                    upvars_projection_def_id,
-                    [
-                        ty::GenericArg::from(kind_ty),
-                        Ty::from_closure_kind(tcx, goal_kind).into(),
-                        env_region.into(),
-                        sig.tupled_inputs_ty.into(),
-                        args.tupled_upvars_ty().into(),
-                        args.coroutine_captures_by_ref_ty().into(),
-                    ],
-                );
-                sig.to_coroutine(
-                    tcx,
-                    args.parent_args(),
-                    Ty::from_closure_kind(tcx, goal_kind),
-                    tcx.coroutine_for_closure(def_id),
-                    tupled_upvars_ty,
+
+                coroutine_closure_to_ambiguous_coroutine(
+                    tcx, goal_kind, env_region, def_id, args, sig,
                 )
             };
 
             Ok((
-                args.coroutine_closure_sig().rebind((
-                    sig.tupled_inputs_ty,
-                    sig.return_ty,
-                    coroutine_ty,
-                )),
+                args.coroutine_closure_sig().rebind(AsyncCallableRelevantTypes {
+                    tupled_inputs_ty: sig.tupled_inputs_ty,
+                    output_coroutine_ty: coroutine_ty,
+                    coroutine_return_ty: sig.return_ty,
+                }),
                 nested,
             ))
         }
@@ -418,7 +456,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                 .def_id;
             let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
             Ok((
-                bound_sig.rebind((Ty::new_tup(tcx, sig.inputs()), sig.output(), future_output_ty)),
+                bound_sig.rebind(AsyncCallableRelevantTypes {
+                    tupled_inputs_ty: Ty::new_tup(tcx, sig.inputs()),
+                    output_coroutine_ty: sig.output(),
+                    coroutine_return_ty: future_output_ty,
+                }),
                 nested,
             ))
         }
@@ -469,7 +511,14 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                 .unwrap()
                 .def_id;
             let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
-            Ok((bound_sig.rebind((sig.inputs()[0], sig.output(), future_output_ty)), nested))
+            Ok((
+                bound_sig.rebind(AsyncCallableRelevantTypes {
+                    tupled_inputs_ty: sig.inputs()[0],
+                    output_coroutine_ty: sig.output(),
+                    coroutine_return_ty: future_output_ty,
+                }),
+                nested,
+            ))
         }
 
         ty::Bool
@@ -502,6 +551,68 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
     }
 }
 
+/// Given a coroutine-closure, project to its returned coroutine when we are *certain*
+/// that the closure's kind is compatible with the goal.
+fn coroutine_closure_to_certain_coroutine<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    goal_kind: ty::ClosureKind,
+    goal_region: ty::Region<'tcx>,
+    def_id: DefId,
+    args: ty::CoroutineClosureArgs<'tcx>,
+    sig: ty::CoroutineClosureSignature<'tcx>,
+) -> Ty<'tcx> {
+    sig.to_coroutine_given_kind_and_upvars(
+        tcx,
+        args.parent_args(),
+        tcx.coroutine_for_closure(def_id),
+        goal_kind,
+        goal_region,
+        args.tupled_upvars_ty(),
+        args.coroutine_captures_by_ref_ty(),
+    )
+}
+
+/// Given a coroutine-closure, project to its returned coroutine when we are *not certain*
+/// that the closure's kind is compatible with the goal, and therefore also don't know
+/// yet what the closure's upvars are.
+///
+/// Note that we do not also push a `AsyncFnKindHelper` goal here.
+fn coroutine_closure_to_ambiguous_coroutine<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    goal_kind: ty::ClosureKind,
+    goal_region: ty::Region<'tcx>,
+    def_id: DefId,
+    args: ty::CoroutineClosureArgs<'tcx>,
+    sig: ty::CoroutineClosureSignature<'tcx>,
+) -> Ty<'tcx> {
+    let async_fn_kind_trait_def_id = tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
+    let upvars_projection_def_id = tcx
+        .associated_items(async_fn_kind_trait_def_id)
+        .filter_by_name_unhygienic(sym::Upvars)
+        .next()
+        .unwrap()
+        .def_id;
+    let tupled_upvars_ty = Ty::new_projection(
+        tcx,
+        upvars_projection_def_id,
+        [
+            ty::GenericArg::from(args.kind_ty()),
+            Ty::from_closure_kind(tcx, goal_kind).into(),
+            goal_region.into(),
+            sig.tupled_inputs_ty.into(),
+            args.tupled_upvars_ty().into(),
+            args.coroutine_captures_by_ref_ty().into(),
+        ],
+    );
+    sig.to_coroutine(
+        tcx,
+        args.parent_args(),
+        Ty::from_closure_kind(tcx, goal_kind),
+        tcx.coroutine_for_closure(def_id),
+        tupled_upvars_ty,
+    )
+}
+
 /// Assemble a list of predicates that would be present on a theoretical
 /// user impl for an object type. These predicates must be checked any time
 /// we assemble a built-in object candidate for an object type, since they
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index aa8cc3667cd..3aba5c85abc 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -1,5 +1,6 @@
 use crate::traits::{check_args_compatible, specialization_graph};
 
+use super::assembly::structural_traits::AsyncCallableRelevantTypes;
 use super::assembly::{self, structural_traits, Candidate};
 use super::{EvalCtxt, GoalSource};
 use rustc_hir::def::DefKind;
@@ -392,46 +393,56 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                 goal_kind,
                 env_region,
             )?;
-        let output_is_sized_pred =
-            tupled_inputs_and_output_and_coroutine.map_bound(|(_, output, _)| {
-                ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output])
-            });
+        let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
+            |AsyncCallableRelevantTypes { output_coroutine_ty: output_ty, .. }| {
+                ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output_ty])
+            },
+        );
 
         let pred = tupled_inputs_and_output_and_coroutine
-            .map_bound(|(inputs, output, coroutine)| {
-                let (projection_ty, term) = match tcx.item_name(goal.predicate.def_id()) {
-                    sym::CallOnceFuture => (
-                        ty::AliasTy::new(
-                            tcx,
-                            goal.predicate.def_id(),
-                            [goal.predicate.self_ty(), inputs],
+            .map_bound(
+                |AsyncCallableRelevantTypes {
+                     tupled_inputs_ty,
+                     output_coroutine_ty,
+                     coroutine_return_ty,
+                 }| {
+                    let (projection_ty, term) = match tcx.item_name(goal.predicate.def_id()) {
+                        sym::CallOnceFuture => (
+                            ty::AliasTy::new(
+                                tcx,
+                                goal.predicate.def_id(),
+                                [goal.predicate.self_ty(), tupled_inputs_ty],
+                            ),
+                            output_coroutine_ty.into(),
                         ),
-                        coroutine.into(),
-                    ),
-                    sym::CallMutFuture | sym::CallFuture => (
-                        ty::AliasTy::new(
-                            tcx,
-                            goal.predicate.def_id(),
-                            [
-                                ty::GenericArg::from(goal.predicate.self_ty()),
-                                inputs.into(),
-                                env_region.into(),
-                            ],
+                        sym::CallMutFuture | sym::CallFuture => (
+                            ty::AliasTy::new(
+                                tcx,
+                                goal.predicate.def_id(),
+                                [
+                                    ty::GenericArg::from(goal.predicate.self_ty()),
+                                    tupled_inputs_ty.into(),
+                                    env_region.into(),
+                                ],
+                            ),
+                            output_coroutine_ty.into(),
                         ),
-                        coroutine.into(),
-                    ),
-                    sym::Output => (
-                        ty::AliasTy::new(
-                            tcx,
-                            goal.predicate.def_id(),
-                            [ty::GenericArg::from(goal.predicate.self_ty()), inputs.into()],
+                        sym::Output => (
+                            ty::AliasTy::new(
+                                tcx,
+                                goal.predicate.def_id(),
+                                [
+                                    ty::GenericArg::from(goal.predicate.self_ty()),
+                                    tupled_inputs_ty.into(),
+                                ],
+                            ),
+                            coroutine_return_ty.into(),
                         ),
-                        output.into(),
-                    ),
-                    name => bug!("no such associated type: {name}"),
-                };
-                ty::ProjectionPredicate { projection_ty, term }
-            })
+                        name => bug!("no such associated type: {name}"),
+                    };
+                    ty::ProjectionPredicate { projection_ty, term }
+                },
+            )
             .to_predicate(tcx);
 
         // A built-in `AsyncFn` impl only holds if the output is sized.
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 73bf66f6689..eba6ba3f7b0 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -2,6 +2,7 @@
 
 use crate::traits::supertrait_def_ids;
 
+use super::assembly::structural_traits::AsyncCallableRelevantTypes;
 use super::assembly::{self, structural_traits, Candidate};
 use super::{EvalCtxt, GoalSource, SolverMode};
 use rustc_data_structures::fx::FxIndexSet;
@@ -327,14 +328,19 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
                 // This region doesn't matter because we're throwing away the coroutine type
                 tcx.lifetimes.re_static,
             )?;
-        let output_is_sized_pred =
-            tupled_inputs_and_output_and_coroutine.map_bound(|(_, output, _)| {
-                ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output])
-            });
+        let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
+            |AsyncCallableRelevantTypes { output_coroutine_ty, .. }| {
+                ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output_coroutine_ty])
+            },
+        );
 
         let pred = tupled_inputs_and_output_and_coroutine
-            .map_bound(|(inputs, _, _)| {
-                ty::TraitRef::new(tcx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
+            .map_bound(|AsyncCallableRelevantTypes { tupled_inputs_ty, .. }| {
+                ty::TraitRef::new(
+                    tcx,
+                    goal.predicate.def_id(),
+                    [goal.predicate.self_ty(), tupled_inputs_ty],
+                )
             })
             .to_predicate(tcx);
         // A built-in `AsyncFn` impl only holds if the output is sized.
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 1aaadf6cf04..e789e9c2b6e 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -107,6 +107,15 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
         self.register_infer_ok_obligations(infer_ok)
     }
 
+    pub fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        value: T,
+    ) -> Result<T, Vec<FulfillmentError<'tcx>>> {
+        self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut())
+    }
+
     /// Makes `expected <: actual`.
     pub fn eq_exp<T>(
         &self,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index dcbb63f00f7..d9e49f1eb0a 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -889,7 +889,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 }
             }
 
-            SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id) => self.report_opaque_type_auto_trait_leakage(
+            SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id) => return self.report_opaque_type_auto_trait_leakage(
                 &obligation,
                 def_id,
             ),
@@ -2252,8 +2252,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 ErrorCode::E0282,
                                 false,
                             );
-                            err.stash(span, StashKey::MaybeForgetReturn);
-                            return self.dcx().delayed_bug("stashed error never reported");
+                            return err.stash(span, StashKey::MaybeForgetReturn).unwrap();
                         }
                         Some(e) => return e,
                     }
@@ -2766,7 +2765,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             self.suggest_unsized_bound_if_applicable(err, obligation);
             if let Some(span) = err.span.primary_span()
                 && let Some(mut diag) =
-                    self.tcx.dcx().steal_diagnostic(span, StashKey::AssociatedTypeSuggestion)
+                    self.tcx.dcx().steal_non_err(span, StashKey::AssociatedTypeSuggestion)
                 && let Ok(ref mut s1) = err.suggestions
                 && let Ok(ref mut s2) = diag.suggestions
             {
@@ -3291,7 +3290,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         &self,
         obligation: &PredicateObligation<'tcx>,
         def_id: DefId,
-    ) -> Diag<'tcx> {
+    ) -> ErrorGuaranteed {
         let name = match self.tcx.opaque_type_origin(def_id.expect_local()) {
             hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => {
                 "opaque type".to_string()
@@ -3318,12 +3317,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             }
         };
 
-        if let Some(diag) = self.dcx().steal_diagnostic(self.tcx.def_span(def_id), StashKey::Cycle)
-        {
-            diag.cancel();
-        }
-
-        err
+        self.note_obligation_cause(&mut err, &obligation);
+        self.point_at_returns_when_relevant(&mut err, &obligation);
+        self.dcx().try_steal_replace_and_emit_err(self.tcx.def_span(def_id), StashKey::Cycle, err)
     }
 
     fn report_signature_mismatch_error(
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index d316149731e..b8733bab27b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -923,14 +923,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         [self_ty, Ty::new_tup(tcx, sig.inputs())],
                     )
                 });
+
                 // We must additionally check that the return type impls `Future`.
+
+                // FIXME(async_closures): Investigate this before stabilization.
+                // We instantiate this binder eagerly because the `confirm_future_candidate`
+                // method doesn't support higher-ranked futures, which the `AsyncFn`
+                // traits expressly allow the user to write. To fix this correctly,
+                // we'd need to instantiate trait bounds before we get to selection,
+                // like the new trait solver does.
                 let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
+                let placeholder_output_ty = self.infcx.enter_forall_and_leak_universe(sig.output());
                 nested.push(obligation.with(
                     tcx,
-                    sig.map_bound(|sig| {
-                        ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()])
-                    }),
+                    ty::TraitRef::new(tcx, future_trait_def_id, [placeholder_output_ty]),
                 ));
+
                 (trait_ref, Ty::from_closure_kind(tcx, ty::ClosureKind::Fn))
             }
             ty::Closure(_, args) => {
@@ -943,14 +951,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         [self_ty, sig.inputs()[0]],
                     )
                 });
+
                 // We must additionally check that the return type impls `Future`.
+                // See FIXME in last branch for why we instantiate the binder eagerly.
                 let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
+                let placeholder_output_ty = self.infcx.enter_forall_and_leak_universe(sig.output());
                 nested.push(obligation.with(
                     tcx,
-                    sig.map_bound(|sig| {
-                        ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()])
-                    }),
+                    ty::TraitRef::new(tcx, future_trait_def_id, [placeholder_output_ty]),
                 ));
+
                 (trait_ref, args.kind_ty())
             }
             _ => bug!("expected callable type for AsyncFn candidate"),
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 45e93feb6c5..28695ade5bf 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -152,6 +152,7 @@
 #![feature(set_ptr_value)]
 #![feature(sized_type_properties)]
 #![feature(slice_from_ptr_range)]
+#![feature(slice_index_methods)]
 #![feature(slice_ptr_get)]
 #![feature(slice_ptr_len)]
 #![feature(slice_range)]
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 1d3c04f7807..98ded7f6cdf 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -54,7 +54,7 @@ use core::ops::Add;
 use core::ops::AddAssign;
 #[cfg(not(no_global_oom_handling))]
 use core::ops::Bound::{Excluded, Included, Unbounded};
-use core::ops::{self, Index, IndexMut, Range, RangeBounds};
+use core::ops::{self, Range, RangeBounds};
 use core::ptr;
 use core::slice;
 use core::str::pattern::Pattern;
@@ -2433,100 +2433,26 @@ impl AddAssign<&str> for String {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl ops::Index<ops::Range<usize>> for String {
-    type Output = str;
+impl<I> ops::Index<I> for String
+where
+    I: slice::SliceIndex<str>,
+{
+    type Output = I::Output;
 
     #[inline]
-    fn index(&self, index: ops::Range<usize>) -> &str {
-        &self[..][index]
+    fn index(&self, index: I) -> &I::Output {
+        index.index(self.as_str())
     }
 }
-#[stable(feature = "rust1", since = "1.0.0")]
-impl ops::Index<ops::RangeTo<usize>> for String {
-    type Output = str;
 
-    #[inline]
-    fn index(&self, index: ops::RangeTo<usize>) -> &str {
-        &self[..][index]
-    }
-}
 #[stable(feature = "rust1", since = "1.0.0")]
-impl ops::Index<ops::RangeFrom<usize>> for String {
-    type Output = str;
-
-    #[inline]
-    fn index(&self, index: ops::RangeFrom<usize>) -> &str {
-        &self[..][index]
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl ops::Index<ops::RangeFull> for String {
-    type Output = str;
-
-    #[inline]
-    fn index(&self, _index: ops::RangeFull) -> &str {
-        unsafe { str::from_utf8_unchecked(&self.vec) }
-    }
-}
-#[stable(feature = "inclusive_range", since = "1.26.0")]
-impl ops::Index<ops::RangeInclusive<usize>> for String {
-    type Output = str;
-
-    #[inline]
-    fn index(&self, index: ops::RangeInclusive<usize>) -> &str {
-        Index::index(&**self, index)
-    }
-}
-#[stable(feature = "inclusive_range", since = "1.26.0")]
-impl ops::Index<ops::RangeToInclusive<usize>> for String {
-    type Output = str;
-
-    #[inline]
-    fn index(&self, index: ops::RangeToInclusive<usize>) -> &str {
-        Index::index(&**self, index)
-    }
-}
-
-#[stable(feature = "derefmut_for_string", since = "1.3.0")]
-impl ops::IndexMut<ops::Range<usize>> for String {
-    #[inline]
-    fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
-        &mut self[..][index]
-    }
-}
-#[stable(feature = "derefmut_for_string", since = "1.3.0")]
-impl ops::IndexMut<ops::RangeTo<usize>> for String {
-    #[inline]
-    fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
-        &mut self[..][index]
-    }
-}
-#[stable(feature = "derefmut_for_string", since = "1.3.0")]
-impl ops::IndexMut<ops::RangeFrom<usize>> for String {
-    #[inline]
-    fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
-        &mut self[..][index]
-    }
-}
-#[stable(feature = "derefmut_for_string", since = "1.3.0")]
-impl ops::IndexMut<ops::RangeFull> for String {
-    #[inline]
-    fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
-        unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
-    }
-}
-#[stable(feature = "inclusive_range", since = "1.26.0")]
-impl ops::IndexMut<ops::RangeInclusive<usize>> for String {
-    #[inline]
-    fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &mut str {
-        IndexMut::index_mut(&mut **self, index)
-    }
-}
-#[stable(feature = "inclusive_range", since = "1.26.0")]
-impl ops::IndexMut<ops::RangeToInclusive<usize>> for String {
+impl<I> ops::IndexMut<I> for String
+where
+    I: slice::SliceIndex<str>,
+{
     #[inline]
-    fn index_mut(&mut self, index: ops::RangeToInclusive<usize>) -> &mut str {
-        IndexMut::index_mut(&mut **self, index)
+    fn index_mut(&mut self, index: I) -> &mut I::Output {
+        index.index_mut(self.as_mut_str())
     }
 }
 
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 20f4310603a..d2804b4d20a 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -48,7 +48,7 @@ dlmalloc = { version = "0.2.4", features = ['rustc-dep-of-std'] }
 fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'], public = true }
 
 [target.'cfg(target_os = "hermit")'.dependencies]
-hermit-abi = { version = "0.3.2", features = ['rustc-dep-of-std'], public = true }
+hermit-abi = { version = "0.3.9", features = ['rustc-dep-of-std'], public = true }
 
 [target.'cfg(target_os = "wasi")'.dependencies]
 wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 5bd20ebe208..1f2b8d3007d 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -258,6 +258,9 @@ fn _var(key: &OsStr) -> Result<String, VarError> {
 ///     None => println!("{key} is not defined in the environment.")
 /// }
 /// ```
+///
+/// If expecting a delimited variable (such as `PATH`), [`split_paths`]
+/// can be used to separate items.
 #[must_use]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn var_os<K: AsRef<OsStr>>(key: K) -> Option<OsString> {
@@ -441,6 +444,16 @@ pub struct SplitPaths<'a> {
 /// Returns an iterator over the paths contained in `unparsed`. The iterator
 /// element type is [`PathBuf`].
 ///
+/// On most Unix platforms, the separator is `:` and on Windows it is `;`. This
+/// also performs unquoting on Windows.
+///
+/// [`join_paths`] can be used to recombine elements.
+///
+/// # Panics
+///
+/// This will panic on systems where there is no delimited `PATH` variable,
+/// such as UEFI.
+///
 /// # Examples
 ///
 /// ```
@@ -456,6 +469,7 @@ pub struct SplitPaths<'a> {
 ///     None => println!("{key} is not defined in the environment.")
 /// }
 /// ```
+#[doc(alias = "PATH")]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths<'_> {
     SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) }
@@ -496,7 +510,8 @@ pub struct JoinPathsError {
 ///
 /// Returns an [`Err`] (containing an error message) if one of the input
 /// [`Path`]s contains an invalid character for constructing the `PATH`
-/// variable (a double quote on Windows or a colon on Unix).
+/// variable (a double quote on Windows or a colon on Unix), or if the system
+/// does not have a `PATH`-like variable (e.g. UEFI or WASI).
 ///
 /// # Examples
 ///
@@ -550,6 +565,7 @@ pub struct JoinPathsError {
 /// ```
 ///
 /// [`env::split_paths()`]: split_paths
+#[doc(alias = "PATH")]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
 where
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index b60d7a72411..6ec389400ae 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -31,6 +31,8 @@ pub use core::f32::{
 impl f32 {
     /// Returns the largest integer less than or equal to `self`.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -52,6 +54,8 @@ impl f32 {
 
     /// Returns the smallest integer greater than or equal to `self`.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -73,6 +77,8 @@ impl f32 {
     /// Returns the nearest integer to `self`. If a value is half-way between two
     /// integers, round away from `0.0`.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -99,6 +105,8 @@ impl f32 {
     /// Returns the nearest integer to a number. Rounds half-way cases to the number
     /// with an even least significant digit.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -123,6 +131,8 @@ impl f32 {
     /// Returns the integer part of `self`.
     /// This means that non-integer numbers are always truncated towards zero.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -145,6 +155,8 @@ impl f32 {
 
     /// Returns the fractional part of `self`.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -166,6 +178,8 @@ impl f32 {
 
     /// Computes the absolute value of `self`.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -249,6 +263,12 @@ impl f32 {
     /// this is not always true, and will be heavily dependant on designing
     /// algorithms with specific target hardware in mind.
     ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result. It is specified by IEEE 754 as
+    /// `fusedMultiplyAdd` and guaranteed not to change.
+    ///
     /// # Examples
     ///
     /// ```
@@ -276,6 +296,11 @@ impl f32 {
     /// In other words, the result is `self / rhs` rounded to the integer `n`
     /// such that `self >= n * rhs`.
     ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -309,6 +334,11 @@ impl f32 {
     /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
     /// approximately.
     ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -337,6 +367,10 @@ impl f32 {
     /// It might have a different sequence of rounding operations than `powf`,
     /// so the results are not guaranteed to agree.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -355,6 +389,10 @@ impl f32 {
 
     /// Raises a number to a floating point power.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -375,6 +413,12 @@ impl f32 {
     ///
     /// Returns NaN if `self` is a negative number other than `-0.0`.
     ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
+    /// and guaranteed not to change.
+    ///
     /// # Examples
     ///
     /// ```
@@ -398,6 +442,10 @@ impl f32 {
 
     /// Returns `e^(self)`, (the exponential function).
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -420,6 +468,10 @@ impl f32 {
 
     /// Returns `2^(self)`.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -440,6 +492,10 @@ impl f32 {
 
     /// Returns the natural logarithm of the number.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -466,6 +522,10 @@ impl f32 {
     /// `self.log2()` can produce more accurate results for base 2, and
     /// `self.log10()` can produce more accurate results for base 10.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -486,6 +546,10 @@ impl f32 {
 
     /// Returns the base 2 logarithm of the number.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -506,6 +570,10 @@ impl f32 {
 
     /// Returns the base 10 logarithm of the number.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -529,6 +597,12 @@ impl f32 {
     /// * If `self <= other`: `0.0`
     /// * Else: `self - other`
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `fdimf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -561,6 +635,12 @@ impl f32 {
 
     /// Returns the cube root of a number.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `cbrtf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -584,6 +664,12 @@ impl f32 {
     /// right-angle triangle with other sides having length `x.abs()` and
     /// `y.abs()`.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `hypotf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -605,6 +691,10 @@ impl f32 {
 
     /// Computes the sine of a number (in radians).
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -624,6 +714,10 @@ impl f32 {
 
     /// Computes the cosine of a number (in radians).
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -643,6 +737,12 @@ impl f32 {
 
     /// Computes the tangent of a number (in radians).
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `tanf` from libc on Unix and
+    /// Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -663,6 +763,12 @@ impl f32 {
     /// the range [-pi/2, pi/2] or NaN if the number is outside the range
     /// [-1, 1].
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `asinf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -686,6 +792,12 @@ impl f32 {
     /// the range [0, pi] or NaN if the number is outside the range
     /// [-1, 1].
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `acosf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -708,6 +820,12 @@ impl f32 {
     /// Computes the arctangent of a number. Return value is in radians in the
     /// range [-pi/2, pi/2];
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `atanf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -734,6 +852,12 @@ impl f32 {
     /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
     /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `atan2f` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -764,6 +888,12 @@ impl f32 {
     /// Simultaneously computes the sine and cosine of the number, `x`. Returns
     /// `(sin(x), cos(x))`.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `(f32::sin(x),
+    /// f32::cos(x))`. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -787,6 +917,12 @@ impl f32 {
     /// Returns `e^(self) - 1` in a way that is accurate even if the
     /// number is close to zero.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `expm1f` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -809,6 +945,12 @@ impl f32 {
     /// Returns `ln(1+n)` (natural logarithm) more accurately than if
     /// the operations were performed separately.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `log1pf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -831,6 +973,12 @@ impl f32 {
 
     /// Hyperbolic sine function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `sinhf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -854,6 +1002,12 @@ impl f32 {
 
     /// Hyperbolic cosine function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `coshf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -877,6 +1031,12 @@ impl f32 {
 
     /// Hyperbolic tangent function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `tanhf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -900,6 +1060,10 @@ impl f32 {
 
     /// Inverse hyperbolic sine function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -923,6 +1087,10 @@ impl f32 {
 
     /// Inverse hyperbolic cosine function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -948,6 +1116,10 @@ impl f32 {
 
     /// Inverse hyperbolic tangent function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -969,6 +1141,12 @@ impl f32 {
 
     /// Gamma function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `tgammaf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -991,6 +1169,12 @@ impl f32 {
     ///
     /// The integer part of the tuple indicates the sign of the gamma function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `lgamma_r` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index 88f992b3957..7385576c337 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -31,6 +31,8 @@ pub use core::f64::{
 impl f64 {
     /// Returns the largest integer less than or equal to `self`.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -52,6 +54,8 @@ impl f64 {
 
     /// Returns the smallest integer greater than or equal to `self`.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -73,6 +77,8 @@ impl f64 {
     /// Returns the nearest integer to `self`. If a value is half-way between two
     /// integers, round away from `0.0`.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -99,6 +105,8 @@ impl f64 {
     /// Returns the nearest integer to a number. Rounds half-way cases to the number
     /// with an even least significant digit.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -123,6 +131,8 @@ impl f64 {
     /// Returns the integer part of `self`.
     /// This means that non-integer numbers are always truncated towards zero.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -145,6 +155,8 @@ impl f64 {
 
     /// Returns the fractional part of `self`.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -166,6 +178,8 @@ impl f64 {
 
     /// Computes the absolute value of `self`.
     ///
+    /// This function always returns the precise result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -249,6 +263,12 @@ impl f64 {
     /// this is not always true, and will be heavily dependant on designing
     /// algorithms with specific target hardware in mind.
     ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result. It is specified by IEEE 754 as
+    /// `fusedMultiplyAdd` and guaranteed not to change.
+    ///
     /// # Examples
     ///
     /// ```
@@ -276,6 +296,11 @@ impl f64 {
     /// In other words, the result is `self / rhs` rounded to the integer `n`
     /// such that `self >= n * rhs`.
     ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -309,6 +334,11 @@ impl f64 {
     /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
     /// approximately.
     ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result.
+    ///
     /// # Examples
     ///
     /// ```
@@ -337,6 +367,10 @@ impl f64 {
     /// It might have a different sequence of rounding operations than `powf`,
     /// so the results are not guaranteed to agree.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -355,6 +389,10 @@ impl f64 {
 
     /// Raises a number to a floating point power.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -375,6 +413,12 @@ impl f64 {
     ///
     /// Returns NaN if `self` is a negative number other than `-0.0`.
     ///
+    /// # Precision
+    ///
+    /// The result of this operation is guaranteed to be the rounded
+    /// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
+    /// and guaranteed not to change.
+    ///
     /// # Examples
     ///
     /// ```
@@ -398,6 +442,10 @@ impl f64 {
 
     /// Returns `e^(self)`, (the exponential function).
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -420,6 +468,10 @@ impl f64 {
 
     /// Returns `2^(self)`.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -440,6 +492,10 @@ impl f64 {
 
     /// Returns the natural logarithm of the number.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -466,6 +522,10 @@ impl f64 {
     /// `self.log2()` can produce more accurate results for base 2, and
     /// `self.log10()` can produce more accurate results for base 10.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -486,6 +546,10 @@ impl f64 {
 
     /// Returns the base 2 logarithm of the number.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -506,6 +570,10 @@ impl f64 {
 
     /// Returns the base 10 logarithm of the number.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -529,6 +597,12 @@ impl f64 {
     /// * If `self <= other`: `0.0`
     /// * Else: `self - other`
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `fdim` from libc on Unix and
+    /// Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -561,6 +635,12 @@ impl f64 {
 
     /// Returns the cube root of a number.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `cbrt` from libc on Unix and
+    /// Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -584,6 +664,12 @@ impl f64 {
     /// right-angle triangle with other sides having length `x.abs()` and
     /// `y.abs()`.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `hypot` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -605,6 +691,10 @@ impl f64 {
 
     /// Computes the sine of a number (in radians).
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -624,6 +714,10 @@ impl f64 {
 
     /// Computes the cosine of a number (in radians).
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -643,6 +737,12 @@ impl f64 {
 
     /// Computes the tangent of a number (in radians).
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `tan` from libc on Unix and
+    /// Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -663,6 +763,12 @@ impl f64 {
     /// the range [-pi/2, pi/2] or NaN if the number is outside the range
     /// [-1, 1].
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `asin` from libc on Unix and
+    /// Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -686,6 +792,12 @@ impl f64 {
     /// the range [0, pi] or NaN if the number is outside the range
     /// [-1, 1].
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `acos` from libc on Unix and
+    /// Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -708,6 +820,12 @@ impl f64 {
     /// Computes the arctangent of a number. Return value is in radians in the
     /// range [-pi/2, pi/2];
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `atan` from libc on Unix and
+    /// Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -734,6 +852,12 @@ impl f64 {
     /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
     /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `atan2` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -764,6 +888,12 @@ impl f64 {
     /// Simultaneously computes the sine and cosine of the number, `x`. Returns
     /// `(sin(x), cos(x))`.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `(f64::sin(x),
+    /// f64::cos(x))`. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -787,6 +917,12 @@ impl f64 {
     /// Returns `e^(self) - 1` in a way that is accurate even if the
     /// number is close to zero.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `expm1` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -809,6 +945,12 @@ impl f64 {
     /// Returns `ln(1+n)` (natural logarithm) more accurately than if
     /// the operations were performed separately.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `log1p` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -831,6 +973,12 @@ impl f64 {
 
     /// Hyperbolic sine function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `sinh` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -854,6 +1002,12 @@ impl f64 {
 
     /// Hyperbolic cosine function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `cosh` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -877,6 +1031,12 @@ impl f64 {
 
     /// Hyperbolic tangent function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `tanh` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -900,6 +1060,10 @@ impl f64 {
 
     /// Inverse hyperbolic sine function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -923,6 +1087,10 @@ impl f64 {
 
     /// Inverse hyperbolic cosine function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -948,6 +1116,10 @@ impl f64 {
 
     /// Inverse hyperbolic tangent function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    ///
     /// # Examples
     ///
     /// ```
@@ -969,6 +1141,12 @@ impl f64 {
 
     /// Gamma function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `tgamma` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
@@ -991,6 +1169,12 @@ impl f64 {
     ///
     /// The integer part of the tuple indicates the sign of the gamma function.
     ///
+    /// # Platform-specific precision
+    ///
+    /// The precision of this function varies by platform and Rust version.
+    /// This function currently corresponds to the `lgamma_r` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
     /// # Examples
     ///
     /// ```
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 261b570dee7..455de6d98ba 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -11,8 +11,9 @@ use crate::fs::File;
 use crate::io::{
     self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines, SpecReadByte,
 };
+use crate::panic::{RefUnwindSafe, UnwindSafe};
 use crate::sync::atomic::{AtomicBool, Ordering};
-use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantMutex, ReentrantMutexGuard};
+use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantLock, ReentrantLockGuard};
 use crate::sys::stdio;
 
 type LocalStream = Arc<Mutex<Vec<u8>>>;
@@ -545,7 +546,7 @@ pub struct Stdout {
     // FIXME: this should be LineWriter or BufWriter depending on the state of
     //        stdout (tty or not). Note that if this is not line buffered it
     //        should also flush-on-panic or some form of flush-on-abort.
-    inner: &'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>,
+    inner: &'static ReentrantLock<RefCell<LineWriter<StdoutRaw>>>,
 }
 
 /// A locked reference to the [`Stdout`] handle.
@@ -567,10 +568,10 @@ pub struct Stdout {
 #[must_use = "if unused stdout will immediately unlock"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StdoutLock<'a> {
-    inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
+    inner: ReentrantLockGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
 }
 
-static STDOUT: OnceLock<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = OnceLock::new();
+static STDOUT: OnceLock<ReentrantLock<RefCell<LineWriter<StdoutRaw>>>> = OnceLock::new();
 
 /// Constructs a new handle to the standard output of the current process.
 ///
@@ -624,7 +625,7 @@ static STDOUT: OnceLock<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = OnceLo
 pub fn stdout() -> Stdout {
     Stdout {
         inner: STDOUT
-            .get_or_init(|| ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))),
+            .get_or_init(|| ReentrantLock::new(RefCell::new(LineWriter::new(stdout_raw())))),
     }
 }
 
@@ -635,7 +636,7 @@ pub fn cleanup() {
     let mut initialized = false;
     let stdout = STDOUT.get_or_init(|| {
         initialized = true;
-        ReentrantMutex::new(RefCell::new(LineWriter::with_capacity(0, stdout_raw())))
+        ReentrantLock::new(RefCell::new(LineWriter::with_capacity(0, stdout_raw())))
     });
 
     if !initialized {
@@ -678,6 +679,12 @@ impl Stdout {
     }
 }
 
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl UnwindSafe for Stdout {}
+
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl RefUnwindSafe for Stdout {}
+
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stdout {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -737,6 +744,12 @@ impl Write for &Stdout {
     }
 }
 
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl UnwindSafe for StdoutLock<'_> {}
+
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl RefUnwindSafe for StdoutLock<'_> {}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Write for StdoutLock<'_> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
@@ -786,7 +799,7 @@ impl fmt::Debug for StdoutLock<'_> {
 /// standard library or via raw Windows API calls, will fail.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stderr {
-    inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
+    inner: &'static ReentrantLock<RefCell<StderrRaw>>,
 }
 
 /// A locked reference to the [`Stderr`] handle.
@@ -808,7 +821,7 @@ pub struct Stderr {
 #[must_use = "if unused stderr will immediately unlock"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct StderrLock<'a> {
-    inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,
+    inner: ReentrantLockGuard<'a, RefCell<StderrRaw>>,
 }
 
 /// Constructs a new handle to the standard error of the current process.
@@ -862,8 +875,8 @@ pub fn stderr() -> Stderr {
     // Note that unlike `stdout()` we don't use `at_exit` here to register a
     // destructor. Stderr is not buffered, so there's no need to run a
     // destructor for flushing the buffer
-    static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
-        ReentrantMutex::new(RefCell::new(stderr_raw()));
+    static INSTANCE: ReentrantLock<RefCell<StderrRaw>> =
+        ReentrantLock::new(RefCell::new(stderr_raw()));
 
     Stderr { inner: &INSTANCE }
 }
@@ -898,6 +911,12 @@ impl Stderr {
     }
 }
 
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl UnwindSafe for Stderr {}
+
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl RefUnwindSafe for Stderr {}
+
 #[stable(feature = "std_debug", since = "1.16.0")]
 impl fmt::Debug for Stderr {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -957,6 +976,12 @@ impl Write for &Stderr {
     }
 }
 
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl UnwindSafe for StderrLock<'_> {}
+
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl RefUnwindSafe for StderrLock<'_> {}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Write for StderrLock<'_> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 3728d5b64b8..3d576af681e 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -6,7 +6,7 @@ use crate::any::Any;
 use crate::collections;
 use crate::panicking;
 use crate::sync::atomic::{AtomicU8, Ordering};
-use crate::sync::{Mutex, RwLock};
+use crate::sync::{Condvar, Mutex, RwLock};
 use crate::thread::Result;
 
 #[doc(hidden)]
@@ -67,11 +67,15 @@ pub fn panic_any<M: 'static + Any + Send>(msg: M) -> ! {
 impl<T: ?Sized> UnwindSafe for Mutex<T> {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: ?Sized> UnwindSafe for RwLock<T> {}
+#[stable(feature = "catch_unwind", since = "1.9.0")]
+impl UnwindSafe for Condvar {}
 
 #[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
 impl<T: ?Sized> RefUnwindSafe for Mutex<T> {}
 #[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
 impl<T: ?Sized> RefUnwindSafe for RwLock<T> {}
+#[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")]
+impl RefUnwindSafe for Condvar {}
 
 // https://github.com/rust-lang/rust/issues/62301
 #[stable(feature = "hashbrown", since = "1.36.0")]
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index ca62179e95b..e8c35bd48a7 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -184,7 +184,8 @@ pub use self::lazy_lock::LazyLock;
 #[stable(feature = "once_cell", since = "1.70.0")]
 pub use self::once_lock::OnceLock;
 
-pub(crate) use self::remutex::{ReentrantMutex, ReentrantMutexGuard};
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+pub use self::reentrant_lock::{ReentrantLock, ReentrantLockGuard};
 
 pub mod mpsc;
 
@@ -196,5 +197,5 @@ mod mutex;
 pub(crate) mod once;
 mod once_lock;
 mod poison;
-mod remutex;
+mod reentrant_lock;
 mod rwlock;
diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs
index a1b275112a1..9e7148c716c 100644
--- a/library/std/src/sync/mpmc/list.rs
+++ b/library/std/src/sync/mpmc/list.rs
@@ -547,6 +547,9 @@ impl<T> Channel<T> {
         }
 
         let mut head = self.head.index.load(Ordering::Acquire);
+        // The channel may be uninitialized, so we have to swap to avoid overwriting any sender's attempts
+        // to initalize the first block before noticing that the receivers disconnected. Late allocations
+        // will be deallocated by the sender in Drop.
         let mut block = self.head.block.swap(ptr::null_mut(), Ordering::AcqRel);
 
         // If we're going to be dropping messages we need to synchronize with initialization
diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs
new file mode 100644
index 00000000000..9a44998ebf6
--- /dev/null
+++ b/library/std/src/sync/reentrant_lock.rs
@@ -0,0 +1,320 @@
+#[cfg(all(test, not(target_os = "emscripten")))]
+mod tests;
+
+use crate::cell::UnsafeCell;
+use crate::fmt;
+use crate::ops::Deref;
+use crate::panic::{RefUnwindSafe, UnwindSafe};
+use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
+use crate::sys::locks as sys;
+
+/// A re-entrant mutual exclusion lock
+///
+/// This lock will block *other* threads waiting for the lock to become
+/// available. The thread which has already locked the mutex can lock it
+/// multiple times without blocking, preventing a common source of deadlocks.
+///
+/// # Examples
+///
+/// Allow recursively calling a function needing synchronization from within
+/// a callback (this is how [`StdoutLock`](crate::io::StdoutLock) is currently
+/// implemented):
+///
+/// ```
+/// #![feature(reentrant_lock)]
+///
+/// use std::cell::RefCell;
+/// use std::sync::ReentrantLock;
+///
+/// pub struct Log {
+///     data: RefCell<String>,
+/// }
+///
+/// impl Log {
+///     pub fn append(&self, msg: &str) {
+///         self.data.borrow_mut().push_str(msg);
+///     }
+/// }
+///
+/// static LOG: ReentrantLock<Log> = ReentrantLock::new(Log { data: RefCell::new(String::new()) });
+///
+/// pub fn with_log<R>(f: impl FnOnce(&Log) -> R) -> R {
+///     let log = LOG.lock();
+///     f(&*log)
+/// }
+///
+/// with_log(|log| {
+///     log.append("Hello");
+///     with_log(|log| log.append(" there!"));
+/// });
+/// ```
+///
+// # Implementation details
+//
+// The 'owner' field tracks which thread has locked the mutex.
+//
+// We use current_thread_unique_ptr() as the thread identifier,
+// which is just the address of a thread local variable.
+//
+// If `owner` is set to the identifier of the current thread,
+// we assume the mutex is already locked and instead of locking it again,
+// we increment `lock_count`.
+//
+// When unlocking, we decrement `lock_count`, and only unlock the mutex when
+// it reaches zero.
+//
+// `lock_count` is protected by the mutex and only accessed by the thread that has
+// locked the mutex, so needs no synchronization.
+//
+// `owner` can be checked by other threads that want to see if they already
+// hold the lock, so needs to be atomic. If it compares equal, we're on the
+// same thread that holds the mutex and memory access can use relaxed ordering
+// since we're not dealing with multiple threads. If it's not equal,
+// synchronization is left to the mutex, making relaxed memory ordering for
+// the `owner` field fine in all cases.
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+pub struct ReentrantLock<T: ?Sized> {
+    mutex: sys::Mutex,
+    owner: AtomicUsize,
+    lock_count: UnsafeCell<u32>,
+    data: T,
+}
+
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+unsafe impl<T: Send + ?Sized> Send for ReentrantLock<T> {}
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+unsafe impl<T: Send + ?Sized> Sync for ReentrantLock<T> {}
+
+// Because of the `UnsafeCell`, these traits are not implemented automatically
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+impl<T: UnwindSafe + ?Sized> UnwindSafe for ReentrantLock<T> {}
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+impl<T: RefUnwindSafe + ?Sized> RefUnwindSafe for ReentrantLock<T> {}
+
+/// An RAII implementation of a "scoped lock" of a re-entrant lock. When this
+/// structure is dropped (falls out of scope), the lock will be unlocked.
+///
+/// The data protected by the mutex can be accessed through this guard via its
+/// [`Deref`] implementation.
+///
+/// This structure is created by the [`lock`](ReentrantLock::lock) method on
+/// [`ReentrantLock`].
+///
+/// # Mutability
+///
+/// Unlike [`MutexGuard`](super::MutexGuard), `ReentrantLockGuard` does not
+/// implement [`DerefMut`](crate::ops::DerefMut), because implementation of
+/// the trait would violate Rust’s reference aliasing rules. Use interior
+/// mutability (usually [`RefCell`](crate::cell::RefCell)) in order to mutate
+/// the guarded data.
+#[must_use = "if unused the ReentrantLock will immediately unlock"]
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+pub struct ReentrantLockGuard<'a, T: ?Sized + 'a> {
+    lock: &'a ReentrantLock<T>,
+}
+
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+impl<T: ?Sized> !Send for ReentrantLockGuard<'_, T> {}
+
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+impl<T> ReentrantLock<T> {
+    /// Creates a new re-entrant lock in an unlocked state ready for use.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(reentrant_lock)]
+    /// use std::sync::ReentrantLock;
+    ///
+    /// let lock = ReentrantLock::new(0);
+    /// ```
+    pub const fn new(t: T) -> ReentrantLock<T> {
+        ReentrantLock {
+            mutex: sys::Mutex::new(),
+            owner: AtomicUsize::new(0),
+            lock_count: UnsafeCell::new(0),
+            data: t,
+        }
+    }
+
+    /// Consumes this lock, returning the underlying data.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(reentrant_lock)]
+    ///
+    /// use std::sync::ReentrantLock;
+    ///
+    /// let lock = ReentrantLock::new(0);
+    /// assert_eq!(lock.into_inner(), 0);
+    /// ```
+    pub fn into_inner(self) -> T {
+        self.data
+    }
+}
+
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+impl<T: ?Sized> ReentrantLock<T> {
+    /// Acquires the lock, blocking the current thread until it is able to do
+    /// so.
+    ///
+    /// This function will block the caller until it is available to acquire
+    /// the lock. Upon returning, the thread is the only thread with the lock
+    /// held. When the thread calling this method already holds the lock, the
+    /// call succeeds without blocking.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(reentrant_lock)]
+    /// use std::cell::Cell;
+    /// use std::sync::{Arc, ReentrantLock};
+    /// use std::thread;
+    ///
+    /// let lock = Arc::new(ReentrantLock::new(Cell::new(0)));
+    /// let c_lock = Arc::clone(&lock);
+    ///
+    /// thread::spawn(move || {
+    ///     c_lock.lock().set(10);
+    /// }).join().expect("thread::spawn failed");
+    /// assert_eq!(lock.lock().get(), 10);
+    /// ```
+    pub fn lock(&self) -> ReentrantLockGuard<'_, T> {
+        let this_thread = current_thread_unique_ptr();
+        // Safety: We only touch lock_count when we own the lock.
+        unsafe {
+            if self.owner.load(Relaxed) == this_thread {
+                self.increment_lock_count().expect("lock count overflow in reentrant mutex");
+            } else {
+                self.mutex.lock();
+                self.owner.store(this_thread, Relaxed);
+                debug_assert_eq!(*self.lock_count.get(), 0);
+                *self.lock_count.get() = 1;
+            }
+        }
+        ReentrantLockGuard { lock: self }
+    }
+
+    /// Returns a mutable reference to the underlying data.
+    ///
+    /// Since this call borrows the `ReentrantLock` mutably, no actual locking
+    /// needs to take place -- the mutable borrow statically guarantees no locks
+    /// exist.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(reentrant_lock)]
+    /// use std::sync::ReentrantLock;
+    ///
+    /// let mut lock = ReentrantLock::new(0);
+    /// *lock.get_mut() = 10;
+    /// assert_eq!(*lock.lock(), 10);
+    /// ```
+    pub fn get_mut(&mut self) -> &mut T {
+        &mut self.data
+    }
+
+    /// Attempts to acquire this lock.
+    ///
+    /// If the lock could not be acquired at this time, then `None` is returned.
+    /// Otherwise, an RAII guard is returned.
+    ///
+    /// This function does not block.
+    pub(crate) fn try_lock(&self) -> Option<ReentrantLockGuard<'_, T>> {
+        let this_thread = current_thread_unique_ptr();
+        // Safety: We only touch lock_count when we own the lock.
+        unsafe {
+            if self.owner.load(Relaxed) == this_thread {
+                self.increment_lock_count()?;
+                Some(ReentrantLockGuard { lock: self })
+            } else if self.mutex.try_lock() {
+                self.owner.store(this_thread, Relaxed);
+                debug_assert_eq!(*self.lock_count.get(), 0);
+                *self.lock_count.get() = 1;
+                Some(ReentrantLockGuard { lock: self })
+            } else {
+                None
+            }
+        }
+    }
+
+    unsafe fn increment_lock_count(&self) -> Option<()> {
+        *self.lock_count.get() = (*self.lock_count.get()).checked_add(1)?;
+        Some(())
+    }
+}
+
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+impl<T: fmt::Debug + ?Sized> fmt::Debug for ReentrantLock<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut d = f.debug_struct("ReentrantLock");
+        match self.try_lock() {
+            Some(v) => d.field("data", &&*v),
+            None => d.field("data", &format_args!("<locked>")),
+        };
+        d.finish_non_exhaustive()
+    }
+}
+
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+impl<T: Default> Default for ReentrantLock<T> {
+    fn default() -> Self {
+        Self::new(T::default())
+    }
+}
+
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+impl<T> From<T> for ReentrantLock<T> {
+    fn from(t: T) -> Self {
+        Self::new(t)
+    }
+}
+
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+impl<T: ?Sized> Deref for ReentrantLockGuard<'_, T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &self.lock.data
+    }
+}
+
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+impl<T: fmt::Debug + ?Sized> fmt::Debug for ReentrantLockGuard<'_, T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        (**self).fmt(f)
+    }
+}
+
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+impl<T: fmt::Display + ?Sized> fmt::Display for ReentrantLockGuard<'_, T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        (**self).fmt(f)
+    }
+}
+
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+impl<T: ?Sized> Drop for ReentrantLockGuard<'_, T> {
+    #[inline]
+    fn drop(&mut self) {
+        // Safety: We own the lock.
+        unsafe {
+            *self.lock.lock_count.get() -= 1;
+            if *self.lock.lock_count.get() == 0 {
+                self.lock.owner.store(0, Relaxed);
+                self.lock.mutex.unlock();
+            }
+        }
+    }
+}
+
+/// Get an address that is unique per running thread.
+///
+/// This can be used as a non-null usize-sized ID.
+pub(crate) fn current_thread_unique_ptr() -> usize {
+    // Use a non-drop type to make sure it's still available during thread destruction.
+    thread_local! { static X: u8 = const { 0 } }
+    X.with(|x| <*const _>::addr(x))
+}
diff --git a/library/std/src/sync/remutex/tests.rs b/library/std/src/sync/reentrant_lock/tests.rs
index fc553081d42..d4c1d440c61 100644
--- a/library/std/src/sync/remutex/tests.rs
+++ b/library/std/src/sync/reentrant_lock/tests.rs
@@ -1,17 +1,17 @@
-use super::{ReentrantMutex, ReentrantMutexGuard};
+use super::{ReentrantLock, ReentrantLockGuard};
 use crate::cell::RefCell;
 use crate::sync::Arc;
 use crate::thread;
 
 #[test]
 fn smoke() {
-    let m = ReentrantMutex::new(());
+    let l = ReentrantLock::new(());
     {
-        let a = m.lock();
+        let a = l.lock();
         {
-            let b = m.lock();
+            let b = l.lock();
             {
-                let c = m.lock();
+                let c = l.lock();
                 assert_eq!(*c, ());
             }
             assert_eq!(*b, ());
@@ -22,15 +22,15 @@ fn smoke() {
 
 #[test]
 fn is_mutex() {
-    let m = Arc::new(ReentrantMutex::new(RefCell::new(0)));
-    let m2 = m.clone();
-    let lock = m.lock();
+    let l = Arc::new(ReentrantLock::new(RefCell::new(0)));
+    let l2 = l.clone();
+    let lock = l.lock();
     let child = thread::spawn(move || {
-        let lock = m2.lock();
+        let lock = l2.lock();
         assert_eq!(*lock.borrow(), 4950);
     });
     for i in 0..100 {
-        let lock = m.lock();
+        let lock = l.lock();
         *lock.borrow_mut() += i;
     }
     drop(lock);
@@ -39,20 +39,20 @@ fn is_mutex() {
 
 #[test]
 fn trylock_works() {
-    let m = Arc::new(ReentrantMutex::new(()));
-    let m2 = m.clone();
-    let _lock = m.try_lock();
-    let _lock2 = m.try_lock();
+    let l = Arc::new(ReentrantLock::new(()));
+    let l2 = l.clone();
+    let _lock = l.try_lock();
+    let _lock2 = l.try_lock();
     thread::spawn(move || {
-        let lock = m2.try_lock();
+        let lock = l2.try_lock();
         assert!(lock.is_none());
     })
     .join()
     .unwrap();
-    let _lock3 = m.try_lock();
+    let _lock3 = l.try_lock();
 }
 
-pub struct Answer<'a>(pub ReentrantMutexGuard<'a, RefCell<u32>>);
+pub struct Answer<'a>(pub ReentrantLockGuard<'a, RefCell<u32>>);
 impl Drop for Answer<'_> {
     fn drop(&mut self) {
         *self.0.borrow_mut() = 42;
diff --git a/library/std/src/sync/remutex.rs b/library/std/src/sync/remutex.rs
deleted file mode 100644
index 0ced48d10b7..00000000000
--- a/library/std/src/sync/remutex.rs
+++ /dev/null
@@ -1,178 +0,0 @@
-#[cfg(all(test, not(target_os = "emscripten")))]
-mod tests;
-
-use crate::cell::UnsafeCell;
-use crate::ops::Deref;
-use crate::panic::{RefUnwindSafe, UnwindSafe};
-use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
-use crate::sys::locks as sys;
-
-/// A reentrant mutual exclusion
-///
-/// This mutex will block *other* threads waiting for the lock to become
-/// available. The thread which has already locked the mutex can lock it
-/// multiple times without blocking, preventing a common source of deadlocks.
-///
-/// This is used by stdout().lock() and friends.
-///
-/// ## Implementation details
-///
-/// The 'owner' field tracks which thread has locked the mutex.
-///
-/// We use current_thread_unique_ptr() as the thread identifier,
-/// which is just the address of a thread local variable.
-///
-/// If `owner` is set to the identifier of the current thread,
-/// we assume the mutex is already locked and instead of locking it again,
-/// we increment `lock_count`.
-///
-/// When unlocking, we decrement `lock_count`, and only unlock the mutex when
-/// it reaches zero.
-///
-/// `lock_count` is protected by the mutex and only accessed by the thread that has
-/// locked the mutex, so needs no synchronization.
-///
-/// `owner` can be checked by other threads that want to see if they already
-/// hold the lock, so needs to be atomic. If it compares equal, we're on the
-/// same thread that holds the mutex and memory access can use relaxed ordering
-/// since we're not dealing with multiple threads. If it's not equal,
-/// synchronization is left to the mutex, making relaxed memory ordering for
-/// the `owner` field fine in all cases.
-pub struct ReentrantMutex<T> {
-    mutex: sys::Mutex,
-    owner: AtomicUsize,
-    lock_count: UnsafeCell<u32>,
-    data: T,
-}
-
-unsafe impl<T: Send> Send for ReentrantMutex<T> {}
-unsafe impl<T: Send> Sync for ReentrantMutex<T> {}
-
-impl<T> UnwindSafe for ReentrantMutex<T> {}
-impl<T> RefUnwindSafe for ReentrantMutex<T> {}
-
-/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
-/// dropped (falls out of scope), the lock will be unlocked.
-///
-/// The data protected by the mutex can be accessed through this guard via its
-/// Deref implementation.
-///
-/// # Mutability
-///
-/// Unlike `MutexGuard`, `ReentrantMutexGuard` does not implement `DerefMut`,
-/// because implementation of the trait would violate Rust’s reference aliasing
-/// rules. Use interior mutability (usually `RefCell`) in order to mutate the
-/// guarded data.
-#[must_use = "if unused the ReentrantMutex will immediately unlock"]
-pub struct ReentrantMutexGuard<'a, T: 'a> {
-    lock: &'a ReentrantMutex<T>,
-}
-
-impl<T> !Send for ReentrantMutexGuard<'_, T> {}
-
-impl<T> ReentrantMutex<T> {
-    /// Creates a new reentrant mutex in an unlocked state.
-    pub const fn new(t: T) -> ReentrantMutex<T> {
-        ReentrantMutex {
-            mutex: sys::Mutex::new(),
-            owner: AtomicUsize::new(0),
-            lock_count: UnsafeCell::new(0),
-            data: t,
-        }
-    }
-
-    /// Acquires a mutex, blocking the current thread until it is able to do so.
-    ///
-    /// This function will block the caller until it is available to acquire the mutex.
-    /// Upon returning, the thread is the only thread with the mutex held. When the thread
-    /// calling this method already holds the lock, the call shall succeed without
-    /// blocking.
-    ///
-    /// # Errors
-    ///
-    /// If another user of this mutex panicked while holding the mutex, then
-    /// this call will return failure if the mutex would otherwise be
-    /// acquired.
-    pub fn lock(&self) -> ReentrantMutexGuard<'_, T> {
-        let this_thread = current_thread_unique_ptr();
-        // Safety: We only touch lock_count when we own the lock.
-        unsafe {
-            if self.owner.load(Relaxed) == this_thread {
-                self.increment_lock_count();
-            } else {
-                self.mutex.lock();
-                self.owner.store(this_thread, Relaxed);
-                debug_assert_eq!(*self.lock_count.get(), 0);
-                *self.lock_count.get() = 1;
-            }
-        }
-        ReentrantMutexGuard { lock: self }
-    }
-
-    /// Attempts to acquire this lock.
-    ///
-    /// If the lock could not be acquired at this time, then `Err` is returned.
-    /// Otherwise, an RAII guard is returned.
-    ///
-    /// This function does not block.
-    ///
-    /// # Errors
-    ///
-    /// If another user of this mutex panicked while holding the mutex, then
-    /// this call will return failure if the mutex would otherwise be
-    /// acquired.
-    pub fn try_lock(&self) -> Option<ReentrantMutexGuard<'_, T>> {
-        let this_thread = current_thread_unique_ptr();
-        // Safety: We only touch lock_count when we own the lock.
-        unsafe {
-            if self.owner.load(Relaxed) == this_thread {
-                self.increment_lock_count();
-                Some(ReentrantMutexGuard { lock: self })
-            } else if self.mutex.try_lock() {
-                self.owner.store(this_thread, Relaxed);
-                debug_assert_eq!(*self.lock_count.get(), 0);
-                *self.lock_count.get() = 1;
-                Some(ReentrantMutexGuard { lock: self })
-            } else {
-                None
-            }
-        }
-    }
-
-    unsafe fn increment_lock_count(&self) {
-        *self.lock_count.get() = (*self.lock_count.get())
-            .checked_add(1)
-            .expect("lock count overflow in reentrant mutex");
-    }
-}
-
-impl<T> Deref for ReentrantMutexGuard<'_, T> {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        &self.lock.data
-    }
-}
-
-impl<T> Drop for ReentrantMutexGuard<'_, T> {
-    #[inline]
-    fn drop(&mut self) {
-        // Safety: We own the lock.
-        unsafe {
-            *self.lock.lock_count.get() -= 1;
-            if *self.lock.lock_count.get() == 0 {
-                self.lock.owner.store(0, Relaxed);
-                self.lock.mutex.unlock();
-            }
-        }
-    }
-}
-
-/// Get an address that is unique per running thread.
-///
-/// This can be used as a non-null usize-sized ID.
-pub fn current_thread_unique_ptr() -> usize {
-    // Use a non-drop type to make sure it's still available during thread destruction.
-    thread_local! { static X: u8 = const { 0 } }
-    X.with(|x| <*const _>::addr(x))
-}
diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs
index a54536aecb8..645f0dc1e31 100644
--- a/library/std/src/sys/pal/hermit/os.rs
+++ b/library/std/src/sys/pal/hermit/os.rs
@@ -14,15 +14,15 @@ use crate::sys::unsupported;
 use crate::vec;
 
 pub fn errno() -> i32 {
-    0
+    unsafe { abi::get_errno() }
 }
 
-pub fn error_string(_errno: i32) -> String {
-    "operation successful".to_string()
+pub fn error_string(errno: i32) -> String {
+    abi::error_string(errno).to_string()
 }
 
 pub fn getcwd() -> io::Result<PathBuf> {
-    unsupported()
+    Ok(PathBuf::from("/"))
 }
 
 pub fn chdir(_: &path::Path) -> io::Result<()> {
@@ -188,7 +188,7 @@ pub fn unsetenv(k: &OsStr) -> io::Result<()> {
 }
 
 pub fn temp_dir() -> PathBuf {
-    panic!("no filesystem on hermit")
+    PathBuf::from("/tmp")
 }
 
 pub fn home_dir() -> Option<PathBuf> {
diff --git a/library/std/src/sys/pal/windows/thread_local_key.rs b/library/std/src/sys/pal/windows/thread_local_key.rs
index 5eee4a9667b..1d9cb316a45 100644
--- a/library/std/src/sys/pal/windows/thread_local_key.rs
+++ b/library/std/src/sys/pal/windows/thread_local_key.rs
@@ -1,7 +1,7 @@
 use crate::cell::UnsafeCell;
 use crate::ptr;
 use crate::sync::atomic::{
-    AtomicBool, AtomicPtr, AtomicU32,
+    AtomicPtr, AtomicU32,
     Ordering::{AcqRel, Acquire, Relaxed, Release},
 };
 use crate::sys::c;
@@ -9,10 +9,6 @@ use crate::sys::c;
 #[cfg(test)]
 mod tests;
 
-/// An optimization hint. The compiler is often smart enough to know if an atomic
-/// is never set and can remove dead code based on that fact.
-static HAS_DTORS: AtomicBool = AtomicBool::new(false);
-
 // Using a per-thread list avoids the problems in synchronizing global state.
 #[thread_local]
 #[cfg(target_thread_local)]
@@ -24,12 +20,11 @@ static DESTRUCTORS: crate::cell::RefCell<Vec<(*mut u8, unsafe extern "C" fn(*mut
 #[inline(never)]
 #[cfg(target_thread_local)]
 pub unsafe fn register_keyless_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
+    dtors_used();
     match DESTRUCTORS.try_borrow_mut() {
         Ok(mut dtors) => dtors.push((t, dtor)),
         Err(_) => rtabort!("global allocator may not use TLS"),
     }
-
-    HAS_DTORS.store(true, Relaxed);
 }
 
 #[inline(never)] // See comment above
@@ -130,6 +125,7 @@ impl StaticKey {
     #[cold]
     unsafe fn init(&'static self) -> Key {
         if self.dtor.is_some() {
+            dtors_used();
             let mut pending = c::FALSE;
             let r = c::InitOnceBeginInitialize(self.once.get(), 0, &mut pending, ptr::null_mut());
             assert_eq!(r, c::TRUE);
@@ -215,7 +211,6 @@ unsafe fn register_dtor(key: &'static StaticKey) {
             Err(new) => head = new,
         }
     }
-    HAS_DTORS.store(true, Release);
 }
 
 // -------------------------------------------------------------------------
@@ -281,17 +276,16 @@ unsafe fn register_dtor(key: &'static StaticKey) {
 // the address of the symbol to ensure it sticks around.
 
 #[link_section = ".CRT$XLB"]
-#[allow(dead_code, unused_variables)]
-#[used] // we don't want LLVM eliminating this symbol for any reason, and
-// when the symbol makes it to the linker the linker will take over
 pub static p_thread_callback: unsafe extern "system" fn(c::LPVOID, c::DWORD, c::LPVOID) =
     on_tls_callback;
 
-#[allow(dead_code, unused_variables)]
-unsafe extern "system" fn on_tls_callback(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID) {
-    if !HAS_DTORS.load(Acquire) {
-        return;
-    }
+fn dtors_used() {
+    // we don't want LLVM eliminating p_thread_callback when destructors are used.
+    // when the symbol makes it to the linker the linker will take over
+    unsafe { crate::intrinsics::volatile_load(&p_thread_callback) };
+}
+
+unsafe extern "system" fn on_tls_callback(_h: c::LPVOID, dwReason: c::DWORD, _pv: c::LPVOID) {
     if dwReason == c::DLL_THREAD_DETACH || dwReason == c::DLL_PROCESS_DETACH {
         #[cfg(not(target_thread_local))]
         run_dtors();
@@ -301,19 +295,16 @@ unsafe extern "system" fn on_tls_callback(h: c::LPVOID, dwReason: c::DWORD, pv:
 
     // See comments above for what this is doing. Note that we don't need this
     // trickery on GNU windows, just on MSVC.
-    reference_tls_used();
-    #[cfg(target_env = "msvc")]
-    unsafe fn reference_tls_used() {
+    #[cfg(all(target_env = "msvc", not(target_thread_local)))]
+    {
         extern "C" {
             static _tls_used: u8;
         }
         crate::intrinsics::volatile_load(&_tls_used);
     }
-    #[cfg(not(target_env = "msvc"))]
-    unsafe fn reference_tls_used() {}
 }
 
-#[allow(dead_code)] // actually called below
+#[cfg(not(target_thread_local))]
 unsafe fn run_dtors() {
     for _ in 0..5 {
         let mut any_run = false;
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index 69c8792b031..700c3ee4fda 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -279,8 +279,8 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
     let thread = std::thread::spawn(move || {
         let mut children = VecDeque::new();
         while let Ok(path) = rx.recv() {
-            // try getting a few more paths from the channel to amortize the overhead of spawning processes
-            let paths: Vec<_> = rx.try_iter().take(7).chain(std::iter::once(path)).collect();
+            // try getting more paths from the channel to amortize the overhead of spawning processes
+            let paths: Vec<_> = rx.try_iter().take(63).chain(std::iter::once(path)).collect();
 
             let child = rustfmt(&src, &rustfmt_path, paths.as_slice(), check);
             children.push_back(child);
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index e169cba3c13..8223a80c931 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -642,22 +642,22 @@ impl<'a> ShouldRun<'a> {
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
 pub enum Kind {
-    #[clap(alias = "b")]
+    #[value(alias = "b")]
     Build,
-    #[clap(alias = "c")]
+    #[value(alias = "c")]
     Check,
     Clippy,
     Fix,
     Format,
-    #[clap(alias = "t")]
+    #[value(alias = "t")]
     Test,
     Bench,
-    #[clap(alias = "d")]
+    #[value(alias = "d")]
     Doc,
     Clean,
     Dist,
     Install,
-    #[clap(alias = "r")]
+    #[value(alias = "r")]
     Run,
     Setup,
     Suggest,
diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs
index 8af454001a6..7262b785ee0 100644
--- a/src/bootstrap/src/core/config/flags.rs
+++ b/src/bootstrap/src/core/config/flags.rs
@@ -31,7 +31,7 @@ pub enum Warnings {
 
 /// Deserialized version of all flags for this compile.
 #[derive(Debug, Parser)]
-#[clap(
+#[command(
     override_usage = "x.py <subcommand> [options] [<paths>...]",
     disable_help_subcommand(true),
     about = "",
@@ -118,7 +118,7 @@ pub struct Flags {
     // This overrides the deny-warnings configuration option,
     // which passes -Dwarnings to the compiler invocations.
     #[arg(global(true), long)]
-    #[clap(value_enum, default_value_t=Warnings::Default, value_name = "deny|warn")]
+    #[arg(value_enum, default_value_t=Warnings::Default, value_name = "deny|warn")]
     /// if value is deny, will deny warnings
     /// if value is warn, will emit warnings
     /// otherwise, use the default configured behaviour
@@ -132,7 +132,7 @@ pub struct Flags {
     pub json_output: bool,
 
     #[arg(global(true), long, value_name = "STYLE")]
-    #[clap(value_enum, default_value_t = Color::Auto)]
+    #[arg(value_enum, default_value_t = Color::Auto)]
     /// whether to use color in cargo and rustc output
     pub color: Color,
 
@@ -188,7 +188,7 @@ impl Flags {
         let it = std::iter::once(&first).chain(args.iter());
         // We need to check for `<cmd> -h -v`, in which case we list the paths
         #[derive(Parser)]
-        #[clap(disable_help_flag(true))]
+        #[command(disable_help_flag(true))]
         struct HelpVerboseOnly {
             #[arg(short, long)]
             help: bool,
@@ -218,7 +218,7 @@ impl Flags {
 
 #[derive(Debug, Clone, Default, clap::Subcommand)]
 pub enum Subcommand {
-    #[clap(aliases = ["b"], long_about = "\n
+    #[command(aliases = ["b"], long_about = "\n
     Arguments:
         This subcommand accepts a number of paths to directories to the crates
         and/or artifacts to compile. For example, for a quick build of a usable
@@ -233,7 +233,7 @@ pub enum Subcommand {
     /// Compile either the compiler or libraries
     #[default]
     Build,
-    #[clap(aliases = ["c"], long_about = "\n
+    #[command(aliases = ["c"], long_about = "\n
     Arguments:
         This subcommand accepts a number of paths to directories to the crates
         and/or artifacts to compile. For example:
@@ -246,7 +246,7 @@ pub enum Subcommand {
         all_targets: bool,
     },
     /// Run Clippy (uses rustup/cargo-installed clippy binary)
-    #[clap(long_about = "\n
+    #[command(long_about = "\n
     Arguments:
         This subcommand accepts a number of paths to directories to the crates
         and/or artifacts to run clippy against. For example:
@@ -273,14 +273,14 @@ pub enum Subcommand {
         forbid: Vec<String>,
     },
     /// Run cargo fix
-    #[clap(long_about = "\n
+    #[command(long_about = "\n
     Arguments:
         This subcommand accepts a number of paths to directories to the crates
         and/or artifacts to run `cargo fix` against. For example:
             ./x.py fix library/core
             ./x.py fix library/core library/proc_macro")]
     Fix,
-    #[clap(
+    #[command(
         name = "fmt",
         long_about = "\n
     Arguments:
@@ -295,7 +295,7 @@ pub enum Subcommand {
         #[arg(long)]
         check: bool,
     },
-    #[clap(aliases = ["d"], long_about = "\n
+    #[command(aliases = ["d"], long_about = "\n
     Arguments:
         This subcommand accepts a number of paths to directories of documentation
         to build. For example:
@@ -316,7 +316,7 @@ pub enum Subcommand {
         /// render the documentation in JSON format in addition to the usual HTML format
         json: bool,
     },
-    #[clap(aliases = ["t"], long_about = "\n
+    #[command(aliases = ["t"], long_about = "\n
     Arguments:
         This subcommand accepts a number of paths to test directories that
         should be compiled and run. For example:
@@ -400,7 +400,7 @@ pub enum Subcommand {
     Dist,
     /// Install distribution artifacts
     Install,
-    #[clap(aliases = ["r"], long_about = "\n
+    #[command(aliases = ["r"], long_about = "\n
     Arguments:
         This subcommand accepts a number of paths to tools to build and run. For
         example:
@@ -413,7 +413,7 @@ pub enum Subcommand {
         args: Vec<String>,
     },
     /// Set up the environment for development
-    #[clap(long_about = format!(
+    #[command(long_about = format!(
         "\n
 x.py setup creates a `config.toml` which changes the defaults for x.py itself,
 as well as setting up a git pre-push hook, VS Code config and toolchain link.
@@ -434,7 +434,7 @@ Arguments:
         profile: Option<PathBuf>,
     },
     /// Suggest a subset of tests to run, based on modified files
-    #[clap(long_about = "\n")]
+    #[command(long_about = "\n")]
     Suggest {
         /// run suggested tests
         #[arg(long)]
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index d4ca91977a6..90ac97f35f6 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -39,6 +39,7 @@
     - [\*-unknown-fuchsia](platform-support/fuchsia.md)
     - [\*-kmc-solid_\*](platform-support/kmc-solid.md)
     - [csky-unknown-linux-gnuabiv2\*](platform-support/csky-unknown-linux-gnuabiv2.md)
+    - [hexagon-unknown-linux-musl](platform-support/hexagon-unknown-linux-musl.md)
     - [hexagon-unknown-none-elf](platform-support/hexagon-unknown-none-elf.md)
     - [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md)
     - [loongarch\*-unknown-none\*](platform-support/loongarch-none.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 984cb13f790..f1e3ad81b85 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -286,8 +286,8 @@ target | std | host | notes
 `bpfel-unknown-none` | * |  | BPF (little endian)
 `csky-unknown-linux-gnuabiv2` | ✓ |  | C-SKY abiv2 Linux (little endian)
 `csky-unknown-linux-gnuabiv2hf` | ✓ |  | C-SKY abiv2 Linux, hardfloat (little endian)
-[`hexagon-unknown-none-elf`](platform-support/hexagon-unknown-none-elf.md)| * | Bare Hexagon (v60+, HVX)
-`hexagon-unknown-linux-musl` | ? |  |
+[`hexagon-unknown-none-elf`](platform-support/hexagon-unknown-none-elf.md)| * | | Bare Hexagon (v60+, HVX)
+[`hexagon-unknown-linux-musl`](platform-support/hexagon-unknown-linux-musl.md) | ✓ | | Hexagon Linux
 `i386-apple-ios` | ✓ |  | 32-bit x86 iOS [^x86_32-floats-return-ABI]
 [`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * |  | 32-bit x86 QNX Neutrino 7.0 RTOS  [^x86_32-floats-return-ABI]
 [`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ |  | 32-bit x86, restricted to Pentium
diff --git a/src/doc/rustc/src/platform-support/hexagon-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/hexagon-unknown-linux-musl.md
new file mode 100644
index 00000000000..c1372726a35
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/hexagon-unknown-linux-musl.md
@@ -0,0 +1,102 @@
+# `hexagon-unknown-linux-musl`
+
+**Tier: 3**
+
+Target for cross-compiling Linux user-mode applications targeting the Hexagon
+DSP architecture.
+
+| Target                   | Descriptions                              |
+| ------------------------ | ----------------------------------------- |
+| hexagon-unknown-linux-musl | Hexagon 32-bit Linux |
+
+## Target maintainers
+
+- [Brian Cain](https://github.com/androm3da), `bcain@quicinc.com`
+
+## Requirements
+The target is cross-compiled. This target supports `std`.  By default, code
+generated with this target should run on Hexagon DSP hardware.
+
+- `-Ctarget-cpu=hexagonv73` adds support for instructions defined up to Hexagon V73.
+
+Binaries can be run using QEMU user emulation. On Debian-based systems, it should be
+sufficient to install the package `qemu-user-static` to be able to run simple static
+binaries:
+
+```text
+# apt install qemu-user-static
+# qemu-hexagon-static ./hello
+```
+
+In order to build linux programs with Rust, you will require a linker capable
+of targeting hexagon.  You can use `clang`/`lld` from the [hexagon toolchain
+using exclusively public open source repos](https://github.com/quic/toolchain_for_hexagon/releases).
+
+Also included in that toolchain is the C library that can be used when creating
+dynamically linked executables.
+
+```text
+# /opt/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/bin/qemu-hexagon -L /opt/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr/ ./hello
+```
+
+## Building the target
+Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this
+target.
+
+Therefore, you can build Rust with support for the target by adding it to the
+target list in `config.toml`, a sample configuration is shown below.
+
+```toml
+[build]
+target = [ "hexagon-unknown-linux-musl"]
+
+[target.hexagon-unknown-linux-musl]
+
+cc = "hexagon-unknown-linux-musl-clang"
+cxx = "hexagon-unknown-linux-musl-clang++"
+linker = "hexagon-unknown-linux-musl-clang"
+ar = "hexagon-unknown-linux-musl-ar"
+ranlib = "hexagon-unknown-linux-musl-ranlib"
+musl-root = "/opt/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr"
+llvm-libunwind = 'in-tree'
+qemu-rootfs = "/opt/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr"
+```
+
+
+## Testing
+
+Currently there is no support to run the rustc test suite for this target.
+
+
+## Building Rust programs
+
+Download and install the hexagon open source toolchain from https://github.com/quic/toolchain_for_hexagon/releases
+
+The following `.cargo/config` is needed inside any project directory to build
+for the Hexagon Linux target:
+
+```toml
+[build]
+target = "hexagon-unknown-linux-musl"
+
+[target.hexagon-unknown-linux-musl]
+linker = "hexagon-unknown-linux-musl-clang"
+ar = "hexagon-unknown-linux-musl-ar"
+runner = "qemu-hexagon -L /opt/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr"
+```
+
+Edit the "runner" in `.cargo/config` to point to the path to your toolchain's
+C library.
+
+```text
+...
+runner = "qemu-hexagon -L /path/to/my/inst/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/target/hexagon-unknown-linux-musl/usr"
+...
+```
+
+Build/run your rust program with `qemu-hexagon` in your `PATH`:
+
+```text
+export PATH=/path/to/my/inst/clang+llvm-18.1.0-cross-hexagon-unknown-linux-musl/x86_64-linux-gnu/bin/:$PATH
+cargo run -Zbuild-std -Zbuild-std-features=llvm-libunwind
+```
diff --git a/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md b/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md
index 3ac1d2c2460..a0e26b798ac 100644
--- a/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md
+++ b/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md
@@ -41,6 +41,8 @@ target = ["<target for your host>", "hexagon-unknown-none-elf"]
 cc = "hexagon-unknown-none-elf-clang"
 cxx = "hexagon-unknown-none-elf-clang++"
 linker = "hexagon-unknown-none-elf-clang"
+ranlib = "hexagon-unknown-none-elf-ranlib"
+ar = "hexagon-unknown-none-elf-ar"
 llvm-libunwind = 'in-tree'
 ```
 
@@ -142,7 +144,7 @@ ${cc} --target=hexagon-unknown-none-elf -o testit \
     ${g0_lib_path}/init.o \
     -L${sdk_libs}/${q6_arch}/ \
     -L${sdk_libs}/ \
-    testit.c \
+    wrap.c \
     target/hexagon-unknown-none-elf/${build_cfg}/libdemo1_hexagon.rlib \
     target/hexagon-unknown-none-elf/${build_cfg}/deps/libcore-*.rlib \
     target/hexagon-unknown-none-elf/${build_cfg}/deps/libcompiler_builtins-*.rlib \
@@ -217,7 +219,18 @@ fn rust_eh_personality() {}
 
 ```
 
-Next, save the script below as `build.sh` and edit it to suit your
+Next, create a C program as an entry point, save the content below as
+`wrap.c`:
+
+```C
+int hello();
+
+int main() {
+    hello();
+}
+```
+
+Then, save the script below as `build.sh` and edit it to suit your
 environment.  The script below will build a shared object against the QuRT
 RTOS which is suitable for emulation or on-device testing when loaded via
 the fastrpc-shell.
@@ -248,7 +261,7 @@ ${cc} --target=hexagon-unknown-none-elf -o testit.so \
       -Wl,--wrap=realloc \
       -Wl,--wrap=memalign \
     -m${q6_arch} \
-    testit.c \
+    wrap.c \
     target/hexagon-unknown-none-elf/${build_cfg}/libdemo2_hexagon.rlib \
     target/hexagon-unknown-none-elf/${build_cfg}/deps/libcore-*.rlib \
     target/hexagon-unknown-none-elf/${build_cfg}/deps/libcompiler_builtins-*.rlib \
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 1cdc792a819..aa5998876d9 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -136,6 +136,7 @@ fn can_merge(class1: Option<Class>, class2: Option<Class>, text: &str) -> bool {
     match (class1, class2) {
         (Some(c1), Some(c2)) => c1.is_equal_to(c2),
         (Some(Class::Ident(_)), None) | (None, Some(Class::Ident(_))) => true,
+        (Some(Class::Macro(_)), _) => false,
         (Some(_), None) | (None, Some(_)) => text.trim().is_empty(),
         (None, None) => true,
     }
diff --git a/src/librustdoc/html/highlight/fixtures/sample.html b/src/librustdoc/html/highlight/fixtures/sample.html
index aa735e81597..773afd5c2cc 100644
--- a/src/librustdoc/html/highlight/fixtures/sample.html
+++ b/src/librustdoc/html/highlight/fixtures/sample.html
@@ -32,7 +32,7 @@
     }
 }
 
-<span class="macro">macro_rules! </span>bar {
+<span class="macro">macro_rules!</span> bar {
     (<span class="macro-nonterminal">$foo</span>:tt) =&gt; {};
 }
 </code></pre>
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10912.rs b/src/tools/clippy/tests/ui/crashes/ice-10912.rs
index 8dfce194221..1d689e1d008 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-10912.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-10912.rs
@@ -2,7 +2,5 @@
 //@no-rustfix
 fn f2() -> impl Sized { && 3.14159265358979323846E }
 //~^ ERROR: expected at least one digit in exponent
-//~| ERROR: long literal lacking separators
-//~| NOTE: `-D clippy::unreadable-literal` implied by `-D warnings`
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10912.stderr b/src/tools/clippy/tests/ui/crashes/ice-10912.stderr
index cc80354c7c6..c697e54679f 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-10912.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-10912.stderr
@@ -4,14 +4,5 @@ error: expected at least one digit in exponent
 LL | fn f2() -> impl Sized { && 3.14159265358979323846E }
    |                            ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: long literal lacking separators
-  --> tests/ui/crashes/ice-10912.rs:3:28
-   |
-LL | fn f2() -> impl Sized { && 3.14159265358979323846E }
-   |                            ^^^^^^^^^^^^^^^^^^^^^^^ help: consider: `3.141_592_653_589_793_238_46`
-   |
-   = note: `-D clippy::unreadable-literal` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::unreadable_literal)]`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.rs b/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.rs
new file mode 100644
index 00000000000..b56abccbd41
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.rs
@@ -0,0 +1,8 @@
+struct Foo(isize, isize, isize, isize);
+
+pub fn main() {
+    let Self::anything_here_kills_it(a, b, ..) = Foo(5, 5, 5, 5);
+    match [5, 5, 5, 5] {
+        [..] => { }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.stderr b/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.stderr
new file mode 100644
index 00000000000..9e0d3b934b8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/unreachable-array-or-slice.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: `Self` is only available in impls, traits, and type definitions
+  --> tests/ui/crashes/unreachable-array-or-slice.rs:4:9
+   |
+LL |     let Self::anything_here_kills_it(a, b, ..) = Foo(5, 5, 5, 5);
+   |         ^^^^ `Self` is only available in impls, traits, and type definitions
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 8a7133fea43..281a32b77c5 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -68,7 +68,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
         queries: &'tcx rustc_interface::Queries<'tcx>,
     ) -> Compilation {
         queries.global_ctxt().unwrap().enter(|tcx| {
-            if tcx.sess.dcx().has_errors().is_some() {
+            if tcx.sess.dcx().has_errors_or_delayed_bugs().is_some() {
                 tcx.dcx().fatal("miri cannot be run on programs that fail compilation");
             }
 
diff --git a/src/tools/rustfmt/src/formatting.rs b/src/tools/rustfmt/src/formatting.rs
index 323ae83fe6e..1c64921b1a6 100644
--- a/src/tools/rustfmt/src/formatting.rs
+++ b/src/tools/rustfmt/src/formatting.rs
@@ -109,7 +109,7 @@ fn format_project<T: FormatHandler>(
     let main_file = input.file_name();
     let input_is_stdin = main_file == FileName::Stdin;
 
-    let mut parse_session = ParseSess::new(config)?;
+    let parse_session = ParseSess::new(config)?;
     if config.skip_children() && parse_session.ignore_file(&main_file) {
         return Ok(FormatReport::new());
     }
@@ -118,20 +118,11 @@ fn format_project<T: FormatHandler>(
     let mut report = FormatReport::new();
     let directory_ownership = input.to_directory_ownership();
 
-    // rustfmt doesn't use `run_compiler` like other tools, so it must emit any
-    // stashed diagnostics itself, otherwise the `DiagCtxt` will assert when
-    // dropped. The final result here combines the parsing result and the
-    // `emit_stashed_diagnostics` result.
-    let parse_res = Parser::parse_crate(input, &parse_session);
-    let stashed_res = parse_session.emit_stashed_diagnostics();
-    let krate = match (parse_res, stashed_res) {
-        (Ok(krate), None) => krate,
-        (parse_res, _) => {
-            // Surface parse error via Session (errors are merged there from report).
-            let forbid_verbose = match parse_res {
-                Err(e) if e != ParserError::ParsePanicError => true,
-                _ => input_is_stdin,
-            };
+    let krate = match Parser::parse_crate(input, &parse_session) {
+        Ok(krate) => krate,
+        // Surface parse error via Session (errors are merged there from report)
+        Err(e) => {
+            let forbid_verbose = input_is_stdin || e != ParserError::ParsePanicError;
             should_emit_verbose(forbid_verbose, config, || {
                 eprintln!("The Rust parser panicked");
             });
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs
index 7e6517a66dd..d6386a9504d 100644
--- a/src/tools/rustfmt/src/parse/session.rs
+++ b/src/tools/rustfmt/src/parse/session.rs
@@ -5,9 +5,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
 use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
 use rustc_errors::emitter::{stderr_destination, DynEmitter, Emitter, HumanEmitter};
 use rustc_errors::translation::Translate;
-use rustc_errors::{
-    ColorConfig, Diag, DiagCtxt, DiagInner, ErrorGuaranteed, Level as DiagnosticLevel,
-};
+use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel};
 use rustc_session::parse::ParseSess as RawParseSess;
 use rustc_span::{
     source_map::{FilePathMapping, SourceMap},
@@ -233,10 +231,6 @@ impl ParseSess {
         self.ignore_path_set.as_ref().is_match(path)
     }
 
-    pub(crate) fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
-        self.parse_sess.dcx.emit_stashed_diagnostics()
-    }
-
     pub(crate) fn set_silent_emitter(&mut self) {
         self.parse_sess.dcx = DiagCtxt::new(silent_emitter());
     }
diff --git a/tests/codegen/sanitizer/cfi-emit-type-metadata-attr-cfi-encoding.rs b/tests/codegen/sanitizer/cfi-emit-type-metadata-attr-cfi-encoding.rs
index f15ca30b7e3..be4af9b7962 100644
--- a/tests/codegen/sanitizer/cfi-emit-type-metadata-attr-cfi-encoding.rs
+++ b/tests/codegen/sanitizer/cfi-emit-type-metadata-attr-cfi-encoding.rs
@@ -18,6 +18,13 @@ extern {
 #[repr(transparent)]
 pub struct Type3(i32);
 
+#[cfi_encoding = "i"]
+pub struct Type4(i32);
+
+#[cfi_encoding = "j"]
+#[repr(transparent)]
+pub struct Type5(u32);
+
 pub fn foo0(_: Type1) { }
 // CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo1(_: Type1, _: Type1) { }
@@ -36,6 +43,18 @@ pub fn foo7(_: *mut Type3, _: *mut Type3) { }
 // CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo8(_: *mut Type3, _: *mut Type3, _: *mut Type3) { }
 // CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo9(_: Type4) { }
+// CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo10(_: Type4, _: Type4) { }
+// CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo11(_: Type4, _: Type4, _: Type4) { }
+// CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo12(_: Type5) { }
+// CHECK: define{{.*}}foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo13(_: Type5, _: Type5) { }
+// CHECK: define{{.*}}foo13{{.*}}!type ![[TYPE13:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
+pub fn foo14(_: Type5, _: Type5, _: Type5) { }
+// CHECK: define{{.*}}foo14{{.*}}!type ![[TYPE14:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 
 // CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFv3FooE"}
 // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFv3FooS_E"}
@@ -46,3 +65,9 @@ pub fn foo8(_: *mut Type3, _: *mut Type3, _: *mut Type3) { }
 // CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvP3BazE"}
 // CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvP3BazS0_E"}
 // CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvP3BazS0_S0_E"}
+// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFviE"}
+// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFviiE"}
+// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFviiiE"}
+// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvjE"}
+// CHECK: ![[TYPE13]] = !{i64 0, !"_ZTSFvjjE"}
+// CHECK: ![[TYPE14]] = !{i64 0, !"_ZTSFvjjjE"}
diff --git a/tests/codegen/sse42-implies-crc32.rs b/tests/codegen/sse42-implies-crc32.rs
index c627be5c30e..94fcd77bc88 100644
--- a/tests/codegen/sse42-implies-crc32.rs
+++ b/tests/codegen/sse42-implies-crc32.rs
@@ -12,4 +12,4 @@ pub unsafe fn crc32sse(v: u8) -> u32 {
     _mm_crc32_u8(out, v)
 }
 
-// CHECK: attributes #0 {{.*"target-features"="\+sse4.2,\+crc32"}}
+// CHECK: attributes #0 {{.*"target-features"=".*\+sse4.2,\+crc32"}}
diff --git a/tests/rustdoc-ui/lints/doc_cfg_hide.stderr b/tests/rustdoc-ui/lints/doc_cfg_hide.stderr
index b7e8870fdf5..ca6a14a42b8 100644
--- a/tests/rustdoc-ui/lints/doc_cfg_hide.stderr
+++ b/tests/rustdoc-ui/lints/doc_cfg_hide.stderr
@@ -18,7 +18,7 @@ help: to apply to the crate, use an inner attribute
 LL | #![doc(cfg_hide(doc))]
    |  +
 
-error: `#[doc(cfg_hide(...)]` takes a list of attributes
+error: `#[doc(cfg_hide(...))]` takes a list of attributes
   --> $DIR/doc_cfg_hide.rs:4:8
    |
 LL | #![doc(cfg_hide = "test")]
@@ -27,7 +27,7 @@ LL | #![doc(cfg_hide = "test")]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
 
-error: `#[doc(cfg_hide(...)]` takes a list of attributes
+error: `#[doc(cfg_hide(...))]` takes a list of attributes
   --> $DIR/doc_cfg_hide.rs:6:8
    |
 LL | #![doc(cfg_hide)]
diff --git a/tests/rustdoc/source-code-highlight.rs b/tests/rustdoc/source-code-highlight.rs
new file mode 100644
index 00000000000..0a1be791ec2
--- /dev/null
+++ b/tests/rustdoc/source-code-highlight.rs
@@ -0,0 +1,29 @@
+// We need this option to be enabled for the `foo` macro declaration to ensure
+// that the link on the ident is not including whitespace characters.
+
+//@ compile-flags: -Zunstable-options --generate-link-to-definition
+#![crate_name = "foo"]
+
+// @has 'src/foo/source-code-highlight.rs.html'
+
+// @hasraw - '<a href="../../foo/macro.foo.html">foo</a>'
+#[macro_export]
+macro_rules! foo {
+    () => {}
+}
+
+// @hasraw - '<span class="macro">foo!</span>'
+foo! {}
+
+// @hasraw - '<a href="../../foo/fn.f.html">f</a>'
+#[rustfmt::skip]
+pub fn f () {}
+// @hasraw - '<a href="../../foo/struct.Bar.html">Bar</a>'
+// @hasraw - '<a href="../../foo/struct.Bar.html">Bar</a>'
+// @hasraw - '<a href="{{channel}}/std/primitive.u32.html">u32</a>'
+#[rustfmt::skip]
+pub struct Bar ( u32 );
+// @hasraw - '<a href="../../foo/enum.Foo.html">Foo</a>'
+pub enum Foo {
+    A,
+}
diff --git a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs
index 9c3b458cd3a..be436465315 100644
--- a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs
+++ b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs
@@ -8,11 +8,15 @@ extern crate block_on;
 
 fn main() {
     block_on::block_on(async {
-        let x = async || {};
-
         async fn needs_async_fn_once(x: impl async FnOnce()) {
             x().await;
         }
-        needs_async_fn_once(x).await;
+
+        needs_async_fn_once(async || {}).await;
+
+        needs_async_fn_once(|| async {}).await;
+
+        async fn foo() {}
+        needs_async_fn_once(foo).await;
     });
 }
diff --git a/tests/ui/async-await/async-closures/is-fn.rs b/tests/ui/async-await/async-closures/is-fn.rs
new file mode 100644
index 00000000000..64cc28e425f
--- /dev/null
+++ b/tests/ui/async-await/async-closures/is-fn.rs
@@ -0,0 +1,24 @@
+//@ aux-build:block-on.rs
+//@ edition:2021
+//@ build-pass
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(async_closure)]
+
+use std::future::Future;
+
+extern crate block_on;
+
+// Check that closures that don't capture any state may implement `Fn`.
+
+fn main() {
+    block_on::block_on(async {
+        async fn call_once<F: Future>(x: impl FnOnce(&'static str) -> F) -> F::Output {
+            x("hello, world").await
+        }
+        call_once(async |x: &'static str| {
+            println!("hello, {x}");
+        }).await
+    });
+}
diff --git a/tests/ui/async-await/async-closures/move-is-async-fn.rs b/tests/ui/async-await/async-closures/move-is-async-fn.rs
index 0ccd137266d..79e2298f609 100644
--- a/tests/ui/async-await/async-closures/move-is-async-fn.rs
+++ b/tests/ui/async-await/async-closures/move-is-async-fn.rs
@@ -2,7 +2,7 @@
 //@ edition:2021
 //@ build-pass
 
-#![feature(async_closure)]
+#![feature(async_closure, async_fn_traits)]
 
 extern crate block_on;
 
@@ -15,7 +15,11 @@ fn main() {
         c().await;
         c().await;
 
-        fn is_static<T: 'static>(_: T) {}
-        is_static(c);
+        fn is_static<T: 'static>(_: &T) {}
+        is_static(&c);
+
+        // Check that `<{async fn} as AsyncFnOnce>::CallOnceFuture` owns its captures.
+        fn call_once<F: async FnOnce()>(f: F) -> F::CallOnceFuture { f() }
+        is_static(&call_once(c));
     });
 }
diff --git a/tests/ui/async-await/async-closures/once.rs b/tests/ui/async-await/async-closures/once.rs
index 55e4cedb267..761df3de444 100644
--- a/tests/ui/async-await/async-closures/once.rs
+++ b/tests/ui/async-await/async-closures/once.rs
@@ -1,6 +1,8 @@
 //@ aux-build:block-on.rs
 //@ edition:2021
 //@ build-pass
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
 
 #![feature(async_closure)]
 
@@ -8,11 +10,11 @@ use std::future::Future;
 
 extern crate block_on;
 
-struct NoCopy;
+// Check that async closures always implement `FnOnce`
 
 fn main() {
     block_on::block_on(async {
-        async fn call_once<F: Future>(x: impl Fn(&'static str) -> F) -> F::Output {
+        async fn call_once<F: Future>(x: impl FnOnce(&'static str) -> F) -> F::Output {
             x("hello, world").await
         }
         call_once(async |x: &'static str| {
diff --git a/tests/ui/async-await/async-closures/refd.rs b/tests/ui/async-await/async-closures/refd.rs
index 1d9bc1a601b..0b8d3d7aff5 100644
--- a/tests/ui/async-await/async-closures/refd.rs
+++ b/tests/ui/async-await/async-closures/refd.rs
@@ -2,8 +2,6 @@
 //@ edition:2021
 //@ build-pass
 
-// check that `&{async-closure}` implements `AsyncFn`.
-
 #![feature(async_closure)]
 
 extern crate block_on;
@@ -13,6 +11,15 @@ struct NoCopy;
 fn main() {
     block_on::block_on(async {
         async fn call_once(x: impl async Fn()) { x().await }
-        call_once(&async || {}).await
+
+        // check that `&{async-closure}` implements `async Fn`.
+        call_once(&async || {}).await;
+
+        // check that `&{closure}` implements `async Fn`.
+        call_once(&|| async {}).await;
+
+        // check that `&fndef` implements `async Fn`.
+        async fn foo() {}
+        call_once(&foo).await;
     });
 }
diff --git a/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs
new file mode 100644
index 00000000000..5680c057737
--- /dev/null
+++ b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs
@@ -0,0 +1,31 @@
+//@ aux-build:block-on.rs
+//@ edition:2018
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ build-pass (since it ICEs during mono)
+
+#![feature(async_closure)]
+
+extern crate block_on;
+
+use std::future::Future;
+
+async fn f(arg: &i32) {}
+
+async fn func<F>(f: F)
+where
+    F: async for<'a> Fn(&'a i32),
+{
+    let x: i32 = 0;
+    f(&x).await;
+}
+
+fn main() {
+    block_on::block_on(async {
+        // Function
+        func(f).await;
+
+        // Regular closure (doesn't capture)
+        func(|x: &i32| async {});
+    });
+}
diff --git a/tests/ui/async-await/async-fn/project.rs b/tests/ui/async-await/async-fn/project.rs
new file mode 100644
index 00000000000..302564bb951
--- /dev/null
+++ b/tests/ui/async-await/async-fn/project.rs
@@ -0,0 +1,12 @@
+//@ edition:2018
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+#![feature(async_closure, unboxed_closures, async_fn_traits)]
+
+fn project<F: async Fn<()>>(_: F) -> Option<F::Output> { None }
+
+fn main() {
+    let x: Option<i32> = project(|| async { 1i32 });
+}
diff --git a/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs b/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs
index 66d562d2eb5..5c2c3b8ec61 100644
--- a/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs
+++ b/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs
@@ -1,6 +1,5 @@
 const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹⋅s⁻²
 //~^ ERROR expected at least one digit in exponent
 //~| ERROR unknown start of token: \u{2212}
-//~| ERROR cannot subtract `{integer}` from `{float}`
 
 fn main() {}
diff --git a/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr b/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr
index 44bdbb93ff5..4b3d429c750 100644
--- a/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr
+++ b/tests/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr
@@ -15,24 +15,5 @@ help: Unicode character '−' (Minus Sign) looks like '-' (Minus/Hyphen), but it
 LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e-11; // m³⋅kg⁻¹⋅s⁻²
    |                                                     ~
 
-error[E0277]: cannot subtract `{integer}` from `{float}`
-  --> $DIR/issue-49746-unicode-confusable-in-float-literal-expt.rs:1:53
-   |
-LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹⋅s⁻²
-   |                                                     ^ no implementation for `{float} - {integer}`
-   |
-   = help: the trait `Sub<{integer}>` is not implemented for `{float}`
-   = help: the following other types implement trait `Sub<Rhs>`:
-             <isize as Sub>
-             <isize as Sub<&isize>>
-             <i8 as Sub>
-             <i8 as Sub<&i8>>
-             <i16 as Sub>
-             <i16 as Sub<&i16>>
-             <i32 as Sub>
-             <i32 as Sub<&i32>>
-           and 48 others
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/foreign/stashed-issue-121451.rs b/tests/ui/foreign/stashed-issue-121451.rs
new file mode 100644
index 00000000000..97a4af37475
--- /dev/null
+++ b/tests/ui/foreign/stashed-issue-121451.rs
@@ -0,0 +1,4 @@
+extern "C" fn _f() -> libc::uintptr_t {}
+//~^ ERROR failed to resolve: use of undeclared crate or module `libc`
+
+fn main() {}
diff --git a/tests/ui/foreign/stashed-issue-121451.stderr b/tests/ui/foreign/stashed-issue-121451.stderr
new file mode 100644
index 00000000000..440d98d6f46
--- /dev/null
+++ b/tests/ui/foreign/stashed-issue-121451.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared crate or module `libc`
+  --> $DIR/stashed-issue-121451.rs:1:23
+   |
+LL | extern "C" fn _f() -> libc::uintptr_t {}
+   |                       ^^^^ use of undeclared crate or module `libc`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/impl-trait/in-trait/refine-normalize.rs b/tests/ui/impl-trait/in-trait/refine-normalize.rs
new file mode 100644
index 00000000000..95f2cda6a74
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/refine-normalize.rs
@@ -0,0 +1,20 @@
+//@ check-pass
+//@ edition: 2021
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+
+#![deny(refining_impl_trait)]
+
+pub trait Foo {
+    type Item;
+
+    fn hello() -> impl Iterator<Item = Self::Item>;
+}
+
+impl Foo for () {
+    type Item = ();
+
+    fn hello() -> impl Iterator<Item = ()> { [()].into_iter() }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/stashed-diag-issue-121504.rs b/tests/ui/impl-trait/stashed-diag-issue-121504.rs
new file mode 100644
index 00000000000..4ac8ffe8931
--- /dev/null
+++ b/tests/ui/impl-trait/stashed-diag-issue-121504.rs
@@ -0,0 +1,13 @@
+//@ edition: 2021
+
+trait MyTrait {
+    async fn foo(self) -> (Self, i32);
+}
+
+impl MyTrait for xyz::T { //~ ERROR failed to resolve: use of undeclared crate or module `xyz`
+    async fn foo(self, key: i32) -> (u32, i32) {
+        (self, key)
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/stashed-diag-issue-121504.stderr b/tests/ui/impl-trait/stashed-diag-issue-121504.stderr
new file mode 100644
index 00000000000..6a881dc7f9f
--- /dev/null
+++ b/tests/ui/impl-trait/stashed-diag-issue-121504.stderr
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared crate or module `xyz`
+  --> $DIR/stashed-diag-issue-121504.rs:7:18
+   |
+LL | impl MyTrait for xyz::T {
+   |                  ^^^ use of undeclared crate or module `xyz`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.rs b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.rs
index 7f3817b326a..5e3d21eb26a 100644
--- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.rs
+++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.rs
@@ -10,7 +10,7 @@ pub trait MessageListenersInterface {
 
 impl<'a> MessageListenersInterface for MessageListeners<'a> {
     fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> {
-        //~^ ERROR cannot infer an appropriate lifetime for lifetime parameter 'b in generic type due to conflicting requirements
+        //~^ ERROR in type `&'a MessageListeners<'_>`, reference has a longer lifetime than the data it references
         self
     }
 }
diff --git a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr
index 6a412eb5e4b..e0cf15d0d1f 100644
--- a/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr
+++ b/tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr
@@ -1,27 +1,15 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'b in generic type due to conflicting requirements
+error[E0491]: in type `&'a MessageListeners<'_>`, reference has a longer lifetime than the data it references
   --> $DIR/impl-implied-bounds-compatibility.rs:12:5
    |
 LL |     fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: first, the lifetime cannot outlive the lifetime `'c` as defined here...
-  --> $DIR/impl-implied-bounds-compatibility.rs:12:5
-   |
-LL |     fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...so that the method type is compatible with trait
-  --> $DIR/impl-implied-bounds-compatibility.rs:12:5
-   |
-LL |     fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected `fn(&'c MessageListeners<'_>) -> &'c MessageListeners<'c>`
-              found `fn(&MessageListeners<'_>) -> &'a MessageListeners<'_>`
-note: but, the lifetime must be valid for the lifetime `'a` as defined here...
+note: the pointer is valid for the lifetime `'a` as defined here
   --> $DIR/impl-implied-bounds-compatibility.rs:11:6
    |
 LL | impl<'a> MessageListenersInterface for MessageListeners<'a> {
    |      ^^
-note: ...so that the reference type `&'a MessageListeners<'_>` does not outlive the data it points at
+note: but the referenced data is only valid for the lifetime `'c` as defined here
   --> $DIR/impl-implied-bounds-compatibility.rs:12:5
    |
 LL |     fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> {
@@ -29,4 +17,4 @@ LL |     fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> {
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0491`.
diff --git a/tests/ui/lowering/issue-121108.rs b/tests/ui/lowering/issue-121108.rs
index 6b2dd24e4a8..6dfb7e00821 100644
--- a/tests/ui/lowering/issue-121108.rs
+++ b/tests/ui/lowering/issue-121108.rs
@@ -3,7 +3,7 @@
 use std::ptr::addr_of;
 
 const UNINHABITED_VARIANT: () = unsafe {
-    let v = *addr_of!(data).cast(); //~ ERROR cannot determine resolution for the macro `addr_of`
+    let v = *addr_of!(data).cast();
 };
 
 fn main() {}
diff --git a/tests/ui/lowering/issue-121108.stderr b/tests/ui/lowering/issue-121108.stderr
index c2c5746d6f1..e4942e8cb07 100644
--- a/tests/ui/lowering/issue-121108.stderr
+++ b/tests/ui/lowering/issue-121108.stderr
@@ -13,13 +13,5 @@ LL - #![derive(Clone, Copy)]
 LL + #[derive(Clone, Copy)]
    |
 
-error: cannot determine resolution for the macro `addr_of`
-  --> $DIR/issue-121108.rs:6:14
-   |
-LL |     let v = *addr_of!(data).cast();
-   |              ^^^^^^^
-   |
-   = note: import resolution is stuck, try simplifying macro imports
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/float-field.rs b/tests/ui/parser/float-field.rs
index eaa7465dc4d..59fefee26aa 100644
--- a/tests/ui/parser/float-field.rs
+++ b/tests/ui/parser/float-field.rs
@@ -3,60 +3,91 @@ struct S(u8, (u8, u8));
 fn main() {
     let s = S(0, (0, 0));
 
-    s.1e1; //~ ERROR no field `1e1` on type `S`
-    s.1.; //~ ERROR unexpected token: `;`
-    s.1.1;
-    s.1.1e1; //~ ERROR no field `1e1` on type `(u8, u8)`
+    { s.1e1; } //~ ERROR no field `1e1` on type `S`
+
+    { s.1.; } //~ ERROR unexpected token: `;`
+
+    { s.1.1; }
+
+    { s.1.1e1; } //~ ERROR no field `1e1` on type `(u8, u8)`
+
     { s.1e+; } //~ ERROR unexpected token: `1e+`
                //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+`
                //~| ERROR expected at least one digit in exponent
+
     { s.1e-; } //~ ERROR unexpected token: `1e-`
                //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-`
                //~| ERROR expected at least one digit in exponent
+
     { s.1e+1; } //~ ERROR unexpected token: `1e+1`
                 //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1`
+
     { s.1e-1; } //~ ERROR unexpected token: `1e-1`
                 //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1`
+
     { s.1.1e+1; } //~ ERROR unexpected token: `1.1e+1`
                   //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1`
+
     { s.1.1e-1; } //~ ERROR unexpected token: `1.1e-1`
                   //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1`
-    s.0x1e1;  //~ ERROR no field `0x1e1` on type `S`
-    s.0x1.; //~ ERROR no field `0x1` on type `S`
-            //~| ERROR hexadecimal float literal is not supported
-            //~| ERROR unexpected token: `;`
-    s.0x1.1; //~ ERROR no field `0x1` on type `S`
-             //~| ERROR hexadecimal float literal is not supported
-    s.0x1.1e1; //~ ERROR no field `0x1` on type `S`
-               //~| ERROR hexadecimal float literal is not supported
+
+    { s.0x1e1; } //~ ERROR no field `0x1e1` on type `S`
+
+    { s.0x1.; } //~ ERROR hexadecimal float literal is not supported
+                //~| ERROR unexpected token: `0x1.`
+                //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.`
+
+    { s.0x1.1; } //~ ERROR hexadecimal float literal is not supported
+                 //~| ERROR unexpected token: `0x1.1`
+                 //~| expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1`
+
+    { s.0x1.1e1; } //~ ERROR hexadecimal float literal is not supported
+                   //~| ERROR unexpected token: `0x1.1e1`
+                   //~| expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e1`
+
     { s.0x1e+; } //~ ERROR expected expression, found `;`
+
     { s.0x1e-; } //~ ERROR expected expression, found `;`
-    s.0x1e+1; //~ ERROR no field `0x1e` on type `S`
-    s.0x1e-1; //~ ERROR no field `0x1e` on type `S`
+
+    { s.0x1e+1; } //~ ERROR no field `0x1e` on type `S`
+
+    { s.0x1e-1; } //~ ERROR no field `0x1e` on type `S`
+
     { s.0x1.1e+1; } //~ ERROR unexpected token: `0x1.1e+1`
                     //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e+1`
                     //~| ERROR hexadecimal float literal is not supported
+
     { s.0x1.1e-1; } //~ ERROR unexpected token: `0x1.1e-1`
                     //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e-1`
                     //~| ERROR hexadecimal float literal is not supported
-    s.1e1f32; //~ ERROR no field `1e1` on type `S`
-              //~| ERROR suffixes on a tuple index are invalid
-    s.1.f32; //~ ERROR no field `f32` on type `(u8, u8)`
-    s.1.1f32; //~ ERROR suffixes on a tuple index are invalid
-    s.1.1e1f32; //~ ERROR no field `1e1` on type `(u8, u8)`
-                //~| ERROR suffixes on a tuple index are invalid
+
+    { s.1e1f32; } //~ ERROR no field `1e1` on type `S`
+                  //~| ERROR suffixes on a tuple index are invalid
+
+    { s.1.f32; } //~ ERROR no field `f32` on type `(u8, u8)`
+
+    { s.1.1f32; } //~ ERROR suffixes on a tuple index are invalid
+
+    { s.1.1e1f32; } //~ ERROR no field `1e1` on type `(u8, u8)`
+                    //~| ERROR suffixes on a tuple index are invalid
+
     { s.1e+f32; } //~ ERROR unexpected token: `1e+f32`
                   //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+f32`
                   //~| ERROR expected at least one digit in exponent
+
     { s.1e-f32; } //~ ERROR unexpected token: `1e-f32`
                   //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-f32`
                   //~| ERROR expected at least one digit in exponent
+
     { s.1e+1f32; } //~ ERROR unexpected token: `1e+1f32`
                    //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1f32`
+
     { s.1e-1f32; } //~ ERROR unexpected token: `1e-1f32`
                    //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1f32`
+
     { s.1.1e+1f32; } //~ ERROR unexpected token: `1.1e+1f32`
                     //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1f32`
+
     { s.1.1e-1f32; } //~ ERROR unexpected token: `1.1e-1f32`
                     //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1f32`
 }
diff --git a/tests/ui/parser/float-field.stderr b/tests/ui/parser/float-field.stderr
index d67d270ef7b..0cc1b0767dc 100644
--- a/tests/ui/parser/float-field.stderr
+++ b/tests/ui/parser/float-field.stderr
@@ -1,349 +1,355 @@
 error: expected at least one digit in exponent
-  --> $DIR/float-field.rs:10:9
+  --> $DIR/float-field.rs:14:9
    |
 LL |     { s.1e+; }
    |         ^^^
 
 error: expected at least one digit in exponent
-  --> $DIR/float-field.rs:13:9
+  --> $DIR/float-field.rs:18:9
    |
 LL |     { s.1e-; }
    |         ^^^
 
 error: hexadecimal float literal is not supported
-  --> $DIR/float-field.rs:25:7
+  --> $DIR/float-field.rs:36:9
    |
-LL |     s.0x1.;
-   |       ^^^^
+LL |     { s.0x1.; }
+   |         ^^^^
 
 error: hexadecimal float literal is not supported
-  --> $DIR/float-field.rs:28:7
+  --> $DIR/float-field.rs:40:9
    |
-LL |     s.0x1.1;
-   |       ^^^^^
+LL |     { s.0x1.1; }
+   |         ^^^^^
 
 error: hexadecimal float literal is not supported
-  --> $DIR/float-field.rs:30:7
+  --> $DIR/float-field.rs:44:9
    |
-LL |     s.0x1.1e1;
-   |       ^^^^^^^
+LL |     { s.0x1.1e1; }
+   |         ^^^^^^^
 
 error: hexadecimal float literal is not supported
-  --> $DIR/float-field.rs:36:9
+  --> $DIR/float-field.rs:56:9
    |
 LL |     { s.0x1.1e+1; }
    |         ^^^^^^^^
 
 error: hexadecimal float literal is not supported
-  --> $DIR/float-field.rs:39:9
+  --> $DIR/float-field.rs:60:9
    |
 LL |     { s.0x1.1e-1; }
    |         ^^^^^^^^
 
 error: expected at least one digit in exponent
-  --> $DIR/float-field.rs:48:9
+  --> $DIR/float-field.rs:74:9
    |
 LL |     { s.1e+f32; }
    |         ^^^^^^
 
 error: expected at least one digit in exponent
-  --> $DIR/float-field.rs:51:9
+  --> $DIR/float-field.rs:78:9
    |
 LL |     { s.1e-f32; }
    |         ^^^^^^
 
 error: unexpected token: `;`
-  --> $DIR/float-field.rs:7:9
+  --> $DIR/float-field.rs:8:11
    |
-LL |     s.1.;
-   |         ^
+LL |     { s.1.; }
+   |           ^
 
 error: unexpected token: `1e+`
-  --> $DIR/float-field.rs:10:9
+  --> $DIR/float-field.rs:14:9
    |
 LL |     { s.1e+; }
    |         ^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+`
-  --> $DIR/float-field.rs:10:9
+  --> $DIR/float-field.rs:14:9
    |
 LL |     { s.1e+; }
    |         ^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error: unexpected token: `1e-`
-  --> $DIR/float-field.rs:13:9
+  --> $DIR/float-field.rs:18:9
    |
 LL |     { s.1e-; }
    |         ^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-`
-  --> $DIR/float-field.rs:13:9
+  --> $DIR/float-field.rs:18:9
    |
 LL |     { s.1e-; }
    |         ^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error: unexpected token: `1e+1`
-  --> $DIR/float-field.rs:16:9
+  --> $DIR/float-field.rs:22:9
    |
 LL |     { s.1e+1; }
    |         ^^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1`
-  --> $DIR/float-field.rs:16:9
+  --> $DIR/float-field.rs:22:9
    |
 LL |     { s.1e+1; }
    |         ^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error: unexpected token: `1e-1`
-  --> $DIR/float-field.rs:18:9
+  --> $DIR/float-field.rs:25:9
    |
 LL |     { s.1e-1; }
    |         ^^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1`
-  --> $DIR/float-field.rs:18:9
+  --> $DIR/float-field.rs:25:9
    |
 LL |     { s.1e-1; }
    |         ^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error: unexpected token: `1.1e+1`
-  --> $DIR/float-field.rs:20:9
+  --> $DIR/float-field.rs:28:9
    |
 LL |     { s.1.1e+1; }
    |         ^^^^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1`
-  --> $DIR/float-field.rs:20:9
+  --> $DIR/float-field.rs:28:9
    |
 LL |     { s.1.1e+1; }
    |         ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error: unexpected token: `1.1e-1`
-  --> $DIR/float-field.rs:22:9
+  --> $DIR/float-field.rs:31:9
    |
 LL |     { s.1.1e-1; }
    |         ^^^^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1`
-  --> $DIR/float-field.rs:22:9
+  --> $DIR/float-field.rs:31:9
    |
 LL |     { s.1.1e-1; }
    |         ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
-error: unexpected token: `;`
-  --> $DIR/float-field.rs:25:11
+error: unexpected token: `0x1.`
+  --> $DIR/float-field.rs:36:9
    |
-LL |     s.0x1.;
-   |           ^
+LL |     { s.0x1.; }
+   |         ^^^^
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.`
+  --> $DIR/float-field.rs:36:9
+   |
+LL |     { s.0x1.; }
+   |         ^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
+
+error: unexpected token: `0x1.1`
+  --> $DIR/float-field.rs:40:9
+   |
+LL |     { s.0x1.1; }
+   |         ^^^^^
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1`
+  --> $DIR/float-field.rs:40:9
+   |
+LL |     { s.0x1.1; }
+   |         ^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
+
+error: unexpected token: `0x1.1e1`
+  --> $DIR/float-field.rs:44:9
+   |
+LL |     { s.0x1.1e1; }
+   |         ^^^^^^^
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e1`
+  --> $DIR/float-field.rs:44:9
+   |
+LL |     { s.0x1.1e1; }
+   |         ^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error: expected expression, found `;`
-  --> $DIR/float-field.rs:32:14
+  --> $DIR/float-field.rs:48:14
    |
 LL |     { s.0x1e+; }
    |              ^ expected expression
 
 error: expected expression, found `;`
-  --> $DIR/float-field.rs:33:14
+  --> $DIR/float-field.rs:50:14
    |
 LL |     { s.0x1e-; }
    |              ^ expected expression
 
 error: unexpected token: `0x1.1e+1`
-  --> $DIR/float-field.rs:36:9
+  --> $DIR/float-field.rs:56:9
    |
 LL |     { s.0x1.1e+1; }
    |         ^^^^^^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e+1`
-  --> $DIR/float-field.rs:36:9
+  --> $DIR/float-field.rs:56:9
    |
 LL |     { s.0x1.1e+1; }
    |         ^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error: unexpected token: `0x1.1e-1`
-  --> $DIR/float-field.rs:39:9
+  --> $DIR/float-field.rs:60:9
    |
 LL |     { s.0x1.1e-1; }
    |         ^^^^^^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e-1`
-  --> $DIR/float-field.rs:39:9
+  --> $DIR/float-field.rs:60:9
    |
 LL |     { s.0x1.1e-1; }
    |         ^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error: suffixes on a tuple index are invalid
-  --> $DIR/float-field.rs:42:7
+  --> $DIR/float-field.rs:64:9
    |
-LL |     s.1e1f32;
-   |       ^^^^^^ invalid suffix `f32`
+LL |     { s.1e1f32; }
+   |         ^^^^^^ invalid suffix `f32`
 
 error: suffixes on a tuple index are invalid
-  --> $DIR/float-field.rs:45:7
+  --> $DIR/float-field.rs:69:9
    |
-LL |     s.1.1f32;
-   |       ^^^^^^ invalid suffix `f32`
+LL |     { s.1.1f32; }
+   |         ^^^^^^ invalid suffix `f32`
 
 error: suffixes on a tuple index are invalid
-  --> $DIR/float-field.rs:46:7
+  --> $DIR/float-field.rs:71:9
    |
-LL |     s.1.1e1f32;
-   |       ^^^^^^^^ invalid suffix `f32`
+LL |     { s.1.1e1f32; }
+   |         ^^^^^^^^ invalid suffix `f32`
 
 error: unexpected token: `1e+f32`
-  --> $DIR/float-field.rs:48:9
+  --> $DIR/float-field.rs:74:9
    |
 LL |     { s.1e+f32; }
    |         ^^^^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+f32`
-  --> $DIR/float-field.rs:48:9
+  --> $DIR/float-field.rs:74:9
    |
 LL |     { s.1e+f32; }
    |         ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error: unexpected token: `1e-f32`
-  --> $DIR/float-field.rs:51:9
+  --> $DIR/float-field.rs:78:9
    |
 LL |     { s.1e-f32; }
    |         ^^^^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-f32`
-  --> $DIR/float-field.rs:51:9
+  --> $DIR/float-field.rs:78:9
    |
 LL |     { s.1e-f32; }
    |         ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error: unexpected token: `1e+1f32`
-  --> $DIR/float-field.rs:54:9
+  --> $DIR/float-field.rs:82:9
    |
 LL |     { s.1e+1f32; }
    |         ^^^^^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1f32`
-  --> $DIR/float-field.rs:54:9
+  --> $DIR/float-field.rs:82:9
    |
 LL |     { s.1e+1f32; }
    |         ^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error: unexpected token: `1e-1f32`
-  --> $DIR/float-field.rs:56:9
+  --> $DIR/float-field.rs:85:9
    |
 LL |     { s.1e-1f32; }
    |         ^^^^^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1f32`
-  --> $DIR/float-field.rs:56:9
+  --> $DIR/float-field.rs:85:9
    |
 LL |     { s.1e-1f32; }
    |         ^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error: unexpected token: `1.1e+1f32`
-  --> $DIR/float-field.rs:58:9
+  --> $DIR/float-field.rs:88:9
    |
 LL |     { s.1.1e+1f32; }
    |         ^^^^^^^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1f32`
-  --> $DIR/float-field.rs:58:9
+  --> $DIR/float-field.rs:88:9
    |
 LL |     { s.1.1e+1f32; }
    |         ^^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error: unexpected token: `1.1e-1f32`
-  --> $DIR/float-field.rs:60:9
+  --> $DIR/float-field.rs:91:9
    |
 LL |     { s.1.1e-1f32; }
    |         ^^^^^^^^^
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1f32`
-  --> $DIR/float-field.rs:60:9
+  --> $DIR/float-field.rs:91:9
    |
 LL |     { s.1.1e-1f32; }
    |         ^^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator
 
 error[E0609]: no field `1e1` on type `S`
-  --> $DIR/float-field.rs:6:7
+  --> $DIR/float-field.rs:6:9
    |
-LL |     s.1e1;
-   |       ^^^ unknown field
+LL |     { s.1e1; }
+   |         ^^^ unknown field
    |
    = note: available fields are: `0`, `1`
 
 error[E0609]: no field `1e1` on type `(u8, u8)`
-  --> $DIR/float-field.rs:9:9
+  --> $DIR/float-field.rs:12:11
    |
-LL |     s.1.1e1;
-   |         ^^^ unknown field
+LL |     { s.1.1e1; }
+   |           ^^^ unknown field
 
 error[E0609]: no field `0x1e1` on type `S`
-  --> $DIR/float-field.rs:24:7
-   |
-LL |     s.0x1e1;
-   |       ^^^^^ unknown field
-   |
-   = note: available fields are: `0`, `1`
-
-error[E0609]: no field `0x1` on type `S`
-  --> $DIR/float-field.rs:25:7
-   |
-LL |     s.0x1.;
-   |       ^^^ unknown field
-   |
-   = note: available fields are: `0`, `1`
-
-error[E0609]: no field `0x1` on type `S`
-  --> $DIR/float-field.rs:28:7
-   |
-LL |     s.0x1.1;
-   |       ^^^ unknown field
-   |
-   = note: available fields are: `0`, `1`
-
-error[E0609]: no field `0x1` on type `S`
-  --> $DIR/float-field.rs:30:7
+  --> $DIR/float-field.rs:34:9
    |
-LL |     s.0x1.1e1;
-   |       ^^^ unknown field
+LL |     { s.0x1e1; }
+   |         ^^^^^ unknown field
    |
    = note: available fields are: `0`, `1`
 
 error[E0609]: no field `0x1e` on type `S`
-  --> $DIR/float-field.rs:34:7
+  --> $DIR/float-field.rs:52:9
    |
-LL |     s.0x1e+1;
-   |       ^^^^ unknown field
+LL |     { s.0x1e+1; }
+   |         ^^^^ unknown field
    |
    = note: available fields are: `0`, `1`
 
 error[E0609]: no field `0x1e` on type `S`
-  --> $DIR/float-field.rs:35:7
+  --> $DIR/float-field.rs:54:9
    |
-LL |     s.0x1e-1;
-   |       ^^^^ unknown field
+LL |     { s.0x1e-1; }
+   |         ^^^^ unknown field
    |
    = note: available fields are: `0`, `1`
 
 error[E0609]: no field `1e1` on type `S`
-  --> $DIR/float-field.rs:42:7
+  --> $DIR/float-field.rs:64:9
    |
-LL |     s.1e1f32;
-   |       ^^^^^^ unknown field
+LL |     { s.1e1f32; }
+   |         ^^^^^^ unknown field
    |
    = note: available fields are: `0`, `1`
 
 error[E0609]: no field `f32` on type `(u8, u8)`
-  --> $DIR/float-field.rs:44:9
+  --> $DIR/float-field.rs:67:11
    |
-LL |     s.1.f32;
-   |         ^^^ unknown field
+LL |     { s.1.f32; }
+   |           ^^^ unknown field
 
 error[E0609]: no field `1e1` on type `(u8, u8)`
-  --> $DIR/float-field.rs:46:7
+  --> $DIR/float-field.rs:71:9
    |
-LL |     s.1.1e1f32;
-   |       ^^^^^^^^ unknown field
+LL |     { s.1.1e1f32; }
+   |         ^^^^^^^^ unknown field
 
-error: aborting due to 55 previous errors
+error: aborting due to 57 previous errors
 
 For more information about this error, try `rustc --explain E0609`.
diff --git a/tests/ui/resolve/issue-111312.rs b/tests/ui/resolve/issue-111312.rs
index 68fc8573dde..79c6f67dadd 100644
--- a/tests/ui/resolve/issue-111312.rs
+++ b/tests/ui/resolve/issue-111312.rs
@@ -7,5 +7,7 @@ trait Has {
 trait HasNot {}
 
 fn main() {
-    HasNot::has(); //~ ERROR
+    HasNot::has();
+    //~^ ERROR trait objects must include the `dyn` keyword
+    //~| ERROR no function or associated item named `has` found for trait `HasNot`
 }
diff --git a/tests/ui/resolve/issue-111312.stderr b/tests/ui/resolve/issue-111312.stderr
index 7e7ef22ae61..431802ead30 100644
--- a/tests/ui/resolve/issue-111312.stderr
+++ b/tests/ui/resolve/issue-111312.stderr
@@ -1,3 +1,14 @@
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/issue-111312.rs:10:5
+   |
+LL |     HasNot::has();
+   |     ^^^^^^
+   |
+help: add `dyn` keyword before this trait
+   |
+LL |     <dyn HasNot>::has();
+   |     ++++       +
+
 error[E0599]: no function or associated item named `has` found for trait `HasNot`
   --> $DIR/issue-111312.rs:10:13
    |
@@ -10,6 +21,7 @@ note: `Has` defines an item `has`
 LL | trait Has {
    | ^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0599`.
+Some errors have detailed explanations: E0599, E0782.
+For more information about an error, try `rustc --explain E0599`.
diff --git a/tests/ui/resolve/issue-111727.rs b/tests/ui/resolve/issue-111727.rs
index 740037fe434..fcab924b809 100644
--- a/tests/ui/resolve/issue-111727.rs
+++ b/tests/ui/resolve/issue-111727.rs
@@ -1,5 +1,7 @@
 //@ edition: 2021
 
 fn main() {
-    std::any::Any::create(); //~ ERROR
+    std::any::Any::create();
+    //~^ ERROR trait objects must include the `dyn` keyword
+    //~| ERROR no function or associated item named `create` found for trait `Any`
 }
diff --git a/tests/ui/resolve/issue-111727.stderr b/tests/ui/resolve/issue-111727.stderr
index b58168d0e75..1ef5a1a1d5e 100644
--- a/tests/ui/resolve/issue-111727.stderr
+++ b/tests/ui/resolve/issue-111727.stderr
@@ -1,9 +1,21 @@
+error[E0782]: trait objects must include the `dyn` keyword
+  --> $DIR/issue-111727.rs:4:5
+   |
+LL |     std::any::Any::create();
+   |     ^^^^^^^^^^^^^
+   |
+help: add `dyn` keyword before this trait
+   |
+LL |     <dyn std::any::Any>::create();
+   |     ++++              +
+
 error[E0599]: no function or associated item named `create` found for trait `Any`
   --> $DIR/issue-111727.rs:4:20
    |
 LL |     std::any::Any::create();
    |                    ^^^^^^ function or associated item not found in `Any`
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0599`.
+Some errors have detailed explanations: E0599, E0782.
+For more information about an error, try `rustc --explain E0599`.
diff --git a/tests/ui/suggestions/silenced-binding-typo.stderr b/tests/ui/suggestions/silenced-binding-typo.stderr
index 8dbd94208d6..c362d00c713 100644
--- a/tests/ui/suggestions/silenced-binding-typo.stderr
+++ b/tests/ui/suggestions/silenced-binding-typo.stderr
@@ -4,7 +4,7 @@ error[E0425]: cannot find value `x` in this scope
 LL |     let _y = x;
    |              ^
    |
-help: a local variable with a similar name exists, consider changing it
+help: a local variable with a similar name exists, consider renaming `_x` into `x`
    |
 LL |     let x = 42;
    |         ~
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
index b2842df150a..4b5f455e381 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
@@ -11,6 +11,7 @@ fn foo<'a, 'b>() -> Tait<'a> {
     }
     let x: Tait<'a> = ();
     x
+    //~^ ERROR concrete type differs from previous defining opaque type use
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
index e5cee49cf29..6f5be5467f7 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
@@ -1,4 +1,16 @@
 error: concrete type differs from previous defining opaque type use
+  --> $DIR/different_defining_uses_never_type-2.rs:13:5
+   |
+LL |     x
+   |     ^ expected `i32`, got `()`
+   |
+note: previous use here
+  --> $DIR/different_defining_uses_never_type-2.rs:8:31
+   |
+LL |             let y: Tait<'b> = 1i32;
+   |                               ^^^^
+
+error: concrete type differs from previous defining opaque type use
   --> $DIR/different_defining_uses_never_type-2.rs:8:31
    |
 LL |             let y: Tait<'b> = 1i32;
@@ -10,5 +22,5 @@ note: previous use here
 LL |         if { return } {
    |              ^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
diff --git a/triagebot.toml b/triagebot.toml
index e084b555464..802079f496e 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -673,6 +673,12 @@ compiler = [
 libs = [
     "@cuviper",
     "@Mark-Simulacrum",
+    "@m-ou-se",
+    "@Amanieu",
+    "@Nilstrieb",
+    "@workingjubilee",
+    "@joboet",
+    "@jhpratt",
 ]
 bootstrap = [
     "@Mark-Simulacrum",
@@ -810,7 +816,7 @@ project-stable-mir = [
 "/compiler/rustc_type_ir" =                              ["compiler", "types"]
 "/compiler/stable_mir" =                                 ["project-stable-mir"]
 "/library/alloc" =                                       ["libs"]
-"/library/core" =                                        ["libs"]
+"/library/core" =                                        ["libs", "@scottmcm"]
 "/library/panic_abort" =                                 ["libs"]
 "/library/panic_unwind" =                                ["libs"]
 "/library/proc_macro" =                                  ["@petrochenkov"]