Auto merge of #130025 - Urgau:missing_docs-expect, r=petrochenkov

Also emit `missing_docs` lint with `--test` to fulfil expectations

This PR removes the "test harness" suppression of the `missing_docs` lint to be able to fulfil `#[expect]` (expectations) as it is now "relevant".

I think the goal was to maybe avoid false-positive while linting on public items under `#[cfg(test)]` but with effective visibility we should no longer have any false-positive.

Another possibility would be to query the lint level and only emit the lint if it's of expect level, but that is even more hacky.

Fixes https://github.com/rust-lang/rust/issues/130021

try-job: x86_64-gnu-aux
diff --git a/.gitmodules b/.gitmodules
index b5250d4..9268073 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -47,3 +47,7 @@
 	path = src/tools/rustc-perf
 	url = https://github.com/rust-lang/rustc-perf.git
 	shallow = true
+[submodule "src/tools/enzyme"]
+	path = src/tools/enzyme
+	url = https://github.com/EnzymeAD/Enzyme.git
+	shallow = true
diff --git a/Cargo.lock b/Cargo.lock
index d671419..81aecf1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4167,6 +4167,7 @@
  "rustc_errors",
  "rustc_feature",
  "rustc_fluent_macro",
+ "rustc_index",
  "rustc_lexer",
  "rustc_macros",
  "rustc_session",
diff --git a/RELEASES.md b/RELEASES.md
index 29c872e..b49470c 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -34,7 +34,6 @@
   - [Add Tier 3 `std` Xtensa targets:](https://github.com/rust-lang/rust/pull/126380/) `xtensa-esp32-espidf`, `xtensa-esp32s2-espidf`, `xtensa-esp32s3-espidf`
   - [Add Tier 3 i686 Redox OS target:](https://github.com/rust-lang/rust/pull/126192/) `i686-unknown-redox`
   - [Promote `arm64ec-pc-windows-msvc` to Tier 2.](https://github.com/rust-lang/rust/pull/126039/)
-  - [Promote `wasm32-wasip2` to Tier 2.](https://github.com/rust-lang/rust/pull/126967/)
   - [Promote `loongarch64-unknown-linux-musl` to Tier 2 with host tools.](https://github.com/rust-lang/rust/pull/126298/)
   - [Enable full tools and profiler for LoongArch Linux targets.](https://github.com/rust-lang/rust/pull/127078/)
   - [Unconditionally warn on usage of `wasm32-wasi`.](https://github.com/rust-lang/rust/pull/126662/) (see compatibility note below)
@@ -100,6 +99,9 @@
   The reason is that these types have different roles: `std::panic::PanicHookInfo` is the argument to the [panic hook](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) in std context (where panics can have an arbitrary payload), while `core::panic::PanicInfo` is the argument to the [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) in no_std context (where panics always carry a formatted *message*). Separating these types allows us to add more useful methods to these types, such as `std::panic::PanicHookInfo::payload_as_str()` and `core::panic::PanicInfo::message()`.
 
 * The new sort implementations may panic if a type's implementation of [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) (or the given comparison function) does not implement a [total order](https://en.wikipedia.org/wiki/Total_order) as the trait requires. `Ord`'s supertraits (`PartialOrd`, `Eq`, and `PartialEq`) must also be consistent. The previous implementations would not "notice" any problem, but the new implementations have a good chance of detecting inconsistencies, throwing a panic rather than returning knowingly unsorted data.
+* [In very rare cases, a change in the internal evaluation order of the trait
+  solver may result in new fatal overflow errors.](https://github.com/rust-lang/rust/pull/126128)
+
 
 <a id="1.81.0-Internal-Changes"></a>
 
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 8a66894..7c8af6c 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -752,7 +752,7 @@ fn visit_lazy_tts<T: MutVisitor>(vis: &mut T, lazy_tts: &mut Option<LazyAttrToke
 pub fn visit_token<T: MutVisitor>(vis: &mut T, t: &mut Token) {
     let Token { kind, span } = t;
     match kind {
-        token::Ident(name, _ /*raw*/) | token::Lifetime(name) => {
+        token::Ident(name, _is_raw) | token::Lifetime(name, _is_raw) => {
             let mut ident = Ident::new(*name, *span);
             vis.visit_ident(&mut ident);
             *name = ident.name;
@@ -762,7 +762,7 @@ pub fn visit_token<T: MutVisitor>(vis: &mut T, t: &mut Token) {
         token::NtIdent(ident, _is_raw) => {
             vis.visit_ident(ident);
         }
-        token::NtLifetime(ident) => {
+        token::NtLifetime(ident, _is_raw) => {
             vis.visit_ident(ident);
         }
         token::Interpolated(nt) => {
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index f1dddb3..a0082a4 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -331,11 +331,11 @@ pub enum TokenKind {
     /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
     /// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to
     /// treat regular and interpolated lifetime identifiers in the same way.
-    Lifetime(Symbol),
+    Lifetime(Symbol, IdentIsRaw),
     /// This identifier (and its span) is the lifetime passed to the
     /// declarative macro. The span in the surrounding `Token` is the span of
     /// the `lifetime` metavariable in the macro's RHS.
-    NtLifetime(Ident),
+    NtLifetime(Ident, IdentIsRaw),
 
     /// An embedded AST node, as produced by a macro. This only exists for
     /// historical reasons. We'd like to get rid of it, for multiple reasons.
@@ -458,7 +458,7 @@ pub fn from_ast_ident(ident: Ident) -> Self {
     /// if they keep spans or perform edition checks.
     pub fn uninterpolated_span(&self) -> Span {
         match self.kind {
-            NtIdent(ident, _) | NtLifetime(ident) => ident.span,
+            NtIdent(ident, _) | NtLifetime(ident, _) => ident.span,
             Interpolated(ref nt) => nt.use_span(),
             _ => self.span,
         }
@@ -661,7 +661,9 @@ pub fn can_begin_string_literal(&self) -> bool {
     pub fn uninterpolate(&self) -> Cow<'_, Token> {
         match self.kind {
             NtIdent(ident, is_raw) => Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)),
-            NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)),
+            NtLifetime(ident, is_raw) => {
+                Cow::Owned(Token::new(Lifetime(ident.name, is_raw), ident.span))
+            }
             _ => Cow::Borrowed(self),
         }
     }
@@ -679,11 +681,11 @@ pub fn ident(&self) -> Option<(Ident, IdentIsRaw)> {
 
     /// Returns a lifetime identifier if this token is a lifetime.
     #[inline]
-    pub fn lifetime(&self) -> Option<Ident> {
+    pub fn lifetime(&self) -> Option<(Ident, IdentIsRaw)> {
         // We avoid using `Token::uninterpolate` here because it's slow.
         match self.kind {
-            Lifetime(name) => Some(Ident::new(name, self.span)),
-            NtLifetime(ident) => Some(ident),
+            Lifetime(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
+            NtLifetime(ident, is_raw) => Some((ident, is_raw)),
             _ => None,
         }
     }
@@ -865,7 +867,7 @@ pub fn glue(&self, joint: &Token) -> Option<Token> {
                 _ => return None,
             },
             SingleQuote => match joint.kind {
-                Ident(name, IdentIsRaw::No) => Lifetime(Symbol::intern(&format!("'{name}"))),
+                Ident(name, is_raw) => Lifetime(Symbol::intern(&format!("'{name}")), is_raw),
                 _ => return None,
             },
 
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 057b445..fc1dd2c 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -482,11 +482,11 @@ fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree {
             token::NtIdent(ident, is_raw) => {
                 TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing)
             }
-            token::NtLifetime(ident) => TokenTree::Delimited(
+            token::NtLifetime(ident, is_raw) => TokenTree::Delimited(
                 DelimSpan::from_single(token.span),
                 DelimSpacing::new(Spacing::JointHidden, spacing),
                 Delimiter::Invisible,
-                TokenStream::token_alone(token::Lifetime(ident.name), ident.span),
+                TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span),
             ),
             token::Interpolated(ref nt) => TokenTree::Delimited(
                 DelimSpan::from_single(token.span),
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index c7ff39d..3b1449d 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -11,7 +11,9 @@
 use ast::TraitBoundModifiers;
 use rustc_ast::attr::AttrIdGenerator;
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, Token, TokenKind};
+use rustc_ast::token::{
+    self, BinOpToken, CommentKind, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind,
+};
 use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
 use rustc_ast::util::classify;
 use rustc_ast::util::comments::{Comment, CommentStyle};
@@ -947,8 +949,13 @@ fn token_kind_to_string_ext(
             token::NtIdent(ident, is_raw) => {
                 IdentPrinter::for_ast_ident(ident, is_raw.into()).to_string().into()
             }
-            token::Lifetime(name) => name.to_string().into(),
-            token::NtLifetime(ident) => ident.name.to_string().into(),
+
+            token::Lifetime(name, IdentIsRaw::No)
+            | token::NtLifetime(Ident { name, .. }, IdentIsRaw::No) => name.to_string().into(),
+            token::Lifetime(name, IdentIsRaw::Yes)
+            | token::NtLifetime(Ident { name, .. }, IdentIsRaw::Yes) => {
+                format!("'r#{}", &name.as_str()[1..]).into()
+            }
 
             /* Other */
             token::DocComment(comment_kind, attr_style, data) => {
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index 2c672db..3a7e407 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -8,7 +8,7 @@
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
 
-impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     pub(crate) fn dcx(&self) -> DiagCtxtHandle<'infcx> {
         self.infcx.dcx()
     }
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 9bb6109..39994ad 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -15,24 +15,24 @@
 use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext};
 
 /// The results of the dataflow analyses used by the borrow checker.
-pub(crate) struct BorrowckResults<'a, 'mir, 'tcx> {
-    pub(crate) borrows: Results<'tcx, Borrows<'a, 'mir, 'tcx>>,
-    pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>,
-    pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'mir, 'tcx>>,
+pub(crate) struct BorrowckResults<'a, 'tcx> {
+    pub(crate) borrows: Results<'tcx, Borrows<'a, 'tcx>>,
+    pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'tcx>>,
+    pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'tcx>>,
 }
 
 /// The transient state of the dataflow analyses used by the borrow checker.
 #[derive(Debug)]
-pub(crate) struct BorrowckFlowState<'a, 'mir, 'tcx> {
-    pub(crate) borrows: <Borrows<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
-    pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
-    pub(crate) ever_inits: <EverInitializedPlaces<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
+pub(crate) struct BorrowckFlowState<'a, 'tcx> {
+    pub(crate) borrows: <Borrows<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
+    pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
+    pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
 }
 
-impl<'a, 'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'mir, 'tcx> {
+impl<'a, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'tcx> {
     // All three analyses are forward, but we have to use just one here.
-    type Direction = <Borrows<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Direction;
-    type FlowState = BorrowckFlowState<'a, 'mir, 'tcx>;
+    type Direction = <Borrows<'a, 'tcx> as AnalysisDomain<'tcx>>::Direction;
+    type FlowState = BorrowckFlowState<'a, 'tcx>;
 
     fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
         BorrowckFlowState {
@@ -106,10 +106,9 @@ pub struct BorrowIndex {}
 /// `BorrowIndex`, and maps each such index to a `BorrowData`
 /// describing the borrow. These indexes are used for representing the
 /// borrows in compact bitvectors.
-pub struct Borrows<'a, 'mir, 'tcx> {
+pub struct Borrows<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    body: &'mir Body<'tcx>,
-
+    body: &'a Body<'tcx>,
     borrow_set: &'a BorrowSet<'tcx>,
     borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
 }
@@ -389,10 +388,10 @@ fn loan_kill_location(
     }
 }
 
-impl<'a, 'mir, 'tcx> Borrows<'a, 'mir, 'tcx> {
+impl<'a, 'tcx> Borrows<'a, 'tcx> {
     pub fn new(
         tcx: TyCtxt<'tcx>,
-        body: &'mir Body<'tcx>,
+        body: &'a Body<'tcx>,
         regioncx: &RegionInferenceContext<'tcx>,
         borrow_set: &'a BorrowSet<'tcx>,
     ) -> Self {
@@ -494,7 +493,7 @@ fn kill_borrows_on_place(&self, trans: &mut impl GenKill<BorrowIndex>, place: Pl
     }
 }
 
-impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, '_, 'tcx> {
+impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
     type Domain = BitSet<BorrowIndex>;
 
     const NAME: &'static str = "borrows";
@@ -517,7 +516,7 @@ fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {
 ///   region stops containing the CFG points reachable from the issuing location.
 /// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of
 ///   `a.b.c` when `a` is overwritten.
-impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, '_, 'tcx> {
+impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
     type Idx = BorrowIndex;
 
     fn domain_size(&self, _: &mir::Body<'tcx>) -> usize {
@@ -617,8 +616,8 @@ fn call_return_effect(
     }
 }
 
-impl DebugWithContext<Borrows<'_, '_, '_>> for BorrowIndex {
-    fn fmt_with(&self, ctxt: &Borrows<'_, '_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl DebugWithContext<Borrows<'_, '_>> for BorrowIndex {
+    fn fmt_with(&self, ctxt: &Borrows<'_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?}", ctxt.location(*self))
     }
 }
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 8a4e89d4..ee28e55 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -52,7 +52,7 @@ pub(crate) fn relate(expected: Ty<'tcx>, found: Ty<'tcx>) -> UniverseInfo<'tcx>
 
     pub(crate) fn report_error(
         &self,
-        mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
         placeholder: ty::PlaceholderRegion,
         error_element: RegionElement,
         cause: ObligationCause<'tcx>,
@@ -151,7 +151,7 @@ trait TypeOpInfo<'tcx> {
 
     fn nice_error<'infcx>(
         &self,
-        mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
         cause: ObligationCause<'tcx>,
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
@@ -160,7 +160,7 @@ fn nice_error<'infcx>(
     #[instrument(level = "debug", skip(self, mbcx))]
     fn report_error(
         &self,
-        mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
         placeholder: ty::PlaceholderRegion,
         error_element: RegionElement,
         cause: ObligationCause<'tcx>,
@@ -233,7 +233,7 @@ fn base_universe(&self) -> ty::UniverseIndex {
 
     fn nice_error<'infcx>(
         &self,
-        mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
         cause: ObligationCause<'tcx>,
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
@@ -277,7 +277,7 @@ fn base_universe(&self) -> ty::UniverseIndex {
 
     fn nice_error<'infcx>(
         &self,
-        mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
         cause: ObligationCause<'tcx>,
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
@@ -324,7 +324,7 @@ fn base_universe(&self) -> ty::UniverseIndex {
 
     fn nice_error<'infcx>(
         &self,
-        mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
         cause: ObligationCause<'tcx>,
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
@@ -357,7 +357,7 @@ fn base_universe(&self) -> ty::UniverseIndex {
 
     fn nice_error<'infcx>(
         &self,
-        mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
         _cause: ObligationCause<'tcx>,
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index c817b6f..a47518f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -69,7 +69,7 @@ enum StorageDeadOrDrop<'tcx> {
     Destructor(Ty<'tcx>),
 }
 
-impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     pub(crate) fn report_use_of_moved_or_uninitialized(
         &mut self,
         location: Location,
@@ -4358,11 +4358,7 @@ enum AnnotatedBorrowFnSignature<'tcx> {
 impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
     /// Annotate the provided diagnostic with information about borrow from the fn signature that
     /// helps explain.
-    pub(crate) fn emit(
-        &self,
-        cx: &MirBorrowckCtxt<'_, '_, '_, 'tcx>,
-        diag: &mut Diag<'_>,
-    ) -> String {
+    pub(crate) fn emit(&self, cx: &MirBorrowckCtxt<'_, '_, 'tcx>, diag: &mut Diag<'_>) -> String {
         match self {
             &AnnotatedBorrowFnSignature::Closure { argument_ty, argument_span } => {
                 diag.span_label(
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 91b02a3..419e72d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -390,7 +390,7 @@ fn add_lifetime_bound_suggestion_to_diagnostic(
     }
 }
 
-impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
+impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
     fn free_region_constraint_info(
         &self,
         borrow_region: RegionVid,
@@ -662,9 +662,10 @@ fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
                                                 // `&dyn Trait`
                                                 ty::Ref(_, ty, _) if ty.is_trait() => true,
                                                 // `Box<dyn Trait>`
-                                                _ if ty.is_box() && ty.boxed_ty().is_trait() => {
+                                                _ if ty.boxed_ty().is_some_and(Ty::is_trait) => {
                                                     true
                                                 }
+
                                                 // `dyn Trait`
                                                 _ if ty.is_trait() => true,
                                                 // Anything else.
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 5ab6696..e52ddfa 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -68,7 +68,7 @@ pub(super) struct DescribePlaceOpt {
 
 pub(super) struct IncludingTupleField(pub(super) bool);
 
-impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     /// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure
     /// is moved after being invoked.
     ///
@@ -345,9 +345,9 @@ fn describe_field_from_ty(
         variant_index: Option<VariantIdx>,
         including_tuple_field: IncludingTupleField,
     ) -> Option<String> {
-        if ty.is_box() {
+        if let Some(boxed_ty) = ty.boxed_ty() {
             // If the type is a box, the field is described from the boxed type
-            self.describe_field_from_ty(ty.boxed_ty(), field, variant_index, including_tuple_field)
+            self.describe_field_from_ty(boxed_ty, field, variant_index, including_tuple_field)
         } else {
             match *ty.kind() {
                 ty::Adt(def, _) => {
@@ -772,7 +772,7 @@ struct CapturedMessageOpt {
     maybe_reinitialized_locations_is_empty: bool,
 }
 
-impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     /// Finds the spans associated to a move or copy of move_place at location.
     pub(super) fn move_spans(
         &self,
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 3dab027..5a9eba3 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -93,7 +93,7 @@ enum GroupedMoveError<'tcx> {
     },
 }
 
-impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     pub(crate) fn report_move_errors(&mut self) {
         let grouped_errors = self.group_move_errors();
         for error in grouped_errors {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 337125f..6e3fac1 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -32,7 +32,7 @@ pub(crate) enum AccessKind {
     Mutate,
 }
 
-impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     pub(crate) fn report_mutability_error(
         &mut self,
         access_place: Place<'tcx>,
diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
index b205dc9f..bd0cf35 100644
--- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
@@ -76,7 +76,7 @@ fn region_name_is_suggestable(name: &RegionName) -> bool {
     /// Returns a name for the region if it is suggestable. See `region_name_is_suggestable`.
     fn region_vid_to_name(
         &self,
-        mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
+        mbcx: &MirBorrowckCtxt<'_, '_, '_>,
         region: RegionVid,
     ) -> Option<RegionName> {
         mbcx.give_region_a_name(region).filter(Self::region_name_is_suggestable)
@@ -85,7 +85,7 @@ fn region_vid_to_name(
     /// Compiles a list of all suggestions to be printed in the final big suggestion.
     fn compile_all_suggestions(
         &self,
-        mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
+        mbcx: &MirBorrowckCtxt<'_, '_, '_>,
     ) -> SmallVec<[SuggestedConstraint; 2]> {
         let mut suggested = SmallVec::new();
 
@@ -161,7 +161,7 @@ pub(crate) fn collect_constraint(&mut self, fr: RegionVid, outlived_fr: RegionVi
     /// Emit an intermediate note on the given `Diag` if the involved regions are suggestable.
     pub(crate) fn intermediate_suggestion(
         &mut self,
-        mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
+        mbcx: &MirBorrowckCtxt<'_, '_, '_>,
         errci: &ErrorConstraintInfo<'_>,
         diag: &mut Diag<'_>,
     ) {
@@ -180,7 +180,7 @@ pub(crate) fn intermediate_suggestion(
 
     /// If there is a suggestion to emit, add a diagnostic to the buffer. This is the final
     /// suggestion including all collected constraints.
-    pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_, '_, '_>) {
+    pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_, '_>) {
         // No constraints to add? Done.
         if self.constraints_to_add.is_empty() {
             debug!("No constraints to suggest.");
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index d49d36d..57c3a08 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -156,7 +156,7 @@ pub(crate) struct ErrorConstraintInfo<'tcx> {
     pub(super) span: Span,
 }
 
-impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     /// Converts a region inference variable into a `ty::Region` that
     /// we can use for error reporting. If `r` is universally bound,
     /// then we use the name that we have on record for it. If `r` is
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index cb05812..58fcda2 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -200,7 +200,7 @@ fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
     }
 }
 
-impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
+impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
     pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId {
         self.body.source.def_id().expect_local()
     }
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index ffb350b..d5f297a 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -304,11 +304,11 @@ fn do_mir_borrowck<'tcx>(
         promoted_mbcx.report_move_errors();
         diags = promoted_mbcx.diags;
 
-        struct MoveVisitor<'a, 'b, 'mir, 'infcx, 'tcx> {
-            ctxt: &'a mut MirBorrowckCtxt<'b, 'mir, 'infcx, 'tcx>,
+        struct MoveVisitor<'a, 'b, 'infcx, 'tcx> {
+            ctxt: &'a mut MirBorrowckCtxt<'b, 'infcx, 'tcx>,
         }
 
-        impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, '_, '_, 'tcx> {
+        impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, '_, 'tcx> {
             fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
                 if let Operand::Move(place) = operand {
                     self.ctxt.check_movable_place(location, *place);
@@ -522,10 +522,10 @@ fn deref(&self) -> &Self::Target {
     }
 }
 
-struct MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx> {
+struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
     infcx: &'infcx BorrowckInferCtxt<'tcx>,
     param_env: ParamEnv<'tcx>,
-    body: &'mir Body<'tcx>,
+    body: &'a Body<'tcx>,
     move_data: &'a MoveData<'tcx>,
 
     /// Map from MIR `Location` to `LocationIndex`; created
@@ -599,16 +599,16 @@ struct MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx> {
 // 2. loans made in overlapping scopes do not conflict
 // 3. assignments do not affect things loaned out as immutable
 // 4. moves do not affect things loaned out in any way
-impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
-    for MirBorrowckCtxt<'a, 'mir, '_, 'tcx>
+impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
+    for MirBorrowckCtxt<'a, '_, 'tcx>
 {
-    type FlowState = Flows<'a, 'mir, 'tcx>;
+    type FlowState = Flows<'a, 'tcx>;
 
     fn visit_statement_before_primary_effect(
         &mut self,
         _results: &mut R,
-        flow_state: &Flows<'_, 'mir, 'tcx>,
-        stmt: &'mir Statement<'tcx>,
+        flow_state: &Flows<'a, 'tcx>,
+        stmt: &'a Statement<'tcx>,
         location: Location,
     ) {
         debug!("MirBorrowckCtxt::process_statement({:?}, {:?}): {:?}", location, stmt, flow_state);
@@ -677,8 +677,8 @@ fn visit_statement_before_primary_effect(
     fn visit_terminator_before_primary_effect(
         &mut self,
         _results: &mut R,
-        flow_state: &Flows<'_, 'mir, 'tcx>,
-        term: &'mir Terminator<'tcx>,
+        flow_state: &Flows<'a, 'tcx>,
+        term: &'a Terminator<'tcx>,
         loc: Location,
     ) {
         debug!("MirBorrowckCtxt::process_terminator({:?}, {:?}): {:?}", loc, term, flow_state);
@@ -794,8 +794,8 @@ fn visit_terminator_before_primary_effect(
     fn visit_terminator_after_primary_effect(
         &mut self,
         _results: &mut R,
-        flow_state: &Flows<'_, 'mir, 'tcx>,
-        term: &'mir Terminator<'tcx>,
+        flow_state: &Flows<'a, 'tcx>,
+        term: &'a Terminator<'tcx>,
         loc: Location,
     ) {
         let span = term.source_info.span;
@@ -972,8 +972,8 @@ fn as_general_verb_in_past_tense(self) -> &'static str {
     }
 }
 
-impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
-    fn body(&self) -> &'mir Body<'tcx> {
+impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
+    fn body(&self) -> &'a Body<'tcx> {
         self.body
     }
 
@@ -989,7 +989,7 @@ fn access_place(
         place_span: (Place<'tcx>, Span),
         kind: (AccessDepth, ReadOrWrite),
         is_local_mutation_allowed: LocalMutationIsAllowed,
-        flow_state: &Flows<'_, 'mir, 'tcx>,
+        flow_state: &Flows<'a, 'tcx>,
     ) {
         let (sd, rw) = kind;
 
@@ -1039,7 +1039,7 @@ fn check_access_for_conflict(
         place_span: (Place<'tcx>, Span),
         sd: AccessDepth,
         rw: ReadOrWrite,
-        flow_state: &Flows<'_, 'mir, 'tcx>,
+        flow_state: &Flows<'a, 'tcx>,
     ) -> bool {
         let mut error_reported = false;
         let borrow_set = Rc::clone(&self.borrow_set);
@@ -1180,7 +1180,7 @@ fn mutate_place(
         location: Location,
         place_span: (Place<'tcx>, Span),
         kind: AccessDepth,
-        flow_state: &Flows<'_, 'mir, 'tcx>,
+        flow_state: &Flows<'a, 'tcx>,
     ) {
         // Write of P[i] or *P requires P init'd.
         self.check_if_assigned_path_is_moved(location, place_span, flow_state);
@@ -1197,8 +1197,8 @@ fn mutate_place(
     fn consume_rvalue(
         &mut self,
         location: Location,
-        (rvalue, span): (&'mir Rvalue<'tcx>, Span),
-        flow_state: &Flows<'_, 'mir, 'tcx>,
+        (rvalue, span): (&'a Rvalue<'tcx>, Span),
+        flow_state: &Flows<'a, 'tcx>,
     ) {
         match rvalue {
             &Rvalue::Ref(_ /*rgn*/, bk, place) => {
@@ -1455,8 +1455,8 @@ fn propagate_closure_used_mut_upvar(&mut self, operand: &Operand<'tcx>) {
     fn consume_operand(
         &mut self,
         location: Location,
-        (operand, span): (&'mir Operand<'tcx>, Span),
-        flow_state: &Flows<'_, 'mir, 'tcx>,
+        (operand, span): (&'a Operand<'tcx>, Span),
+        flow_state: &Flows<'a, 'tcx>,
     ) {
         match *operand {
             Operand::Copy(place) => {
@@ -1576,12 +1576,7 @@ fn check_for_local_borrow(&mut self, borrow: &BorrowData<'tcx>, yield_span: Span
         }
     }
 
-    fn check_activations(
-        &mut self,
-        location: Location,
-        span: Span,
-        flow_state: &Flows<'_, 'mir, 'tcx>,
-    ) {
+    fn check_activations(&mut self, location: Location, span: Span, flow_state: &Flows<'a, 'tcx>) {
         // Two-phase borrow support: For each activation that is newly
         // generated at this statement, check if it interferes with
         // another borrow.
@@ -1744,7 +1739,7 @@ fn check_if_full_path_is_moved(
         location: Location,
         desired_action: InitializationRequiringAction,
         place_span: (PlaceRef<'tcx>, Span),
-        flow_state: &Flows<'_, 'mir, 'tcx>,
+        flow_state: &Flows<'a, 'tcx>,
     ) {
         let maybe_uninits = &flow_state.uninits;
 
@@ -1849,7 +1844,7 @@ fn check_if_path_or_subpath_is_moved(
         location: Location,
         desired_action: InitializationRequiringAction,
         place_span: (PlaceRef<'tcx>, Span),
-        flow_state: &Flows<'_, 'mir, 'tcx>,
+        flow_state: &Flows<'a, 'tcx>,
     ) {
         let maybe_uninits = &flow_state.uninits;
 
@@ -1948,7 +1943,7 @@ fn check_if_assigned_path_is_moved(
         &mut self,
         location: Location,
         (place, span): (Place<'tcx>, Span),
-        flow_state: &Flows<'_, 'mir, 'tcx>,
+        flow_state: &Flows<'a, 'tcx>,
     ) {
         debug!("check_if_assigned_path_is_moved place: {:?}", place);
 
@@ -2009,12 +2004,12 @@ fn check_if_assigned_path_is_moved(
             }
         }
 
-        fn check_parent_of_field<'mir, 'tcx>(
-            this: &mut MirBorrowckCtxt<'_, 'mir, '_, 'tcx>,
+        fn check_parent_of_field<'a, 'tcx>(
+            this: &mut MirBorrowckCtxt<'a, '_, 'tcx>,
             location: Location,
             base: PlaceRef<'tcx>,
             span: Span,
-            flow_state: &Flows<'_, 'mir, 'tcx>,
+            flow_state: &Flows<'a, 'tcx>,
         ) {
             // rust-lang/rust#21232: Until Rust allows reads from the
             // initialized parts of partially initialized structs, we
@@ -2105,7 +2100,7 @@ fn check_access_permissions(
         (place, span): (Place<'tcx>, Span),
         kind: ReadOrWrite,
         is_local_mutation_allowed: LocalMutationIsAllowed,
-        flow_state: &Flows<'_, 'mir, 'tcx>,
+        flow_state: &Flows<'a, 'tcx>,
         location: Location,
     ) -> bool {
         debug!(
@@ -2221,7 +2216,7 @@ fn check_access_permissions(
     fn is_local_ever_initialized(
         &self,
         local: Local,
-        flow_state: &Flows<'_, 'mir, 'tcx>,
+        flow_state: &Flows<'a, 'tcx>,
     ) -> Option<InitIndex> {
         let mpi = self.move_data.rev_lookup.find_local(local)?;
         let ii = &self.move_data.init_path_map[mpi];
@@ -2229,7 +2224,7 @@ fn is_local_ever_initialized(
     }
 
     /// Adds the place into the used mutable variables set
-    fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'_, 'mir, 'tcx>) {
+    fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'a, 'tcx>) {
         match root_place {
             RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
                 // If the local may have been initialized, and it is now currently being
@@ -2484,7 +2479,7 @@ pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) {
         }
     }
 
-    impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+    impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) {
             self.diags.buffer_error(diag);
         }
@@ -2522,7 +2517,7 @@ pub(crate) fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count:
         }
 
         pub(crate) fn emit_errors(&mut self) -> Option<ErrorGuaranteed> {
-            let mut res = None;
+            let mut res = self.infcx.tainted_by_errors();
 
             // Buffer any move errors that we collected and de-duplicated.
             for (_, (_, diag)) in std::mem::take(&mut self.diags.buffered_move_errors) {
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 6525bef..8575eb9 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -75,14 +75,14 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
 /// Computes the (non-lexical) regions from the input MIR.
 ///
 /// This may result in errors being reported.
-pub(crate) fn compute_regions<'cx, 'tcx>(
+pub(crate) fn compute_regions<'a, 'tcx>(
     infcx: &BorrowckInferCtxt<'tcx>,
     universal_regions: UniversalRegions<'tcx>,
     body: &Body<'tcx>,
     promoted: &IndexSlice<Promoted, Body<'tcx>>,
     location_table: &LocationTable,
     param_env: ty::ParamEnv<'tcx>,
-    flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'_, 'cx, 'tcx>>,
+    flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
     upvars: &[&ty::CapturedPlace<'tcx>],
@@ -301,13 +301,13 @@ pub(super) fn dump_nll_mir<'tcx>(
 
 #[allow(rustc::diagnostic_outside_of_impl)]
 #[allow(rustc::untranslatable_diagnostic)]
-pub(super) fn dump_annotation<'tcx, 'cx>(
-    infcx: &'cx BorrowckInferCtxt<'tcx>,
+pub(super) fn dump_annotation<'tcx, 'infcx>(
+    infcx: &'infcx BorrowckInferCtxt<'tcx>,
     body: &Body<'tcx>,
     regioncx: &RegionInferenceContext<'tcx>,
     closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
     opaque_type_values: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
-    diags: &mut crate::diags::BorrowckDiags<'cx, 'tcx>,
+    diags: &mut crate::diags::BorrowckDiags<'infcx, 'tcx>,
 ) {
     let tcx = infcx.tcx;
     let base_def_id = tcx.typeck_root_def_id(body.source.def_id());
diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs
index 39d8313..aeb8a6c 100644
--- a/compiler/rustc_borrowck/src/prefixes.rs
+++ b/compiler/rustc_borrowck/src/prefixes.rs
@@ -34,7 +34,7 @@ pub(super) enum PrefixSet {
     Shallow,
 }
 
-impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
+impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
     /// Returns an iterator over the prefixes of `place`
     /// (inclusive) from longest to smallest, potentially
     /// terminating the iteration early based on `kind`.
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index a24fd95e..79db8f4 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -30,11 +30,11 @@
 ///
 /// N.B., this computation requires normalization; therefore, it must be
 /// performed before
-pub(super) fn generate<'mir, 'tcx>(
+pub(super) fn generate<'a, 'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
     body: &Body<'tcx>,
     elements: &Rc<DenseLocationMap>,
-    flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
+    flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
 ) {
     debug!("liveness::generate");
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 6186904..4d47863 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -37,11 +37,11 @@
 /// DROP-LIVE set are to the liveness sets for regions found in the
 /// `dropck_outlives` result of the variable's type (in particular,
 /// this respects `#[may_dangle]` annotations).
-pub(super) fn trace<'mir, 'tcx>(
+pub(super) fn trace<'a, 'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
     body: &Body<'tcx>,
     elements: &Rc<DenseLocationMap>,
-    flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
+    flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     relevant_live_locals: Vec<Local>,
     boring_locals: Vec<Local>,
@@ -99,29 +99,29 @@ pub(super) fn trace<'mir, 'tcx>(
 }
 
 /// Contextual state for the type-liveness coroutine.
-struct LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx> {
+struct LivenessContext<'a, 'typeck, 'b, 'tcx> {
     /// Current type-checker, giving us our inference context etc.
-    typeck: &'me mut TypeChecker<'typeck, 'tcx>,
+    typeck: &'a mut TypeChecker<'typeck, 'tcx>,
 
     /// Defines the `PointIndex` mapping
-    elements: &'me DenseLocationMap,
+    elements: &'a DenseLocationMap,
 
     /// MIR we are analyzing.
-    body: &'me Body<'tcx>,
+    body: &'a Body<'tcx>,
 
     /// Mapping to/from the various indices used for initialization tracking.
-    move_data: &'me MoveData<'tcx>,
+    move_data: &'a MoveData<'tcx>,
 
     /// Cache for the results of `dropck_outlives` query.
     drop_data: FxIndexMap<Ty<'tcx>, DropData<'tcx>>,
 
     /// Results of dataflow tracking which variables (and paths) have been
     /// initialized.
-    flow_inits: &'me mut ResultsCursor<'flow, 'tcx, MaybeInitializedPlaces<'a, 'flow, 'tcx>>,
+    flow_inits: &'a mut ResultsCursor<'b, 'tcx, MaybeInitializedPlaces<'b, 'tcx>>,
 
     /// Index indicating where each variable is assigned, used, or
     /// dropped.
-    local_use_map: &'me LocalUseMap,
+    local_use_map: &'a LocalUseMap,
 }
 
 struct DropData<'tcx> {
@@ -129,8 +129,8 @@ struct DropData<'tcx> {
     region_constraint_data: Option<&'tcx QueryRegionConstraints<'tcx>>,
 }
 
-struct LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> {
-    cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>,
+struct LivenessResults<'a, 'typeck, 'b, 'tcx> {
+    cx: LivenessContext<'a, 'typeck, 'b, 'tcx>,
 
     /// Set of points that define the current local.
     defs: BitSet<PointIndex>,
@@ -151,8 +151,8 @@ struct LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> {
     stack: Vec<PointIndex>,
 }
 
-impl<'a, 'me, 'typeck, 'flow, 'tcx> LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> {
-    fn new(cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>) -> Self {
+impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
+    fn new(cx: LivenessContext<'a, 'typeck, 'b, 'tcx>) -> Self {
         let num_points = cx.elements.num_points();
         LivenessResults {
             cx,
@@ -505,7 +505,7 @@ fn compute_drop_live_points_for_block(&mut self, mpi: MovePathIndex, term_point:
     }
 }
 
-impl<'tcx> LivenessContext<'_, '_, '_, '_, 'tcx> {
+impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
     /// Returns `true` if the local variable (or some part of it) is initialized at the current
     /// cursor position. Callers should call one of the `seek` methods immediately before to point
     /// the cursor to the desired location.
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 224f8d5..3e5a6ad 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -116,7 +116,7 @@ macro_rules! span_mirbug_and_err {
 /// - `flow_inits` -- results of a maybe-init dataflow analysis
 /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
 /// - `elements` -- MIR region map
-pub(crate) fn type_check<'mir, 'tcx>(
+pub(crate) fn type_check<'a, 'tcx>(
     infcx: &BorrowckInferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     body: &Body<'tcx>,
@@ -125,7 +125,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
     location_table: &LocationTable,
     borrow_set: &BorrowSet<'tcx>,
     all_facts: &mut Option<AllFacts>,
-    flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
+    flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     elements: &Rc<DenseLocationMap>,
     upvars: &[&ty::CapturedPlace<'tcx>],
@@ -1979,19 +1979,76 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
 
                 match cast_kind {
                     CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
-                        let fn_sig = op.ty(body, tcx).fn_sig(tcx);
+                        let src_sig = op.ty(body, tcx).fn_sig(tcx);
+
+                        // HACK: This shouldn't be necessary... We can remove this when we actually
+                        // get binders with where clauses, then elaborate implied bounds into that
+                        // binder, and implement a higher-ranked subtyping algorithm that actually
+                        // respects these implied bounds.
+                        //
+                        // This protects against the case where we are casting from a higher-ranked
+                        // fn item to a non-higher-ranked fn pointer, where the cast throws away
+                        // implied bounds that would've needed to be checked at the call site. This
+                        // only works when we're casting to a non-higher-ranked fn ptr, since
+                        // placeholders in the target signature could have untracked implied
+                        // bounds, resulting in incorrect errors.
+                        //
+                        // We check that this signature is WF before subtyping the signature with
+                        // the target fn sig.
+                        if src_sig.has_bound_regions()
+                            && let ty::FnPtr(target_fn_tys, target_hdr) = *ty.kind()
+                            && let target_sig = target_fn_tys.with(target_hdr)
+                            && let Some(target_sig) = target_sig.no_bound_vars()
+                        {
+                            let src_sig = self.infcx.instantiate_binder_with_fresh_vars(
+                                span,
+                                BoundRegionConversionTime::HigherRankedType,
+                                src_sig,
+                            );
+                            let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig));
+                            self.prove_predicate(
+                                ty::ClauseKind::WellFormed(src_ty.into()),
+                                location.to_locations(),
+                                ConstraintCategory::Cast { unsize_to: None },
+                            );
+
+                            let src_ty = self.normalize(src_ty, location);
+                            if let Err(terr) = self.sub_types(
+                                src_ty,
+                                *ty,
+                                location.to_locations(),
+                                ConstraintCategory::Cast { unsize_to: None },
+                            ) {
+                                span_mirbug!(
+                                    self,
+                                    rvalue,
+                                    "equating {:?} with {:?} yields {:?}",
+                                    target_sig,
+                                    src_sig,
+                                    terr
+                                );
+                            };
+                        }
+
+                        let src_ty = Ty::new_fn_ptr(tcx, src_sig);
+                        // HACK: We want to assert that the signature of the source fn is
+                        // well-formed, because we don't enforce that via the WF of FnDef
+                        // types normally. This should be removed when we improve the tracking
+                        // of implied bounds of fn signatures.
+                        self.prove_predicate(
+                            ty::ClauseKind::WellFormed(src_ty.into()),
+                            location.to_locations(),
+                            ConstraintCategory::Cast { unsize_to: None },
+                        );
 
                         // The type that we see in the fcx is like
                         // `foo::<'a, 'b>`, where `foo` is the path to a
                         // function definition. When we extract the
                         // signature, it comes from the `fn_sig` query,
                         // and hence may contain unnormalized results.
-                        let fn_sig = self.normalize(fn_sig, location);
-
-                        let ty_fn_ptr_from = Ty::new_fn_ptr(tcx, fn_sig);
-
+                        let src_ty = self.normalize(src_ty, location);
                         if let Err(terr) = self.sub_types(
-                            ty_fn_ptr_from,
+                            src_ty,
                             *ty,
                             location.to_locations(),
                             ConstraintCategory::Cast { unsize_to: None },
@@ -2000,7 +2057,7 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                                 self,
                                 rvalue,
                                 "equating {:?} with {:?} yields {:?}",
-                                ty_fn_ptr_from,
+                                src_ty,
                                 ty,
                                 terr
                             );
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 9eabe81..c3edbcb 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -29,7 +29,8 @@
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{
-    self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt,
+    self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty,
+    TyCtxt, TypeVisitableExt,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::{kw, sym};
@@ -422,8 +423,8 @@ pub(crate) fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
     }
 }
 
-struct UniversalRegionsBuilder<'cx, 'tcx> {
-    infcx: &'cx BorrowckInferCtxt<'tcx>,
+struct UniversalRegionsBuilder<'infcx, 'tcx> {
+    infcx: &'infcx BorrowckInferCtxt<'tcx>,
     mir_def: LocalDefId,
     param_env: ty::ParamEnv<'tcx>,
 }
@@ -688,7 +689,8 @@ fn compute_inputs_and_output(
         defining_ty: DefiningTy<'tcx>,
     ) -> ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>> {
         let tcx = self.infcx.tcx;
-        match defining_ty {
+
+        let inputs_and_output = match defining_ty {
             DefiningTy::Closure(def_id, args) => {
                 assert_eq!(self.mir_def.to_def_id(), def_id);
                 let closure_sig = args.as_closure().sig();
@@ -798,6 +800,7 @@ fn compute_inputs_and_output(
                 // "output" (the type of the constant).
                 assert_eq!(self.mir_def.to_def_id(), def_id);
                 let ty = tcx.type_of(self.mir_def).instantiate_identity();
+
                 let ty = indices.fold_to_region_vids(tcx, ty);
                 ty::Binder::dummy(tcx.mk_type_list(&[ty]))
             }
@@ -807,7 +810,14 @@ fn compute_inputs_and_output(
                 let ty = args.as_inline_const().ty();
                 ty::Binder::dummy(tcx.mk_type_list(&[ty]))
             }
+        };
+
+        // FIXME(#129952): We probably want a more principled approach here.
+        if let Err(terr) = inputs_and_output.skip_binder().error_reported() {
+            self.infcx.set_tainted_by_errors(terr);
         }
+
+        inputs_and_output
     }
 }
 
diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs
index 981e7da..bde07c0 100644
--- a/compiler/rustc_borrowck/src/used_muts.rs
+++ b/compiler/rustc_borrowck/src/used_muts.rs
@@ -7,7 +7,7 @@
 
 use crate::MirBorrowckCtxt;
 
-impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
+impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
     /// Walks the MIR adding to the set of `used_mut` locals that will be ignored for the purposes
     /// of the `unused_mut` lint.
     ///
@@ -46,13 +46,13 @@ pub(crate) fn gather_used_muts(
 
 /// MIR visitor for collecting used mutable variables.
 /// The 'visit lifetime represents the duration of the MIR walk.
-struct GatherUsedMutsVisitor<'visit, 'a, 'mir, 'infcx, 'tcx> {
+struct GatherUsedMutsVisitor<'a, 'b, 'infcx, 'tcx> {
     temporary_used_locals: FxIndexSet<Local>,
-    never_initialized_mut_locals: &'visit mut FxIndexSet<Local>,
-    mbcx: &'visit mut MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx>,
+    never_initialized_mut_locals: &'a mut FxIndexSet<Local>,
+    mbcx: &'a mut MirBorrowckCtxt<'b, 'infcx, 'tcx>,
 }
 
-impl GatherUsedMutsVisitor<'_, '_, '_, '_, '_> {
+impl GatherUsedMutsVisitor<'_, '_, '_, '_> {
     fn remove_never_initialized_mut_locals(&mut self, into: Place<'_>) {
         // Remove any locals that we found were initialized from the
         // `never_initialized_mut_locals` set. At the end, the only remaining locals will
@@ -64,7 +64,7 @@ fn remove_never_initialized_mut_locals(&mut self, into: Place<'_>) {
     }
 }
 
-impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, '_, 'tcx> {
+impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, 'tcx> {
     fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
         debug!("visit_terminator: terminator={:?}", terminator);
         match &terminator.kind {
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index ae2627d..e313016 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -812,6 +812,44 @@ pub(super) fn expand_asm<'cx>(
     })
 }
 
+pub(super) fn expand_naked_asm<'cx>(
+    ecx: &'cx mut ExtCtxt<'_>,
+    sp: Span,
+    tts: TokenStream,
+) -> MacroExpanderResult<'cx> {
+    ExpandResult::Ready(match parse_args(ecx, sp, tts, false) {
+        Ok(args) => {
+            let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else {
+                return ExpandResult::Retry(());
+            };
+            let expr = match mac {
+                Ok(mut inline_asm) => {
+                    // for future compatibility, we always set the NORETURN option.
+                    //
+                    // When we turn `asm!` into `naked_asm!` with this implementation, we can drop
+                    // the `options(noreturn)`, which makes the upgrade smooth when `naked_asm!`
+                    // starts disallowing the `noreturn` option in the future
+                    inline_asm.options |= ast::InlineAsmOptions::NORETURN;
+
+                    P(ast::Expr {
+                        id: ast::DUMMY_NODE_ID,
+                        kind: ast::ExprKind::InlineAsm(P(inline_asm)),
+                        span: sp,
+                        attrs: ast::AttrVec::new(),
+                        tokens: None,
+                    })
+                }
+                Err(guar) => DummyResult::raw_expr(sp, Some(guar)),
+            };
+            MacEager::expr(expr)
+        }
+        Err(err) => {
+            let guar = err.emit();
+            DummyResult::any(sp, guar)
+        }
+    })
+}
+
 pub(super) fn expand_global_asm<'cx>(
     ecx: &'cx mut ExtCtxt<'_>,
     sp: Span,
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 30e1c8d..ebe5e2b 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -94,6 +94,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
         line: source_util::expand_line,
         log_syntax: log_syntax::expand_log_syntax,
         module_path: source_util::expand_mod,
+        naked_asm: asm::expand_naked_asm,
         option_env: env::expand_option_env,
         pattern_type: pattern_type::expand,
         std_panic: edition_panic::expand_panic,
diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md
index 6766e2f..18a840f 100644
--- a/compiler/rustc_codegen_cranelift/Readme.md
+++ b/compiler/rustc_codegen_cranelift/Readme.md
@@ -70,7 +70,7 @@
 |AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]|
 |Other unixes|❓|❓|❓|❓|
 |macOS|✅|✅|N/A|N/A|
-|Windows|✅[^no-rustup]|❌|N/A|N/A|
+|Windows|✅|❌|N/A|N/A|
 
 ✅: Fully supported and tested
 ❓: Maybe supported, not tested
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index 915229f..0eb264f 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -12,63 +12,12 @@
 ]
 
 [[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "bitflags"
-version = "2.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
-
-[[package]]
 name = "boml"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "85fdb93f04c73bff54305fa437ffea5449c41edcaadfe882f35836206b166ac5"
 
 [[package]]
-name = "cc"
-version = "1.0.79"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "errno"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
-dependencies = [
- "errno-dragonfly",
- "libc",
- "windows-sys",
-]
-
-[[package]]
-name = "errno-dragonfly"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
-name = "fastrand"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
-
-[[package]]
 name = "fm"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -133,12 +82,6 @@
 checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
 
 [[package]]
-name = "linux-raw-sys"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
-
-[[package]]
 name = "memchr"
 version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -155,24 +98,6 @@
 ]
 
 [[package]]
-name = "object"
-version = "0.30.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
-dependencies = [
- "bitflags 1.3.2",
-]
-
-[[package]]
 name = "regex"
 version = "1.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -196,22 +121,6 @@
  "boml",
  "gccjit",
  "lang_tester",
- "object",
- "smallvec",
- "tempfile",
-]
-
-[[package]]
-name = "rustix"
-version = "0.38.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
-dependencies = [
- "bitflags 2.4.0",
- "errno",
- "libc",
- "linux-raw-sys",
- "windows-sys",
 ]
 
 [[package]]
@@ -224,25 +133,6 @@
 ]
 
 [[package]]
-name = "smallvec"
-version = "1.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
-
-[[package]]
-name = "tempfile"
-version = "3.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651"
-dependencies = [
- "cfg-if",
- "fastrand",
- "redox_syscall",
- "rustix",
- "windows-sys",
-]
-
-[[package]]
 name = "termcolor"
 version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -315,69 +205,3 @@
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.48.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
-dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml
index 5caca63..44fb5ee 100644
--- a/compiler/rustc_codegen_gcc/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/Cargo.toml
@@ -23,21 +23,11 @@
 
 [dependencies]
 gccjit = "2.1"
-
 # Local copy.
 #gccjit = { path = "../gccjit.rs" }
 
-object = { version = "0.30.1", default-features = false, features = [
-    "std",
-    "read",
-] }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
-# TODO(antoyo): make tempfile optional.
-tempfile = "3.7.1"
-
 [dev-dependencies]
 lang_tester = "0.8.0"
-tempfile = "3.1.0"
 boml = "0.3.1"
 
 [profile.dev]
diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs
index 6b2dbbb..c2adab7 100644
--- a/compiler/rustc_codegen_gcc/src/back/lto.rs
+++ b/compiler/rustc_codegen_gcc/src/back/lto.rs
@@ -272,7 +272,6 @@ fn fat_lto(
             }*/
         }
     };
-    let mut serialized_bitcode = Vec::new();
     {
         info!("using {:?} as a base module", module.name);
 
@@ -317,7 +316,6 @@ fn fat_lto(
                     unimplemented!("from uncompressed file")
                 }
             }
-            serialized_bitcode.push(bc_decoded);
         }
         save_temp_bitcode(cgcx, &module, "lto.input");
 
@@ -337,7 +335,7 @@ fn fat_lto(
     // of now.
     module.module_llvm.temp_dir = Some(tmp_path);
 
-    Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: serialized_bitcode })
+    Ok(LtoModuleCodegen::Fat(module))
 }
 
 pub struct ModuleBuffer(PathBuf);
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 94f0162..4de671a 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -24,6 +24,14 @@
 #![deny(clippy::pattern_type_mismatch)]
 #![allow(clippy::needless_lifetimes)]
 
+// Some "regular" crates we want to share with rustc
+extern crate object;
+extern crate smallvec;
+extern crate tempfile;
+#[macro_use]
+extern crate tracing;
+
+// The rustc crates we need
 extern crate rustc_apfloat;
 extern crate rustc_ast;
 extern crate rustc_attr;
@@ -42,8 +50,6 @@
 extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
-#[macro_use]
-extern crate tracing;
 
 // This prevents duplicating functions and statics that are already part of the host rustc process.
 #[allow(unused_extern_crates)]
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 92a857c..9d4497d 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -411,26 +411,31 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
             // the string "false". Now it is disabled by absence of the attribute.
             to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false"));
         }
-    } else if llvm_util::get_version() >= (19, 0, 0) {
-        // For non-naked functions, set branch protection attributes on aarch64.
-        if let Some(BranchProtection { bti, pac_ret }) =
-            cx.sess().opts.unstable_opts.branch_protection
-        {
-            assert!(cx.sess().target.arch == "aarch64");
-            if bti {
-                to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement"));
-            }
-            if let Some(PacRet { leaf, key }) = pac_ret {
-                to_add.push(llvm::CreateAttrStringValue(
-                    cx.llcx,
-                    "sign-return-address",
-                    if leaf { "all" } else { "non-leaf" },
-                ));
-                to_add.push(llvm::CreateAttrStringValue(
-                    cx.llcx,
-                    "sign-return-address-key",
-                    if key == PAuthKey::A { "a_key" } else { "b_key" },
-                ));
+    } else {
+        // Do not set sanitizer attributes for naked functions.
+        to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
+
+        if llvm_util::get_version() >= (19, 0, 0) {
+            // For non-naked functions, set branch protection attributes on aarch64.
+            if let Some(BranchProtection { bti, pac_ret }) =
+                cx.sess().opts.unstable_opts.branch_protection
+            {
+                assert!(cx.sess().target.arch == "aarch64");
+                if bti {
+                    to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement"));
+                }
+                if let Some(PacRet { leaf, key }) = pac_ret {
+                    to_add.push(llvm::CreateAttrStringValue(
+                        cx.llcx,
+                        "sign-return-address",
+                        if leaf { "all" } else { "non-leaf" },
+                    ));
+                    to_add.push(llvm::CreateAttrStringValue(
+                        cx.llcx,
+                        "sign-return-address-key",
+                        if key == PAuthKey::A { "a_key" } else { "b_key" },
+                    ));
+                }
             }
         }
     }
@@ -485,7 +490,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
     if let Some(backchain) = backchain_attr(cx) {
         to_add.push(backchain);
     }
-    to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
     to_add.extend(patchable_function_entry_attrs(cx, codegen_fn_attrs.patchable_function_entry));
 
     // Always annotate functions with the target-cpu they are compiled for.
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index aa6842c..09896b8 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -314,7 +314,6 @@ fn fat_lto(
             }
         }
     };
-    let mut serialized_bitcode = Vec::new();
     {
         let (llcx, llmod) = {
             let llvm = &module.module_llvm;
@@ -342,9 +341,7 @@ fn fat_lto(
         serialized_modules.sort_by(|module1, module2| module1.1.cmp(&module2.1));
 
         // For all serialized bitcode files we parse them and link them in as we did
-        // above, this is all mostly handled in C++. Like above, though, we don't
-        // know much about the memory management here so we err on the side of being
-        // save and persist everything with the original module.
+        // above, this is all mostly handled in C++.
         let mut linker = Linker::new(llmod);
         for (bc_decoded, name) in serialized_modules {
             let _timer = cgcx
@@ -355,7 +352,6 @@ fn fat_lto(
             info!("linking {:?}", name);
             let data = bc_decoded.data();
             linker.add(data).map_err(|()| write::llvm_err(dcx, LlvmError::LoadBitcode { name }))?;
-            serialized_bitcode.push(bc_decoded);
         }
         drop(linker);
         save_temp_bitcode(cgcx, &module, "lto.input");
@@ -372,7 +368,7 @@ fn fat_lto(
         }
     }
 
-    Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: serialized_bitcode })
+    Ok(LtoModuleCodegen::Fat(module))
 }
 
 pub(crate) struct Linker<'a>(&'a mut llvm::Linker<'a>);
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index b143e28..d60122fc 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -390,7 +390,7 @@ fn codegen_static_item(&self, def_id: DefId) {
             let val_llty = self.val_ty(v);
 
             let g = self.get_static_inner(def_id, val_llty);
-            let llty = self.val_ty(g);
+            let llty = llvm::LLVMGlobalGetValueType(g);
 
             let g = if val_llty == llty {
                 g
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 17a9630..d231b10 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -456,7 +456,7 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) ->
             if def.is_box()
                 && args.get(1).map_or(true, |arg| cx.layout_of(arg.expect_ty()).is_1zst()) =>
         {
-            build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id)
+            build_pointer_or_reference_di_node(cx, t, t.expect_boxed_ty(), unique_type_id)
         }
         ty::FnDef(..) | ty::FnPtr(..) => build_subroutine_type_di_node(cx, unique_type_id),
         ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id),
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index a300f5f..05fb77a 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -187,9 +187,7 @@ fn codegen_intrinsic_call(
                     Some(instance),
                 )
             }
-            sym::likely => {
-                self.call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(true)])
-            }
+            sym::likely => self.expect(args[0].immediate(), true),
             sym::is_val_statically_known => {
                 let intrinsic_type = args[0].layout.immediate_llvm_type(self.cx);
                 let kind = self.type_kind(intrinsic_type);
@@ -210,8 +208,7 @@ fn codegen_intrinsic_call(
                     self.const_bool(false)
                 }
             }
-            sym::unlikely => self
-                .call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(false)]),
+            sym::unlikely => self.expect(args[0].immediate(), false),
             sym::select_unpredictable => {
                 let cond = args[0].immediate();
                 assert_eq!(args[1].layout, args[2].layout);
@@ -604,11 +601,17 @@ fn abort(&mut self) {
     }
 
     fn assume(&mut self, val: Self::Value) {
-        self.call_intrinsic("llvm.assume", &[val]);
+        if self.cx.sess().opts.optimize != rustc_session::config::OptLevel::No {
+            self.call_intrinsic("llvm.assume", &[val]);
+        }
     }
 
     fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value {
-        self.call_intrinsic("llvm.expect.i1", &[cond, self.const_bool(expected)])
+        if self.cx.sess().opts.optimize != rustc_session::config::OptLevel::No {
+            self.call_intrinsic("llvm.expect.i1", &[cond, self.const_bool(expected)])
+        } else {
+            cond
+        }
     }
 
     fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value {
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 6a303e1..7f26bbd 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -6,7 +6,6 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
-#![cfg_attr(bootstrap, feature(unsafe_extern_blocks))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 138cc32..3bf4d49 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -974,6 +974,7 @@ pub fn LLVMConstInBoundsGEP2<'a>(
     pub fn LLVMGetAlignment(Global: &Value) -> c_uint;
     pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint);
     pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass);
+    pub fn LLVMGlobalGetValueType(Global: &Value) -> &Type;
 
     // Operations on global variables
     pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 618602e..d55220b 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -353,9 +353,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
                 None
             }
         })
-        .filter(|feature| {
-            RUSTC_SPECIAL_FEATURES.contains(feature) || features.contains(&Symbol::intern(feature))
-        })
+        .filter(|feature| features.contains(&Symbol::intern(feature)))
         .map(|feature| Symbol::intern(feature))
         .collect()
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs
index 8b6f6b5..1e1e039 100644
--- a/compiler/rustc_codegen_ssa/src/back/lto.rs
+++ b/compiler/rustc_codegen_ssa/src/back/lto.rs
@@ -41,18 +41,14 @@ pub struct ThinShared<B: WriteBackendMethods> {
 }
 
 pub enum LtoModuleCodegen<B: WriteBackendMethods> {
-    Fat {
-        module: ModuleCodegen<B::Module>,
-        _serialized_bitcode: Vec<SerializedModule<B::ModuleBuffer>>,
-    },
-
+    Fat(ModuleCodegen<B::Module>),
     Thin(ThinModule<B>),
 }
 
 impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
     pub fn name(&self) -> &str {
         match *self {
-            LtoModuleCodegen::Fat { .. } => "everything",
+            LtoModuleCodegen::Fat(_) => "everything",
             LtoModuleCodegen::Thin(ref m) => m.name(),
         }
     }
@@ -68,7 +64,7 @@ pub unsafe fn optimize(
         cgcx: &CodegenContext<B>,
     ) -> Result<ModuleCodegen<B::Module>, FatalError> {
         match self {
-            LtoModuleCodegen::Fat { mut module, .. } => {
+            LtoModuleCodegen::Fat(mut module) => {
                 B::optimize_fat(cgcx, &mut module)?;
                 Ok(module)
             }
@@ -81,7 +77,7 @@ pub unsafe fn optimize(
     pub fn cost(&self) -> u64 {
         match *self {
             // Only one module with fat LTO, so the cost doesn't matter.
-            LtoModuleCodegen::Fat { .. } => 0,
+            LtoModuleCodegen::Fat(_) => 0,
             LtoModuleCodegen::Thin(ref m) => m.cost(),
         }
     }
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 9b5a797..0fd9d7f 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -372,27 +372,42 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
     Some(file)
 }
 
-/// Since Xcode 15 Apple's LD requires object files to contain information about what they were
-/// built for (LC_BUILD_VERSION): the platform (macOS/watchOS etc), minimum OS version, and SDK
-/// version. This returns a `MachOBuildVersion` for the target.
+/// Mach-O files contain information about:
+/// - The platform/OS they were built for (macOS/watchOS/Mac Catalyst/iOS simulator etc).
+/// - The minimum OS version / deployment target.
+/// - The version of the SDK they were targetting.
+///
+/// In the past, this was accomplished using the LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS,
+/// LC_VERSION_MIN_TVOS or LC_VERSION_MIN_WATCHOS load commands, which each contain information
+/// about the deployment target and SDK version, and implicitly, by their presence, which OS they
+/// target. Simulator targets were determined if the architecture was x86_64, but there was e.g. a
+/// LC_VERSION_MIN_IPHONEOS present.
+///
+/// This is of course brittle and limited, so modern tooling emit the LC_BUILD_VERSION load
+/// command (which contains all three pieces of information in one) when the deployment target is
+/// high enough, or the target is something that wouldn't be encodable with the old load commands
+/// (such as Mac Catalyst, or Aarch64 iOS simulator).
+///
+/// Since Xcode 15, Apple's LD apparently requires object files to use this load command, so this
+/// returns the `MachOBuildVersion` for the target to do so.
 fn macho_object_build_version_for_target(target: &Target) -> object::write::MachOBuildVersion {
     /// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz"
     /// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200
-    fn pack_version((major, minor): (u32, u32)) -> u32 {
-        (major << 16) | (minor << 8)
+    fn pack_version((major, minor, patch): (u16, u8, u8)) -> u32 {
+        let (major, minor, patch) = (major as u32, minor as u32, patch as u32);
+        (major << 16) | (minor << 8) | patch
     }
 
     let platform =
         rustc_target::spec::current_apple_platform(target).expect("unknown Apple target OS");
-    let min_os = rustc_target::spec::current_apple_deployment_target(target)
-        .expect("unknown Apple target OS");
-    let sdk =
+    let min_os = rustc_target::spec::current_apple_deployment_target(target);
+    let (sdk_major, sdk_minor) =
         rustc_target::spec::current_apple_sdk_version(platform).expect("unknown Apple target OS");
 
     let mut build_version = object::write::MachOBuildVersion::default();
     build_version.platform = platform;
     build_version.minos = pack_version(min_os);
-    build_version.sdk = pack_version(sdk);
+    build_version.sdk = pack_version((sdk_major, sdk_minor, 0));
     build_version
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index d94c6f8..91fd990 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -382,7 +382,7 @@ fn assume_scalar_range(
         scalar: abi::Scalar,
         backend_ty: Bx::Type,
     ) {
-        if matches!(self.cx.sess().opts.optimize, OptLevel::No | OptLevel::Less)
+        if matches!(self.cx.sess().opts.optimize, OptLevel::No)
             // For now, the critical niches are all over `Int`eger values.
             // Should floating-point values or pointers ever get more complex
             // niches, then this code will probably want to handle them too.
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs
index 2ef860f..73283ca 100644
--- a/compiler/rustc_codegen_ssa/src/mir/statement.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs
@@ -1,6 +1,5 @@
 use rustc_middle::mir::{self, NonDivergingIntrinsic};
 use rustc_middle::span_bug;
-use rustc_session::config::OptLevel;
 use tracing::instrument;
 
 use super::{FunctionCx, LocalRef};
@@ -68,10 +67,8 @@ pub fn codegen_statement(&mut self, bx: &mut Bx, statement: &mir::Statement<'tcx
                 self.codegen_coverage(bx, kind, statement.source_info.scope);
             }
             mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => {
-                if !matches!(bx.tcx().sess.opts.optimize, OptLevel::No | OptLevel::Less) {
-                    let op_val = self.codegen_operand(bx, op);
-                    bx.assume(op_val.immediate());
-                }
+                let op_val = self.codegen_operand(bx, op);
+                bx.assume(op_val.immediate());
             }
             mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
                 mir::CopyNonOverlapping { ref count, ref src, ref dst },
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 96b3ec6..7ccebd8 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -94,7 +94,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
     let intern_result = intern_const_alloc_recursive(ecx, intern_kind, &ret);
 
     // Since evaluation had no errors, validate the resulting constant.
-    const_validate_mplace(&ecx, &ret, cid)?;
+    const_validate_mplace(ecx, &ret, cid)?;
 
     // Only report this after validation, as validaiton produces much better diagnostics.
     // FIXME: ensure validation always reports this and stop making interning care about it.
@@ -391,7 +391,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
 
 #[inline(always)]
 fn const_validate_mplace<'tcx>(
-    ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
+    ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
     mplace: &MPlaceTy<'tcx>,
     cid: GlobalId<'tcx>,
 ) -> Result<(), ErrorHandled> {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 9c1fef0..7405ca0 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -1,16 +1,16 @@
-use std::borrow::Borrow;
+use std::borrow::{Borrow, Cow};
 use std::fmt;
 use std::hash::Hash;
 use std::ops::ControlFlow;
 
 use rustc_ast::Mutability;
-use rustc_data_structures::fx::{FxIndexMap, IndexEntry};
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{self as hir, LangItem, CRATE_HIR_ID};
 use rustc_middle::mir::AssertMessage;
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{bug, mir};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
@@ -24,8 +24,8 @@
 use crate::interpret::{
     self, compile_time_machine, err_ub, throw_exhaust, throw_inval, throw_ub_custom, throw_unsup,
     throw_unsup_format, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame,
-    GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, Scalar,
-    StackPopCleanup,
+    GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic,
+    RangeSet, Scalar, StackPopCleanup,
 };
 
 /// When hitting this many interpreted terminators we emit a deny by default lint
@@ -65,6 +65,9 @@ pub struct CompileTimeMachine<'tcx> {
     /// storing the result in the given `AllocId`.
     /// Used to prevent reads from a static's base allocation, as that may allow for self-initialization loops.
     pub(crate) static_root_ids: Option<(AllocId, LocalDefId)>,
+
+    /// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes).
+    union_data_ranges: FxHashMap<Ty<'tcx>, RangeSet>,
 }
 
 #[derive(Copy, Clone)]
@@ -99,6 +102,7 @@ pub(crate) fn new(
             can_access_mut_global,
             check_alignment,
             static_root_ids: None,
+            union_data_ranges: FxHashMap::default(),
         }
     }
 }
@@ -766,6 +770,19 @@ fn before_alloc_read(ecx: &InterpCx<'tcx, Self>, alloc_id: AllocId) -> InterpRes
         }
         Ok(())
     }
+
+    fn cached_union_data_range<'e>(
+        ecx: &'e mut InterpCx<'tcx, Self>,
+        ty: Ty<'tcx>,
+        compute_range: impl FnOnce() -> RangeSet,
+    ) -> Cow<'e, RangeSet> {
+        if ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks {
+            Cow::Borrowed(ecx.machine.union_data_ranges.entry(ty).or_insert_with(compute_range))
+        } else {
+            // Don't bother caching, we're only doing one validation at the end anyway.
+            Cow::Owned(compute_range())
+        }
+    }
 }
 
 // Please do not add any code below the above `Machine` trait impl. I (oli-obk) plan more cleanups
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index 82438eb..568a9a3 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -189,7 +189,7 @@ fn layout_compat(
                 ty::Ref(_, ty, _) => *ty,
                 ty::RawPtr(ty, _) => *ty,
                 // We only accept `Box` with the default allocator.
-                _ if ty.is_box_global(*self.tcx) => ty.boxed_ty(),
+                _ if ty.is_box_global(*self.tcx) => ty.expect_boxed_ty(),
                 _ => return Ok(None),
             }))
         };
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 0008a15..de93ed8 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -7,7 +7,7 @@
 use tracing::{instrument, trace};
 
 use super::{
-    err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable,
+    err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Projectable, Scalar, Writeable,
 };
 
 impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
@@ -60,7 +60,7 @@ pub fn write_discriminant(
     #[instrument(skip(self), level = "trace")]
     pub fn read_discriminant(
         &self,
-        op: &impl Readable<'tcx, M::Provenance>,
+        op: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, VariantIdx> {
         let ty = op.layout().ty;
         trace!("read_discriminant_value {:#?}", op.layout());
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 6cfd7be..8cab3c3 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -10,6 +10,7 @@
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::ty::Ty;
 use rustc_middle::{mir, ty};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
@@ -19,7 +20,7 @@
 use super::{
     throw_unsup, throw_unsup_format, AllocBytes, AllocId, AllocKind, AllocRange, Allocation,
     ConstAllocation, CtfeProvenance, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy,
-    MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, CTFE_ALLOC_SALT,
+    MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, RangeSet, CTFE_ALLOC_SALT,
 };
 
 /// Data returned by [`Machine::after_stack_pop`], and consumed by
@@ -578,6 +579,15 @@ fn get_global_alloc_salt(
         ecx: &InterpCx<'tcx, Self>,
         instance: Option<ty::Instance<'tcx>>,
     ) -> usize;
+
+    fn cached_union_data_range<'e>(
+        _ecx: &'e mut InterpCx<'tcx, Self>,
+        _ty: Ty<'tcx>,
+        compute_range: impl FnOnce() -> RangeSet,
+    ) -> Cow<'e, RangeSet> {
+        // Default to no caching.
+        Cow::Owned(compute_range())
+    }
 }
 
 /// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 45a5eb9..d875884 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -8,9 +8,8 @@
 
 use std::assert_matches::assert_matches;
 use std::borrow::Cow;
-use std::cell::Cell;
 use std::collections::VecDeque;
-use std::{fmt, ptr};
+use std::{fmt, mem, ptr};
 
 use rustc_ast::Mutability;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
@@ -118,7 +117,7 @@ pub struct Memory<'tcx, M: Machine<'tcx>> {
     /// This stores whether we are currently doing reads purely for the purpose of validation.
     /// Those reads do not trigger the machine's hooks for memory reads.
     /// Needless to say, this must only be set with great care!
-    validation_in_progress: Cell<bool>,
+    validation_in_progress: bool,
 }
 
 /// A reference to some allocation that was already bounds-checked for the given region
@@ -145,7 +144,7 @@ pub fn new() -> Self {
             alloc_map: M::MemoryMap::default(),
             extra_fn_ptr_map: FxIndexMap::default(),
             dead_alloc_map: FxIndexMap::default(),
-            validation_in_progress: Cell::new(false),
+            validation_in_progress: false,
         }
     }
 
@@ -682,7 +681,7 @@ pub fn get_ptr_alloc<'a>(
         // We want to call the hook on *all* accesses that involve an AllocId, including zero-sized
         // accesses. That means we cannot rely on the closure above or the `Some` branch below. We
         // do this after `check_and_deref_ptr` to ensure some basic sanity has already been checked.
-        if !self.memory.validation_in_progress.get() {
+        if !self.memory.validation_in_progress {
             if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr, size_i64) {
                 M::before_alloc_read(self, alloc_id)?;
             }
@@ -690,7 +689,7 @@ pub fn get_ptr_alloc<'a>(
 
         if let Some((alloc_id, offset, prov, alloc)) = ptr_and_alloc {
             let range = alloc_range(offset, size);
-            if !self.memory.validation_in_progress.get() {
+            if !self.memory.validation_in_progress {
                 M::before_memory_read(
                     self.tcx,
                     &self.machine,
@@ -766,11 +765,14 @@ pub fn get_ptr_alloc_mut<'a>(
         let parts = self.get_ptr_access(ptr, size)?;
         if let Some((alloc_id, offset, prov)) = parts {
             let tcx = self.tcx;
+            let validation_in_progress = self.memory.validation_in_progress;
             // FIXME: can we somehow avoid looking up the allocation twice here?
             // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`.
             let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?;
             let range = alloc_range(offset, size);
-            M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?;
+            if !validation_in_progress {
+                M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?;
+            }
             Ok(Some(AllocRefMut { alloc, range, tcx: *tcx, alloc_id }))
         } else {
             Ok(None)
@@ -1014,16 +1016,16 @@ pub fn find_leaked_allocations(
     ///
     /// We do this so Miri's allocation access tracking does not show the validation
     /// reads as spurious accesses.
-    pub fn run_for_validation<R>(&self, f: impl FnOnce() -> R) -> R {
+    pub fn run_for_validation<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
         // This deliberately uses `==` on `bool` to follow the pattern
         // `assert!(val.replace(new) == old)`.
         assert!(
-            self.memory.validation_in_progress.replace(true) == false,
+            mem::replace(&mut self.memory.validation_in_progress, true) == false,
             "`validation_in_progress` was already set"
         );
-        let res = f();
+        let res = f(self);
         assert!(
-            self.memory.validation_in_progress.replace(false) == true,
+            mem::replace(&mut self.memory.validation_in_progress, false) == true,
             "`validation_in_progress` was unset by someone else"
         );
         res
@@ -1115,6 +1117,10 @@ fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra, Bytes: AllocByte
 impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes>
     AllocRefMut<'a, 'tcx, Prov, Extra, Bytes>
 {
+    pub fn as_ref<'b>(&'b self) -> AllocRef<'b, 'tcx, Prov, Extra, Bytes> {
+        AllocRef { alloc: self.alloc, range: self.range, tcx: self.tcx, alloc_id: self.alloc_id }
+    }
+
     /// `range` is relative to this allocation reference, not the base of the allocation.
     pub fn write_scalar(&mut self, range: AllocRange, val: Scalar<Prov>) -> InterpResult<'tcx> {
         let range = self.range.subrange(range);
@@ -1130,13 +1136,30 @@ pub fn write_ptr_sized(&mut self, offset: Size, val: Scalar<Prov>) -> InterpResu
         self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size), val)
     }
 
+    /// Mark the given sub-range (relative to this allocation reference) as uninitialized.
+    pub fn write_uninit(&mut self, range: AllocRange) -> InterpResult<'tcx> {
+        let range = self.range.subrange(range);
+        Ok(self
+            .alloc
+            .write_uninit(&self.tcx, range)
+            .map_err(|e| e.to_interp_error(self.alloc_id))?)
+    }
+
     /// Mark the entire referenced range as uninitialized
-    pub fn write_uninit(&mut self) -> InterpResult<'tcx> {
+    pub fn write_uninit_full(&mut self) -> InterpResult<'tcx> {
         Ok(self
             .alloc
             .write_uninit(&self.tcx, self.range)
             .map_err(|e| e.to_interp_error(self.alloc_id))?)
     }
+
+    /// Remove all provenance in the reference range.
+    pub fn clear_provenance(&mut self) -> InterpResult<'tcx> {
+        Ok(self
+            .alloc
+            .clear_provenance(&self.tcx, self.range)
+            .map_err(|e| e.to_interp_error(self.alloc_id))?)
+    }
 }
 
 impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> {
@@ -1278,7 +1301,7 @@ pub fn mem_copy_repeatedly(
         };
         let src_alloc = self.get_alloc_raw(src_alloc_id)?;
         let src_range = alloc_range(src_offset, size);
-        assert!(!self.memory.validation_in_progress.get(), "we can't be copying during validation");
+        assert!(!self.memory.validation_in_progress, "we can't be copying during validation");
         M::before_memory_read(
             tcx,
             &self.machine,
diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs
index 511756e..561d681 100644
--- a/compiler/rustc_const_eval/src/interpret/mod.rs
+++ b/compiler/rustc_const_eval/src/interpret/mod.rs
@@ -33,11 +33,11 @@
 pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, ReturnAction};
 pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
 use self::operand::Operand;
-pub use self::operand::{ImmTy, Immediate, OpTy, Readable};
+pub use self::operand::{ImmTy, Immediate, OpTy};
 pub use self::place::{MPlaceTy, MemPlaceMeta, PlaceTy, Writeable};
 use self::place::{MemPlace, Place};
 pub use self::projection::{OffsetMode, Projectable};
 pub use self::stack::{Frame, FrameInfo, LocalState, StackPopCleanup, StackPopInfo};
 pub(crate) use self::util::create_static_alloc;
-pub use self::validity::{CtfeValidationMode, RefTracking};
+pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking};
 pub use self::visitor::ValueVisitor;
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 9a8ccaa..b906e34 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -111,6 +111,46 @@ pub fn to_scalar_and_meta(self) -> (Scalar<Prov>, MemPlaceMeta<Prov>) {
             Immediate::Uninit => bug!("Got uninit where a scalar or scalar pair was expected"),
         }
     }
+
+    /// Assert that this immediate is a valid value for the given ABI.
+    pub fn assert_matches_abi(self, abi: Abi, cx: &impl HasDataLayout) {
+        match (self, abi) {
+            (Immediate::Scalar(scalar), Abi::Scalar(s)) => {
+                assert_eq!(scalar.size(), s.size(cx));
+                if !matches!(s.primitive(), abi::Pointer(..)) {
+                    assert!(matches!(scalar, Scalar::Int(..)));
+                }
+            }
+            (Immediate::ScalarPair(a_val, b_val), Abi::ScalarPair(a, b)) => {
+                assert_eq!(a_val.size(), a.size(cx));
+                if !matches!(a.primitive(), abi::Pointer(..)) {
+                    assert!(matches!(a_val, Scalar::Int(..)));
+                }
+                assert_eq!(b_val.size(), b.size(cx));
+                if !matches!(b.primitive(), abi::Pointer(..)) {
+                    assert!(matches!(b_val, Scalar::Int(..)));
+                }
+            }
+            (Immediate::Uninit, _) => {}
+            _ => {
+                bug!("value {self:?} does not match ABI {abi:?})",)
+            }
+        }
+    }
+
+    pub fn clear_provenance<'tcx>(&mut self) -> InterpResult<'tcx> {
+        match self {
+            Immediate::Scalar(s) => {
+                s.clear_provenance()?;
+            }
+            Immediate::ScalarPair(a, b) => {
+                a.clear_provenance()?;
+                b.clear_provenance()?;
+            }
+            Immediate::Uninit => {}
+        }
+        Ok(())
+    }
 }
 
 // ScalarPair needs a type to interpret, so we often have an immediate and a type together
@@ -490,32 +530,6 @@ fn to_op<M: Machine<'tcx, Provenance = Prov>>(
     }
 }
 
-/// The `Readable` trait describes interpreter values that one can read from.
-pub trait Readable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> {
-    fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>>;
-}
-
-impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for OpTy<'tcx, Prov> {
-    #[inline(always)]
-    fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
-        self.as_mplace_or_imm()
-    }
-}
-
-impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
-    #[inline(always)]
-    fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
-        Left(self.clone())
-    }
-}
-
-impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for ImmTy<'tcx, Prov> {
-    #[inline(always)]
-    fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
-        Right(self.clone())
-    }
-}
-
 impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     /// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`.
     /// Returns `None` if the layout does not permit loading this as a value.
@@ -588,9 +602,9 @@ fn read_immediate_from_mplace_raw(
     /// ConstProp needs it, though.
     pub fn read_immediate_raw(
         &self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, Either<MPlaceTy<'tcx, M::Provenance>, ImmTy<'tcx, M::Provenance>>> {
-        Ok(match src.as_mplace_or_imm() {
+        Ok(match src.to_op(self)?.as_mplace_or_imm() {
             Left(ref mplace) => {
                 if let Some(val) = self.read_immediate_from_mplace_raw(mplace)? {
                     Right(val)
@@ -608,7 +622,7 @@ pub fn read_immediate_raw(
     #[inline(always)]
     pub fn read_immediate(
         &self,
-        op: &impl Readable<'tcx, M::Provenance>,
+        op: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
         if !matches!(
             op.layout().abi,
@@ -627,7 +641,7 @@ pub fn read_immediate(
     /// Read a scalar from a place
     pub fn read_scalar(
         &self,
-        op: &impl Readable<'tcx, M::Provenance>,
+        op: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, Scalar<M::Provenance>> {
         Ok(self.read_immediate(op)?.to_scalar())
     }
@@ -638,21 +652,21 @@ pub fn read_scalar(
     /// Read a pointer from a place.
     pub fn read_pointer(
         &self,
-        op: &impl Readable<'tcx, M::Provenance>,
+        op: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> {
         self.read_scalar(op)?.to_pointer(self)
     }
     /// Read a pointer-sized unsigned integer from a place.
     pub fn read_target_usize(
         &self,
-        op: &impl Readable<'tcx, M::Provenance>,
+        op: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, u64> {
         self.read_scalar(op)?.to_target_usize(self)
     }
     /// Read a pointer-sized signed integer from a place.
     pub fn read_target_isize(
         &self,
-        op: &impl Readable<'tcx, M::Provenance>,
+        op: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, i64> {
         self.read_scalar(op)?.to_target_isize(self)
     }
@@ -717,7 +731,7 @@ pub fn place_to_op(
     ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
         match place.as_mplace_or_local() {
             Left(mplace) => Ok(mplace.into()),
-            Right((local, offset, locals_addr)) => {
+            Right((local, offset, locals_addr, _)) => {
                 debug_assert!(place.layout.is_sized()); // only sized locals can ever be `Place::Local`.
                 debug_assert_eq!(locals_addr, self.frame().locals_addr());
                 let base = self.local_to_op(local, None)?;
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 840f798..3b14142 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -15,7 +15,7 @@
 use super::{
     alloc_range, mir_assign_valid_types, AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance,
     ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy,
-    Operand, Pointer, Projectable, Provenance, Readable, Scalar,
+    Operand, Pointer, Projectable, Provenance, Scalar,
 };
 
 #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
@@ -180,7 +180,8 @@ pub(super) enum Place<Prov: Provenance = CtfeProvenance> {
     Ptr(MemPlace<Prov>),
 
     /// To support alloc-free locals, we are able to write directly to a local. The offset indicates
-    /// where in the local this place is located; if it is `None`, no projection has been applied.
+    /// where in the local this place is located; if it is `None`, no projection has been applied
+    /// and the type of the place is exactly the type of the local.
     /// Such projections are meaningful even if the offset is 0, since they can change layouts.
     /// (Without that optimization, we'd just always be a `MemPlace`.)
     /// `Local` places always refer to the current stack frame, so they are unstable under
@@ -231,10 +232,12 @@ pub(super) fn place(&self) -> &Place<Prov> {
     #[inline(always)]
     pub fn as_mplace_or_local(
         &self,
-    ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize)> {
+    ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)> {
         match self.place {
             Place::Ptr(mplace) => Left(MPlaceTy { mplace, layout: self.layout }),
-            Place::Local { local, offset, locals_addr } => Right((local, offset, locals_addr)),
+            Place::Local { local, offset, locals_addr } => {
+                Right((local, offset, locals_addr, self.layout))
+            }
         }
     }
 
@@ -277,7 +280,7 @@ fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
     ) -> InterpResult<'tcx, Self> {
         Ok(match self.as_mplace_or_local() {
             Left(mplace) => mplace.offset_with_meta(offset, mode, meta, layout, ecx)?.into(),
-            Right((local, old_offset, locals_addr)) => {
+            Right((local, old_offset, locals_addr, _)) => {
                 debug_assert!(layout.is_sized(), "unsized locals should live in memory");
                 assert_matches!(meta, MemPlaceMeta::None); // we couldn't store it anyway...
                 // `Place::Local` are always in-bounds of their surrounding local, so we can just
@@ -328,9 +331,7 @@ pub fn assert_mem_place(&self) -> MPlaceTy<'tcx, Prov> {
 
 /// The `Weiteable` trait describes interpreter values that can be written to.
 pub trait Writeable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> {
-    fn as_mplace_or_local(
-        &self,
-    ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)>;
+    fn to_place(&self) -> PlaceTy<'tcx, Prov>;
 
     fn force_mplace<M: Machine<'tcx, Provenance = Prov>>(
         &self,
@@ -340,11 +341,8 @@ fn force_mplace<M: Machine<'tcx, Provenance = Prov>>(
 
 impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
     #[inline(always)]
-    fn as_mplace_or_local(
-        &self,
-    ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)> {
-        self.as_mplace_or_local()
-            .map_right(|(local, offset, locals_addr)| (local, offset, locals_addr, self.layout))
+    fn to_place(&self) -> PlaceTy<'tcx, Prov> {
+        self.clone()
     }
 
     #[inline(always)]
@@ -358,10 +356,8 @@ fn force_mplace<M: Machine<'tcx, Provenance = Prov>>(
 
 impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
     #[inline(always)]
-    fn as_mplace_or_local(
-        &self,
-    ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)> {
-        Left(self.clone())
+    fn to_place(&self) -> PlaceTy<'tcx, Prov> {
+        self.clone().into()
     }
 
     #[inline(always)]
@@ -436,7 +432,7 @@ pub fn mplace_to_ref(
     #[instrument(skip(self), level = "trace")]
     pub fn deref_pointer(
         &self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
         if src.layout().ty.is_box() {
             // Derefer should have removed all Box derefs.
@@ -562,6 +558,40 @@ pub fn eval_place(
         Ok(place)
     }
 
+    /// Given a place, returns either the underlying mplace or a reference to where the value of
+    /// this place is stored.
+    fn as_mplace_or_mutable_local(
+        &mut self,
+        place: &PlaceTy<'tcx, M::Provenance>,
+    ) -> InterpResult<
+        'tcx,
+        Either<MPlaceTy<'tcx, M::Provenance>, (&mut Immediate<M::Provenance>, TyAndLayout<'tcx>)>,
+    > {
+        Ok(match place.to_place().as_mplace_or_local() {
+            Left(mplace) => Left(mplace),
+            Right((local, offset, locals_addr, layout)) => {
+                if offset.is_some() {
+                    // This has been projected to a part of this local, or had the type changed.
+                    // FIMXE: there are cases where we could still avoid allocating an mplace.
+                    Left(place.force_mplace(self)?)
+                } else {
+                    debug_assert_eq!(locals_addr, self.frame().locals_addr());
+                    debug_assert_eq!(self.layout_of_local(self.frame(), local, None)?, layout);
+                    match self.frame_mut().locals[local].access_mut()? {
+                        Operand::Indirect(mplace) => {
+                            // The local is in memory.
+                            Left(MPlaceTy { mplace: *mplace, layout })
+                        }
+                        Operand::Immediate(local_val) => {
+                            // The local still has the optimized representation.
+                            Right((local_val, layout))
+                        }
+                    }
+                }
+            }
+        })
+    }
+
     /// Write an immediate to a place
     #[inline(always)]
     #[instrument(skip(self), level = "trace")]
@@ -574,9 +604,11 @@ pub fn write_immediate(
 
         if M::enforce_validity(self, dest.layout()) {
             // Data got changed, better make sure it matches the type!
+            // Also needed to reset padding.
             self.validate_operand(
-                &dest.to_op(self)?,
+                &dest.to_place(),
                 M::enforce_validity_recursively(self, dest.layout()),
+                /*reset_provenance_and_padding*/ true,
             )?;
         }
 
@@ -606,67 +638,27 @@ pub fn write_pointer(
     /// Write an immediate to a place.
     /// If you use this you are responsible for validating that things got copied at the
     /// right type.
-    fn write_immediate_no_validate(
+    pub(super) fn write_immediate_no_validate(
         &mut self,
         src: Immediate<M::Provenance>,
         dest: &impl Writeable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
         assert!(dest.layout().is_sized(), "Cannot write unsized immediate data");
 
-        // See if we can avoid an allocation. This is the counterpart to `read_immediate_raw`,
-        // but not factored as a separate function.
-        let mplace = match dest.as_mplace_or_local() {
-            Right((local, offset, locals_addr, layout)) => {
-                if offset.is_some() {
-                    // This has been projected to a part of this local. We could have complicated
-                    // logic to still keep this local as an `Operand`... but it's much easier to
-                    // just fall back to the indirect path.
-                    dest.force_mplace(self)?
-                } else {
-                    debug_assert_eq!(locals_addr, self.frame().locals_addr());
-                    match self.frame_mut().locals[local].access_mut()? {
-                        Operand::Immediate(local_val) => {
-                            // Local can be updated in-place.
-                            *local_val = src;
-                            // Double-check that the value we are storing and the local fit to each other.
-                            // (*After* doing the update for borrow checker reasons.)
-                            if cfg!(debug_assertions) {
-                                let local_layout =
-                                    self.layout_of_local(&self.frame(), local, None)?;
-                                match (src, local_layout.abi) {
-                                    (Immediate::Scalar(scalar), Abi::Scalar(s)) => {
-                                        assert_eq!(scalar.size(), s.size(self))
-                                    }
-                                    (
-                                        Immediate::ScalarPair(a_val, b_val),
-                                        Abi::ScalarPair(a, b),
-                                    ) => {
-                                        assert_eq!(a_val.size(), a.size(self));
-                                        assert_eq!(b_val.size(), b.size(self));
-                                    }
-                                    (Immediate::Uninit, _) => {}
-                                    (src, abi) => {
-                                        bug!(
-                                            "value {src:?} cannot be written into local with type {} (ABI {abi:?})",
-                                            local_layout.ty
-                                        )
-                                    }
-                                };
-                            }
-                            return Ok(());
-                        }
-                        Operand::Indirect(mplace) => {
-                            // The local is in memory, go on below.
-                            MPlaceTy { mplace: *mplace, layout }
-                        }
-                    }
+        match self.as_mplace_or_mutable_local(&dest.to_place())? {
+            Right((local_val, local_layout)) => {
+                // Local can be updated in-place.
+                *local_val = src;
+                // Double-check that the value we are storing and the local fit to each other.
+                if cfg!(debug_assertions) {
+                    src.assert_matches_abi(local_layout.abi, self);
                 }
             }
-            Left(mplace) => mplace, // already referring to memory
-        };
-
-        // This is already in memory, write there.
-        self.write_immediate_to_mplace_no_validate(src, mplace.layout, mplace.mplace)
+            Left(mplace) => {
+                self.write_immediate_to_mplace_no_validate(src, mplace.layout, mplace.mplace)?;
+            }
+        }
+        Ok(())
     }
 
     /// Write an immediate to memory.
@@ -678,6 +670,9 @@ fn write_immediate_to_mplace_no_validate(
         layout: TyAndLayout<'tcx>,
         dest: MemPlace<M::Provenance>,
     ) -> InterpResult<'tcx> {
+        if cfg!(debug_assertions) {
+            value.assert_matches_abi(layout.abi, self);
+        }
         // Note that it is really important that the type here is the right one, and matches the
         // type things are read at. In case `value` is a `ScalarPair`, we don't do any magic here
         // to handle padding properly, which is only correct if we never look at this data with the
@@ -691,15 +686,7 @@ fn write_immediate_to_mplace_no_validate(
 
         match value {
             Immediate::Scalar(scalar) => {
-                let Abi::Scalar(s) = layout.abi else {
-                    span_bug!(
-                        self.cur_span(),
-                        "write_immediate_to_mplace: invalid Scalar layout: {layout:#?}",
-                    )
-                };
-                let size = s.size(&tcx);
-                assert_eq!(size, layout.size, "abi::Scalar size does not match layout size");
-                alloc.write_scalar(alloc_range(Size::ZERO, size), scalar)
+                alloc.write_scalar(alloc_range(Size::ZERO, scalar.size()), scalar)
             }
             Immediate::ScalarPair(a_val, b_val) => {
                 let Abi::ScalarPair(a, b) = layout.abi else {
@@ -709,18 +696,19 @@ fn write_immediate_to_mplace_no_validate(
                         layout
                     )
                 };
-                let (a_size, b_size) = (a.size(&tcx), b.size(&tcx));
-                let b_offset = a_size.align_to(b.align(&tcx).abi);
+                let b_offset = a.size(&tcx).align_to(b.align(&tcx).abi);
                 assert!(b_offset.bytes() > 0); // in `operand_field` we use the offset to tell apart the fields
 
                 // It is tempting to verify `b_offset` against `layout.fields.offset(1)`,
                 // but that does not work: We could be a newtype around a pair, then the
                 // fields do not match the `ScalarPair` components.
 
-                alloc.write_scalar(alloc_range(Size::ZERO, a_size), a_val)?;
-                alloc.write_scalar(alloc_range(b_offset, b_size), b_val)
+                alloc.write_scalar(alloc_range(Size::ZERO, a_val.size()), a_val)?;
+                alloc.write_scalar(alloc_range(b_offset, b_val.size()), b_val)?;
+                // We don't have to reset padding here, `write_immediate` will anyway do a validation run.
+                Ok(())
             }
-            Immediate::Uninit => alloc.write_uninit(),
+            Immediate::Uninit => alloc.write_uninit_full(),
         }
     }
 
@@ -728,35 +716,38 @@ pub fn write_uninit(
         &mut self,
         dest: &impl Writeable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
-        let mplace = match dest.as_mplace_or_local() {
-            Left(mplace) => mplace,
-            Right((local, offset, locals_addr, layout)) => {
-                if offset.is_some() {
-                    // This has been projected to a part of this local. We could have complicated
-                    // logic to still keep this local as an `Operand`... but it's much easier to
-                    // just fall back to the indirect path.
-                    // FIXME: share the logic with `write_immediate_no_validate`.
-                    dest.force_mplace(self)?
-                } else {
-                    debug_assert_eq!(locals_addr, self.frame().locals_addr());
-                    match self.frame_mut().locals[local].access_mut()? {
-                        Operand::Immediate(local) => {
-                            *local = Immediate::Uninit;
-                            return Ok(());
-                        }
-                        Operand::Indirect(mplace) => {
-                            // The local is in memory, go on below.
-                            MPlaceTy { mplace: *mplace, layout }
-                        }
-                    }
-                }
+        match self.as_mplace_or_mutable_local(&dest.to_place())? {
+            Right((local_val, _local_layout)) => {
+                *local_val = Immediate::Uninit;
             }
-        };
-        let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else {
-            // Zero-sized access
-            return Ok(());
-        };
-        alloc.write_uninit()?;
+            Left(mplace) => {
+                let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else {
+                    // Zero-sized access
+                    return Ok(());
+                };
+                alloc.write_uninit_full()?;
+            }
+        }
+        Ok(())
+    }
+
+    /// Remove all provenance in the given place.
+    pub fn clear_provenance(
+        &mut self,
+        dest: &impl Writeable<'tcx, M::Provenance>,
+    ) -> InterpResult<'tcx> {
+        match self.as_mplace_or_mutable_local(&dest.to_place())? {
+            Right((local_val, _local_layout)) => {
+                local_val.clear_provenance()?;
+            }
+            Left(mplace) => {
+                let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else {
+                    // Zero-sized access
+                    return Ok(());
+                };
+                alloc.clear_provenance()?;
+            }
+        }
         Ok(())
     }
 
@@ -768,7 +759,7 @@ pub fn write_uninit(
     #[inline(always)]
     pub(super) fn copy_op_no_dest_validation(
         &mut self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
         dest: &impl Writeable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
         self.copy_op_inner(
@@ -781,7 +772,7 @@ pub(super) fn copy_op_no_dest_validation(
     #[inline(always)]
     pub fn copy_op_allow_transmute(
         &mut self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
         dest: &impl Writeable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
         self.copy_op_inner(
@@ -794,7 +785,7 @@ pub fn copy_op_allow_transmute(
     #[inline(always)]
     pub fn copy_op(
         &mut self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
         dest: &impl Writeable<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
         self.copy_op_inner(
@@ -808,28 +799,35 @@ pub fn copy_op(
     #[instrument(skip(self), level = "trace")]
     fn copy_op_inner(
         &mut self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
         dest: &impl Writeable<'tcx, M::Provenance>,
         allow_transmute: bool,
         validate_dest: bool,
     ) -> InterpResult<'tcx> {
-        // Generally for transmutation, data must be valid both at the old and new type.
-        // But if the types are the same, the 2nd validation below suffices.
-        if src.layout().ty != dest.layout().ty && M::enforce_validity(self, src.layout()) {
-            self.validate_operand(
-                &src.to_op(self)?,
-                M::enforce_validity_recursively(self, src.layout()),
-            )?;
-        }
+        // These are technically *two* typed copies: `src` is a not-yet-loaded value,
+        // so we're going a typed copy at `src` type from there to some intermediate storage.
+        // And then we're doing a second typed copy from that intermediate storage to `dest`.
+        // But as an optimization, we only make a single direct copy here.
 
         // Do the actual copy.
         self.copy_op_no_validate(src, dest, allow_transmute)?;
 
         if validate_dest && M::enforce_validity(self, dest.layout()) {
-            // Data got changed, better make sure it matches the type!
+            let dest = dest.to_place();
+            // Given that there were two typed copies, we have to ensure this is valid at both types,
+            // and we have to ensure this loses provenance and padding according to both types.
+            // But if the types are identical, we only do one pass.
+            if allow_transmute && src.layout().ty != dest.layout().ty {
+                self.validate_operand(
+                    &dest.transmute(src.layout(), self)?,
+                    M::enforce_validity_recursively(self, src.layout()),
+                    /*reset_provenance_and_padding*/ true,
+                )?;
+            }
             self.validate_operand(
-                &dest.to_op(self)?,
+                &dest,
                 M::enforce_validity_recursively(self, dest.layout()),
+                /*reset_provenance_and_padding*/ true,
             )?;
         }
 
@@ -843,7 +841,7 @@ fn copy_op_inner(
     #[instrument(skip(self), level = "trace")]
     fn copy_op_no_validate(
         &mut self,
-        src: &impl Readable<'tcx, M::Provenance>,
+        src: &impl Projectable<'tcx, M::Provenance>,
         dest: &impl Writeable<'tcx, M::Provenance>,
         allow_transmute: bool,
     ) -> InterpResult<'tcx> {
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 26b7251..fb24f98 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -4,6 +4,7 @@
 //! That's useful because it means other passes (e.g. promotion) can rely on `const`s
 //! to be const-safe.
 
+use std::borrow::Cow;
 use std::fmt::Write;
 use std::hash::Hash;
 use std::num::NonZero;
@@ -16,22 +17,22 @@
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::ValidationErrorKind::{self, *};
 use rustc_middle::mir::interpret::{
-    ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance,
+    alloc_range, ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance,
     UnsupportedOpInfo, ValidationErrorInfo,
 };
-use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::{
-    Abi, FieldIdx, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
+    Abi, FieldIdx, FieldsShape, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
 };
 use tracing::trace;
 
 use super::machine::AllocMap;
 use super::{
     err_ub, format_interp_error, throw_ub, AllocId, AllocKind, CheckInAllocMsg, GlobalAlloc, ImmTy,
-    Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, Pointer, Projectable,
-    Scalar, ValueVisitor,
+    Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, PlaceTy, Pointer,
+    Projectable, Scalar, ValueVisitor,
 };
 
 // for the validation errors
@@ -125,6 +126,7 @@ pub enum PathElem {
     EnumTag,
     CoroutineTag,
     DynDowncast,
+    Vtable,
 }
 
 /// Extra things to check for during validation of CTFE results.
@@ -163,22 +165,22 @@ impl<T: Clone + Eq + Hash + std::fmt::Debug, PATH: Default> RefTracking<T, PATH>
     pub fn empty() -> Self {
         RefTracking { seen: FxHashSet::default(), todo: vec![] }
     }
-    pub fn new(op: T) -> Self {
+    pub fn new(val: T) -> Self {
         let mut ref_tracking_for_consts =
-            RefTracking { seen: FxHashSet::default(), todo: vec![(op.clone(), PATH::default())] };
-        ref_tracking_for_consts.seen.insert(op);
+            RefTracking { seen: FxHashSet::default(), todo: vec![(val.clone(), PATH::default())] };
+        ref_tracking_for_consts.seen.insert(val);
         ref_tracking_for_consts
     }
     pub fn next(&mut self) -> Option<(T, PATH)> {
         self.todo.pop()
     }
 
-    fn track(&mut self, op: T, path: impl FnOnce() -> PATH) {
-        if self.seen.insert(op.clone()) {
-            trace!("Recursing below ptr {:#?}", op);
+    fn track(&mut self, val: T, path: impl FnOnce() -> PATH) {
+        if self.seen.insert(val.clone()) {
+            trace!("Recursing below ptr {:#?}", val);
             let path = path();
             // Remember to come back to this later.
-            self.todo.push((op, path));
+            self.todo.push((val, path));
         }
     }
 }
@@ -204,11 +206,62 @@ fn write_path(out: &mut String, path: &[PathElem]) {
             // not the root.
             Deref => write!(out, ".<deref>"),
             DynDowncast => write!(out, ".<dyn-downcast>"),
+            Vtable => write!(out, ".<vtable>"),
         }
         .unwrap()
     }
 }
 
+/// Represents a set of `Size` values as a sorted list of ranges.
+// These are (offset, length) pairs, and they are sorted and mutually disjoint,
+// and never adjacent (i.e. there's always a gap between two of them).
+#[derive(Debug, Clone)]
+pub struct RangeSet(Vec<(Size, Size)>);
+
+impl RangeSet {
+    fn add_range(&mut self, offset: Size, size: Size) {
+        if size.bytes() == 0 {
+            // No need to track empty ranges.
+            return;
+        }
+        let v = &mut self.0;
+        // We scan for a partition point where the left partition is all the elements that end
+        // strictly before we start. Those are elements that are too "low" to merge with us.
+        let idx =
+            v.partition_point(|&(other_offset, other_size)| other_offset + other_size < offset);
+        // Now we want to either merge with the first element of the second partition, or insert ourselves before that.
+        if let Some(&(other_offset, other_size)) = v.get(idx)
+            && offset + size >= other_offset
+        {
+            // Their end is >= our start (otherwise it would not be in the 2nd partition) and
+            // our end is >= their start. This means we can merge the ranges.
+            let new_start = other_offset.min(offset);
+            let mut new_end = (other_offset + other_size).max(offset + size);
+            // We grew to the right, so merge with overlapping/adjacent elements.
+            // (We also may have grown to the left, but that can never make us adjacent with
+            // anything there since we selected the first such candidate via `partition_point`.)
+            let mut scan_right = 1;
+            while let Some(&(next_offset, next_size)) = v.get(idx + scan_right)
+                && new_end >= next_offset
+            {
+                // Increase our size to absorb the next element.
+                new_end = new_end.max(next_offset + next_size);
+                // Look at the next element.
+                scan_right += 1;
+            }
+            // Update the element we grew.
+            v[idx] = (new_start, new_end - new_start);
+            // Remove the elements we absorbed (if any).
+            if scan_right > 1 {
+                drop(v.drain((idx + 1)..(idx + scan_right)));
+            }
+        } else {
+            // Insert new element.
+            v.insert(idx, (offset, size));
+        }
+    }
+}
+
 struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
     /// The `path` may be pushed to, but the part that is present when a function
     /// starts must not be changed!  `visit_fields` and `visit_array` rely on
@@ -217,7 +270,17 @@ struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
     ref_tracking: Option<&'rt mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>>,
     /// `None` indicates this is not validating for CTFE (but for runtime).
     ctfe_mode: Option<CtfeValidationMode>,
-    ecx: &'rt InterpCx<'tcx, M>,
+    ecx: &'rt mut InterpCx<'tcx, M>,
+    /// Whether provenance should be reset outside of pointers (emulating the effect of a typed
+    /// copy).
+    reset_provenance_and_padding: bool,
+    /// This tracks which byte ranges in this value contain data; the remaining bytes are padding.
+    /// The ideal representation here would be pointer-length pairs, but to keep things more compact
+    /// we only store a (range) set of offsets -- the base pointer is the same throughout the entire
+    /// visit, after all.
+    /// If this is `Some`, then `reset_provenance_and_padding` must be true (but not vice versa:
+    /// we might not track data vs padding bytes if the operand isn't stored in memory anyway).
+    data_bytes: Option<RangeSet>,
 }
 
 impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
@@ -287,8 +350,14 @@ fn aggregate_field_path_elem(&mut self, layout: TyAndLayout<'tcx>, field: usize)
             // arrays/slices
             ty::Array(..) | ty::Slice(..) => PathElem::ArrayElem(field),
 
+            // dyn* vtables
+            ty::Dynamic(_, _, ty::DynKind::DynStar) if field == 1 => PathElem::Vtable,
+
             // dyn traits
-            ty::Dynamic(..) => PathElem::DynDowncast,
+            ty::Dynamic(..) => {
+                assert_eq!(field, 0);
+                PathElem::DynDowncast
+            }
 
             // nothing else has an aggregate layout
             _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", layout.ty),
@@ -314,11 +383,11 @@ fn with_elem<R>(
 
     fn read_immediate(
         &self,
-        op: &OpTy<'tcx, M::Provenance>,
+        val: &PlaceTy<'tcx, M::Provenance>,
         expected: ExpectedKind,
     ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
         Ok(try_validation!(
-            self.ecx.read_immediate(op),
+            self.ecx.read_immediate(val),
             self.path,
             Ub(InvalidUninitBytes(None)) =>
                 Uninit { expected },
@@ -332,10 +401,40 @@ fn read_immediate(
 
     fn read_scalar(
         &self,
-        op: &OpTy<'tcx, M::Provenance>,
+        val: &PlaceTy<'tcx, M::Provenance>,
         expected: ExpectedKind,
     ) -> InterpResult<'tcx, Scalar<M::Provenance>> {
-        Ok(self.read_immediate(op, expected)?.to_scalar())
+        Ok(self.read_immediate(val, expected)?.to_scalar())
+    }
+
+    fn deref_pointer(
+        &mut self,
+        val: &PlaceTy<'tcx, M::Provenance>,
+        expected: ExpectedKind,
+    ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
+        // Not using `ecx.deref_pointer` since we want to use our `read_immediate` wrapper.
+        let imm = self.read_immediate(val, expected)?;
+        // Reset provenance: ensure slice tail metadata does not preserve provenance,
+        // and ensure all pointers do not preserve partial provenance.
+        if self.reset_provenance_and_padding {
+            if matches!(imm.layout.abi, Abi::Scalar(..)) {
+                // A thin pointer. If it has provenance, we don't have to do anything.
+                // If it does not, ensure we clear the provenance in memory.
+                if matches!(imm.to_scalar(), Scalar::Int(..)) {
+                    self.ecx.clear_provenance(val)?;
+                }
+            } else {
+                // A wide pointer. This means we have to worry both about the pointer itself and the
+                // metadata. We do the lazy thing and just write back the value we got. Just
+                // clearing provenance in a targeted manner would be more efficient, but unless this
+                // is a perf hotspot it's just not worth the effort.
+                self.ecx.write_immediate_no_validate(*imm, val)?;
+            }
+            // The entire thing is data, not padding.
+            self.add_data_range_place(val);
+        }
+        // Now turn it into a place.
+        self.ecx.ref_to_mplace(&imm)
     }
 
     fn check_wide_ptr_meta(
@@ -376,11 +475,10 @@ fn check_wide_ptr_meta(
     /// Check a reference or `Box`.
     fn check_safe_pointer(
         &mut self,
-        value: &OpTy<'tcx, M::Provenance>,
+        value: &PlaceTy<'tcx, M::Provenance>,
         ptr_kind: PointerKind,
     ) -> InterpResult<'tcx> {
-        // Not using `deref_pointer` since we want to use our `read_immediate` wrapper.
-        let place = self.ecx.ref_to_mplace(&self.read_immediate(value, ptr_kind.into())?)?;
+        let place = self.deref_pointer(value, ptr_kind.into())?;
         // Handle wide pointers.
         // Check metadata early, for better diagnostics
         if place.layout.is_unsized() {
@@ -564,31 +662,39 @@ fn check_safe_pointer(
     /// Note that not all of these have `FieldsShape::Primitive`, e.g. wide references.
     fn try_visit_primitive(
         &mut self,
-        value: &OpTy<'tcx, M::Provenance>,
+        value: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, bool> {
         // Go over all the primitive types
         let ty = value.layout.ty;
         match ty.kind() {
             ty::Bool => {
-                let value = self.read_scalar(value, ExpectedKind::Bool)?;
+                let scalar = self.read_scalar(value, ExpectedKind::Bool)?;
                 try_validation!(
-                    value.to_bool(),
+                    scalar.to_bool(),
                     self.path,
                     Ub(InvalidBool(..)) => ValidationErrorKind::InvalidBool {
-                        value: format!("{value:x}"),
+                        value: format!("{scalar:x}"),
                     }
                 );
+                if self.reset_provenance_and_padding {
+                    self.ecx.clear_provenance(value)?;
+                    self.add_data_range_place(value);
+                }
                 Ok(true)
             }
             ty::Char => {
-                let value = self.read_scalar(value, ExpectedKind::Char)?;
+                let scalar = self.read_scalar(value, ExpectedKind::Char)?;
                 try_validation!(
-                    value.to_char(),
+                    scalar.to_char(),
                     self.path,
                     Ub(InvalidChar(..)) => ValidationErrorKind::InvalidChar {
-                        value: format!("{value:x}"),
+                        value: format!("{scalar:x}"),
                     }
                 );
+                if self.reset_provenance_and_padding {
+                    self.ecx.clear_provenance(value)?;
+                    self.add_data_range_place(value);
+                }
                 Ok(true)
             }
             ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
@@ -602,11 +708,14 @@ fn try_visit_primitive(
                         ExpectedKind::Int
                     },
                 )?;
+                if self.reset_provenance_and_padding {
+                    self.ecx.clear_provenance(value)?;
+                    self.add_data_range_place(value);
+                }
                 Ok(true)
             }
             ty::RawPtr(..) => {
-                let place =
-                    self.ecx.ref_to_mplace(&self.read_immediate(value, ExpectedKind::RawPtr)?)?;
+                let place = self.deref_pointer(value, ExpectedKind::RawPtr)?;
                 if place.layout.is_unsized() {
                     self.check_wide_ptr_meta(place.meta(), place.layout)?;
                 }
@@ -617,11 +726,11 @@ fn try_visit_primitive(
                 Ok(true)
             }
             ty::FnPtr(..) => {
-                let value = self.read_scalar(value, ExpectedKind::FnPtr)?;
+                let scalar = self.read_scalar(value, ExpectedKind::FnPtr)?;
 
                 // If we check references recursively, also check that this points to a function.
                 if let Some(_) = self.ref_tracking {
-                    let ptr = value.to_pointer(self.ecx)?;
+                    let ptr = scalar.to_pointer(self.ecx)?;
                     let _fn = try_validation!(
                         self.ecx.get_ptr_fn(ptr),
                         self.path,
@@ -631,10 +740,18 @@ fn try_visit_primitive(
                     // FIXME: Check if the signature matches
                 } else {
                     // Otherwise (for standalone Miri), we have to still check it to be non-null.
-                    if self.ecx.scalar_may_be_null(value)? {
+                    if self.ecx.scalar_may_be_null(scalar)? {
                         throw_validation_failure!(self.path, NullFnPtr);
                     }
                 }
+                if self.reset_provenance_and_padding {
+                    // Make sure we do not preserve partial provenance. This matches the thin
+                    // pointer handling in `deref_pointer`.
+                    if matches!(scalar, Scalar::Int(..)) {
+                        self.ecx.clear_provenance(value)?;
+                    }
+                    self.add_data_range_place(value);
+                }
                 Ok(true)
             }
             ty::Never => throw_validation_failure!(self.path, NeverVal),
@@ -716,13 +833,178 @@ fn visit_scalar(
         }
     }
 
-    fn in_mutable_memory(&self, op: &OpTy<'tcx, M::Provenance>) -> bool {
-        if let Some(mplace) = op.as_mplace_or_imm().left() {
+    fn in_mutable_memory(&self, val: &PlaceTy<'tcx, M::Provenance>) -> bool {
+        if let Some(mplace) = val.as_mplace_or_local().left() {
             if let Some(alloc_id) = mplace.ptr().provenance.and_then(|p| p.get_alloc_id()) {
-                return mutability(self.ecx, alloc_id).is_mut();
+                mutability(self.ecx, alloc_id).is_mut()
+            } else {
+                // No memory at all.
+                false
+            }
+        } else {
+            // A local variable -- definitely mutable.
+            true
+        }
+    }
+
+    /// Add the given pointer-length pair to the "data" range of this visit.
+    fn add_data_range(&mut self, ptr: Pointer<Option<M::Provenance>>, size: Size) {
+        if let Some(data_bytes) = self.data_bytes.as_mut() {
+            // We only have to store the offset, the rest is the same for all pointers here.
+            let (_prov, offset) = ptr.into_parts();
+            // Add this.
+            data_bytes.add_range(offset, size);
+        };
+    }
+
+    /// Add the entire given place to the "data" range of this visit.
+    fn add_data_range_place(&mut self, place: &PlaceTy<'tcx, M::Provenance>) {
+        // Only sized places can be added this way.
+        debug_assert!(place.layout.abi.is_sized());
+        if let Some(data_bytes) = self.data_bytes.as_mut() {
+            let offset = Self::data_range_offset(self.ecx, place);
+            data_bytes.add_range(offset, place.layout.size);
+        }
+    }
+
+    /// Convert a place into the offset it starts at, for the purpose of data_range tracking.
+    /// Must only be called if `data_bytes` is `Some(_)`.
+    fn data_range_offset(ecx: &InterpCx<'tcx, M>, place: &PlaceTy<'tcx, M::Provenance>) -> Size {
+        // The presence of `data_bytes` implies that our place is in memory.
+        let ptr = ecx
+            .place_to_op(place)
+            .expect("place must be in memory")
+            .as_mplace_or_imm()
+            .expect_left("place must be in memory")
+            .ptr();
+        let (_prov, offset) = ptr.into_parts();
+        offset
+    }
+
+    fn reset_padding(&mut self, place: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
+        let Some(data_bytes) = self.data_bytes.as_mut() else { return Ok(()) };
+        // Our value must be in memory, otherwise we would not have set up `data_bytes`.
+        let mplace = self.ecx.force_allocation(place)?;
+        // Determine starting offset and size.
+        let (_prov, start_offset) = mplace.ptr().into_parts();
+        let (size, _align) = self
+            .ecx
+            .size_and_align_of_mplace(&mplace)?
+            .unwrap_or((mplace.layout.size, mplace.layout.align.abi));
+        // If there is no padding at all, we can skip the rest: check for
+        // a single data range covering the entire value.
+        if data_bytes.0 == &[(start_offset, size)] {
+            return Ok(());
+        }
+        // Get a handle for the allocation. Do this only once, to avoid looking up the same
+        // allocation over and over again. (Though to be fair, iterating the value already does
+        // exactly that.)
+        let Some(mut alloc) = self.ecx.get_ptr_alloc_mut(mplace.ptr(), size)? else {
+            // A ZST, no padding to clear.
+            return Ok(());
+        };
+        // Add a "finalizer" data range at the end, so that the iteration below finds all gaps
+        // between ranges.
+        data_bytes.0.push((start_offset + size, Size::ZERO));
+        // Iterate, and reset gaps.
+        let mut padding_cleared_until = start_offset;
+        for &(offset, size) in data_bytes.0.iter() {
+            assert!(
+                offset >= padding_cleared_until,
+                "reset_padding on {}: previous field ended at offset {}, next field starts at {} (and has a size of {} bytes)",
+                mplace.layout.ty,
+                (padding_cleared_until - start_offset).bytes(),
+                (offset - start_offset).bytes(),
+                size.bytes(),
+            );
+            if offset > padding_cleared_until {
+                // We found padding. Adjust the range to be relative to `alloc`, and make it uninit.
+                let padding_start = padding_cleared_until - start_offset;
+                let padding_size = offset - padding_cleared_until;
+                let range = alloc_range(padding_start, padding_size);
+                trace!("reset_padding on {}: resetting padding range {range:?}", mplace.layout.ty);
+                alloc.write_uninit(range)?;
+            }
+            padding_cleared_until = offset + size;
+        }
+        assert!(padding_cleared_until == start_offset + size);
+        Ok(())
+    }
+
+    /// Computes the data range of this union type:
+    /// which bytes are inside a field (i.e., not padding.)
+    fn union_data_range<'e>(
+        ecx: &'e mut InterpCx<'tcx, M>,
+        layout: TyAndLayout<'tcx>,
+    ) -> Cow<'e, RangeSet> {
+        assert!(layout.ty.is_union());
+        assert!(layout.abi.is_sized(), "there are no unsized unions");
+        let layout_cx = LayoutCx { tcx: *ecx.tcx, param_env: ecx.param_env };
+        return M::cached_union_data_range(ecx, layout.ty, || {
+            let mut out = RangeSet(Vec::new());
+            union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out);
+            out
+        });
+
+        /// Helper for recursive traversal: add data ranges of the given type to `out`.
+        fn union_data_range_uncached<'tcx>(
+            cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+            layout: TyAndLayout<'tcx>,
+            base_offset: Size,
+            out: &mut RangeSet,
+        ) {
+            // If this is a ZST, we don't contain any data. In particular, this helps us to quickly
+            // skip over huge arrays of ZST.
+            if layout.is_zst() {
+                return;
+            }
+            // Just recursively add all the fields of everything to the output.
+            match &layout.fields {
+                FieldsShape::Primitive => {
+                    out.add_range(base_offset, layout.size);
+                }
+                &FieldsShape::Union(fields) => {
+                    // Currently, all fields start at offset 0 (relative to `base_offset`).
+                    for field in 0..fields.get() {
+                        let field = layout.field(cx, field);
+                        union_data_range_uncached(cx, field, base_offset, out);
+                    }
+                }
+                &FieldsShape::Array { stride, count } => {
+                    let elem = layout.field(cx, 0);
+
+                    // Fast-path for large arrays of simple types that do not contain any padding.
+                    if elem.abi.is_scalar() {
+                        out.add_range(base_offset, elem.size * count);
+                    } else {
+                        for idx in 0..count {
+                            // This repeats the same computation for every array element... but the alternative
+                            // is to allocate temporary storage for a dedicated `out` set for the array element,
+                            // and replicating that N times. Is that better?
+                            union_data_range_uncached(cx, elem, base_offset + idx * stride, out);
+                        }
+                    }
+                }
+                FieldsShape::Arbitrary { offsets, .. } => {
+                    for (field, &offset) in offsets.iter_enumerated() {
+                        let field = layout.field(cx, field.as_usize());
+                        union_data_range_uncached(cx, field, base_offset + offset, out);
+                    }
+                }
+            }
+            // Don't forget potential other variants.
+            match &layout.variants {
+                Variants::Single { .. } => {
+                    // Fully handled above.
+                }
+                Variants::Multiple { variants, .. } => {
+                    for variant in variants.indices() {
+                        let variant = layout.for_variant(cx, variant);
+                        union_data_range_uncached(cx, variant, base_offset, out);
+                    }
+                }
             }
         }
-        false
     }
 }
 
@@ -774,7 +1056,7 @@ fn mutability<'tcx>(ecx: &InterpCx<'tcx, impl Machine<'tcx>>, alloc_id: AllocId)
 }
 
 impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, 'tcx, M> {
-    type V = OpTy<'tcx, M::Provenance>;
+    type V = PlaceTy<'tcx, M::Provenance>;
 
     #[inline(always)]
     fn ecx(&self) -> &InterpCx<'tcx, M> {
@@ -783,11 +1065,11 @@ fn ecx(&self) -> &InterpCx<'tcx, M> {
 
     fn read_discriminant(
         &mut self,
-        op: &OpTy<'tcx, M::Provenance>,
+        val: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, VariantIdx> {
         self.with_elem(PathElem::EnumTag, move |this| {
             Ok(try_validation!(
-                this.ecx.read_discriminant(op),
+                this.ecx.read_discriminant(val),
                 this.path,
                 Ub(InvalidTag(val)) => InvalidEnumTag {
                     value: format!("{val:x}"),
@@ -802,44 +1084,54 @@ fn read_discriminant(
     #[inline]
     fn visit_field(
         &mut self,
-        old_op: &OpTy<'tcx, M::Provenance>,
+        old_val: &PlaceTy<'tcx, M::Provenance>,
         field: usize,
-        new_op: &OpTy<'tcx, M::Provenance>,
+        new_val: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
-        let elem = self.aggregate_field_path_elem(old_op.layout, field);
-        self.with_elem(elem, move |this| this.visit_value(new_op))
+        let elem = self.aggregate_field_path_elem(old_val.layout, field);
+        self.with_elem(elem, move |this| this.visit_value(new_val))
     }
 
     #[inline]
     fn visit_variant(
         &mut self,
-        old_op: &OpTy<'tcx, M::Provenance>,
+        old_val: &PlaceTy<'tcx, M::Provenance>,
         variant_id: VariantIdx,
-        new_op: &OpTy<'tcx, M::Provenance>,
+        new_val: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
-        let name = match old_op.layout.ty.kind() {
+        let name = match old_val.layout.ty.kind() {
             ty::Adt(adt, _) => PathElem::Variant(adt.variant(variant_id).name),
             // Coroutines also have variants
             ty::Coroutine(..) => PathElem::CoroutineState(variant_id),
-            _ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty),
+            _ => bug!("Unexpected type with variant: {:?}", old_val.layout.ty),
         };
-        self.with_elem(name, move |this| this.visit_value(new_op))
+        self.with_elem(name, move |this| this.visit_value(new_val))
     }
 
     #[inline(always)]
     fn visit_union(
         &mut self,
-        op: &OpTy<'tcx, M::Provenance>,
+        val: &PlaceTy<'tcx, M::Provenance>,
         _fields: NonZero<usize>,
     ) -> InterpResult<'tcx> {
         // Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory.
         if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) {
-            if !op.layout.is_zst() && !op.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) {
-                if !self.in_mutable_memory(op) {
+            if !val.layout.is_zst() && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) {
+                if !self.in_mutable_memory(val) {
                     throw_validation_failure!(self.path, UnsafeCellInImmutable);
                 }
             }
         }
+        if self.reset_provenance_and_padding
+            && let Some(data_bytes) = self.data_bytes.as_mut()
+        {
+            let base_offset = Self::data_range_offset(self.ecx, val);
+            // Determine and add data range for this union.
+            let union_data_range = Self::union_data_range(self.ecx, val.layout);
+            for &(offset, size) in union_data_range.0.iter() {
+                data_bytes.add_range(base_offset + offset, size);
+            }
+        }
         Ok(())
     }
 
@@ -847,39 +1139,41 @@ fn visit_union(
     fn visit_box(
         &mut self,
         _box_ty: Ty<'tcx>,
-        op: &OpTy<'tcx, M::Provenance>,
+        val: &PlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx> {
-        self.check_safe_pointer(op, PointerKind::Box)?;
+        self.check_safe_pointer(val, PointerKind::Box)?;
         Ok(())
     }
 
     #[inline]
-    fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
-        trace!("visit_value: {:?}, {:?}", *op, op.layout);
+    fn visit_value(&mut self, val: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
+        trace!("visit_value: {:?}, {:?}", *val, val.layout);
 
         // Check primitive types -- the leaves of our recursive descent.
+        // This is called even for enum discriminants (which are "fields" of their enum),
+        // so for integer-typed discriminants the provenance reset will happen here.
         // We assume that the Scalar validity range does not restrict these values
         // any further than `try_visit_primitive` does!
-        if self.try_visit_primitive(op)? {
+        if self.try_visit_primitive(val)? {
             return Ok(());
         }
 
         // Special check preventing `UnsafeCell` in the inner part of constants
         if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) {
-            if !op.layout.is_zst()
-                && let Some(def) = op.layout.ty.ty_adt_def()
+            if !val.layout.is_zst()
+                && let Some(def) = val.layout.ty.ty_adt_def()
                 && def.is_unsafe_cell()
             {
-                if !self.in_mutable_memory(op) {
+                if !self.in_mutable_memory(val) {
                     throw_validation_failure!(self.path, UnsafeCellInImmutable);
                 }
             }
         }
 
         // Recursively walk the value at its type. Apply optimizations for some large types.
-        match op.layout.ty.kind() {
+        match val.layout.ty.kind() {
             ty::Str => {
-                let mplace = op.assert_mem_place(); // strings are unsized and hence never immediate
+                let mplace = val.assert_mem_place(); // strings are unsized and hence never immediate
                 let len = mplace.len(self.ecx)?;
                 try_validation!(
                     self.ecx.read_bytes_ptr_strip_provenance(mplace.ptr(), Size::from_bytes(len)),
@@ -889,11 +1183,10 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx>
                 );
             }
             ty::Array(tys, ..) | ty::Slice(tys)
-                // This optimization applies for types that can hold arbitrary bytes (such as
-                // integer and floating point types) or for structs or tuples with no fields.
-                // FIXME(wesleywiser) This logic could be extended further to arbitrary structs
-                // or tuples made up of integer/floating point types or inhabited ZSTs with no
-                // padding.
+                // This optimization applies for types that can hold arbitrary non-provenance bytes (such as
+                // integer and floating point types).
+                // FIXME(wesleywiser) This logic could be extended further to arbitrary structs or
+                // tuples made up of integer/floating point types or inhabited ZSTs with no padding.
                 if matches!(tys.kind(), ty::Int(..) | ty::Uint(..) | ty::Float(..))
                 =>
             {
@@ -901,18 +1194,19 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx>
                 // Optimized handling for arrays of integer/float type.
 
                 // This is the length of the array/slice.
-                let len = op.len(self.ecx)?;
+                let len = val.len(self.ecx)?;
                 // This is the element type size.
                 let layout = self.ecx.layout_of(*tys)?;
                 // This is the size in bytes of the whole array. (This checks for overflow.)
                 let size = layout.size * len;
                 // If the size is 0, there is nothing to check.
-                // (`size` can only be 0 of `len` is 0, and empty arrays are always valid.)
+                // (`size` can only be 0 if `len` is 0, and empty arrays are always valid.)
                 if size == Size::ZERO {
                     return Ok(());
                 }
-                // Now that we definitely have a non-ZST array, we know it lives in memory.
-                let mplace = match op.as_mplace_or_imm() {
+                // Now that we definitely have a non-ZST array, we know it lives in memory -- except it may
+                // be an uninitialized local variable, those are also "immediate".
+                let mplace = match val.to_op(self.ecx)?.as_mplace_or_imm() {
                     Left(mplace) => mplace,
                     Right(imm) => match *imm {
                         Immediate::Uninit =>
@@ -958,20 +1252,30 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx>
                         }
                     }
                 }
+
+                // Don't forget that these are all non-pointer types, and thus do not preserve
+                // provenance.
+                if self.reset_provenance_and_padding {
+                    // We can't share this with above as above, we might be looking at read-only memory.
+                    let mut alloc = self.ecx.get_ptr_alloc_mut(mplace.ptr(), size)?.expect("we already excluded size 0");
+                    alloc.clear_provenance()?;
+                    // Also, mark this as containing data, not padding.
+                    self.add_data_range(mplace.ptr(), size);
+                }
             }
             // Fast path for arrays and slices of ZSTs. We only need to check a single ZST element
             // of an array and not all of them, because there's only a single value of a specific
             // ZST type, so either validation fails for all elements or none.
             ty::Array(tys, ..) | ty::Slice(tys) if self.ecx.layout_of(*tys)?.is_zst() => {
                 // Validate just the first element (if any).
-                if op.len(self.ecx)? > 0 {
-                    self.visit_field(op, 0, &self.ecx.project_index(op, 0)?)?;
+                if val.len(self.ecx)? > 0 {
+                    self.visit_field(val, 0, &self.ecx.project_index(val, 0)?)?;
                 }
             }
             _ => {
                 // default handler
                 try_validation!(
-                    self.walk_value(op),
+                    self.walk_value(val),
                     self.path,
                     // It's not great to catch errors here, since we can't give a very good path,
                     // but it's better than ICEing.
@@ -992,15 +1296,15 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx>
         // FIXME: We could avoid some redundant checks here. For newtypes wrapping
         // scalars, we do the same check on every "level" (e.g., first we check
         // MyNewtype and then the scalar in there).
-        match op.layout.abi {
+        match val.layout.abi {
             Abi::Uninhabited => {
-                let ty = op.layout.ty;
+                let ty = val.layout.ty;
                 throw_validation_failure!(self.path, UninhabitedVal { ty });
             }
             Abi::Scalar(scalar_layout) => {
                 if !scalar_layout.is_uninit_valid() {
                     // There is something to check here.
-                    let scalar = self.read_scalar(op, ExpectedKind::InitScalar)?;
+                    let scalar = self.read_scalar(val, ExpectedKind::InitScalar)?;
                     self.visit_scalar(scalar, scalar_layout)?;
                 }
             }
@@ -1010,7 +1314,7 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx>
                 // the other must be init.
                 if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
                     let (a, b) =
-                        self.read_immediate(op, ExpectedKind::InitScalar)?.to_scalar_pair();
+                        self.read_immediate(val, ExpectedKind::InitScalar)?.to_scalar_pair();
                     self.visit_scalar(a, a_layout)?;
                     self.visit_scalar(b, b_layout)?;
                 }
@@ -1031,19 +1335,34 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx>
 
 impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     fn validate_operand_internal(
-        &self,
-        op: &OpTy<'tcx, M::Provenance>,
+        &mut self,
+        val: &PlaceTy<'tcx, M::Provenance>,
         path: Vec<PathElem>,
         ref_tracking: Option<&mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>>,
         ctfe_mode: Option<CtfeValidationMode>,
+        reset_provenance_and_padding: bool,
     ) -> InterpResult<'tcx> {
-        trace!("validate_operand_internal: {:?}, {:?}", *op, op.layout.ty);
+        trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty);
 
-        // Construct a visitor
-        let mut visitor = ValidityVisitor { path, ref_tracking, ctfe_mode, ecx: self };
-
-        // Run it.
-        match self.run_for_validation(|| visitor.visit_value(op)) {
+        // Run the visitor.
+        match self.run_for_validation(|ecx| {
+            let reset_padding = reset_provenance_and_padding && {
+                // Check if `val` is actually stored in memory. If not, padding is not even
+                // represented and we need not reset it.
+                ecx.place_to_op(val)?.as_mplace_or_imm().is_left()
+            };
+            let mut v = ValidityVisitor {
+                path,
+                ref_tracking,
+                ctfe_mode,
+                ecx,
+                reset_provenance_and_padding,
+                data_bytes: reset_padding.then_some(RangeSet(Vec::new())),
+            };
+            v.visit_value(val)?;
+            v.reset_padding(val)?;
+            InterpResult::Ok(())
+        }) {
             Ok(()) => Ok(()),
             // Pass through validation failures and "invalid program" issues.
             Err(err)
@@ -1079,13 +1398,19 @@ fn validate_operand_internal(
     /// - no `UnsafeCell` or non-ZST `&mut`.
     #[inline(always)]
     pub(crate) fn const_validate_operand(
-        &self,
-        op: &OpTy<'tcx, M::Provenance>,
+        &mut self,
+        val: &PlaceTy<'tcx, M::Provenance>,
         path: Vec<PathElem>,
         ref_tracking: &mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>,
         ctfe_mode: CtfeValidationMode,
     ) -> InterpResult<'tcx> {
-        self.validate_operand_internal(op, path, Some(ref_tracking), Some(ctfe_mode))
+        self.validate_operand_internal(
+            val,
+            path,
+            Some(ref_tracking),
+            Some(ctfe_mode),
+            /*reset_provenance*/ false,
+        )
     }
 
     /// This function checks the data at `op` to be runtime-valid.
@@ -1093,21 +1418,41 @@ pub(crate) fn const_validate_operand(
     /// It will error if the bits at the destination do not match the ones described by the layout.
     #[inline(always)]
     pub fn validate_operand(
-        &self,
-        op: &OpTy<'tcx, M::Provenance>,
+        &mut self,
+        val: &PlaceTy<'tcx, M::Provenance>,
         recursive: bool,
+        reset_provenance_and_padding: bool,
     ) -> InterpResult<'tcx> {
         // Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's
         // still correct to not use `ctfe_mode`: that mode is for validation of the final constant
         // value, it rules out things like `UnsafeCell` in awkward places.
         if !recursive {
-            return self.validate_operand_internal(op, vec![], None, None);
+            return self.validate_operand_internal(
+                val,
+                vec![],
+                None,
+                None,
+                reset_provenance_and_padding,
+            );
         }
         // Do a recursive check.
         let mut ref_tracking = RefTracking::empty();
-        self.validate_operand_internal(op, vec![], Some(&mut ref_tracking), None)?;
+        self.validate_operand_internal(
+            val,
+            vec![],
+            Some(&mut ref_tracking),
+            None,
+            reset_provenance_and_padding,
+        )?;
         while let Some((mplace, path)) = ref_tracking.todo.pop() {
-            self.validate_operand_internal(&mplace.into(), path, Some(&mut ref_tracking), None)?;
+            // Things behind reference do *not* have the provenance reset.
+            self.validate_operand_internal(
+                &mplace.into(),
+                path,
+                Some(&mut ref_tracking),
+                None,
+                /*reset_provenance_and_padding*/ false,
+            )?;
         }
         Ok(())
     }
diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs
index b02f12e..d8af67b 100644
--- a/compiler/rustc_const_eval/src/interpret/visitor.rs
+++ b/compiler/rustc_const_eval/src/interpret/visitor.rs
@@ -5,6 +5,7 @@
 
 use rustc_index::IndexVec;
 use rustc_middle::mir::interpret::InterpResult;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::{FieldIdx, FieldsShape, VariantIdx, Variants};
 use tracing::trace;
@@ -82,6 +83,7 @@ fn visit_variant(
         self.visit_value(new_val)
     }
 
+    /// Traversal logic; should not be overloaded.
     fn walk_value(&mut self, v: &Self::V) -> InterpResult<'tcx> {
         let ty = v.layout().ty;
         trace!("walk_value: type: {ty}");
@@ -104,6 +106,17 @@ fn walk_value(&mut self, v: &Self::V) -> InterpResult<'tcx> {
                 // DynStar types. Very different from a dyn type (but strangely part of the
                 // same variant in `TyKind`): These are pairs where the 2nd component is the
                 // vtable, and the first component is the data (which must be ptr-sized).
+
+                // First make sure the vtable can be read at its type.
+                // The type of this vtable is fake, it claims to be a reference to some actual memory but that isn't true.
+                // So we transmute it to a raw pointer.
+                let raw_ptr_ty = Ty::new_mut_ptr(*self.ecx().tcx, self.ecx().tcx.types.unit);
+                let raw_ptr_ty = self.ecx().layout_of(raw_ptr_ty)?;
+                let vtable_field =
+                    self.ecx().project_field(v, 1)?.transmute(raw_ptr_ty, self.ecx())?;
+                self.visit_field(v, 1, &vtable_field)?;
+
+                // Then unpack the first field, and continue.
                 let data = self.ecx().unpack_dyn_star(v, data)?;
                 return self.visit_field(v, 0, &data);
             }
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index cbd1fde..611a8e1 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -4,7 +4,7 @@
 use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
 
 use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
-use crate::interpret::{InterpCx, MemoryKind, OpTy};
+use crate::interpret::{InterpCx, MemoryKind};
 
 /// Determines if this type permits "raw" initialization by just transmuting some memory into an
 /// instance of `T`.
@@ -32,15 +32,15 @@ pub fn check_validity_requirement<'tcx>(
 
     let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env };
     if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
-        might_permit_raw_init_strict(layout, &layout_cx, kind)
+        check_validity_requirement_strict(layout, &layout_cx, kind)
     } else {
-        might_permit_raw_init_lax(layout, &layout_cx, kind)
+        check_validity_requirement_lax(layout, &layout_cx, kind)
     }
 }
 
-/// Implements the 'strict' version of the `might_permit_raw_init` checks; see that function for
-/// details.
-fn might_permit_raw_init_strict<'tcx>(
+/// Implements the 'strict' version of the [`check_validity_requirement`] checks; see that function
+/// for details.
+fn check_validity_requirement_strict<'tcx>(
     ty: TyAndLayout<'tcx>,
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
     kind: ValidityRequirement,
@@ -61,18 +61,24 @@ fn might_permit_raw_init_strict<'tcx>(
         .expect("failed to write bytes for zero valid check");
     }
 
-    let ot: OpTy<'_, _> = allocated.into();
-
     // Assume that if it failed, it's a validation failure.
     // This does *not* actually check that references are dereferenceable, but since all types that
     // require dereferenceability also require non-null, we don't actually get any false negatives
     // due to this.
-    Ok(cx.validate_operand(&ot, /*recursive*/ false).is_ok())
+    // The value we are validating is temporary and discarded at the end of this function, so
+    // there is no point in reseting provenance and padding.
+    Ok(cx
+        .validate_operand(
+            &allocated.into(),
+            /*recursive*/ false,
+            /*reset_provenance_and_padding*/ false,
+        )
+        .is_ok())
 }
 
-/// Implements the 'lax' (default) version of the `might_permit_raw_init` checks; see that function for
-/// details.
-fn might_permit_raw_init_lax<'tcx>(
+/// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that
+/// function for details.
+fn check_validity_requirement_lax<'tcx>(
     this: TyAndLayout<'tcx>,
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
     init_kind: ValidityRequirement,
@@ -137,7 +143,7 @@ fn might_permit_raw_init_lax<'tcx>(
         }
         FieldsShape::Arbitrary { offsets, .. } => {
             for idx in 0..offsets.len() {
-                if !might_permit_raw_init_lax(this.field(cx, idx), cx, init_kind)? {
+                if !check_validity_requirement_lax(this.field(cx, idx), cx, init_kind)? {
                     // We found a field that is unhappy with this kind of initialization.
                     return Ok(false);
                 }
diff --git a/compiler/rustc_data_structures/src/steal.rs b/compiler/rustc_data_structures/src/steal.rs
index 0f2c0ee..aaa95f6 100644
--- a/compiler/rustc_data_structures/src/steal.rs
+++ b/compiler/rustc_data_structures/src/steal.rs
@@ -57,6 +57,7 @@ pub fn steal(&self) -> T {
     ///
     /// This should not be used within rustc as it leaks information not tracked
     /// by the query system, breaking incremental compilation.
+    #[cfg_attr(not(bootstrap), rustc_lint_untracked_query_information)]
     pub fn is_stolen(&self) -> bool {
         self.value.borrow().is_none()
     }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index cb2fa6e..1b7ca61 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -7,7 +7,6 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
 #![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
-#![cfg_attr(bootstrap, feature(unsafe_extern_blocks))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(decl_macro)]
@@ -862,9 +861,9 @@ fn print_crate_info(
                 use rustc_target::spec::current_apple_deployment_target;
 
                 if sess.target.is_like_osx {
-                    let (major, minor) = current_apple_deployment_target(&sess.target)
-                        .expect("unknown Apple target OS");
-                    println_info!("deployment_target={}", format!("{major}.{minor}"))
+                    let (major, minor, patch) = current_apple_deployment_target(&sess.target);
+                    let patch = if patch != 0 { format!(".{patch}") } else { String::new() };
+                    println_info!("deployment_target={major}.{minor}{patch}")
                 } else {
                     #[allow(rustc::diagnostic_outside_of_impl)]
                     sess.dcx().fatal("only Apple targets currently support deployment version info")
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 9011d02..501a241 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -398,8 +398,10 @@ pub(crate) enum NamedMatch {
 fn token_name_eq(t1: &Token, t2: &Token) -> bool {
     if let (Some((ident1, is_raw1)), Some((ident2, is_raw2))) = (t1.ident(), t2.ident()) {
         ident1.name == ident2.name && is_raw1 == is_raw2
-    } else if let (Some(ident1), Some(ident2)) = (t1.lifetime(), t2.lifetime()) {
-        ident1.name == ident2.name
+    } else if let (Some((ident1, is_raw1)), Some((ident2, is_raw2))) =
+        (t1.lifetime(), t2.lifetime())
+    {
+        ident1.name == ident2.name && is_raw1 == is_raw2
     } else {
         t1.kind == t2.kind
     }
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index b069105..39489a8 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -283,9 +283,9 @@ pub(super) fn transcribe<'a>(
                             let kind = token::NtIdent(*ident, *is_raw);
                             TokenTree::token_alone(kind, sp)
                         }
-                        MatchedSingle(ParseNtResult::Lifetime(ident)) => {
+                        MatchedSingle(ParseNtResult::Lifetime(ident, is_raw)) => {
                             marker.visit_span(&mut sp);
-                            let kind = token::NtLifetime(*ident);
+                            let kind = token::NtLifetime(*ident, *is_raw);
                             TokenTree::token_alone(kind, sp)
                         }
                         MatchedSingle(ParseNtResult::Nt(nt)) => {
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 4ff5da1..5798bce 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -229,15 +229,16 @@ fn from_internal((stream, rustc): (TokenStream, &mut Rustc<'_, '_>)) -> Self {
                     span: ident.span,
                 })),
 
-                Lifetime(name) => {
+                Lifetime(name, is_raw) => {
                     let ident = symbol::Ident::new(name, span).without_first_quote();
                     trees.extend([
                         TokenTree::Punct(Punct { ch: b'\'', joint: true, span }),
-                        TokenTree::Ident(Ident { sym: ident.name, is_raw: false, span }),
+                        TokenTree::Ident(Ident { sym: ident.name, is_raw: is_raw.into(), span }),
                     ]);
                 }
-                NtLifetime(ident) => {
-                    let stream = TokenStream::token_alone(token::Lifetime(ident.name), ident.span);
+                NtLifetime(ident, is_raw) => {
+                    let stream =
+                        TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span);
                     trees.push(TokenTree::Group(Group {
                         delimiter: pm::Delimiter::None,
                         stream: Some(stream),
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 9223c3c..8949fdf 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -61,7 +61,7 @@ macro_rules! declare_features {
     /// Allows explicit discriminants on non-unit enum variants.
     (accepted, arbitrary_enum_discriminant, "1.66.0", Some(60553)),
     /// Allows using `const` operands in inline assembly.
-    (accepted, asm_const, "CURRENT_RUSTC_VERSION", Some(93332)),
+    (accepted, asm_const, "1.82.0", Some(93332)),
     /// Allows using `sym` operands in inline assembly.
     (accepted, asm_sym, "1.66.0", Some(93333)),
     /// Allows the definition of associated constants in `trait` or `impl` blocks.
@@ -116,7 +116,7 @@ macro_rules! declare_features {
     /// Allows calling constructor functions in `const fn`.
     (accepted, const_constructor, "1.40.0", Some(61456)),
     /// Allows basic arithmetic on floating point types in a `const fn`.
-    (accepted, const_fn_floating_point_arithmetic, "CURRENT_RUSTC_VERSION", Some(57241)),
+    (accepted, const_fn_floating_point_arithmetic, "1.82.0", Some(57241)),
     /// Allows using and casting function pointers in a `const fn`.
     (accepted, const_fn_fn_ptr_basics, "1.61.0", Some(57563)),
     /// Allows trait bounds in `const fn`.
@@ -272,7 +272,7 @@ macro_rules! declare_features {
     /// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions.
     (accepted, min_const_unsafe_fn, "1.33.0", Some(55607)),
     /// Allows exhaustive pattern matching on uninhabited types when matched by value.
-    (accepted, min_exhaustive_patterns, "CURRENT_RUSTC_VERSION", Some(119612)),
+    (accepted, min_exhaustive_patterns, "1.82.0", Some(119612)),
     /// Allows using `Self` and associated types in struct expressions and patterns.
     (accepted, more_struct_aliases, "1.16.0", Some(37544)),
     /// Allows using the MOVBE target feature.
@@ -299,7 +299,7 @@ macro_rules! declare_features {
     /// Allows `foo.rs` as an alternative to `foo/mod.rs`.
     (accepted, non_modrs_mods, "1.30.0", Some(44660)),
     /// Allows using multiple nested field accesses in offset_of!
-    (accepted, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(120140)),
+    (accepted, offset_of_nested, "1.82.0", Some(120140)),
     /// Allows the use of or-patterns (e.g., `0 | 1`).
     (accepted, or_patterns, "1.53.0", Some(54883)),
     /// Allows using `+bundle,+whole-archive` link modifiers with native libs.
@@ -312,7 +312,7 @@ macro_rules! declare_features {
     /// Allows parentheses in patterns.
     (accepted, pattern_parentheses, "1.31.0", Some(51087)),
     /// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.
-    (accepted, precise_capturing, "CURRENT_RUSTC_VERSION", Some(123432)),
+    (accepted, precise_capturing, "1.82.0", Some(123432)),
     /// Allows procedural macros in `proc-macro` crates.
     (accepted, proc_macro, "1.29.0", Some(38356)),
     /// Allows multi-segment paths in attributes and derives.
@@ -326,7 +326,7 @@ macro_rules! declare_features {
     /// Allows keywords to be escaped for use as identifiers.
     (accepted, raw_identifiers, "1.30.0", Some(48589)),
     /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
-    (accepted, raw_ref_op, "CURRENT_RUSTC_VERSION", Some(64490)),
+    (accepted, raw_ref_op, "1.82.0", Some(64490)),
     /// Allows relaxing the coherence rules such that
     /// `impl<T> ForeignTrait<LocalType> for ForeignType<T>` is permitted.
     (accepted, re_rebalance_coherence, "1.41.0", Some(55437)),
@@ -399,11 +399,11 @@ macro_rules! declare_features {
     /// Allows arbitrary delimited token streams in non-macro attributes.
     (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208)),
     /// Allows unsafe attributes.
-    (accepted, unsafe_attributes, "CURRENT_RUSTC_VERSION", Some(123757)),
+    (accepted, unsafe_attributes, "1.82.0", Some(123757)),
     /// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block.
     (accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668)),
     /// Allows unsafe on extern declarations and safety qualifiers over internal items.
-    (accepted, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)),
+    (accepted, unsafe_extern_blocks, "1.82.0", Some(123743)),
     /// Allows importing and reexporting macros with `use`,
     /// enables macro modularization in general.
     (accepted, use_extern_macros, "1.30.0", Some(35896)),
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index e249192..3b7e0d8 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -793,6 +793,12 @@ pub struct BuiltinAttribute {
         rustc_lint_query_instability, Normal, template!(Word),
         WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
     ),
+    // Used by the `rustc::untracked_query_information` lint to warn methods which
+    // might not be stable during incremental compilation.
+    rustc_attr!(
+        rustc_lint_untracked_query_information, Normal, template!(Word),
+        WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
+    ),
     // Used by the `rustc::diagnostic_outside_of_impl` lints to assist in changes to diagnostic
     // APIs. Any function with this attribute will be checked by that lint.
     rustc_attr!(
@@ -1180,3 +1186,11 @@ pub fn is_valid_for_get_attr(name: Symbol) -> bool {
         }
         map
     });
+
+pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool {
+    match sym {
+        sym::on_unimplemented => true,
+        sym::do_not_recommend => features.do_not_recommend,
+        _ => false,
+    }
+}
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index adaaba3..fe12930 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -130,8 +130,9 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u
 pub use accepted::ACCEPTED_FEATURES;
 pub use builtin_attrs::{
     deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name,
-    is_valid_for_get_attr, AttributeDuplicates, AttributeGate, AttributeSafety, AttributeTemplate,
-    AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
+    is_stable_diagnostic_attribute, is_valid_for_get_attr, AttributeDuplicates, AttributeGate,
+    AttributeSafety, AttributeTemplate, AttributeType, BuiltinAttribute, GatedCfg,
+    BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
 };
 pub use removed::REMOVED_FEATURES;
 pub use unstable::{Features, INCOMPATIBLE_FEATURES, UNSTABLE_FEATURES};
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index b7f0ed5..3d7d877 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -83,7 +83,7 @@ macro_rules! declare_features {
     (removed, custom_derive, "1.32.0", Some(29644),
      Some("subsumed by `#[proc_macro_derive]`")),
     /// Allows default type parameters to influence type inference.
-    (removed, default_type_parameter_fallback, "CURRENT_RUSTC_VERSION", Some(27336),
+    (removed, default_type_parameter_fallback, "1.82.0", Some(27336),
      Some("never properly implemented; requires significant design work")),
     /// Allows using `#[doc(keyword = "...")]`.
     (removed, doc_keyword, "1.28.0", Some(51315),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index fba6588..3254dab 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -208,7 +208,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     /// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
     (unstable, link_cfg, "1.14.0", None),
     /// Allows using `?Trait` trait bounds in more contexts.
-    (internal, more_maybe_bounds, "CURRENT_RUSTC_VERSION", None),
+    (internal, more_maybe_bounds, "1.82.0", None),
     /// Allows the `multiple_supertrait_upcastable` lint.
     (unstable, multiple_supertrait_upcastable, "1.69.0", None),
     /// Allow negative trait bounds. This is an internal-only feature for testing the trait solver!
@@ -302,7 +302,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     // FIXME: Document these and merge with the list below.
 
     // Unstable `#[target_feature]` directives.
-    (unstable, aarch64_unstable_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)),
+    (unstable, aarch64_unstable_target_feature, "1.82.0", Some(44839)),
     (unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)),
     (unstable, arm_target_feature, "1.27.0", Some(44839)),
     (unstable, avx512_target_feature, "1.27.0", Some(44839)),
@@ -317,7 +317,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     (unstable, prfchw_target_feature, "1.78.0", Some(44839)),
     (unstable, riscv_target_feature, "1.45.0", Some(44839)),
     (unstable, rtm_target_feature, "1.35.0", Some(44839)),
-    (unstable, s390x_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)),
+    (unstable, s390x_target_feature, "1.82.0", Some(44839)),
     (unstable, sse4a_target_feature, "1.27.0", Some(44839)),
     (unstable, tbm_target_feature, "1.27.0", Some(44839)),
     (unstable, wasm_target_feature, "1.30.0", Some(44839)),
@@ -474,7 +474,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     /// Allows the use of `#[ffi_pure]` on foreign functions.
     (unstable, ffi_pure, "1.45.0", Some(58329)),
     /// Controlling the behavior of fmt::Debug
-    (unstable, fmt_debug, "CURRENT_RUSTC_VERSION", Some(129709)),
+    (unstable, fmt_debug, "1.82.0", Some(129709)),
     /// Allows using `#[repr(align(...))]` on function items
     (unstable, fn_align, "1.53.0", Some(82232)),
     /// Support delegating implementation of functions to other already implemented functions.
@@ -586,8 +586,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
     /// Allows `extern "rust-cold"`.
     (unstable, rust_cold_cc, "1.63.0", Some(97544)),
     /// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics
-    (unstable, sha512_sm_x86, "CURRENT_RUSTC_VERSION", Some(126624)),
-    /// Shorten the tail expression lifetime
+    (unstable, sha512_sm_x86, "1.82.0", Some(126624)),
+    /// Shortern the tail expression lifetime
     (unstable, shorter_tail_lifetimes, "1.79.0", Some(123739)),
     /// Allows the use of SIMD types in functions declared in `extern` blocks.
     (unstable, simd_ffi, "1.0.0", Some(27731)),
@@ -625,7 +625,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
     (incomplete, unnamed_fields, "1.74.0", Some(49804)),
     /// Allows const generic parameters to be defined with types that
     /// are not `Sized`, e.g. `fn foo<const N: [u8]>() {`.
-    (incomplete, unsized_const_params, "CURRENT_RUSTC_VERSION", Some(95174)),
+    (incomplete, unsized_const_params, "1.82.0", Some(95174)),
     /// Allows unsized fn parameters.
     (internal, unsized_fn_params, "1.49.0", Some(48055)),
     /// Allows unsized rvalues at arguments and parameters.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 57c47d2..b01c24c 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -168,6 +168,19 @@ pub fn suggestion_position(&self) -> (LifetimeSuggestionPosition, Span) {
             (LifetimeSuggestionPosition::Normal, self.ident.span)
         }
     }
+
+    pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) {
+        debug_assert!(new_lifetime.starts_with('\''));
+        let (pos, span) = self.suggestion_position();
+        let code = match pos {
+            LifetimeSuggestionPosition::Normal => format!("{new_lifetime}"),
+            LifetimeSuggestionPosition::Ampersand => format!("{new_lifetime} "),
+            LifetimeSuggestionPosition::ElidedPath => format!("<{new_lifetime}>"),
+            LifetimeSuggestionPosition::ElidedPathArgument => format!("{new_lifetime}, "),
+            LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lifetime}"),
+        };
+        (span, code)
+    }
 }
 
 /// A `Path` is essentially Rust's notion of a name; for instance,
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index bd8b43e..9fce927 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -93,7 +93,8 @@ fn check_def_id(
                 }
             }
 
-            if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) {
+            if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer)
+            {
                 self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
             } else {
                 bug!("unexpected self type: {:?}", self_ty);
@@ -132,7 +133,7 @@ fn check_primitive_impl(
             }
         }
 
-        if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsCandidateKey) {
+        if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::InstantiateWithInfer) {
             self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
         } else {
             bug!("unexpected primitive type: {:?}", ty);
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 9211180..ac99761 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -1698,8 +1698,6 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
             trait_ref: ty::EarlyBinder::bind(trait_ref),
             safety: impl_.safety,
             polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
-            do_not_recommend: tcx.features().do_not_recommend
-                && tcx.has_attrs_with_path(def_id, &[sym::diagnostic, sym::do_not_recommend]),
         }
     })
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index be6c3f0..ba01ea3f 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -59,6 +59,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
     let hir_id = tcx.local_def_id_to_hir_id(def_id);
 
     let node = tcx.hir_node(hir_id);
+    if let Some(sig) = node.fn_sig()
+        && let Some(sig_id) = sig.decl.opt_delegation_sig_id()
+    {
+        return inherit_generics_for_delegation_item(tcx, def_id, sig_id);
+    }
+
     let parent_def_id = match node {
         Node::ImplItem(_)
         | Node::TraitItem(_)
@@ -229,16 +235,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                 // inherit the generics of the item.
                 Some(parent.to_def_id())
             }
-            ItemKind::Fn(sig, _, _) => {
-                // For a delegation item inherit generics from callee.
-                if let Some(sig_id) = sig.decl.opt_delegation_sig_id()
-                    && let Some(generics) =
-                        inherit_generics_for_delegation_item(tcx, def_id, sig_id)
-                {
-                    return generics;
-                }
-                None
-            }
             _ => None,
         },
         _ => None,
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index a47aaf2..7243e85 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -138,6 +138,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     let hir_id = tcx.local_def_id_to_hir_id(def_id);
     let node = tcx.hir_node(hir_id);
 
+    if let Some(sig) = node.fn_sig()
+        && let Some(sig_id) = sig.decl.opt_delegation_sig_id()
+    {
+        return inherit_predicates_for_delegation_item(tcx, def_id, sig_id);
+    }
+
     let mut is_trait = None;
     let mut is_default_impl_trait = None;
 
@@ -164,16 +170,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
             ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => {
                 is_trait = Some(self_bounds);
             }
-
-            ItemKind::Fn(sig, _, _) => {
-                // For a delegation item inherit predicates from callee.
-                if let Some(sig_id) = sig.decl.opt_delegation_sig_id()
-                    && let Some(predicates) =
-                        inherit_predicates_for_delegation_item(tcx, def_id, sig_id)
-                {
-                    return predicates;
-                }
-            }
             _ => {}
         }
     };
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index fe46eb5..b4cbd1f 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1191,23 +1191,7 @@ fn resolve_lifetime_ref(
                                     (generics.span, "<'a>".to_owned())
                                 };
 
-                            let lifetime_sugg = match lifetime_ref.suggestion_position() {
-                                (hir::LifetimeSuggestionPosition::Normal, span) => {
-                                    (span, "'a".to_owned())
-                                }
-                                (hir::LifetimeSuggestionPosition::Ampersand, span) => {
-                                    (span, "'a ".to_owned())
-                                }
-                                (hir::LifetimeSuggestionPosition::ElidedPath, span) => {
-                                    (span, "<'a>".to_owned())
-                                }
-                                (hir::LifetimeSuggestionPosition::ElidedPathArgument, span) => {
-                                    (span, "'a, ".to_owned())
-                                }
-                                (hir::LifetimeSuggestionPosition::ObjectDefault, span) => {
-                                    (span, "+ 'a".to_owned())
-                                }
-                            };
+                            let lifetime_sugg = lifetime_ref.suggestion("'a");
                             let suggestions = vec![lifetime_sugg, new_param_sugg];
 
                             diag.span_label(
diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs
index 20aaa43..2c9f20b 100644
--- a/compiler/rustc_hir_analysis/src/delegation.rs
+++ b/compiler/rustc_hir_analysis/src/delegation.rs
@@ -1,3 +1,7 @@
+//! Support inheriting generic parameters and predicates for function delegation.
+//!
+//! For more information about delegation design, see the tracking issue #118212.
+
 use std::assert_matches::debug_assert_matches;
 
 use rustc_data_structures::fx::FxHashMap;
@@ -5,7 +9,7 @@
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_span::ErrorGuaranteed;
+use rustc_span::{ErrorGuaranteed, Span};
 use rustc_type_ir::visit::TypeVisitableExt;
 
 type RemapTable = FxHashMap<u32, u32>;
@@ -76,127 +80,381 @@ fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind {
     }
 }
 
+/// Given the current context(caller and callee `FnKind`), it specifies
+/// the policy of predicates and generic parameters inheritance.
+#[derive(Clone, Copy, Debug, PartialEq)]
+enum InheritanceKind {
+    /// Copying all predicates and parameters, including those of the parent
+    /// container.
+    ///
+    /// Boolean value defines whether the `Self` parameter or `Self: Trait`
+    /// predicate are copied. It's always equal to `false` except when
+    /// delegating from a free function to a trait method.
+    ///
+    /// FIXME(fn_delegation): This often leads to type inference
+    /// errors. Support providing generic arguments or restrict use sites.
+    WithParent(bool),
+    /// The trait implementation should be compatible with the original trait.
+    /// Therefore, for trait implementations only the method's own parameters
+    /// and predicates are copied.
+    Own,
+}
+
+struct GenericsBuilder<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    sig_id: DefId,
+    parent: Option<DefId>,
+    inh_kind: InheritanceKind,
+}
+
+impl<'tcx> GenericsBuilder<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>, sig_id: DefId) -> GenericsBuilder<'tcx> {
+        GenericsBuilder { tcx, sig_id, parent: None, inh_kind: InheritanceKind::WithParent(false) }
+    }
+
+    fn with_parent(mut self, parent: DefId) -> Self {
+        self.parent = Some(parent);
+        self
+    }
+
+    fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self {
+        self.inh_kind = inh_kind;
+        self
+    }
+
+    fn build(self) -> ty::Generics {
+        let mut own_params = vec![];
+
+        let sig_generics = self.tcx.generics_of(self.sig_id);
+        if let InheritanceKind::WithParent(has_self) = self.inh_kind
+            && let Some(parent_def_id) = sig_generics.parent
+        {
+            let sig_parent_generics = self.tcx.generics_of(parent_def_id);
+            own_params.append(&mut sig_parent_generics.own_params.clone());
+            if !has_self {
+                own_params.remove(0);
+            }
+        }
+        own_params.append(&mut sig_generics.own_params.clone());
+
+        // Lifetime parameters must be declared before type and const parameters.
+        // Therefore, When delegating from a free function to a associated function,
+        // generic parameters need to be reordered:
+        //
+        // trait Trait<'a, A> {
+        //     fn foo<'b, B>(...) {...}
+        // }
+        //
+        // reuse Trait::foo;
+        // desugaring:
+        // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
+        //     Trait::foo(...)
+        // }
+        own_params.sort_by_key(|key| key.kind.is_ty_or_const());
+
+        let param_def_id_to_index =
+            own_params.iter().map(|param| (param.def_id, param.index)).collect();
+
+        let (parent_count, has_self) = if let Some(def_id) = self.parent {
+            let parent_generics = self.tcx.generics_of(def_id);
+            let parent_kind = self.tcx.def_kind(def_id);
+            (parent_generics.count(), parent_kind == DefKind::Trait)
+        } else {
+            (0, false)
+        };
+
+        for (idx, param) in own_params.iter_mut().enumerate() {
+            param.index = (idx + parent_count) as u32;
+            // FIXME(fn_delegation): Default parameters are not inherited, because they are
+            // not permitted in functions. Therefore, there are 2 options here:
+            //
+            // - We can create non-default generic parameters.
+            // - We can substitute default parameters into the signature.
+            //
+            // At the moment, first option has been selected as the most general.
+            if let ty::GenericParamDefKind::Type { has_default, .. }
+            | ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
+            {
+                *has_default = false;
+            }
+        }
+
+        ty::Generics {
+            parent: self.parent,
+            parent_count,
+            own_params,
+            param_def_id_to_index,
+            has_self,
+            has_late_bound_regions: sig_generics.has_late_bound_regions,
+            host_effect_index: sig_generics.host_effect_index,
+        }
+    }
+}
+
+struct PredicatesBuilder<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    sig_id: DefId,
+    parent: Option<DefId>,
+    inh_kind: InheritanceKind,
+    args: ty::GenericArgsRef<'tcx>,
+}
+
+impl<'tcx> PredicatesBuilder<'tcx> {
+    fn new(
+        tcx: TyCtxt<'tcx>,
+        args: ty::GenericArgsRef<'tcx>,
+        sig_id: DefId,
+    ) -> PredicatesBuilder<'tcx> {
+        PredicatesBuilder {
+            tcx,
+            sig_id,
+            parent: None,
+            inh_kind: InheritanceKind::WithParent(false),
+            args,
+        }
+    }
+
+    fn with_parent(mut self, parent: DefId) -> Self {
+        self.parent = Some(parent);
+        self
+    }
+
+    fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self {
+        self.inh_kind = inh_kind;
+        self
+    }
+
+    fn build(self) -> ty::GenericPredicates<'tcx> {
+        struct PredicatesCollector<'tcx> {
+            tcx: TyCtxt<'tcx>,
+            preds: Vec<(ty::Clause<'tcx>, Span)>,
+            args: ty::GenericArgsRef<'tcx>,
+        }
+
+        impl<'tcx> PredicatesCollector<'tcx> {
+            fn new(tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> PredicatesCollector<'tcx> {
+                PredicatesCollector { tcx, preds: vec![], args }
+            }
+
+            fn with_own_preds(
+                mut self,
+                f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>,
+                def_id: DefId,
+            ) -> Self {
+                let preds = f(def_id).instantiate_own(self.tcx, self.args);
+                self.preds.extend(preds);
+                self
+            }
+
+            fn with_preds(
+                mut self,
+                f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy,
+                def_id: DefId,
+            ) -> Self {
+                let preds = f(def_id);
+                if let Some(parent_def_id) = preds.parent {
+                    self = self.with_own_preds(f, parent_def_id);
+                }
+                self.with_own_preds(f, def_id)
+            }
+        }
+        let collector = PredicatesCollector::new(self.tcx, self.args);
+
+        // `explicit_predicates_of` is used here to avoid copying `Self: Trait` predicate.
+        // Note: `predicates_of` query can also add inferred outlives predicates, but that
+        // is not the case here as `sig_id` is either a trait or a function.
+        let preds = match self.inh_kind {
+            InheritanceKind::WithParent(false) => {
+                collector.with_preds(|def_id| self.tcx.explicit_predicates_of(def_id), self.sig_id)
+            }
+            InheritanceKind::WithParent(true) => {
+                collector.with_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id)
+            }
+            InheritanceKind::Own => {
+                collector.with_own_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id)
+            }
+        }
+        .preds;
+
+        ty::GenericPredicates {
+            parent: self.parent,
+            predicates: self.tcx.arena.alloc_from_iter(preds),
+            // FIXME(fn_delegation): Support effects.
+            effects_min_tys: ty::List::empty(),
+        }
+    }
+}
+
+struct GenericArgsBuilder<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    remap_table: RemapTable,
+    sig_id: DefId,
+    def_id: LocalDefId,
+}
+
+impl<'tcx> GenericArgsBuilder<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>, sig_id: DefId, def_id: LocalDefId) -> GenericArgsBuilder<'tcx> {
+        GenericArgsBuilder { tcx, remap_table: FxHashMap::default(), sig_id, def_id }
+    }
+
+    fn build_from_args(mut self, args: ty::GenericArgsRef<'tcx>) -> ty::GenericArgsRef<'tcx> {
+        let caller_generics = self.tcx.generics_of(self.def_id);
+        let callee_generics = self.tcx.generics_of(self.sig_id);
+
+        for caller_param in &caller_generics.own_params {
+            let callee_index =
+                callee_generics.param_def_id_to_index(self.tcx, caller_param.def_id).unwrap();
+            self.remap_table.insert(callee_index, caller_param.index);
+        }
+
+        let mut folder = ParamIndexRemapper { tcx: self.tcx, remap_table: self.remap_table };
+        args.fold_with(&mut folder)
+    }
+}
+
 fn create_generic_args<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
     sig_id: DefId,
 ) -> ty::GenericArgsRef<'tcx> {
-    let caller_generics = tcx.generics_of(def_id);
-    let callee_generics = tcx.generics_of(sig_id);
+    let builder = GenericArgsBuilder::new(tcx, sig_id, def_id);
 
     let caller_kind = fn_kind(tcx, def_id.into());
     let callee_kind = fn_kind(tcx, sig_id);
-    // FIXME(fn_delegation): Support generics on associated delegation items.
-    // Error will be reported in `check_constraints`.
     match (caller_kind, callee_kind) {
-        (FnKind::Free, _) => {
-            // Lifetime parameters must be declared before type and const parameters.
-            // Therefore, When delegating from a free function to a associated function,
-            // generic parameters need to be reordered:
-            //
-            // trait Trait<'a, A> {
-            //     fn foo<'b, B>(...) {...}
-            // }
-            //
-            // reuse Trait::foo;
-            // desugaring:
-            // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
-            //     Trait::foo(...)
-            // }
-            let mut remap_table = RemapTable::default();
-            for caller_param in &caller_generics.own_params {
-                let callee_index =
-                    callee_generics.param_def_id_to_index(tcx, caller_param.def_id).unwrap();
-                remap_table.insert(callee_index, caller_param.index);
-            }
-            let mut folder = ParamIndexRemapper { tcx, remap_table };
-            ty::GenericArgs::identity_for_item(tcx, sig_id).fold_with(&mut folder)
+        (FnKind::Free, FnKind::Free)
+        | (FnKind::Free, FnKind::AssocTrait)
+        | (FnKind::AssocInherentImpl, FnKind::Free)
+        | (FnKind::AssocTrait, FnKind::Free)
+        | (FnKind::AssocTrait, FnKind::AssocTrait) => {
+            let args = ty::GenericArgs::identity_for_item(tcx, sig_id);
+            builder.build_from_args(args)
         }
-        // FIXME(fn_delegation): Only `Self` param supported here.
-        (FnKind::AssocTraitImpl, FnKind::AssocTrait)
-        | (FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
+
+        (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
+            let callee_generics = tcx.generics_of(sig_id);
+            let parent = tcx.parent(def_id.into());
+            let parent_args =
+                tcx.impl_trait_header(parent).unwrap().trait_ref.instantiate_identity().args;
+
+            let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
+            let method_args = tcx.mk_args_from_iter(trait_args.iter().skip(callee_generics.parent_count));
+            let method_args = builder.build_from_args(method_args);
+
+            tcx.mk_args_from_iter(parent_args.iter().chain(method_args))
+        }
+
+        (FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
             let parent = tcx.parent(def_id.into());
             let self_ty = tcx.type_of(parent).instantiate_identity();
             let generic_self_ty = ty::GenericArg::from(self_ty);
-            tcx.mk_args_from_iter(std::iter::once(generic_self_ty))
+
+            let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
+            let trait_args = builder.build_from_args(trait_args);
+
+            let args = std::iter::once(generic_self_ty).chain(trait_args.iter().skip(1));
+            tcx.mk_args_from_iter(args)
         }
-        _ => ty::GenericArgs::identity_for_item(tcx, sig_id),
+
+        // For trait impl's `sig_id` is always equal to the corresponding trait method.
+        (FnKind::AssocTraitImpl, _)
+        | (_, FnKind::AssocTraitImpl)
+        // Delegation to inherent methods is not yet supported.
+        | (_, FnKind::AssocInherentImpl) => unreachable!(),
     }
 }
 
+// FIXME(fn_delegation): Move generics inheritance to the AST->HIR lowering.
+// For now, generic parameters are not propagated to the generated call,
+// which leads to inference errors:
+//
+// fn foo<T>(x: i32) {}
+//
+// reuse foo as bar;
+// desugaring:
+// fn bar<T>() {
+//   foo::<_>() // ERROR: type annotations needed
+// }
 pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
     sig_id: DefId,
-) -> Option<ty::Generics> {
-    // FIXME(fn_delegation): Support generics on associated delegation items.
-    // Error will be reported in `check_constraints`.
-    if fn_kind(tcx, def_id.into()) != FnKind::Free {
-        return None;
-    }
+) -> ty::Generics {
+    let builder = GenericsBuilder::new(tcx, sig_id);
 
-    let mut own_params = vec![];
+    let caller_kind = fn_kind(tcx, def_id.into());
+    let callee_kind = fn_kind(tcx, sig_id);
+    match (caller_kind, callee_kind) {
+        (FnKind::Free, FnKind::Free)
+        | (FnKind::Free, FnKind::AssocTrait) => builder.with_inheritance_kind(InheritanceKind::WithParent(true)).build(),
 
-    let callee_generics = tcx.generics_of(sig_id);
-    if let Some(parent_sig_id) = callee_generics.parent {
-        let parent_sig_generics = tcx.generics_of(parent_sig_id);
-        own_params.append(&mut parent_sig_generics.own_params.clone());
-    }
-    own_params.append(&mut callee_generics.own_params.clone());
-
-    // Lifetimes go first.
-    own_params.sort_by_key(|key| key.kind.is_ty_or_const());
-
-    for (idx, param) in own_params.iter_mut().enumerate() {
-        param.index = idx as u32;
-        // Default parameters are not inherited: they are not allowed
-        // in fn's.
-        if let ty::GenericParamDefKind::Type { has_default, .. }
-        | ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
-        {
-            *has_default = false;
+        (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
+            builder
+            .with_parent(tcx.parent(def_id.into()))
+            .with_inheritance_kind(InheritanceKind::Own)
+            .build()
         }
+
+        (FnKind::AssocInherentImpl, FnKind::AssocTrait)
+        | (FnKind::AssocTrait, FnKind::AssocTrait) => {
+            builder
+            .with_parent(tcx.parent(def_id.into()))
+            .build()
+        }
+
+        (FnKind::AssocInherentImpl, FnKind::Free)
+        | (FnKind::AssocTrait, FnKind::Free) => {
+            builder
+            .with_parent(tcx.parent(def_id.into()))
+            .build()
+        }
+
+        // For trait impl's `sig_id` is always equal to the corresponding trait method.
+        (FnKind::AssocTraitImpl, _)
+        | (_, FnKind::AssocTraitImpl)
+        // Delegation to inherent methods is not yet supported.
+        | (_, FnKind::AssocInherentImpl) => unreachable!(),
     }
-
-    let param_def_id_to_index =
-        own_params.iter().map(|param| (param.def_id, param.index)).collect();
-
-    Some(ty::Generics {
-        parent: None,
-        parent_count: 0,
-        own_params,
-        param_def_id_to_index,
-        has_self: false,
-        has_late_bound_regions: callee_generics.has_late_bound_regions,
-        host_effect_index: callee_generics.host_effect_index,
-    })
 }
 
 pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
     sig_id: DefId,
-) -> Option<ty::GenericPredicates<'tcx>> {
-    // FIXME(fn_delegation): Support generics on associated delegation items.
-    // Error will be reported in `check_constraints`.
-    if fn_kind(tcx, def_id.into()) != FnKind::Free {
-        return None;
-    }
-
-    let callee_predicates = tcx.predicates_of(sig_id);
+) -> ty::GenericPredicates<'tcx> {
     let args = create_generic_args(tcx, def_id, sig_id);
+    let builder = PredicatesBuilder::new(tcx, args, sig_id);
 
-    let mut preds = vec![];
-    if let Some(parent_id) = callee_predicates.parent {
-        preds.extend(tcx.predicates_of(parent_id).instantiate_own(tcx, args));
+    let caller_kind = fn_kind(tcx, def_id.into());
+    let callee_kind = fn_kind(tcx, sig_id);
+    match (caller_kind, callee_kind) {
+        (FnKind::Free, FnKind::Free)
+        | (FnKind::Free, FnKind::AssocTrait) => {
+            builder.with_inheritance_kind(InheritanceKind::WithParent(true)).build()
+        }
+
+        (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
+            builder
+            .with_parent(tcx.parent(def_id.into()))
+            .with_inheritance_kind(InheritanceKind::Own)
+            .build()
+        }
+
+        (FnKind::AssocInherentImpl, FnKind::AssocTrait)
+        | (FnKind::AssocTrait, FnKind::AssocTrait)
+        | (FnKind::AssocInherentImpl, FnKind::Free)
+        | (FnKind::AssocTrait, FnKind::Free) => {
+            builder
+                .with_parent(tcx.parent(def_id.into()))
+                .build()
+        }
+
+        // For trait impl's `sig_id` is always equal to the corresponding trait method.
+        (FnKind::AssocTraitImpl, _)
+        | (_, FnKind::AssocTraitImpl)
+        // Delegation to inherent methods is not yet supported.
+        | (_, FnKind::AssocInherentImpl) => unreachable!(),
     }
-    preds.extend(callee_predicates.instantiate_own(tcx, args));
-
-    Some(ty::GenericPredicates {
-        parent: None,
-        predicates: tcx.arena.alloc_from_iter(preds),
-        effects_min_tys: ty::List::empty(),
-    })
 }
 
 fn check_constraints<'tcx>(
@@ -224,19 +482,6 @@ fn check_constraints<'tcx>(
         emit("recursive delegation is not supported yet");
     }
 
-    if fn_kind(tcx, def_id.into()) != FnKind::Free {
-        let sig_generics = tcx.generics_of(sig_id);
-        let parent = tcx.parent(def_id.into());
-        let parent_generics = tcx.generics_of(parent);
-
-        let parent_has_self = parent_generics.has_self as usize;
-        let sig_has_self = sig_generics.has_self as usize;
-
-        if sig_generics.count() > sig_has_self || parent_generics.count() > parent_has_self {
-            emit("early bound generics are not supported for associated delegation items");
-        }
-    }
-
     ret
 }
 
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
index 1b73cec..5150db7 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
@@ -72,8 +72,11 @@ fn is_valid_cmse_inputs<'tcx>(
     let mut span = None;
     let mut accum = 0u64;
 
-    for (index, arg_def) in fn_sig.inputs().iter().enumerate() {
-        let layout = tcx.layout_of(ParamEnv::reveal_all().and(*arg_def.skip_binder()))?;
+    // this type is only used for layout computation, which does not rely on regions
+    let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig);
+
+    for (index, ty) in fn_sig.inputs().iter().enumerate() {
+        let layout = tcx.layout_of(ParamEnv::reveal_all().and(*ty))?;
 
         let align = layout.layout.align().abi.bytes();
         let size = layout.layout.size().bytes();
@@ -98,7 +101,10 @@ fn is_valid_cmse_output<'tcx>(
     tcx: TyCtxt<'tcx>,
     fn_sig: ty::PolyFnSig<'tcx>,
 ) -> Result<bool, &'tcx LayoutError<'tcx>> {
-    let mut ret_ty = fn_sig.output().skip_binder();
+    // this type is only used for layout computation, which does not rely on regions
+    let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig);
+
+    let mut ret_ty = fn_sig.output();
     let layout = tcx.layout_of(ParamEnv::reveal_all().and(ret_ty))?;
     let size = layout.layout.size().bytes();
 
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index f0d47e5..9bad563 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -447,7 +447,7 @@ fn check_expr_addr_of(
                 // this time with enough precision to check that the value
                 // whose address was taken can actually be made to live as long
                 // as it needs to live.
-                let region = self.next_region_var(infer::AddrOfRegion(expr.span));
+                let region = self.next_region_var(infer::BorrowRegion(expr.span));
                 Ty::new_ref(self.tcx, region, ty, mutbl)
             }
         }
diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
index 0790c6f..ac5e104 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
@@ -63,8 +63,7 @@ pub(super) fn lint_edition_dependent_dot_call(
                     // Instead, the problem is that the array-into_iter hack will no longer
                     // apply in Rust 2021.
                     (ARRAY_INTO_ITER, "2021")
-                } else if self_ty.is_box()
-                    && self_ty.boxed_ty().is_slice()
+                } else if self_ty.boxed_ty().is_some_and(Ty::is_slice)
                     && !span.at_least_rust_2024()
                 {
                     // In this case, it wasn't really a prelude addition that was the problem.
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 2fdba84..3ba3429 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -715,7 +715,7 @@ fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'t
     }
 
     fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) {
-        let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) else {
+        let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer) else {
             bug!("unexpected incoherent type: {:?}", self_ty)
         };
         for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter().flatten() {
@@ -1485,8 +1485,7 @@ fn consider_probe(
 
                         // Some trait methods are excluded for boxed slices before 2024.
                         // (`boxed_slice.into_iter()` wants a slice iterator for compatibility.)
-                        if self_ty.is_box()
-                            && self_ty.boxed_ty().is_slice()
+                        if self_ty.boxed_ty().is_some_and(Ty::is_slice)
                             && !method_name.span.at_least_rust_2024()
                         {
                             let trait_def = self.tcx.trait_def(poly_trait_ref.def_id());
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 9ea57e4..14ad583 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2235,8 +2235,7 @@ fn suggest_associated_call_syntax(
             let target_ty = self
                 .autoderef(sugg_span, rcvr_ty)
                 .find(|(rcvr_ty, _)| {
-                    DeepRejectCtxt::new(self.tcx, TreatParams::ForLookup)
-                        .types_may_unify(*rcvr_ty, impl_ty)
+                    DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify(*rcvr_ty, impl_ty)
                 })
                 .map_or(impl_ty, |(ty, _)| ty)
                 .peel_refs();
@@ -2498,7 +2497,7 @@ fn report_failed_method_call_on_numerical_infer_var(
             .into_iter()
             .any(|info| self.associated_value(info.def_id, item_name).is_some());
         let found_assoc = |ty: Ty<'tcx>| {
-            simplify_type(tcx, ty, TreatParams::AsCandidateKey)
+            simplify_type(tcx, ty, TreatParams::InstantiateWithInfer)
                 .and_then(|simp| {
                     tcx.incoherent_impls(simp)
                         .into_iter()
@@ -3963,7 +3962,7 @@ enum Introducer {
                 // cases where a positive bound implies a negative impl.
                 (candidates, Vec::new())
             } else if let Some(simp_rcvr_ty) =
-                simplify_type(self.tcx, rcvr_ty, TreatParams::ForLookup)
+                simplify_type(self.tcx, rcvr_ty, TreatParams::AsRigid)
             {
                 let mut potential_candidates = Vec::new();
                 let mut explicitly_negative = Vec::new();
@@ -3981,7 +3980,7 @@ enum Introducer {
                         .any(|header| {
                             let imp = header.trait_ref.instantiate_identity();
                             let imp_simp =
-                                simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup);
+                                simplify_type(self.tcx, imp.self_ty(), TreatParams::AsRigid);
                             imp_simp.is_some_and(|s| s == simp_rcvr_ty)
                         })
                     {
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 5789e60..7688a63 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -39,7 +39,6 @@
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::HirId;
-use rustc_infer::infer::UpvarRegion;
 use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind};
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::traits::ObligationCauseCode;
@@ -425,7 +424,11 @@ fn analyze_closure(
                             self.tcx,
                             upvar_ty,
                             capture,
-                            if needs_ref { Some(closure_env_region) } else { child_capture.region },
+                            if needs_ref {
+                                closure_env_region
+                            } else {
+                                self.tcx.lifetimes.re_erased
+                            },
                         );
                     },
                 ),
@@ -587,7 +590,12 @@ fn final_upvar_tys(&self, closure_id: LocalDefId) -> Vec<Ty<'tcx>> {
 
                 debug!(?captured_place.place, ?upvar_ty, ?capture, ?captured_place.mutability);
 
-                apply_capture_kind_on_capture_ty(self.tcx, upvar_ty, capture, captured_place.region)
+                apply_capture_kind_on_capture_ty(
+                    self.tcx,
+                    upvar_ty,
+                    capture,
+                    self.tcx.lifetimes.re_erased,
+                )
             })
             .collect()
     }
@@ -775,13 +783,8 @@ fn compute_min_captures(
 
             let Some(min_cap_list) = root_var_min_capture_list.get_mut(&var_hir_id) else {
                 let mutability = self.determine_capture_mutability(&typeck_results, &place);
-                let min_cap_list = vec![ty::CapturedPlace {
-                    var_ident,
-                    place,
-                    info: capture_info,
-                    mutability,
-                    region: None,
-                }];
+                let min_cap_list =
+                    vec![ty::CapturedPlace { var_ident, place, info: capture_info, mutability }];
                 root_var_min_capture_list.insert(var_hir_id, min_cap_list);
                 continue;
             };
@@ -874,34 +877,12 @@ fn compute_min_captures(
             // Only need to insert when we don't have an ancestor in the existing min capture list
             if !ancestor_found {
                 let mutability = self.determine_capture_mutability(&typeck_results, &place);
-                let captured_place = ty::CapturedPlace {
-                    var_ident,
-                    place,
-                    info: updated_capture_info,
-                    mutability,
-                    region: None,
-                };
+                let captured_place =
+                    ty::CapturedPlace { var_ident, place, info: updated_capture_info, mutability };
                 min_cap_list.push(captured_place);
             }
         }
 
-        // For each capture that is determined to be captured by ref, add region info.
-        for (_, captures) in &mut root_var_min_capture_list {
-            for capture in captures {
-                match capture.info.capture_kind {
-                    ty::UpvarCapture::ByRef(_) => {
-                        let PlaceBase::Upvar(upvar_id) = capture.place.base else {
-                            bug!("expected upvar")
-                        };
-                        let origin = UpvarRegion(upvar_id, closure_span);
-                        let upvar_region = self.next_region_var(origin);
-                        capture.region = Some(upvar_region);
-                    }
-                    _ => (),
-                }
-            }
-        }
-
         debug!(
             "For closure={:?}, min_captures before sorting={:?}",
             closure_def_id, root_var_min_capture_list
@@ -1195,7 +1176,7 @@ fn compute_2229_migrations_for_trait(
                     self.tcx,
                     ty,
                     max_capture_info.capture_kind,
-                    Some(self.tcx.lifetimes.re_erased),
+                    self.tcx.lifetimes.re_erased,
                 )
             }
         };
@@ -1217,7 +1198,7 @@ fn compute_2229_migrations_for_trait(
                 self.tcx,
                 capture.place.ty(),
                 capture.info.capture_kind,
-                Some(self.tcx.lifetimes.re_erased),
+                self.tcx.lifetimes.re_erased,
             );
 
             // Checks if a capture implements any of the auto traits
@@ -1935,13 +1916,11 @@ fn apply_capture_kind_on_capture_ty<'tcx>(
     tcx: TyCtxt<'tcx>,
     ty: Ty<'tcx>,
     capture_kind: UpvarCapture,
-    region: Option<ty::Region<'tcx>>,
+    region: ty::Region<'tcx>,
 ) -> Ty<'tcx> {
     match capture_kind {
         ty::UpvarCapture::ByValue => ty,
-        ty::UpvarCapture::ByRef(kind) => {
-            Ty::new_ref(tcx, region.unwrap(), ty, kind.to_mutbl_lossy())
-        }
+        ty::UpvarCapture::ByRef(kind) => Ty::new_ref(tcx, region, ty, kind.to_mutbl_lossy()),
     }
 }
 
diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs
index be028fe..34f541a 100644
--- a/compiler/rustc_index/src/interval.rs
+++ b/compiler/rustc_index/src/interval.rs
@@ -17,8 +17,8 @@
 /// first value of the following element.
 #[derive(Debug, Clone)]
 pub struct IntervalSet<I> {
-    // Start, end
-    map: SmallVec<[(u32, u32); 4]>,
+    // Start, end (both inclusive)
+    map: SmallVec<[(u32, u32); 2]>,
     domain: usize,
     _data: PhantomData<I>,
 }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 234dc51..63a729b 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -458,8 +458,8 @@ pub enum RegionVariableOrigin {
     PatternRegion(Span),
 
     /// Regions created by `&` operator.
-    ///
-    AddrOfRegion(Span),
+    BorrowRegion(Span),
+
     /// Regions created as part of an autoref of a method receiver.
     Autoref(Span),
 
@@ -1741,7 +1741,7 @@ pub fn span(&self) -> Span {
         match *self {
             MiscVariable(a)
             | PatternRegion(a)
-            | AddrOfRegion(a)
+            | BorrowRegion(a)
             | Autoref(a)
             | Coercion(a)
             | RegionParameterDefinition(a, ..)
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 42fed98..50422df 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -808,7 +808,7 @@ macro_rules! tracked {
     tracked!(mir_opt_level, Some(4));
     tracked!(move_size_limit, Some(4096));
     tracked!(mutable_noalias, false);
-    tracked!(next_solver, Some(NextSolverConfig { coherence: true, globally: false }));
+    tracked!(next_solver, NextSolverConfig { coherence: true, globally: true });
     tracked!(no_generate_arange_section, true);
     tracked!(no_jump_tables, true);
     tracked!(no_link, true);
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index 31fdd2d..60aab66 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -91,6 +91,15 @@ pub enum TokenKind {
     /// tokens.
     UnknownPrefix,
 
+    /// An unknown prefix in a lifetime, like `'foo#`.
+    ///
+    /// Note that like above, only the `'` and prefix are included in the token
+    /// and not the separator.
+    UnknownPrefixLifetime,
+
+    /// `'r#lt`, which in edition < 2021 is split into several tokens: `'r # lt`.
+    RawLifetime,
+
     /// Similar to the above, but *always* an error on every edition. This is used
     /// for emoji identifier recovery, as those are not meant to be ever accepted.
     InvalidPrefix,
@@ -677,9 +686,17 @@ fn lifetime_or_char(&mut self) -> TokenKind {
             return Literal { kind, suffix_start };
         }
 
+        if self.first() == 'r' && self.second() == '#' && is_id_start(self.third()) {
+            // Eat "r" and `#`, and identifier start characters.
+            self.bump();
+            self.bump();
+            self.bump();
+            self.eat_while(is_id_continue);
+            return RawLifetime;
+        }
+
         // Either a lifetime or a character literal with
         // length greater than 1.
-
         let starts_with_number = self.first().is_ascii_digit();
 
         // Skip the literal contents.
@@ -688,15 +705,17 @@ fn lifetime_or_char(&mut self) -> TokenKind {
         self.bump();
         self.eat_while(is_id_continue);
 
-        // Check if after skipping literal contents we've met a closing
-        // single quote (which means that user attempted to create a
-        // string with single quotes).
-        if self.first() == '\'' {
-            self.bump();
-            let kind = Char { terminated: true };
-            Literal { kind, suffix_start: self.pos_within_token() }
-        } else {
-            Lifetime { starts_with_number }
+        match self.first() {
+            // Check if after skipping literal contents we've met a closing
+            // single quote (which means that user attempted to create a
+            // string with single quotes).
+            '\'' => {
+                self.bump();
+                let kind = Char { terminated: true };
+                Literal { kind, suffix_start: self.pos_within_token() }
+            }
+            '#' if !starts_with_number => UnknownPrefixLifetime,
+            _ => Lifetime { starts_with_number },
         }
     }
 
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 3533459..7d4dee4 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -255,6 +255,7 @@
 lint_elided_named_lifetime = elided lifetime has a name
     .label_elided = this elided lifetime gets resolved as `{$name}`
     .label_named = lifetime `{$name}` declared here
+    .suggestion = consider specifying it explicitly
 
 lint_enum_intrinsics_mem_discriminant =
     the return value of `mem::discriminant` is unspecified when called with a non-enum type
@@ -699,11 +700,18 @@
 lint_query_instability = using `{$query}` can result in unstable query results
     .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
 
+lint_query_untracked = `{$method}` accesses information that is not tracked by the query system
+    .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
+
 lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}`
 
 lint_range_use_inclusive_range = use an inclusive range instead
 
 
+lint_raw_prefix = prefix `'r` is reserved
+    .label = reserved prefix
+    .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021
+
 lint_reason_must_be_string_literal = reason must be a string literal
 
 lint_reason_must_come_last = reason in lint attribute must come last
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 5cb5195..7de92a4 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1845,9 +1845,16 @@ fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: &TokenStream) {
                 TokenTree::Token(token, _) => {
                     if let Some((ident, token::IdentIsRaw::No)) = token.ident() {
                         if !prev_dollar {
-                            self.check_ident_token(cx, UnderMacro(true), ident);
+                            self.check_ident_token(cx, UnderMacro(true), ident, "");
                         }
-                    } else if *token == TokenKind::Dollar {
+                    } else if let Some((ident, token::IdentIsRaw::No)) = token.lifetime() {
+                        self.check_ident_token(
+                            cx,
+                            UnderMacro(true),
+                            ident.without_first_quote(),
+                            "'",
+                        );
+                    } else if token.kind == TokenKind::Dollar {
                         prev_dollar = true;
                         continue;
                     }
@@ -1863,6 +1870,7 @@ fn check_ident_token(
         cx: &EarlyContext<'_>,
         UnderMacro(under_macro): UnderMacro,
         ident: Ident,
+        prefix: &'static str,
     ) {
         let (lint, edition) = match ident.name {
             kw::Async | kw::Await | kw::Try => (KEYWORD_IDENTS_2018, Edition::Edition2018),
@@ -1896,7 +1904,7 @@ fn check_ident_token(
         cx.emit_span_lint(
             lint,
             ident.span,
-            BuiltinKeywordIdents { kw: ident, next: edition, suggestion: ident.span },
+            BuiltinKeywordIdents { kw: ident, next: edition, suggestion: ident.span, prefix },
         );
     }
 }
@@ -1909,7 +1917,11 @@ fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) {
         self.check_tokens(cx, &mac.args.tokens);
     }
     fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
-        self.check_ident_token(cx, UnderMacro(false), ident);
+        if ident.name.as_str().starts_with('\'') {
+            self.check_ident_token(cx, UnderMacro(false), ident.without_first_quote(), "'");
+        } else {
+            self.check_ident_token(cx, UnderMacro(false), ident, "");
+        }
     }
 }
 
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index fd43afa..fd13c41 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -8,13 +8,13 @@
     elided_lifetime_in_path_suggestion, Applicability, Diag, DiagArgValue, LintDiagnostic,
 };
 use rustc_middle::middle::stability;
-use rustc_session::lint::BuiltinLintDiag;
+use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution};
 use rustc_session::Session;
 use rustc_span::symbol::kw;
 use rustc_span::BytePos;
 use tracing::debug;
 
-use crate::lints;
+use crate::lints::{self, ElidedNamedLifetime};
 
 mod check_cfg;
 
@@ -172,6 +172,10 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
             }
             .decorate_lint(diag);
         }
+        BuiltinLintDiag::RawPrefix(label_span) => {
+            lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() }
+                .decorate_lint(diag);
+        }
         BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => {
             lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }.decorate_lint(diag);
         }
@@ -442,15 +446,14 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
         BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => {
             lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag)
         }
-        BuiltinLintDiag::ElidedIsStatic { elided } => {
-            lints::ElidedNamedLifetime { elided, name: kw::StaticLifetime, named_declaration: None }
-                .decorate_lint(diag)
-        }
-        BuiltinLintDiag::ElidedIsParam { elided, param: (param_name, param_span) } => {
-            lints::ElidedNamedLifetime {
-                elided,
-                name: param_name,
-                named_declaration: Some(param_span),
+        BuiltinLintDiag::ElidedNamedLifetimes { elided: (span, kind), resolution } => {
+            match resolution {
+                ElidedLifetimeResolution::Static => {
+                    ElidedNamedLifetime { span, kind, name: kw::StaticLifetime, declaration: None }
+                }
+                ElidedLifetimeResolution::Param(name, declaration) => {
+                    ElidedNamedLifetime { span, kind, name, declaration: Some(declaration) }
+                }
             }
             .decorate_lint(diag)
         }
diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
index 8824e1d..c43c650 100644
--- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs
+++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
@@ -1,19 +1,29 @@
-use rustc_data_structures::fx::FxIndexSet;
+use std::assert_matches::debug_assert_matches;
+use std::cell::LazyCell;
+
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
 use rustc_data_structures::unord::UnordSet;
 use rustc_errors::{Applicability, LintDiagnostic};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_macros::LintDiagnostic;
-use rustc_middle::bug;
 use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
+use rustc_middle::ty::relate::{
+    structurally_relate_consts, structurally_relate_tys, Relate, RelateResult, TypeRelation,
+};
 use rustc_middle::ty::{
     self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
+use rustc_middle::{bug, span_bug};
 use rustc_session::lint::FutureIncompatibilityReason;
 use rustc_session::{declare_lint, declare_lint_pass};
 use rustc_span::edition::Edition;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
+use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt;
+use rustc_trait_selection::traits::ObligationCtxt;
 
 use crate::{fluent_generated as fluent, LateContext, LateLintPass};
 
@@ -119,20 +129,41 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::TraitItem<
     }
 }
 
+#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
+enum ParamKind {
+    // Early-bound var.
+    Early(Symbol, u32),
+    // Late-bound var on function, not within a binder. We can capture these.
+    Free(DefId, Symbol),
+    // Late-bound var in a binder. We can't capture these yet.
+    Late,
+}
+
 fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) {
     let sig = tcx.fn_sig(parent_def_id).instantiate_identity();
 
-    let mut in_scope_parameters = FxIndexSet::default();
+    let mut in_scope_parameters = FxIndexMap::default();
     // Populate the in_scope_parameters list first with all of the generics in scope
     let mut current_def_id = Some(parent_def_id.to_def_id());
     while let Some(def_id) = current_def_id {
         let generics = tcx.generics_of(def_id);
         for param in &generics.own_params {
-            in_scope_parameters.insert(param.def_id);
+            in_scope_parameters.insert(param.def_id, ParamKind::Early(param.name, param.index));
         }
         current_def_id = generics.parent;
     }
 
+    for bound_var in sig.bound_vars() {
+        let ty::BoundVariableKind::Region(ty::BoundRegionKind::BrNamed(def_id, name)) = bound_var
+        else {
+            span_bug!(tcx.def_span(parent_def_id), "unexpected non-lifetime binder on fn sig");
+        };
+
+        in_scope_parameters.insert(def_id, ParamKind::Free(def_id, name));
+    }
+
+    let sig = tcx.liberate_late_bound_regions(parent_def_id.to_def_id(), sig);
+
     // Then visit the signature to walk through all the binders (incl. the late-bound
     // vars on the function itself, which we need to count too).
     sig.visit_with(&mut VisitOpaqueTypes {
@@ -140,21 +171,45 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) {
         parent_def_id,
         in_scope_parameters,
         seen: Default::default(),
+        // Lazily compute these two, since they're likely a bit expensive.
+        variances: LazyCell::new(|| {
+            let mut functional_variances = FunctionalVariances {
+                tcx: tcx,
+                variances: FxHashMap::default(),
+                ambient_variance: ty::Covariant,
+                generics: tcx.generics_of(parent_def_id),
+            };
+            functional_variances.relate(sig, sig).unwrap();
+            functional_variances.variances
+        }),
+        outlives_env: LazyCell::new(|| {
+            let param_env = tcx.param_env(parent_def_id);
+            let infcx = tcx.infer_ctxt().build();
+            let ocx = ObligationCtxt::new(&infcx);
+            let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default();
+            let implied_bounds =
+                infcx.implied_bounds_tys_compat(param_env, parent_def_id, &assumed_wf_tys, false);
+            OutlivesEnvironment::with_bounds(param_env, implied_bounds)
+        }),
     });
 }
 
-struct VisitOpaqueTypes<'tcx> {
+struct VisitOpaqueTypes<'tcx, VarFn, OutlivesFn> {
     tcx: TyCtxt<'tcx>,
     parent_def_id: LocalDefId,
-    in_scope_parameters: FxIndexSet<DefId>,
+    in_scope_parameters: FxIndexMap<DefId, ParamKind>,
+    variances: LazyCell<FxHashMap<DefId, ty::Variance>, VarFn>,
+    outlives_env: LazyCell<OutlivesEnvironment<'tcx>, OutlivesFn>,
     seen: FxIndexSet<LocalDefId>,
 }
 
-impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
-    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
-        &mut self,
-        t: &ty::Binder<'tcx, T>,
-    ) -> Self::Result {
+impl<'tcx, VarFn, OutlivesFn> TypeVisitor<TyCtxt<'tcx>>
+    for VisitOpaqueTypes<'tcx, VarFn, OutlivesFn>
+where
+    VarFn: FnOnce() -> FxHashMap<DefId, ty::Variance>,
+    OutlivesFn: FnOnce() -> OutlivesEnvironment<'tcx>,
+{
+    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
         // When we get into a binder, we need to add its own bound vars to the scope.
         let mut added = vec![];
         for arg in t.bound_vars() {
@@ -163,8 +218,8 @@ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
                 ty::BoundVariableKind::Region(ty::BoundRegionKind::BrNamed(def_id, ..))
                 | ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, _)) => {
                     added.push(def_id);
-                    let unique = self.in_scope_parameters.insert(def_id);
-                    assert!(unique);
+                    let unique = self.in_scope_parameters.insert(def_id, ParamKind::Late);
+                    assert_eq!(unique, None);
                 }
                 _ => {
                     self.tcx.dcx().span_delayed_bug(
@@ -184,7 +239,7 @@ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
         }
     }
 
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
+    fn visit_ty(&mut self, t: Ty<'tcx>) {
         if !t.has_aliases() {
             return;
         }
@@ -207,89 +262,126 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
             && let hir::OpaqueTyOrigin::FnReturn(parent_def_id) = opaque.origin
             && parent_def_id == self.parent_def_id
         {
-            // Compute the set of args that are captured by the opaque...
-            let mut captured = FxIndexSet::default();
-            let variances = self.tcx.variances_of(opaque_def_id);
-            let mut current_def_id = Some(opaque_def_id.to_def_id());
-            while let Some(def_id) = current_def_id {
-                let generics = self.tcx.generics_of(def_id);
-                for param in &generics.own_params {
-                    // A param is captured if it's invariant.
-                    if variances[param.index as usize] != ty::Invariant {
-                        continue;
-                    }
-                    // We need to turn all `ty::Param`/`ConstKind::Param` and
-                    // `ReEarlyParam`/`ReBound` into def ids.
-                    captured.insert(extract_def_id_from_arg(
-                        self.tcx,
-                        generics,
-                        opaque_ty.args[param.index as usize],
-                    ));
-                }
-                current_def_id = generics.parent;
-            }
-
-            // Compute the set of in scope params that are not captured. Get their spans,
-            // since that's all we really care about them for emitting the diagnostic.
-            let uncaptured_spans: Vec<_> = self
-                .in_scope_parameters
-                .iter()
-                .filter(|def_id| !captured.contains(*def_id))
-                .map(|def_id| self.tcx.def_span(def_id))
-                .collect();
-
             let opaque_span = self.tcx.def_span(opaque_def_id);
             let new_capture_rules =
                 opaque_span.at_least_rust_2024() || self.tcx.features().lifetime_capture_rules_2024;
-
-            // If we have uncaptured args, and if the opaque doesn't already have
-            // `use<>` syntax on it, and we're < edition 2024, then warn the user.
             if !new_capture_rules
                 && !opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..)))
-                && !uncaptured_spans.is_empty()
             {
-                let suggestion = if let Ok(snippet) =
-                    self.tcx.sess.source_map().span_to_snippet(opaque_span)
-                    && snippet.starts_with("impl ")
-                {
-                    let (lifetimes, others): (Vec<_>, Vec<_>) = captured
-                        .into_iter()
-                        .partition(|def_id| self.tcx.def_kind(*def_id) == DefKind::LifetimeParam);
-                    // Take all lifetime params first, then all others (ty/ct).
-                    let generics: Vec<_> = lifetimes
-                        .into_iter()
-                        .chain(others)
-                        .map(|def_id| self.tcx.item_name(def_id).to_string())
-                        .collect();
-                    // Make sure that we're not trying to name any APITs
-                    if generics.iter().all(|name| !name.starts_with("impl ")) {
-                        Some((
-                            format!(" + use<{}>", generics.join(", ")),
-                            opaque_span.shrink_to_hi(),
-                        ))
+                // Compute the set of args that are captured by the opaque...
+                let mut captured = FxIndexSet::default();
+                let mut captured_regions = FxIndexSet::default();
+                let variances = self.tcx.variances_of(opaque_def_id);
+                let mut current_def_id = Some(opaque_def_id.to_def_id());
+                while let Some(def_id) = current_def_id {
+                    let generics = self.tcx.generics_of(def_id);
+                    for param in &generics.own_params {
+                        // A param is captured if it's invariant.
+                        if variances[param.index as usize] != ty::Invariant {
+                            continue;
+                        }
+
+                        let arg = opaque_ty.args[param.index as usize];
+                        // We need to turn all `ty::Param`/`ConstKind::Param` and
+                        // `ReEarlyParam`/`ReBound` into def ids.
+                        captured.insert(extract_def_id_from_arg(self.tcx, generics, arg));
+
+                        captured_regions.extend(arg.as_region());
+                    }
+                    current_def_id = generics.parent;
+                }
+
+                // Compute the set of in scope params that are not captured.
+                let mut uncaptured_args: FxIndexSet<_> = self
+                    .in_scope_parameters
+                    .iter()
+                    .filter(|&(def_id, _)| !captured.contains(def_id))
+                    .collect();
+                // Remove the set of lifetimes that are in-scope that outlive some other captured
+                // lifetime and are contravariant (i.e. covariant in argument position).
+                uncaptured_args.retain(|&(def_id, kind)| {
+                    let Some(ty::Bivariant | ty::Contravariant) = self.variances.get(def_id) else {
+                        // Keep all covariant/invariant args. Also if variance is `None`,
+                        // then that means it's either not a lifetime, or it didn't show up
+                        // anywhere in the signature.
+                        return true;
+                    };
+                    // We only computed variance of lifetimes...
+                    debug_assert_matches!(self.tcx.def_kind(def_id), DefKind::LifetimeParam);
+                    let uncaptured = match *kind {
+                        ParamKind::Early(name, index) => ty::Region::new_early_param(
+                            self.tcx,
+                            ty::EarlyParamRegion { name, index },
+                        ),
+                        ParamKind::Free(def_id, name) => ty::Region::new_late_param(
+                            self.tcx,
+                            self.parent_def_id.to_def_id(),
+                            ty::BoundRegionKind::BrNamed(def_id, name),
+                        ),
+                        // Totally ignore late bound args from binders.
+                        ParamKind::Late => return true,
+                    };
+                    // Does this region outlive any captured region?
+                    !captured_regions.iter().any(|r| {
+                        self.outlives_env
+                            .free_region_map()
+                            .sub_free_regions(self.tcx, *r, uncaptured)
+                    })
+                });
+
+                // If we have uncaptured args, and if the opaque doesn't already have
+                // `use<>` syntax on it, and we're < edition 2024, then warn the user.
+                if !uncaptured_args.is_empty() {
+                    let suggestion = if let Ok(snippet) =
+                        self.tcx.sess.source_map().span_to_snippet(opaque_span)
+                        && snippet.starts_with("impl ")
+                    {
+                        let (lifetimes, others): (Vec<_>, Vec<_>) =
+                            captured.into_iter().partition(|def_id| {
+                                self.tcx.def_kind(*def_id) == DefKind::LifetimeParam
+                            });
+                        // Take all lifetime params first, then all others (ty/ct).
+                        let generics: Vec<_> = lifetimes
+                            .into_iter()
+                            .chain(others)
+                            .map(|def_id| self.tcx.item_name(def_id).to_string())
+                            .collect();
+                        // Make sure that we're not trying to name any APITs
+                        if generics.iter().all(|name| !name.starts_with("impl ")) {
+                            Some((
+                                format!(" + use<{}>", generics.join(", ")),
+                                opaque_span.shrink_to_hi(),
+                            ))
+                        } else {
+                            None
+                        }
                     } else {
                         None
-                    }
-                } else {
-                    None
-                };
+                    };
 
-                self.tcx.emit_node_span_lint(
-                    IMPL_TRAIT_OVERCAPTURES,
-                    self.tcx.local_def_id_to_hir_id(opaque_def_id),
-                    opaque_span,
-                    ImplTraitOvercapturesLint {
-                        self_ty: t,
-                        num_captured: uncaptured_spans.len(),
-                        uncaptured_spans,
-                        suggestion,
-                    },
-                );
+                    let uncaptured_spans: Vec<_> = uncaptured_args
+                        .into_iter()
+                        .map(|(def_id, _)| self.tcx.def_span(def_id))
+                        .collect();
+
+                    self.tcx.emit_node_span_lint(
+                        IMPL_TRAIT_OVERCAPTURES,
+                        self.tcx.local_def_id_to_hir_id(opaque_def_id),
+                        opaque_span,
+                        ImplTraitOvercapturesLint {
+                            self_ty: t,
+                            num_captured: uncaptured_spans.len(),
+                            uncaptured_spans,
+                            suggestion,
+                        },
+                    );
+                }
             }
+
             // Otherwise, if we are edition 2024, have `use<>` syntax, and
             // have no uncaptured args, then we should warn to the user that
             // it's redundant to capture all args explicitly.
-            else if new_capture_rules
+            if new_capture_rules
                 && let Some((captured_args, capturing_span)) =
                     opaque.bounds.iter().find_map(|bound| match *bound {
                         hir::GenericBound::Use(a, s) => Some((a, s)),
@@ -327,7 +419,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
                 if self
                     .in_scope_parameters
                     .iter()
-                    .all(|def_id| explicitly_captured.contains(def_id))
+                    .all(|(def_id, _)| explicitly_captured.contains(def_id))
                 {
                     self.tcx.emit_node_span_lint(
                         IMPL_TRAIT_REDUNDANT_CAPTURES,
@@ -396,7 +488,11 @@ fn extract_def_id_from_arg<'tcx>(
             ty::ReBound(
                 _,
                 ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, ..), .. },
-            ) => def_id,
+            )
+            | ty::ReLateParam(ty::LateParamRegion {
+                scope: _,
+                bound_region: ty::BoundRegionKind::BrNamed(def_id, ..),
+            }) => def_id,
             _ => unreachable!(),
         },
         ty::GenericArgKind::Type(ty) => {
@@ -413,3 +509,106 @@ fn extract_def_id_from_arg<'tcx>(
         }
     }
 }
+
+/// Computes the variances of regions that appear in the type, but considering
+/// late-bound regions too, which don't have their variance computed usually.
+///
+/// Like generalization, this is a unary operation implemented on top of the binary
+/// relation infrastructure, mostly because it's much easier to have the relation
+/// track the variance for you, rather than having to do it yourself.
+struct FunctionalVariances<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    variances: FxHashMap<DefId, ty::Variance>,
+    ambient_variance: ty::Variance,
+    generics: &'tcx ty::Generics,
+}
+
+impl<'tcx> TypeRelation<TyCtxt<'tcx>> for FunctionalVariances<'tcx> {
+    fn cx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn relate_with_variance<T: ty::relate::Relate<TyCtxt<'tcx>>>(
+        &mut self,
+        variance: rustc_type_ir::Variance,
+        _: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
+        a: T,
+        b: T,
+    ) -> RelateResult<'tcx, T> {
+        let old_variance = self.ambient_variance;
+        self.ambient_variance = self.ambient_variance.xform(variance);
+        self.relate(a, b).unwrap();
+        self.ambient_variance = old_variance;
+        Ok(a)
+    }
+
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        structurally_relate_tys(self, a, b).unwrap();
+        Ok(a)
+    }
+
+    fn regions(
+        &mut self,
+        a: ty::Region<'tcx>,
+        _: ty::Region<'tcx>,
+    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
+        let def_id = match *a {
+            ty::ReEarlyParam(ebr) => self.generics.region_param(ebr, self.tcx).def_id,
+            ty::ReBound(
+                _,
+                ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, ..), .. },
+            )
+            | ty::ReLateParam(ty::LateParamRegion {
+                scope: _,
+                bound_region: ty::BoundRegionKind::BrNamed(def_id, ..),
+            }) => def_id,
+            _ => {
+                return Ok(a);
+            }
+        };
+
+        if let Some(variance) = self.variances.get_mut(&def_id) {
+            *variance = unify(*variance, self.ambient_variance);
+        } else {
+            self.variances.insert(def_id, self.ambient_variance);
+        }
+
+        Ok(a)
+    }
+
+    fn consts(
+        &mut self,
+        a: ty::Const<'tcx>,
+        b: ty::Const<'tcx>,
+    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
+        structurally_relate_consts(self, a, b).unwrap();
+        Ok(a)
+    }
+
+    fn binders<T>(
+        &mut self,
+        a: ty::Binder<'tcx, T>,
+        b: ty::Binder<'tcx, T>,
+    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
+    where
+        T: Relate<TyCtxt<'tcx>>,
+    {
+        self.relate(a.skip_binder(), b.skip_binder()).unwrap();
+        Ok(a)
+    }
+}
+
+/// What is the variance that satisfies the two variances?
+fn unify(a: ty::Variance, b: ty::Variance) -> ty::Variance {
+    match (a, b) {
+        // Bivariance is lattice bottom.
+        (ty::Bivariant, other) | (other, ty::Bivariant) => other,
+        // Invariant is lattice top.
+        (ty::Invariant, _) | (_, ty::Invariant) => ty::Invariant,
+        // If type is required to be covariant and contravariant, then it's invariant.
+        (ty::Contravariant, ty::Covariant) | (ty::Covariant, ty::Contravariant) => ty::Invariant,
+        // Otherwise, co + co = co, contra + contra = contra.
+        (ty::Contravariant, ty::Contravariant) => ty::Contravariant,
+        (ty::Covariant, ty::Covariant) => ty::Covariant,
+    }
+}
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 2e8116b..9d637c1 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -17,8 +17,8 @@
 
 use crate::lints::{
     BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
-    NonGlobImportTypeIrInherent, QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag,
-    TykindKind, TypeIrInherentUsage, UntranslatableDiag,
+    NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, TyQualified,
+    TykindDiag, TykindKind, TypeIrInherentUsage, UntranslatableDiag,
 };
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 
@@ -88,7 +88,18 @@ fn typeck_results_of_method_fn<'tcx>(
     report_in_external_macro: true
 }
 
-declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY]);
+declare_tool_lint! {
+    /// The `untracked_query_information` lint detects use of methods which leak information not
+    /// tracked by the query system, such as whether a `Steal<T>` value has already been stolen. In
+    /// order not to break incremental compilation, such methods must be used very carefully or not
+    /// at all.
+    pub rustc::UNTRACKED_QUERY_INFORMATION,
+    Allow,
+    "require explicit opt-in when accessing information not tracked by the query system",
+    report_in_external_macro: true
+}
+
+declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]);
 
 impl LateLintPass<'_> for QueryStability {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
@@ -102,6 +113,13 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
                     QueryInstability { query: cx.tcx.item_name(def_id) },
                 );
             }
+            if cx.tcx.has_attr(def_id, sym::rustc_lint_untracked_query_information) {
+                cx.emit_span_lint(
+                    UNTRACKED_QUERY_INFORMATION,
+                    span,
+                    QueryUntracked { method: cx.tcx.item_name(def_id) },
+                );
+            }
         }
     }
 }
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index c5a5c5b..a9627e9 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -30,6 +30,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(array_windows)]
+#![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(extract_if)]
@@ -609,6 +610,7 @@ fn register_internals(store: &mut LintStore) {
         vec![
             LintId::of(DEFAULT_HASH_TYPES),
             LintId::of(POTENTIAL_QUERY_INSTABILITY),
+            LintId::of(UNTRACKED_QUERY_INFORMATION),
             LintId::of(USAGE_OF_TY_TYKIND),
             LintId::of(PASS_BY_VALUE),
             LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 7ca282b..e49b102 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -9,7 +9,7 @@
 };
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{self as hir};
+use rustc_hir::{self as hir, MissingLifetimeKind};
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::inhabitedness::InhabitedPredicate;
 use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt};
@@ -363,8 +363,9 @@ pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint {
 pub(crate) struct BuiltinKeywordIdents {
     pub kw: Ident,
     pub next: Edition,
-    #[suggestion(code = "r#{kw}", applicability = "machine-applicable")]
+    #[suggestion(code = "{prefix}r#{kw}", applicability = "machine-applicable")]
     pub suggestion: Span,
+    pub prefix: &'static str,
 }
 
 #[derive(LintDiagnostic)]
@@ -895,6 +896,13 @@ pub(crate) struct QueryInstability {
 }
 
 #[derive(LintDiagnostic)]
+#[diag(lint_query_untracked)]
+#[note]
+pub(crate) struct QueryUntracked {
+    pub method: Symbol,
+}
+
+#[derive(LintDiagnostic)]
 #[diag(lint_span_use_eq_ctxt)]
 pub(crate) struct SpanUseEqCtxtDiag;
 
@@ -2616,14 +2624,56 @@ pub(crate) struct ElidedLifetimesInPaths {
     pub subdiag: ElidedLifetimeInPathSubdiag,
 }
 
-#[derive(LintDiagnostic)]
-#[diag(lint_elided_named_lifetime)]
 pub(crate) struct ElidedNamedLifetime {
-    #[label(lint_label_elided)]
-    pub elided: Span,
+    pub span: Span,
+    pub kind: MissingLifetimeKind,
     pub name: Symbol,
-    #[label(lint_label_named)]
-    pub named_declaration: Option<Span>,
+    pub declaration: Option<Span>,
+}
+
+impl<G: EmissionGuarantee> LintDiagnostic<'_, G> for ElidedNamedLifetime {
+    fn decorate_lint(self, diag: &mut rustc_errors::Diag<'_, G>) {
+        let Self { span, kind, name, declaration } = self;
+        diag.primary_message(fluent::lint_elided_named_lifetime);
+        diag.arg("name", name);
+        diag.span_label(span, fluent::lint_label_elided);
+        if let Some(declaration) = declaration {
+            diag.span_label(declaration, fluent::lint_label_named);
+        }
+        // FIXME(GrigorenkoPV): this `if` and `return` should be removed,
+        //  but currently this lint's suggestions can conflict with those of `clippy::needless_lifetimes`:
+        //  https://github.com/rust-lang/rust/pull/129840#issuecomment-2323349119
+        // HACK: `'static` suggestions will never sonflict, emit only those for now.
+        if name != rustc_span::symbol::kw::StaticLifetime {
+            return;
+        }
+        match kind {
+            MissingLifetimeKind::Underscore => diag.span_suggestion_verbose(
+                span,
+                fluent::lint_suggestion,
+                format!("{name}"),
+                Applicability::MachineApplicable,
+            ),
+            MissingLifetimeKind::Ampersand => diag.span_suggestion_verbose(
+                span.shrink_to_hi(),
+                fluent::lint_suggestion,
+                format!("{name} "),
+                Applicability::MachineApplicable,
+            ),
+            MissingLifetimeKind::Comma => diag.span_suggestion_verbose(
+                span.shrink_to_hi(),
+                fluent::lint_suggestion,
+                format!("{name}, "),
+                Applicability::MachineApplicable,
+            ),
+            MissingLifetimeKind::Brackets => diag.span_suggestion_verbose(
+                span.shrink_to_hi(),
+                fluent::lint_suggestion,
+                format!("<{name}>"),
+                Applicability::MachineApplicable,
+            ),
+        };
+    }
 }
 
 #[derive(LintDiagnostic)]
@@ -2766,6 +2816,15 @@ pub(crate) struct ReservedPrefix {
 }
 
 #[derive(LintDiagnostic)]
+#[diag(lint_raw_prefix)]
+pub(crate) struct RawPrefix {
+    #[label]
+    pub label: Span,
+    #[suggestion(code = " ", applicability = "machine-applicable")]
+    pub suggestion: Span,
+}
+
+#[derive(LintDiagnostic)]
 #[diag(lint_unused_builtin_attribute)]
 pub(crate) struct UnusedBuiltinAttribute {
     #[note]
diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs
index bb9c7d8..bb12250 100644
--- a/compiler/rustc_lint/src/shadowed_into_iter.rs
+++ b/compiler/rustc_lint/src/shadowed_into_iter.rs
@@ -94,12 +94,9 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
         fn is_ref_to_array(ty: Ty<'_>) -> bool {
             if let ty::Ref(_, pointee_ty, _) = *ty.kind() { pointee_ty.is_array() } else { false }
         }
-        fn is_boxed_slice(ty: Ty<'_>) -> bool {
-            ty.is_box() && ty.boxed_ty().is_slice()
-        }
         fn is_ref_to_boxed_slice(ty: Ty<'_>) -> bool {
             if let ty::Ref(_, pointee_ty, _) = *ty.kind() {
-                is_boxed_slice(pointee_ty)
+                pointee_ty.boxed_ty().is_some_and(Ty::is_slice)
             } else {
                 false
             }
@@ -119,7 +116,7 @@ fn is_ref_to_boxed_slice(ty: Ty<'_>) -> bool {
                     .iter()
                     .copied()
                     .take_while(|ty| !is_ref_to_boxed_slice(*ty))
-                    .position(|ty| is_boxed_slice(ty))
+                    .position(|ty| ty.boxed_ty().is_some_and(Ty::is_slice))
             {
                 (BOXED_SLICE_INTO_ITER, "Box<[T]>", "2024", idx == 0)
             } else {
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index f2f7c0e..b5e501b 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1304,8 +1304,10 @@ fn check_type_for_ffi(
 
         match *ty.kind() {
             ty::Adt(def, args) => {
-                if def.is_box() && matches!(self.mode, CItemKind::Definition) {
-                    if ty.boxed_ty().is_sized(tcx, self.cx.param_env) {
+                if let Some(boxed) = ty.boxed_ty()
+                    && matches!(self.mode, CItemKind::Definition)
+                {
+                    if boxed.is_sized(tcx, self.cx.param_env) {
                         return FfiSafe;
                     } else {
                         return FfiUnsafe {
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 761d30b..b7f7b78 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -283,9 +283,8 @@ fn is_ty_must_use<'tcx>(
             }
 
             match *ty.kind() {
-                ty::Adt(..) if ty.is_box() => {
-                    let boxed_ty = ty.boxed_ty();
-                    is_ty_must_use(cx, boxed_ty, expr, span)
+                ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => {
+                    is_ty_must_use(cx, boxed, expr, span)
                         .map(|inner| MustUsePath::Boxed(Box::new(inner)))
                 }
                 ty::Adt(def, args) if cx.tcx.is_lang_item(def.did(), LangItem::Pin) => {
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 6ee3304..5c4b7e5 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -10,7 +10,7 @@
 };
 use rustc_error_messages::{DiagMessage, MultiSpan};
 use rustc_hir::def::Namespace;
-use rustc_hir::{HashStableContext, HirId};
+use rustc_hir::{HashStableContext, HirId, MissingLifetimeKind};
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
@@ -556,6 +556,12 @@ pub enum DeprecatedSinceKind {
     InVersion(String),
 }
 
+#[derive(Debug)]
+pub enum ElidedLifetimeResolution {
+    Static,
+    Param(Symbol, Span),
+}
+
 // This could be a closure, but then implementing derive trait
 // becomes hacky (and it gets allocated).
 #[derive(Debug)]
@@ -568,12 +574,9 @@ pub enum BuiltinLintDiag {
     },
     MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
     ElidedLifetimesInPaths(usize, Span, bool, Span),
-    ElidedIsStatic {
-        elided: Span,
-    },
-    ElidedIsParam {
-        elided: Span,
-        param: (Symbol, Span),
+    ElidedNamedLifetimes {
+        elided: (Span, MissingLifetimeKind),
+        resolution: ElidedLifetimeResolution,
     },
     UnknownCrateTypes {
         span: Span,
@@ -609,6 +612,8 @@ pub enum BuiltinLintDiag {
     LegacyDeriveHelpers(Span),
     OrPatternsBackCompat(Span, String),
     ReservedPrefix(Span, String),
+    /// `'r#` in edition < 2021.
+    RawPrefix(Span),
     TrailingMacro(bool, Ident),
     BreakWithLabelAndLoop(Span),
     UnicodeTextFlow(Span, String),
diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs
index 3532d50..055d2bd 100644
--- a/compiler/rustc_llvm/src/lib.rs
+++ b/compiler/rustc_llvm/src/lib.rs
@@ -1,6 +1,5 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
-#![cfg_attr(bootstrap, feature(unsafe_attributes, unsafe_extern_blocks))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(rustdoc_internals)]
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index c55583b..b617d52 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -9,6 +9,7 @@
 use rustc_data_structures::memmap::{Mmap, MmapMut};
 use rustc_data_structures::sync::{join, par_for_each_in, Lrc};
 use rustc_data_structures::temp_dir::MaybeTempDir;
+use rustc_feature::Features;
 use rustc_hir as hir;
 use rustc_hir::def_id::{LocalDefId, LocalDefIdSet, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathData;
@@ -797,9 +798,10 @@ macro_rules! stat {
     }
 }
 
-struct AnalyzeAttrState {
+struct AnalyzeAttrState<'a> {
     is_exported: bool,
     is_doc_hidden: bool,
+    features: &'a Features,
 }
 
 /// Returns whether an attribute needs to be recorded in metadata, that is, if it's usable and
@@ -812,7 +814,7 @@ struct AnalyzeAttrState {
 /// visibility: this is a piece of data that can be computed once per defid, and not once per
 /// attribute. Some attributes would only be usable downstream if they are public.
 #[inline]
-fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool {
+fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState<'_>) -> bool {
     let mut should_encode = false;
     if !rustc_feature::encode_cross_crate(attr.name_or_empty()) {
         // Attributes not marked encode-cross-crate don't need to be encoded for downstream crates.
@@ -837,6 +839,9 @@ fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool {
                 }
             }
         }
+    } else if attr.path().starts_with(&[sym::diagnostic]) && attr.path().len() == 2 {
+        should_encode =
+            rustc_feature::is_stable_diagnostic_attribute(attr.path()[1], state.features);
     } else {
         should_encode = true;
     }
@@ -1343,6 +1348,7 @@ fn encode_attrs(&mut self, def_id: LocalDefId) {
         let mut state = AnalyzeAttrState {
             is_exported: tcx.effective_visibilities(()).is_exported(def_id),
             is_doc_hidden: false,
+            features: &tcx.features(),
         };
         let attr_iter = tcx
             .hir()
@@ -2033,7 +2039,7 @@ fn encode_impls(&mut self) -> LazyArray<TraitImpls> {
                 let simplified_self_ty = fast_reject::simplify_type(
                     self.tcx,
                     trait_ref.self_ty(),
-                    TreatParams::AsCandidateKey,
+                    TreatParams::InstantiateWithInfer,
                 );
                 trait_impls
                     .entry(trait_ref.def_id)
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 2a85f85..fd6e2ad 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -28,7 +28,6 @@
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::potential_query_instability)]
 #![allow(rustc::untranslatable_diagnostic)]
-#![cfg_attr(bootstrap, feature(min_exhaustive_patterns, unsafe_extern_blocks))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(allocator_api)]
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 5fb8af5..cd56d0e 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -644,6 +644,12 @@ pub fn write_uninit(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> Al
         return Ok(());
     }
 
+    /// Remove all provenance in the given memory range.
+    pub fn clear_provenance(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult {
+        self.provenance.clear(range, cx)?;
+        return Ok(());
+    }
+
     /// Applies a previously prepared provenance copy.
     /// The affected range, as defined in the parameters to `provenance().prepare_copy` is expected
     /// to be clear of provenance.
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 84c17b3..989f03d 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -307,6 +307,13 @@ pub fn try_to_scalar_int(self) -> Result<ScalarInt, Scalar<AllocId>> {
         }
     }
 
+    pub fn clear_provenance(&mut self) -> InterpResult<'tcx> {
+        if matches!(self, Scalar::Ptr(..)) {
+            *self = self.to_scalar_int()?.into();
+        }
+        Ok(())
+    }
+
     #[inline(always)]
     pub fn to_scalar_int(self) -> InterpResult<'tcx, ScalarInt> {
         self.try_to_scalar_int().map_err(|_| err_unsup!(ReadPointerAsInt(None)).into())
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 9906be6..a98e694 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -612,7 +612,9 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io:
     let def_id = body.source.def_id();
     let kind = tcx.def_kind(def_id);
     let is_function = match kind {
-        DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true,
+        DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::SyntheticCoroutineBody => {
+            true
+        }
         _ => tcx.is_closure_like(def_id),
     };
     match (kind, body.source.promoted) {
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 748ca04..22a4b68 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1307,6 +1307,9 @@ pub enum Rvalue<'tcx> {
     /// If the type of the place is an array, this is the array length. For slices (`[T]`, not
     /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is
     /// ill-formed for places of other types.
+    ///
+    /// This cannot be a `UnOp(PtrMetadata, _)` because that expects a value, and we only
+    /// have a place, and `UnOp(PtrMetadata, RawPtr(place))` is not a thing.
     Len(Place<'tcx>),
 
     /// Performs essentially all of the casts that can be performed via `as`.
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 8eb3c01..809801c 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -88,9 +88,6 @@ pub struct CapturedPlace<'tcx> {
 
     /// Represents if `place` can be mutated or not.
     pub mutability: hir::Mutability,
-
-    /// Region of the resulting reference if the upvar is captured by ref.
-    pub region: Option<ty::Region<'tcx>>,
 }
 
 impl<'tcx> CapturedPlace<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 2082806..56fcfe8 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -181,6 +181,10 @@ fn with_global_cache<R>(
         }
     }
 
+    fn evaluation_is_concurrent(&self) -> bool {
+        self.sess.threads() > 1
+    }
+
     fn expand_abstract_consts<T: TypeFoldable<TyCtxt<'tcx>>>(self, t: T) -> T {
         self.expand_abstract_consts(t)
     }
@@ -426,7 +430,7 @@ fn for_each_relevant_impl(
                 let simp = ty::fast_reject::simplify_type(
                     tcx,
                     self_ty,
-                    ty::fast_reject::TreatParams::ForLookup,
+                    ty::fast_reject::TreatParams::AsRigid,
                 )
                 .unwrap();
                 consider_impls_for_simplified_type(simp);
@@ -3128,11 +3132,11 @@ pub fn intrinsic(self, def_id: impl IntoQueryParam<DefId> + Copy) -> Option<ty::
     }
 
     pub fn next_trait_solver_globally(self) -> bool {
-        self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally)
+        self.sess.opts.unstable_opts.next_solver.globally
     }
 
     pub fn next_trait_solver_in_coherence(self) -> bool {
-        self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.coherence)
+        self.sess.opts.unstable_opts.next_solver.coherence
     }
 
     pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
@@ -3183,8 +3187,7 @@ pub fn needs_coroutine_by_move_body_def_id(self, def_id: LocalDefId) -> bool {
 
     /// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]`
     pub fn do_not_recommend_impl(self, def_id: DefId) -> bool {
-        matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true })
-            && self.impl_trait_header(def_id).is_some_and(|header| header.do_not_recommend)
+        self.get_diagnostic_attr(def_id, sym::do_not_recommend).is_some()
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 91344c4..2945a0b 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -3,6 +3,14 @@
 
 use super::TyCtxt;
 
-pub type DeepRejectCtxt<'tcx> = rustc_type_ir::fast_reject::DeepRejectCtxt<TyCtxt<'tcx>>;
+pub type DeepRejectCtxt<
+    'tcx,
+    const INSTANTIATE_LHS_WITH_INFER: bool,
+    const INSTANTIATE_RHS_WITH_INFER: bool,
+> = rustc_type_ir::fast_reject::DeepRejectCtxt<
+    TyCtxt<'tcx>,
+    INSTANTIATE_LHS_WITH_INFER,
+    INSTANTIATE_RHS_WITH_INFER,
+>;
 
 pub type SimplifiedType = rustc_type_ir::fast_reject::SimplifiedType<DefId>;
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index d0a9039..8cec8ea 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1075,11 +1075,13 @@ fn ty_and_layout_pointee_info_at(
                 // the raw pointer, so size and align are set to the boxed type, but `pointee.safe`
                 // will still be `None`.
                 if let Some(ref mut pointee) = result {
-                    if offset.bytes() == 0 && this.ty.is_box() {
+                    if offset.bytes() == 0
+                        && let Some(boxed_ty) = this.ty.boxed_ty()
+                    {
                         debug_assert!(pointee.safe.is_none());
                         let optimize = tcx.sess.opts.optimize != OptLevel::No;
                         pointee.safe = Some(PointerKind::Box {
-                            unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()),
+                            unpin: optimize && boxed_ty.is_unpin(tcx, cx.param_env()),
                             global: this.ty.is_box_global(tcx),
                         });
                     }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index ee70a63..e637ced 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -263,7 +263,6 @@ pub struct ImplTraitHeader<'tcx> {
     pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
     pub polarity: ImplPolarity,
     pub safety: hir::Safety,
-    pub do_not_recommend: bool,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
@@ -1797,6 +1796,37 @@ pub fn get_attrs(
         }
     }
 
+    /// Get an attribute from the diagnostic attribute namespace
+    ///
+    /// This function requests an attribute with the following structure:
+    ///
+    /// `#[diagnostic::$attr]`
+    ///
+    /// This function performs feature checking, so if an attribute is returned
+    /// it can be used by the consumer
+    pub fn get_diagnostic_attr(
+        self,
+        did: impl Into<DefId>,
+        attr: Symbol,
+    ) -> Option<&'tcx ast::Attribute> {
+        let did: DefId = did.into();
+        if did.as_local().is_some() {
+            // it's a crate local item, we need to check feature flags
+            if rustc_feature::is_stable_diagnostic_attribute(attr, self.features()) {
+                self.get_attrs_by_path(did, &[sym::diagnostic, sym::do_not_recommend]).next()
+            } else {
+                None
+            }
+        } else {
+            // we filter out unstable diagnostic attributes before
+            // encoding attributes
+            debug_assert!(rustc_feature::encode_cross_crate(attr));
+            self.item_attrs(did)
+                .iter()
+                .find(|a| matches!(a.path().as_ref(), [sym::diagnostic, a] if *a == attr))
+        }
+    }
+
     pub fn get_attrs_by_path<'attr>(
         self,
         did: DefId,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 89ef30f..730ba26 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1136,6 +1136,7 @@ pub fn is_unsafe_ptr(self) -> bool {
     }
 
     /// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer).
+    /// `Box` is *not* considered a pointer here!
     #[inline]
     pub fn is_any_ptr(self) -> bool {
         self.is_ref() || self.is_unsafe_ptr() || self.is_fn_ptr()
@@ -1170,14 +1171,19 @@ pub fn is_box_global(self, tcx: TyCtxt<'tcx>) -> bool {
         }
     }
 
-    /// Panics if called on any type other than `Box<T>`.
-    pub fn boxed_ty(self) -> Ty<'tcx> {
+    pub fn boxed_ty(self) -> Option<Ty<'tcx>> {
         match self.kind() {
-            Adt(def, args) if def.is_box() => args.type_at(0),
-            _ => bug!("`boxed_ty` is called on non-box type {:?}", self),
+            Adt(def, args) if def.is_box() => Some(args.type_at(0)),
+            _ => None,
         }
     }
 
+    /// Panics if called on any type other than `Box<T>`.
+    pub fn expect_boxed_ty(self) -> Ty<'tcx> {
+        self.boxed_ty()
+            .unwrap_or_else(|| bug!("`expect_boxed_ty` is called on non-box type {:?}", self))
+    }
+
     /// A scalar type is one that denotes an atomic datum, with no sub-components.
     /// (A RawPtr is scalar because it represents a non-managed pointer, so its
     /// contents are abstract to rustc.)
@@ -1323,7 +1329,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
     /// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly.
     pub fn builtin_deref(self, explicit: bool) -> Option<Ty<'tcx>> {
         match *self.kind() {
-            Adt(def, _) if def.is_box() => Some(self.boxed_ty()),
+            _ if let Some(boxed) = self.boxed_ty() => Some(boxed),
             Ref(_, ty, _) => Some(ty),
             RawPtr(ty, _) if explicit => Some(ty),
             _ => None,
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index dfb137f..82690f7 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -168,9 +168,9 @@ pub fn for_each_relevant_impl(
         // whose outer level is not a parameter or projection. Especially for things like
         // `T: Clone` this is incredibly useful as we would otherwise look at all the impls
         // of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
-        // Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using
-        // `TreatParams::AsCandidateKey` while actually adding them.
-        if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::ForLookup) {
+        // Note that we're using `TreatParams::AsRigid` to query `non_blanket_impls` while using
+        // `TreatParams::InstantiateWithInfer` while actually adding them.
+        if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsRigid) {
             if let Some(impls) = impls.non_blanket_impls.get(&simp) {
                 for &impl_def_id in impls {
                     f(impl_def_id);
@@ -190,7 +190,9 @@ pub fn non_blanket_impls_for_ty(
         self_ty: Ty<'tcx>,
     ) -> impl Iterator<Item = DefId> + 'tcx {
         let impls = self.trait_impls_of(trait_def_id);
-        if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) {
+        if let Some(simp) =
+            fast_reject::simplify_type(self, self_ty, TreatParams::InstantiateWithInfer)
+        {
             if let Some(impls) = impls.non_blanket_impls.get(&simp) {
                 return impls.iter().copied();
             }
@@ -239,7 +241,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
         let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
 
         if let Some(simplified_self_ty) =
-            fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsCandidateKey)
+            fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::InstantiateWithInfer)
         {
             impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
         } else {
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index efbccca..d70ff82 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1628,7 +1628,7 @@ pub fn determine<P>(self_arg_ty: Ty<'tcx>, is_self_ty: P) -> ExplicitSelf<'tcx>
             _ if is_self_ty(self_arg_ty) => ByValue,
             ty::Ref(region, ty, mutbl) if is_self_ty(ty) => ByReference(region, mutbl),
             ty::RawPtr(ty, mutbl) if is_self_ty(ty) => ByRawPointer(mutbl),
-            ty::Adt(def, _) if def.is_box() && is_self_ty(self_arg_ty.boxed_ty()) => ByBox,
+            _ if self_arg_ty.boxed_ty().is_some_and(is_self_ty) => ByBox,
             _ => Other,
         }
     }
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index ddfd073..a889274 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -51,15 +51,15 @@
 /// Similarly, at a given `drop` statement, the set-intersection
 /// between this data and `MaybeUninitializedPlaces` yields the set of
 /// places that would require a dynamic drop-flag at that statement.
-pub struct MaybeInitializedPlaces<'a, 'mir, 'tcx> {
+pub struct MaybeInitializedPlaces<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    body: &'mir Body<'tcx>,
+    body: &'a Body<'tcx>,
     move_data: &'a MoveData<'tcx>,
     skip_unreachable_unwind: bool,
 }
 
-impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
+impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
         MaybeInitializedPlaces { tcx, body, move_data, skip_unreachable_unwind: false }
     }
 
@@ -85,7 +85,7 @@ pub fn is_unwind_dead(
     }
 }
 
-impl<'a, 'mir, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'mir, 'tcx> {
+impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> {
     fn move_data(&self) -> &MoveData<'tcx> {
         self.move_data
     }
@@ -126,17 +126,17 @@ fn move_data(&self) -> &MoveData<'tcx> {
 /// Similarly, at a given `drop` statement, the set-intersection
 /// between this data and `MaybeInitializedPlaces` yields the set of
 /// places that would require a dynamic drop-flag at that statement.
-pub struct MaybeUninitializedPlaces<'a, 'mir, 'tcx> {
+pub struct MaybeUninitializedPlaces<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    body: &'mir Body<'tcx>,
+    body: &'a Body<'tcx>,
     move_data: &'a MoveData<'tcx>,
 
     mark_inactive_variants_as_uninit: bool,
     skip_unreachable_unwind: BitSet<mir::BasicBlock>,
 }
 
-impl<'a, 'mir, 'tcx> MaybeUninitializedPlaces<'a, 'mir, 'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
+impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
         MaybeUninitializedPlaces {
             tcx,
             body,
@@ -165,7 +165,7 @@ pub fn skipping_unreachable_unwind(
     }
 }
 
-impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, '_, 'tcx> {
+impl<'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
     fn move_data(&self) -> &MoveData<'tcx> {
         self.move_data
     }
@@ -251,24 +251,24 @@ fn move_data(&self) -> &MoveData<'tcx> {
 ///     c = S;                                  // {a, b, c, d }
 /// }
 /// ```
-pub struct EverInitializedPlaces<'a, 'mir, 'tcx> {
-    body: &'mir Body<'tcx>,
+pub struct EverInitializedPlaces<'a, 'tcx> {
+    body: &'a Body<'tcx>,
     move_data: &'a MoveData<'tcx>,
 }
 
-impl<'a, 'mir, 'tcx> EverInitializedPlaces<'a, 'mir, 'tcx> {
-    pub fn new(body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
+impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> {
+    pub fn new(body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
         EverInitializedPlaces { body, move_data }
     }
 }
 
-impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, '_, 'tcx> {
+impl<'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'_, 'tcx> {
     fn move_data(&self) -> &MoveData<'tcx> {
         self.move_data
     }
 }
 
-impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> {
+impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
     fn update_bits(
         trans: &mut impl GenKill<MovePathIndex>,
         path: MovePathIndex,
@@ -281,7 +281,7 @@ fn update_bits(
     }
 }
 
-impl<'a, 'tcx> MaybeUninitializedPlaces<'a, '_, 'tcx> {
+impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> {
     fn update_bits(
         trans: &mut impl GenKill<MovePathIndex>,
         path: MovePathIndex,
@@ -307,7 +307,7 @@ fn update_bits(
     }
 }
 
-impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> {
+impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
     /// There can be many more `MovePathIndex` than there are locals in a MIR body.
     /// We use a chunked bitset to avoid paying too high a memory footprint.
     type Domain = MaybeReachable<ChunkedBitSet<MovePathIndex>>;
@@ -329,7 +329,7 @@ fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain)
     }
 }
 
-impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> {
+impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
     type Idx = MovePathIndex;
 
     fn domain_size(&self, _: &Body<'tcx>) -> usize {
@@ -442,7 +442,7 @@ fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
     }
 }
 
-impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> {
+impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
     /// There can be many more `MovePathIndex` than there are locals in a MIR body.
     /// We use a chunked bitset to avoid paying too high a memory footprint.
     type Domain = ChunkedBitSet<MovePathIndex>;
@@ -466,7 +466,7 @@ fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain)
     }
 }
 
-impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> {
+impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
     type Idx = MovePathIndex;
 
     fn domain_size(&self, _: &Body<'tcx>) -> usize {
@@ -643,7 +643,7 @@ fn call_return_effect(
     }
 }
 
-impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> {
+impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> {
     /// There can be many more `InitIndex` than there are locals in a MIR body.
     /// We use a chunked bitset to avoid paying too high a memory footprint.
     type Domain = ChunkedBitSet<InitIndex>;
@@ -662,7 +662,7 @@ fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domai
     }
 }
 
-impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> {
+impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
     type Idx = InitIndex;
 
     fn domain_size(&self, _: &Body<'tcx>) -> usize {
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 1439072..87ea729 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -16,6 +16,7 @@
 
 struct MoveDataBuilder<'a, 'tcx, F> {
     body: &'a Body<'tcx>,
+    loc: Location,
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     data: MoveData<'tcx>,
@@ -56,6 +57,7 @@ fn new(
 
         MoveDataBuilder {
             body,
+            loc: Location::START,
             tcx,
             param_env,
             data: MoveData {
@@ -107,7 +109,7 @@ enum MovePathResult {
     Error,
 }
 
-impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
+impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
     /// This creates a MovePath for a given place, returning an `MovePathError`
     /// if that place can't be moved from.
     ///
@@ -116,7 +118,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
     ///
     /// Maybe we should have separate "borrowck" and "moveck" modes.
     fn move_path_for(&mut self, place: Place<'tcx>) -> MovePathResult {
-        let data = &mut self.builder.data;
+        let data = &mut self.data;
 
         debug!("lookup({:?})", place);
         let Some(mut base) = data.rev_lookup.find_local(place.local) else {
@@ -131,8 +133,8 @@ fn move_path_for(&mut self, place: Place<'tcx>) -> MovePathResult {
         let mut union_path = None;
 
         for (place_ref, elem) in data.rev_lookup.un_derefer.iter_projections(place.as_ref()) {
-            let body = self.builder.body;
-            let tcx = self.builder.tcx;
+            let body = self.body;
+            let tcx = self.tcx;
             let place_ty = place_ref.ty(body, tcx).ty;
             if place_ty.references_error() {
                 return MovePathResult::Error;
@@ -238,7 +240,7 @@ fn move_path_for(&mut self, place: Place<'tcx>) -> MovePathResult {
                 | ProjectionElem::Downcast(_, _) => (),
             }
             let elem_ty = PlaceTy::from_ty(place_ty).projection_ty(tcx, elem).ty;
-            if !(self.builder.filter)(elem_ty) {
+            if !(self.filter)(elem_ty) {
                 return MovePathResult::Error;
             }
             if union_path.is_none() {
@@ -274,7 +276,7 @@ fn add_move_path(
             data: MoveData { rev_lookup, move_paths, path_map, init_path_map, .. },
             tcx,
             ..
-        } = self.builder;
+        } = self;
         *rev_lookup.projections.entry((base, elem.lift())).or_insert_with(move || {
             new_move_path(move_paths, path_map, init_path_map, Some(base), mk_place(*tcx))
         })
@@ -285,9 +287,7 @@ fn create_move_path(&mut self, place: Place<'tcx>) {
         // drop), so this not being a valid move path is OK.
         let _ = self.move_path_for(place);
     }
-}
 
-impl<'a, 'tcx, F> MoveDataBuilder<'a, 'tcx, F> {
     fn finalize(self) -> MoveData<'tcx> {
         debug!("{}", {
             debug!("moves for {:?}:", self.body.span);
@@ -317,12 +317,12 @@ pub(super) fn gather_moves<'tcx>(
 
     for (bb, block) in body.basic_blocks.iter_enumerated() {
         for (i, stmt) in block.statements.iter().enumerate() {
-            let source = Location { block: bb, statement_index: i };
-            builder.gather_statement(source, stmt);
+            builder.loc = Location { block: bb, statement_index: i };
+            builder.gather_statement(stmt);
         }
 
-        let terminator_loc = Location { block: bb, statement_index: block.statements.len() };
-        builder.gather_terminator(terminator_loc, block.terminator());
+        builder.loc = Location { block: bb, statement_index: block.statements.len() };
+        builder.gather_terminator(block.terminator());
     }
 
     builder.finalize()
@@ -345,30 +345,14 @@ fn gather_args(&mut self) {
         }
     }
 
-    fn gather_statement(&mut self, loc: Location, stmt: &Statement<'tcx>) {
-        debug!("gather_statement({:?}, {:?})", loc, stmt);
-        (Gatherer { builder: self, loc }).gather_statement(stmt);
-    }
-
-    fn gather_terminator(&mut self, loc: Location, term: &Terminator<'tcx>) {
-        debug!("gather_terminator({:?}, {:?})", loc, term);
-        (Gatherer { builder: self, loc }).gather_terminator(term);
-    }
-}
-
-struct Gatherer<'b, 'a, 'tcx, F> {
-    builder: &'b mut MoveDataBuilder<'a, 'tcx, F>,
-    loc: Location,
-}
-
-impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
     fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
+        debug!("gather_statement({:?}, {:?})", self.loc, stmt);
         match &stmt.kind {
             StatementKind::Assign(box (place, Rvalue::CopyForDeref(reffed))) => {
                 let local = place.as_local().unwrap();
-                assert!(self.builder.body.local_decls[local].is_deref_temp());
+                assert!(self.body.local_decls[local].is_deref_temp());
 
-                let rev_lookup = &mut self.builder.data.rev_lookup;
+                let rev_lookup = &mut self.data.rev_lookup;
 
                 rev_lookup.un_derefer.insert(local, reffed.as_ref());
                 let base_local = rev_lookup.un_derefer.deref_chain(local).first().unwrap().local;
@@ -380,7 +364,7 @@ fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
                     // Box starts out uninitialized - need to create a separate
                     // move-path for the interior so it will be separate from
                     // the exterior.
-                    self.create_move_path(self.builder.tcx.mk_place_deref(*place));
+                    self.create_move_path(self.tcx.mk_place_deref(*place));
                     self.gather_init(place.as_ref(), InitKind::Shallow);
                 } else {
                     self.gather_init(place.as_ref(), InitKind::Deep);
@@ -393,7 +377,7 @@ fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
             StatementKind::StorageLive(_) => {}
             StatementKind::StorageDead(local) => {
                 // DerefTemp locals (results of CopyForDeref) don't actually move anything.
-                if !self.builder.body.local_decls[*local].is_deref_temp() {
+                if !self.body.local_decls[*local].is_deref_temp() {
                     self.gather_move(Place::from(*local));
                 }
             }
@@ -443,6 +427,7 @@ fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
     }
 
     fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
+        debug!("gather_terminator({:?}, {:?})", self.loc, term);
         match term.kind {
             TerminatorKind::Goto { target: _ }
             | TerminatorKind::FalseEdge { .. }
@@ -551,7 +536,7 @@ fn gather_move(&mut self, place: Place<'tcx>) {
             // `ConstIndex` patterns. This is done to ensure that all move paths
             // are disjoint, which is expected by drop elaboration.
             let base_place =
-                Place { local: place.local, projection: self.builder.tcx.mk_place_elems(base) };
+                Place { local: place.local, projection: self.tcx.mk_place_elems(base) };
             let base_path = match self.move_path_for(base_place) {
                 MovePathResult::Path(path) => path,
                 MovePathResult::Union(path) => {
@@ -562,11 +547,9 @@ fn gather_move(&mut self, place: Place<'tcx>) {
                     return;
                 }
             };
-            let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty;
+            let base_ty = base_place.ty(self.body, self.tcx).ty;
             let len: u64 = match base_ty.kind() {
-                ty::Array(_, size) => {
-                    size.eval_target_usize(self.builder.tcx, self.builder.param_env)
-                }
+                ty::Array(_, size) => size.eval_target_usize(self.tcx, self.param_env),
                 _ => bug!("from_end: false slice pattern of non-array type"),
             };
             for offset in from..to {
@@ -587,13 +570,13 @@ fn gather_move(&mut self, place: Place<'tcx>) {
     }
 
     fn record_move(&mut self, place: Place<'tcx>, path: MovePathIndex) {
-        let move_out = self.builder.data.moves.push(MoveOut { path, source: self.loc });
+        let move_out = self.data.moves.push(MoveOut { path, source: self.loc });
         debug!(
             "gather_move({:?}, {:?}): adding move {:?} of {:?}",
             self.loc, place, move_out, path
         );
-        self.builder.data.path_map[path].push(move_out);
-        self.builder.data.loc_map[self.loc].push(move_out);
+        self.data.path_map[path].push(move_out);
+        self.data.loc_map[self.loc].push(move_out);
     }
 
     fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) {
@@ -604,13 +587,13 @@ fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) {
         // Check if we are assigning into a field of a union, if so, lookup the place
         // of the union so it is marked as initialized again.
         if let Some((place_base, ProjectionElem::Field(_, _))) = place.last_projection() {
-            if place_base.ty(self.builder.body, self.builder.tcx).ty.is_union() {
+            if place_base.ty(self.body, self.tcx).ty.is_union() {
                 place = place_base;
             }
         }
 
-        if let LookupResult::Exact(path) = self.builder.data.rev_lookup.find(place) {
-            let init = self.builder.data.inits.push(Init {
+        if let LookupResult::Exact(path) = self.data.rev_lookup.find(place) {
+            let init = self.data.inits.push(Init {
                 location: InitLocation::Statement(self.loc),
                 path,
                 kind,
@@ -621,8 +604,8 @@ fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) {
                 self.loc, place, init, path
             );
 
-            self.builder.data.init_path_map[path].push(init);
-            self.builder.data.init_loc_map[self.loc].push(init);
+            self.data.init_path_map[path].push(init);
+            self.data.init_loc_map[self.loc].push(init);
         }
     }
 }
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 2b20a35..0540436 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -923,14 +923,14 @@ fn cache_preorder_invoke(&mut self, root: PlaceIndex) {
     }
 }
 
-struct PlaceCollector<'a, 'b, 'tcx> {
+struct PlaceCollector<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    body: &'b Body<'tcx>,
+    body: &'a Body<'tcx>,
     map: &'a mut Map<'tcx>,
     assignments: FxIndexSet<(PlaceIndex, PlaceIndex)>,
 }
 
-impl<'tcx> PlaceCollector<'_, '_, 'tcx> {
+impl<'tcx> PlaceCollector<'_, 'tcx> {
     #[tracing::instrument(level = "trace", skip(self))]
     fn register_place(&mut self, place: Place<'tcx>) -> Option<PlaceIndex> {
         // Create a place for this projection.
@@ -967,7 +967,7 @@ fn register_place(&mut self, place: Place<'tcx>) -> Option<PlaceIndex> {
     }
 }
 
-impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, '_, 'tcx> {
+impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, 'tcx> {
     #[tracing::instrument(level = "trace", skip(self))]
     fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, _: Location) {
         if !ctxt.is_use() {
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index e4bc6b3..8291df9 100644
--- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -20,7 +20,7 @@
 /// This forces all unwinds, in panic=abort mode happening in foreign code, to
 /// trigger a process abort.
 #[derive(PartialEq)]
-pub struct AbortUnwindingCalls;
+pub(super) struct AbortUnwindingCalls;
 
 impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
@@ -50,9 +50,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // with a function call, and whose function we're calling may unwind.
         // This will filter to functions with `extern "C-unwind"` ABIs, for
         // example.
-        let mut calls_to_terminate = Vec::new();
-        let mut cleanups_to_remove = Vec::new();
-        for (id, block) in body.basic_blocks.iter_enumerated() {
+        for block in body.basic_blocks.as_mut() {
             if block.is_cleanup {
                 continue;
             }
@@ -61,7 +59,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
             let call_can_unwind = match &terminator.kind {
                 TerminatorKind::Call { func, .. } => {
-                    let ty = func.ty(body, tcx);
+                    let ty = func.ty(&body.local_decls, tcx);
                     let sig = ty.fn_sig(tcx);
                     let fn_def_id = match ty.kind() {
                         ty::FnPtr(..) => None,
@@ -86,31 +84,20 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                 _ => continue,
             };
 
-            // If this function call can't unwind, then there's no need for it
-            // to have a landing pad. This means that we can remove any cleanup
-            // registered for it.
             if !call_can_unwind {
-                cleanups_to_remove.push(id);
-                continue;
+                // If this function call can't unwind, then there's no need for it
+                // to have a landing pad. This means that we can remove any cleanup
+                // registered for it.
+                let cleanup = block.terminator_mut().unwind_mut().unwrap();
+                *cleanup = UnwindAction::Unreachable;
+            } else if !body_can_unwind {
+                // Otherwise if this function can unwind, then if the outer function
+                // can also unwind there's nothing to do. If the outer function
+                // can't unwind, however, we need to change the landing pad for this
+                // function call to one that aborts.
+                let cleanup = block.terminator_mut().unwind_mut().unwrap();
+                *cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi);
             }
-
-            // Otherwise if this function can unwind, then if the outer function
-            // can also unwind there's nothing to do. If the outer function
-            // can't unwind, however, we need to change the landing pad for this
-            // function call to one that aborts.
-            if !body_can_unwind {
-                calls_to_terminate.push(id);
-            }
-        }
-
-        for id in calls_to_terminate {
-            let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
-            *cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi);
-        }
-
-        for id in cleanups_to_remove {
-            let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
-            *cleanup = UnwindAction::Unreachable;
         }
 
         // We may have invalidated some `cleanup` blocks so clean those up now.
diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs
index 78e850d..18a0746 100644
--- a/compiler/rustc_mir_transform/src/add_call_guards.rs
+++ b/compiler/rustc_mir_transform/src/add_call_guards.rs
@@ -4,11 +4,11 @@
 use tracing::debug;
 
 #[derive(PartialEq)]
-pub enum AddCallGuards {
+pub(super) enum AddCallGuards {
     AllCallEdges,
     CriticalCallEdges,
 }
-pub use self::AddCallGuards::*;
+pub(super) use self::AddCallGuards::*;
 
 /**
  * Breaks outgoing critical edges for call terminators in the MIR.
@@ -37,7 +37,7 @@ fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 }
 
 impl AddCallGuards {
-    pub fn add_call_guards(&self, body: &mut Body<'_>) {
+    pub(super) fn add_call_guards(&self, body: &mut Body<'_>) {
         let mut pred_count: IndexVec<_, _> =
             body.basic_blocks.predecessors().iter().map(|ps| ps.len()).collect();
         pred_count[START_BLOCK] += 1;
diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
index 4a8196a..47572d8 100644
--- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
+++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
@@ -35,7 +35,7 @@
 ///
 /// The storage instructions are required to avoid stack space
 /// blowup.
-pub struct AddMovesForPackedDrops;
+pub(super) struct AddMovesForPackedDrops;
 
 impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
@@ -44,7 +44,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     }
 }
 
-pub fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let patch = add_moves_for_packed_drops_patch(tcx, body);
     patch.apply(body);
 }
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index 2e12064..794e85f 100644
--- a/compiler/rustc_mir_transform/src/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -8,7 +8,7 @@
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
-pub struct AddRetag;
+pub(super) struct AddRetag;
 
 /// Determine whether this type may contain a reference (or box), and thus needs retagging.
 /// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this.
diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
index 369f6c6..ab6bf18 100644
--- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
+++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
@@ -1,15 +1,14 @@
-use rustc_index::IndexVec;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::MutVisitor;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
-pub struct Subtyper;
+pub(super) struct Subtyper;
 
-pub struct SubTypeChecker<'a, 'tcx> {
+struct SubTypeChecker<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     patcher: MirPatch<'tcx>,
-    local_decls: &'a IndexVec<Local, LocalDecl<'tcx>>,
+    local_decls: &'a LocalDecls<'tcx>,
 }
 
 impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> {
@@ -52,7 +51,7 @@ fn visit_assign(
 // // gets transformed to
 // let temp: rval_ty = rval;
 // let place: place_ty = temp as place_ty;
-pub fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let patch = MirPatch::new(body);
     let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls };
 
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index 2e072aa..e1d5152 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -7,7 +7,7 @@
 use rustc_session::Session;
 use tracing::{debug, trace};
 
-pub struct CheckAlignment;
+pub(super) struct CheckAlignment;
 
 impl<'tcx> crate::MirPass<'tcx> for CheckAlignment {
     fn is_enabled(&self, sess: &Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
index fb03323..234ed82 100644
--- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -8,7 +8,7 @@
 
 use crate::errors;
 
-pub struct CheckConstItemMutation;
+pub(super) struct CheckConstItemMutation;
 
 impl<'tcx> crate::MirLint<'tcx> for CheckConstItemMutation {
     fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index 2f957de..1922d4f 100644
--- a/compiler/rustc_mir_transform/src/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -5,7 +5,7 @@
 
 use crate::{errors, util};
 
-pub struct CheckPackedRef;
+pub(super) struct CheckPackedRef;
 
 impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef {
     fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
index 2f3be1e..97ce16c 100644
--- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
+++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
@@ -21,7 +21,7 @@
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::TyCtxt;
 
-pub struct CleanupPostBorrowck;
+pub(super) struct CleanupPostBorrowck;
 
 impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck {
     fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
index 85d25ca..dc4ee58 100644
--- a/compiler/rustc_mir_transform/src/copy_prop.rs
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -17,7 +17,7 @@
 /// where each of the locals is only assigned once.
 ///
 /// We want to replace all those locals by `_a`, either copied or moved.
-pub struct CopyProp;
+pub(super) struct CopyProp;
 
 impl<'tcx> crate::MirPass<'tcx> for CopyProp {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index eefb748..90243cd 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -53,7 +53,7 @@
 mod by_move_body;
 use std::{iter, ops};
 
-pub use by_move_body::coroutine_by_move_body_def_id;
+pub(super) use by_move_body::coroutine_by_move_body_def_id;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::pluralize;
 use rustc_hir as hir;
@@ -85,7 +85,7 @@
 use crate::deref_separator::deref_finder;
 use crate::{abort_unwinding_calls, errors, pass_manager as pm, simplify};
 
-pub struct StateTransform;
+pub(super) struct StateTransform;
 
 struct RenameLocalVisitor<'tcx> {
     from: Local,
@@ -872,9 +872,9 @@ fn compute_storage_conflicts<'mir, 'tcx>(
     storage_conflicts
 }
 
-struct StorageConflictVisitor<'mir, 'tcx, 's> {
-    body: &'mir Body<'tcx>,
-    saved_locals: &'s CoroutineSavedLocals,
+struct StorageConflictVisitor<'a, 'tcx> {
+    body: &'a Body<'tcx>,
+    saved_locals: &'a CoroutineSavedLocals,
     // FIXME(tmandry): Consider using sparse bitsets here once we have good
     // benchmarks for coroutines.
     local_conflicts: BitMatrix<Local, Local>,
@@ -882,8 +882,8 @@ struct StorageConflictVisitor<'mir, 'tcx, 's> {
     eligible_storage_live: BitSet<Local>,
 }
 
-impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
-    for StorageConflictVisitor<'mir, 'tcx, '_>
+impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
+    for StorageConflictVisitor<'a, 'tcx>
 {
     type FlowState = BitSet<Local>;
 
@@ -891,7 +891,7 @@ fn visit_statement_before_primary_effect(
         &mut self,
         _results: &mut R,
         state: &Self::FlowState,
-        _statement: &'mir Statement<'tcx>,
+        _statement: &'a Statement<'tcx>,
         loc: Location,
     ) {
         self.apply_state(state, loc);
@@ -901,14 +901,14 @@ fn visit_terminator_before_primary_effect(
         &mut self,
         _results: &mut R,
         state: &Self::FlowState,
-        _terminator: &'mir Terminator<'tcx>,
+        _terminator: &'a Terminator<'tcx>,
         loc: Location,
     ) {
         self.apply_state(state, loc);
     }
 }
 
-impl StorageConflictVisitor<'_, '_, '_> {
+impl StorageConflictVisitor<'_, '_> {
     fn apply_state(&mut self, flow_state: &BitSet<Local>, loc: Location) {
         // Ignore unreachable blocks.
         if let TerminatorKind::Unreachable = self.body.basic_blocks[loc.block].terminator().kind {
@@ -1199,7 +1199,7 @@ fn insert_panic_block<'tcx>(
     message: AssertMessage<'tcx>,
 ) -> BasicBlock {
     let assert_block = BasicBlock::new(body.basic_blocks.len());
-    let term = TerminatorKind::Assert {
+    let kind = TerminatorKind::Assert {
         cond: Operand::Constant(Box::new(ConstOperand {
             span: body.span,
             user_ty: None,
@@ -1211,14 +1211,7 @@ fn insert_panic_block<'tcx>(
         unwind: UnwindAction::Continue,
     };
 
-    let source_info = SourceInfo::outermost(body.span);
-    body.basic_blocks_mut().push(BasicBlockData {
-        statements: Vec::new(),
-        terminator: Some(Terminator { source_info, kind: term }),
-        is_cleanup: false,
-    });
-
-    assert_block
+    insert_term_block(body, kind)
 }
 
 fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index ebe8d2e..6476f3c 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -82,12 +82,17 @@
 use rustc_span::symbol::kw;
 use rustc_target::abi::{FieldIdx, VariantIdx};
 
-pub fn coroutine_by_move_body_def_id<'tcx>(
+pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
     tcx: TyCtxt<'tcx>,
     coroutine_def_id: LocalDefId,
 ) -> DefId {
     let body = tcx.mir_built(coroutine_def_id).borrow();
 
+    // If the typeck results are tainted, no need to make a by-ref body.
+    if body.tainted_by_errors.is_some() {
+        return coroutine_def_id.to_def_id();
+    }
+
     let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) =
         tcx.coroutine_kind(coroutine_def_id)
     else {
@@ -98,7 +103,9 @@ pub fn coroutine_by_move_body_def_id<'tcx>(
     // the MIR body will be constructed well.
     let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
 
-    let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") };
+    let ty::Coroutine(_, args) = *coroutine_ty.kind() else {
+        bug!("tried to create by-move body of non-coroutine receiver");
+    };
     let args = args.as_coroutine();
 
     let coroutine_kind = args.kind_ty().to_opt_closure_kind().unwrap();
@@ -107,7 +114,7 @@ pub fn coroutine_by_move_body_def_id<'tcx>(
     let ty::CoroutineClosure(_, parent_args) =
         *tcx.type_of(parent_def_id).instantiate_identity().kind()
     else {
-        bug!();
+        bug!("coroutine's parent was not a coroutine-closure");
     };
     if parent_args.references_error() {
         return coroutine_def_id.to_def_id();
@@ -207,11 +214,12 @@ pub fn coroutine_by_move_body_def_id<'tcx>(
 
     let mut by_move_body = body.clone();
     MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body);
-    dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(()));
 
-    let body_def = tcx.create_def(coroutine_def_id, kw::Empty, DefKind::SyntheticCoroutineBody);
+    // This will always be `{closure#1}`, since the original coroutine is `{closure#0}`.
+    let body_def = tcx.create_def(parent_def_id, kw::Empty, DefKind::SyntheticCoroutineBody);
     by_move_body.source =
         mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id()));
+    dump_mir(tcx, false, "built", &"after", &by_move_body, |_, _| Ok(()));
 
     // Inherited from the by-ref coroutine.
     body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone());
diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs
index a1c1422..59b4035 100644
--- a/compiler/rustc_mir_transform/src/cost_checker.rs
+++ b/compiler/rustc_mir_transform/src/cost_checker.rs
@@ -12,7 +12,7 @@
 
 /// Verify that the callee body is compatible with the caller.
 #[derive(Clone)]
-pub(crate) struct CostChecker<'b, 'tcx> {
+pub(super) struct CostChecker<'b, 'tcx> {
     tcx: TyCtxt<'tcx>,
     param_env: ParamEnv<'tcx>,
     penalty: usize,
@@ -22,7 +22,7 @@ pub(crate) struct CostChecker<'b, 'tcx> {
 }
 
 impl<'b, 'tcx> CostChecker<'b, 'tcx> {
-    pub fn new(
+    pub(super) fn new(
         tcx: TyCtxt<'tcx>,
         param_env: ParamEnv<'tcx>,
         instance: Option<ty::Instance<'tcx>>,
@@ -36,7 +36,7 @@ pub fn new(
     /// Needed because the `CostChecker` is used sometimes for just blocks,
     /// and even the full `Inline` doesn't call `visit_body`, so there's nowhere
     /// to put this logic in the visitor.
-    pub fn add_function_level_costs(&mut self) {
+    pub(super) fn add_function_level_costs(&mut self) {
         fn is_call_like(bbd: &BasicBlockData<'_>) -> bool {
             use TerminatorKind::*;
             match bbd.terminator().kind {
@@ -64,7 +64,7 @@ fn is_call_like(bbd: &BasicBlockData<'_>) -> bool {
         }
     }
 
-    pub fn cost(&self) -> usize {
+    pub(super) fn cost(&self) -> usize {
         usize::saturating_sub(self.penalty, self.bonus)
     }
 
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 4edba61..042f589 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -1,4 +1,4 @@
-pub mod query;
+pub(super) mod query;
 
 mod counters;
 mod graph;
@@ -32,7 +32,7 @@
 /// Inserts `StatementKind::Coverage` statements that either instrument the binary with injected
 /// counters, via intrinsic `llvm.instrprof.increment`, and/or inject metadata used during codegen
 /// to construct the coverage map.
-pub struct InstrumentCoverage;
+pub(super) struct InstrumentCoverage;
 
 impl<'tcx> crate::MirPass<'tcx> for InstrumentCoverage {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index fcc7745..b904b0d 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -3,7 +3,7 @@
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir;
-use rustc_span::Span;
+use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span};
 use tracing::{debug, debug_span, instrument};
 
 use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
@@ -25,7 +25,7 @@ pub(super) fn extract_refined_covspans(
 
     // First, perform the passes that need macro information.
     covspans.sort_by(|a, b| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb));
-    remove_unwanted_macro_spans(&mut covspans);
+    remove_unwanted_expansion_spans(&mut covspans);
     split_visible_macro_spans(&mut covspans);
 
     // We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`.
@@ -76,18 +76,24 @@ pub(super) fn extract_refined_covspans(
 /// invocation, which is unhelpful. Keeping only the first such span seems to
 /// give better mappings, so remove the others.
 ///
+/// Similarly, `await` expands to a branch on the discriminant of `Poll`, which
+/// leads to incorrect coverage if the `Future` is immediately ready (#98712).
+///
 /// (The input spans should be sorted in BCB dominator order, so that the
 /// retained "first" span is likely to dominate the others.)
-fn remove_unwanted_macro_spans(covspans: &mut Vec<SpanFromMir>) {
-    let mut seen_macro_spans = FxHashSet::default();
-    covspans.retain(|covspan| {
-        // Ignore (retain) non-macro-expansion spans.
-        if covspan.visible_macro.is_none() {
-            return true;
-        }
+fn remove_unwanted_expansion_spans(covspans: &mut Vec<SpanFromMir>) {
+    let mut deduplicated_spans = FxHashSet::default();
 
-        // Retain only the first macro-expanded covspan with this span.
-        seen_macro_spans.insert(covspan.span)
+    covspans.retain(|covspan| {
+        match covspan.expn_kind {
+            // Retain only the first await-related or macro-expanded covspan with this span.
+            Some(ExpnKind::Desugaring(kind)) if kind == DesugaringKind::Await => {
+                deduplicated_spans.insert(covspan.span)
+            }
+            Some(ExpnKind::Macro(MacroKind::Bang, _)) => deduplicated_spans.insert(covspan.span),
+            // Ignore (retain) other spans.
+            _ => true,
+        }
     });
 }
 
@@ -99,7 +105,9 @@ fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
     let mut extra_spans = vec![];
 
     covspans.retain(|covspan| {
-        let Some(visible_macro) = covspan.visible_macro else { return true };
+        let Some(ExpnKind::Macro(MacroKind::Bang, visible_macro)) = covspan.expn_kind else {
+            return true;
+        };
 
         let split_len = visible_macro.as_str().len() as u32 + 1;
         let (before, after) = covspan.span.split_at(split_len);
@@ -111,8 +119,8 @@ fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
             return true;
         }
 
-        extra_spans.push(SpanFromMir::new(before, covspan.visible_macro, covspan.bcb));
-        extra_spans.push(SpanFromMir::new(after, covspan.visible_macro, covspan.bcb));
+        extra_spans.push(SpanFromMir::new(before, covspan.expn_kind.clone(), covspan.bcb));
+        extra_spans.push(SpanFromMir::new(after, covspan.expn_kind.clone(), covspan.bcb));
         false // Discard the original covspan that we just split.
     });
 
diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
index 32bd25b..7f5765c 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
@@ -3,13 +3,13 @@
 use rustc_middle::mir::{
     self, FakeReadCause, Statement, StatementKind, Terminator, TerminatorKind,
 };
-use rustc_span::{Span, Symbol};
+use rustc_span::{ExpnKind, Span};
 
 use crate::coverage::graph::{
     BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB,
 };
 use crate::coverage::spans::Covspan;
-use crate::coverage::unexpand::unexpand_into_body_span_with_visible_macro;
+use crate::coverage::unexpand::unexpand_into_body_span_with_expn_kind;
 use crate::coverage::ExtractedHirInfo;
 
 pub(crate) struct ExtractedCovspans {
@@ -60,7 +60,7 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
         let data = &mir_body[bb];
 
         let unexpand = move |expn_span| {
-            unexpand_into_body_span_with_visible_macro(expn_span, body_span)
+            unexpand_into_body_span_with_expn_kind(expn_span, body_span)
                 // Discard any spans that fill the entire body, because they tend
                 // to represent compiler-inserted code, e.g. implicitly returning `()`.
                 .filter(|(span, _)| !span.source_equal(body_span))
@@ -68,9 +68,9 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
 
         let mut extract_statement_span = |statement| {
             let expn_span = filtered_statement_span(statement)?;
-            let (span, visible_macro) = unexpand(expn_span)?;
+            let (span, expn_kind) = unexpand(expn_span)?;
 
-            initial_covspans.push(SpanFromMir::new(span, visible_macro, bcb));
+            initial_covspans.push(SpanFromMir::new(span, expn_kind, bcb));
             Some(())
         };
         for statement in data.statements.iter() {
@@ -79,9 +79,9 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
 
         let mut extract_terminator_span = |terminator| {
             let expn_span = filtered_terminator_span(terminator)?;
-            let (span, visible_macro) = unexpand(expn_span)?;
+            let (span, expn_kind) = unexpand(expn_span)?;
 
-            initial_covspans.push(SpanFromMir::new(span, visible_macro, bcb));
+            initial_covspans.push(SpanFromMir::new(span, expn_kind, bcb));
             Some(())
         };
         extract_terminator_span(data.terminator());
@@ -214,7 +214,7 @@ pub(crate) struct SpanFromMir {
     /// With the exception of `fn_sig_span`, this should always be contained
     /// within `body_span`.
     pub(crate) span: Span,
-    pub(crate) visible_macro: Option<Symbol>,
+    pub(crate) expn_kind: Option<ExpnKind>,
     pub(crate) bcb: BasicCoverageBlock,
 }
 
@@ -223,12 +223,12 @@ fn for_fn_sig(fn_sig_span: Span) -> Self {
         Self::new(fn_sig_span, None, START_BCB)
     }
 
-    pub(crate) fn new(span: Span, visible_macro: Option<Symbol>, bcb: BasicCoverageBlock) -> Self {
-        Self { span, visible_macro, bcb }
+    pub(crate) fn new(span: Span, expn_kind: Option<ExpnKind>, bcb: BasicCoverageBlock) -> Self {
+        Self { span, expn_kind, bcb }
     }
 
     pub(crate) fn into_covspan(self) -> Covspan {
-        let Self { span, visible_macro: _, bcb } = self;
+        let Self { span, expn_kind: _, bcb } = self;
         Covspan { span, bcb }
     }
 }
diff --git a/compiler/rustc_mir_transform/src/coverage/unexpand.rs b/compiler/rustc_mir_transform/src/coverage/unexpand.rs
index 8cde291..cb86154 100644
--- a/compiler/rustc_mir_transform/src/coverage/unexpand.rs
+++ b/compiler/rustc_mir_transform/src/coverage/unexpand.rs
@@ -1,4 +1,4 @@
-use rustc_span::{ExpnKind, MacroKind, Span, Symbol};
+use rustc_span::{ExpnKind, Span};
 
 /// Walks through the expansion ancestors of `original_span` to find a span that
 /// is contained in `body_span` and has the same [syntax context] as `body_span`.
@@ -13,20 +13,15 @@ pub(crate) fn unexpand_into_body_span(original_span: Span, body_span: Span) -> O
 ///
 /// If the returned span represents a bang-macro invocation (e.g. `foo!(..)`),
 /// the returned symbol will be the name of that macro (e.g. `foo`).
-pub(crate) fn unexpand_into_body_span_with_visible_macro(
+pub(crate) fn unexpand_into_body_span_with_expn_kind(
     original_span: Span,
     body_span: Span,
-) -> Option<(Span, Option<Symbol>)> {
+) -> Option<(Span, Option<ExpnKind>)> {
     let (span, prev) = unexpand_into_body_span_with_prev(original_span, body_span)?;
 
-    let visible_macro = prev
-        .map(|prev| match prev.ctxt().outer_expn_data().kind {
-            ExpnKind::Macro(MacroKind::Bang, name) => Some(name),
-            _ => None,
-        })
-        .flatten();
+    let expn_kind = prev.map(|prev| prev.ctxt().outer_expn_data().kind);
 
-    Some((span, visible_macro))
+    Some((span, expn_kind))
 }
 
 /// Walks through the expansion ancestors of `original_span` to find a span that
diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
index 50aaed0..ce109ef 100644
--- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs
+++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
@@ -10,7 +10,7 @@
 
 use crate::{inline, pass_manager as pm};
 
-pub fn provide(providers: &mut Providers) {
+pub(super) fn provide(providers: &mut Providers) {
     providers.cross_crate_inlinable = cross_crate_inlinable;
 }
 
diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs
index ea473b6..bd58b1b 100644
--- a/compiler/rustc_mir_transform/src/ctfe_limit.rs
+++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs
@@ -8,7 +8,7 @@
 use rustc_middle::ty::TyCtxt;
 use tracing::instrument;
 
-pub struct CtfeLimit;
+pub(super) struct CtfeLimit;
 
 impl<'tcx> crate::MirPass<'tcx> for CtfeLimit {
     #[instrument(skip(self, _tcx, body))]
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 46f7408..79f12be 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -26,7 +26,7 @@
 const BLOCK_LIMIT: usize = 100;
 const PLACE_LIMIT: usize = 100;
 
-pub struct DataflowConstProp;
+pub(super) struct DataflowConstProp;
 
 impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
@@ -332,7 +332,7 @@ fn handle_switch_int<'mir>(
 }
 
 impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self {
+    fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self {
         let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
         Self {
             map,
@@ -838,14 +838,14 @@ fn process_projection_elem(
     }
 }
 
-struct OperandCollector<'tcx, 'map, 'locals, 'a> {
+struct OperandCollector<'a, 'locals, 'tcx> {
     state: &'a State<FlatSet<Scalar>>,
     visitor: &'a mut Collector<'tcx, 'locals>,
-    ecx: &'map mut InterpCx<'tcx, DummyMachine>,
-    map: &'map Map<'tcx>,
+    ecx: &'a mut InterpCx<'tcx, DummyMachine>,
+    map: &'a Map<'tcx>,
 }
 
-impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> {
+impl<'tcx> Visitor<'tcx> for OperandCollector<'_, '_, 'tcx> {
     fn visit_projection_elem(
         &mut self,
         _: PlaceRef<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index 9081a2e..65c0375 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -28,7 +28,7 @@
 ///
 /// The `borrowed` set must be a `BitSet` of all the locals that are ever borrowed in this body. It
 /// can be generated via the [`borrowed_locals`] function.
-pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let borrowed_locals = borrowed_locals(body);
 
     // If the user requests complete debuginfo, mark the locals that appear in it as live, so
@@ -127,7 +127,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     }
 }
 
-pub enum DeadStoreElimination {
+pub(super) enum DeadStoreElimination {
     Initial,
     Final,
 }
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index 71af099..e870a71 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -150,7 +150,7 @@ fn type_will_always_be_passed_directly(ty: Ty<'_>) -> bool {
 /// body of the function instead of just the signature. These can be useful for optimization
 /// purposes on a best-effort basis. We compute them here and store them into the crate metadata so
 /// dependent crates can use them.
-pub fn deduced_param_attrs<'tcx>(
+pub(super) fn deduced_param_attrs<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
 ) -> &'tcx [DeducedParamAttrs] {
diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
index be50c1d..c8179d5 100644
--- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
+++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
@@ -13,7 +13,7 @@
 
 use super::simplify::simplify_cfg;
 
-pub struct DeduplicateBlocks;
+pub(super) struct DeduplicateBlocks;
 
 impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs
index a878f77..ad7ccef 100644
--- a/compiler/rustc_mir_transform/src/deref_separator.rs
+++ b/compiler/rustc_mir_transform/src/deref_separator.rs
@@ -1,16 +1,15 @@
-use rustc_index::IndexVec;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
-pub struct Derefer;
+pub(super) struct Derefer;
 
-pub struct DerefChecker<'a, 'tcx> {
+struct DerefChecker<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     patcher: MirPatch<'tcx>,
-    local_decls: &'a IndexVec<Local, LocalDecl<'tcx>>,
+    local_decls: &'a LocalDecls<'tcx>,
 }
 
 impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> {
@@ -67,7 +66,7 @@ fn visit_place(&mut self, place: &mut Place<'tcx>, cntxt: PlaceContext, loc: Loc
     }
 }
 
-pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+pub(super) fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let patch = MirPatch::new(body);
     let mut checker = DerefChecker { tcx, patcher: patch, local_decls: &body.local_decls };
 
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 8940a21..175097e 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -146,7 +146,7 @@
 use rustc_mir_dataflow::Analysis;
 use tracing::{debug, trace};
 
-pub struct DestinationPropagation;
+pub(super) struct DestinationPropagation;
 
 impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
@@ -163,7 +163,8 @@ fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let def_id = body.source.def_id();
-        let mut allocations = Allocations::default();
+        let mut candidates = Candidates::default();
+        let mut write_info = WriteInfo::default();
         trace!(func = ?tcx.def_path_str(def_id));
 
         let borrowed = rustc_mir_dataflow::impls::borrowed_locals(body);
@@ -191,12 +192,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         loop {
             // PERF: Can we do something smarter than recalculating the candidates and liveness
             // results?
-            let mut candidates = find_candidates(
-                body,
-                &borrowed,
-                &mut allocations.candidates,
-                &mut allocations.candidates_reverse,
-            );
+            candidates.reset_and_find(body, &borrowed);
             trace!(?candidates);
             dest_prop_mir_dump(tcx, body, &points, &live, round_count);
 
@@ -204,7 +200,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                 &mut candidates,
                 &points,
                 &live,
-                &mut allocations.write_info,
+                &mut write_info,
                 body,
             );
 
@@ -253,20 +249,8 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     }
 }
 
-/// Container for the various allocations that we need.
-///
-/// We store these here and hand out `&mut` access to them, instead of dropping and recreating them
-/// frequently. Everything with a `&'alloc` lifetime points into here.
-#[derive(Default)]
-struct Allocations {
-    candidates: FxIndexMap<Local, Vec<Local>>,
-    candidates_reverse: FxIndexMap<Local, Vec<Local>>,
-    write_info: WriteInfo,
-    // PERF: Do this for `MaybeLiveLocals` allocations too.
-}
-
-#[derive(Debug)]
-struct Candidates<'alloc> {
+#[derive(Debug, Default)]
+struct Candidates {
     /// The set of candidates we are considering in this optimization.
     ///
     /// We will always merge the key into at most one of its values.
@@ -281,11 +265,12 @@ struct Candidates<'alloc> {
     ///
     /// We will still report that we would like to merge `_1` and `_2` in an attempt to allow us to
     /// remove that assignment.
-    c: &'alloc mut FxIndexMap<Local, Vec<Local>>,
+    c: FxIndexMap<Local, Vec<Local>>,
+
     /// A reverse index of the `c` set; if the `c` set contains `a => Place { local: b, proj }`,
     /// then this contains `b => a`.
     // PERF: Possibly these should be `SmallVec`s?
-    reverse: &'alloc mut FxIndexMap<Local, Vec<Local>>,
+    reverse: FxIndexMap<Local, Vec<Local>>,
 }
 
 //////////////////////////////////////////////////////////
@@ -358,19 +343,40 @@ fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Locatio
 //
 // This section enforces bullet point 2
 
-struct FilterInformation<'a, 'body, 'alloc, 'tcx> {
-    body: &'body Body<'tcx>,
+struct FilterInformation<'a, 'tcx> {
+    body: &'a Body<'tcx>,
     points: &'a DenseLocationMap,
     live: &'a SparseIntervalMatrix<Local, PointIndex>,
-    candidates: &'a mut Candidates<'alloc>,
-    write_info: &'alloc mut WriteInfo,
+    candidates: &'a mut Candidates,
+    write_info: &'a mut WriteInfo,
     at: Location,
 }
 
 // We first implement some utility functions which we will expose removing candidates according to
 // different needs. Throughout the liveness filtering, the `candidates` are only ever accessed
 // through these methods, and not directly.
-impl<'alloc> Candidates<'alloc> {
+impl Candidates {
+    /// Collects the candidates for merging.
+    ///
+    /// This is responsible for enforcing the first and third bullet point.
+    fn reset_and_find<'tcx>(&mut self, body: &Body<'tcx>, borrowed: &BitSet<Local>) {
+        self.c.clear();
+        self.reverse.clear();
+        let mut visitor = FindAssignments { body, candidates: &mut self.c, borrowed };
+        visitor.visit_body(body);
+        // Deduplicate candidates.
+        for (_, cands) in self.c.iter_mut() {
+            cands.sort();
+            cands.dedup();
+        }
+        // Generate the reverse map.
+        for (src, cands) in self.c.iter() {
+            for dest in cands.iter().copied() {
+                self.reverse.entry(dest).or_default().push(*src);
+            }
+        }
+    }
+
     /// Just `Vec::retain`, but the condition is inverted and we add debugging output
     fn vec_filter_candidates(
         src: Local,
@@ -445,7 +451,7 @@ enum CandidateFilter {
     Remove,
 }
 
-impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
+impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
     /// Filters the set of candidates to remove those that conflict.
     ///
     /// The steps we take are exactly those that are outlined at the top of the file. For each
@@ -463,12 +469,12 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
     /// before the statement/terminator will correctly report locals that are read in the
     /// statement/terminator to be live. We are additionally conservative by treating all written to
     /// locals as also being read from.
-    fn filter_liveness<'b>(
-        candidates: &mut Candidates<'alloc>,
+    fn filter_liveness(
+        candidates: &mut Candidates,
         points: &DenseLocationMap,
         live: &SparseIntervalMatrix<Local, PointIndex>,
-        write_info_alloc: &'alloc mut WriteInfo,
-        body: &'b Body<'tcx>,
+        write_info: &mut WriteInfo,
+        body: &Body<'tcx>,
     ) {
         let mut this = FilterInformation {
             body,
@@ -477,7 +483,7 @@ fn filter_liveness<'b>(
             candidates,
             // We don't actually store anything at this scope, we just keep things here to be able
             // to reuse the allocation.
-            write_info: write_info_alloc,
+            write_info,
             // Doesn't matter what we put here, will be overwritten before being used
             at: Location::START,
         };
@@ -734,40 +740,13 @@ fn places_to_candidate_pair<'tcx>(
     Some((a, b))
 }
 
-/// Collects the candidates for merging
-///
-/// This is responsible for enforcing the first and third bullet point.
-fn find_candidates<'alloc, 'tcx>(
-    body: &Body<'tcx>,
-    borrowed: &BitSet<Local>,
-    candidates: &'alloc mut FxIndexMap<Local, Vec<Local>>,
-    candidates_reverse: &'alloc mut FxIndexMap<Local, Vec<Local>>,
-) -> Candidates<'alloc> {
-    candidates.clear();
-    candidates_reverse.clear();
-    let mut visitor = FindAssignments { body, candidates, borrowed };
-    visitor.visit_body(body);
-    // Deduplicate candidates
-    for (_, cands) in candidates.iter_mut() {
-        cands.sort();
-        cands.dedup();
-    }
-    // Generate the reverse map
-    for (src, cands) in candidates.iter() {
-        for dest in cands.iter().copied() {
-            candidates_reverse.entry(dest).or_default().push(*src);
-        }
-    }
-    Candidates { c: candidates, reverse: candidates_reverse }
-}
-
-struct FindAssignments<'a, 'alloc, 'tcx> {
+struct FindAssignments<'a, 'tcx> {
     body: &'a Body<'tcx>,
-    candidates: &'alloc mut FxIndexMap<Local, Vec<Local>>,
+    candidates: &'a mut FxIndexMap<Local, Vec<Local>>,
     borrowed: &'a BitSet<Local>,
 }
 
-impl<'tcx> Visitor<'tcx> for FindAssignments<'_, '_, 'tcx> {
+impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> {
     fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
         if let StatementKind::Assign(box (
             lhs,
@@ -819,9 +798,9 @@ fn is_local_required(local: Local, body: &Body<'_>) -> bool {
 /////////////////////////////////////////////////////////
 // MIR Dump
 
-fn dest_prop_mir_dump<'body, 'tcx>(
+fn dest_prop_mir_dump<'tcx>(
     tcx: TyCtxt<'tcx>,
-    body: &'body Body<'tcx>,
+    body: &Body<'tcx>,
     points: &DenseLocationMap,
     live: &SparseIntervalMatrix<Local, PointIndex>,
     round: usize,
diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs
index 06ae1b4..1640d34 100644
--- a/compiler/rustc_mir_transform/src/dump_mir.rs
+++ b/compiler/rustc_mir_transform/src/dump_mir.rs
@@ -7,7 +7,7 @@
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{OutFileName, OutputType};
 
-pub struct Marker(pub &'static str);
+pub(super) struct Marker(pub &'static str);
 
 impl<'tcx> crate::MirPass<'tcx> for Marker {
     fn name(&self) -> &'static str {
diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
index 1c54cd7..3884321 100644
--- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
+++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
@@ -90,7 +90,7 @@
 ///     |      ...      |
 ///     =================
 /// ```
-pub struct EarlyOtherwiseBranch;
+pub(super) struct EarlyOtherwiseBranch;
 
 impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
@@ -310,42 +310,28 @@ fn verify_candidate_branch<'tcx>(
 ) -> bool {
     // In order for the optimization to be correct, the branch must...
     // ...have exactly one statement
-    let [statement] = branch.statements.as_slice() else {
-        return false;
-    };
-    // ...assign the discriminant of `place` in that statement
-    let StatementKind::Assign(boxed) = &statement.kind else { return false };
-    let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed else { return false };
-    if *from_place != place {
-        return false;
+    if let [statement] = branch.statements.as_slice()
+        // ...assign the discriminant of `place` in that statement
+        && let StatementKind::Assign(boxed) = &statement.kind
+        && let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed
+        && *from_place == place
+        // ...make that assignment to a local
+        && discr_place.projection.is_empty()
+        // ...terminate on a `SwitchInt` that invalidates that local
+        && let TerminatorKind::SwitchInt { discr: switch_op, targets, .. } =
+            &branch.terminator().kind
+        && *switch_op == Operand::Move(*discr_place)
+        // ...fall through to `destination` if the switch misses
+        && destination == targets.otherwise()
+        // ...have a branch for value `value`
+        && let mut iter = targets.iter()
+        && let Some((target_value, _)) = iter.next()
+        && target_value == value
+        // ...and have no more branches
+        && iter.next().is_none()
+    {
+        true
+    } else {
+        false
     }
-    // ...make that assignment to a local
-    if discr_place.projection.len() != 0 {
-        return false;
-    }
-    // ...terminate on a `SwitchInt` that invalidates that local
-    let TerminatorKind::SwitchInt { discr: switch_op, targets, .. } = &branch.terminator().kind
-    else {
-        return false;
-    };
-    if *switch_op != Operand::Move(*discr_place) {
-        return false;
-    }
-    // ...fall through to `destination` if the switch misses
-    if destination != targets.otherwise() {
-        return false;
-    }
-    // ...have a branch for value `value`
-    let mut iter = targets.iter();
-    let Some((target_value, _)) = iter.next() else {
-        return false;
-    };
-    if target_value != value {
-        return false;
-    }
-    // ...and have no more branches
-    if let Some(_) = iter.next() {
-        return false;
-    }
-    true
 }
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index 5dd82f4..367a8c0 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -11,7 +11,7 @@
 use rustc_target::abi::FieldIdx;
 
 /// Constructs the types used when accessing a Box's pointer
-pub fn build_ptr_tys<'tcx>(
+fn build_ptr_tys<'tcx>(
     tcx: TyCtxt<'tcx>,
     pointee: Ty<'tcx>,
     unique_did: DefId,
@@ -26,7 +26,7 @@ pub fn build_ptr_tys<'tcx>(
 }
 
 /// Constructs the projection needed to access a Box's pointer
-pub fn build_projection<'tcx>(
+pub(super) fn build_projection<'tcx>(
     unique_ty: Ty<'tcx>,
     nonnull_ty: Ty<'tcx>,
     ptr_ty: Ty<'tcx>,
@@ -62,11 +62,13 @@ fn visit_place(
         let base_ty = self.local_decls[place.local].ty;
 
         // Derefer ensures that derefs are always the first projection
-        if place.projection.first() == Some(&PlaceElem::Deref) && base_ty.is_box() {
+        if let Some(PlaceElem::Deref) = place.projection.first()
+            && let Some(boxed_ty) = base_ty.boxed_ty()
+        {
             let source_info = self.local_decls[place.local].source_info;
 
             let (unique_ty, nonnull_ty, ptr_ty) =
-                build_ptr_tys(tcx, base_ty.boxed_ty(), self.unique_did, self.nonnull_did);
+                build_ptr_tys(tcx, boxed_ty, self.unique_did, self.nonnull_did);
 
             let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);
 
@@ -86,66 +88,65 @@ fn visit_place(
     }
 }
 
-pub struct ElaborateBoxDerefs;
+pub(super) struct ElaborateBoxDerefs;
 
 impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        if let Some(def_id) = tcx.lang_items().owned_box() {
-            let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did;
+        // If box is not present, this pass doesn't need to do anything.
+        let Some(def_id) = tcx.lang_items().owned_box() else { return };
 
-            let Some(nonnull_def) = tcx.type_of(unique_did).instantiate_identity().ty_adt_def()
-            else {
-                span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique")
-            };
+        let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did;
 
-            let nonnull_did = nonnull_def.non_enum_variant().fields[FieldIdx::ZERO].did;
+        let Some(nonnull_def) = tcx.type_of(unique_did).instantiate_identity().ty_adt_def() else {
+            span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique")
+        };
 
-            let patch = MirPatch::new(body);
+        let nonnull_did = nonnull_def.non_enum_variant().fields[FieldIdx::ZERO].did;
 
-            let local_decls = &mut body.local_decls;
+        let patch = MirPatch::new(body);
 
-            let mut visitor =
-                ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch };
+        let local_decls = &mut body.local_decls;
 
-            for (block, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
-                visitor.visit_basic_block_data(block, data);
-            }
+        let mut visitor =
+            ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch };
 
-            visitor.patch.apply(body);
+        for (block, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
+            visitor.visit_basic_block_data(block, data);
+        }
 
-            for debug_info in body.var_debug_info.iter_mut() {
-                if let VarDebugInfoContents::Place(place) = &mut debug_info.value {
-                    let mut new_projections: Option<Vec<_>> = None;
+        visitor.patch.apply(body);
 
-                    for (base, elem) in place.iter_projections() {
-                        let base_ty = base.ty(&body.local_decls, tcx).ty;
+        for debug_info in body.var_debug_info.iter_mut() {
+            if let VarDebugInfoContents::Place(place) = &mut debug_info.value {
+                let mut new_projections: Option<Vec<_>> = None;
 
-                        if elem == PlaceElem::Deref && base_ty.is_box() {
-                            // Clone the projections before us, since now we need to mutate them.
-                            let new_projections =
-                                new_projections.get_or_insert_with(|| base.projection.to_vec());
+                for (base, elem) in place.iter_projections() {
+                    let base_ty = base.ty(&body.local_decls, tcx).ty;
 
-                            let (unique_ty, nonnull_ty, ptr_ty) =
-                                build_ptr_tys(tcx, base_ty.boxed_ty(), unique_did, nonnull_did);
+                    if let PlaceElem::Deref = elem
+                        && let Some(boxed_ty) = base_ty.boxed_ty()
+                    {
+                        // Clone the projections before us, since now we need to mutate them.
+                        let new_projections =
+                            new_projections.get_or_insert_with(|| base.projection.to_vec());
 
-                            new_projections.extend_from_slice(&build_projection(
-                                unique_ty, nonnull_ty, ptr_ty,
-                            ));
-                            new_projections.push(PlaceElem::Deref);
-                        } else if let Some(new_projections) = new_projections.as_mut() {
-                            // Keep building up our projections list once we've started it.
-                            new_projections.push(elem);
-                        }
-                    }
+                        let (unique_ty, nonnull_ty, ptr_ty) =
+                            build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did);
 
-                    // Store the mutated projections if we actually changed something.
-                    if let Some(new_projections) = new_projections {
-                        place.projection = tcx.mk_place_elems(&new_projections);
+                        new_projections
+                            .extend_from_slice(&build_projection(unique_ty, nonnull_ty, ptr_ty));
+                        new_projections.push(PlaceElem::Deref);
+                    } else if let Some(new_projections) = new_projections.as_mut() {
+                        // Keep building up our projections list once we've started it.
+                        new_projections.push(elem);
                     }
                 }
+
+                // Store the mutated projections if we actually changed something.
+                if let Some(new_projections) = new_projections {
+                    place.projection = tcx.mk_place_elems(&new_projections);
+                }
             }
-        } else {
-            // box is not present, this pass doesn't need to do anything
         }
     }
 }
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index f4a951e..cb72979 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -47,7 +47,7 @@
 ///     }
 /// }
 /// ```
-pub struct ElaborateDrops;
+pub(super) struct ElaborateDrops;
 
 impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops {
     #[instrument(level = "trace", skip(self, tcx, body))]
@@ -98,9 +98,9 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 /// Records unwind edges which are known to be unreachable, because they are in `drop` terminators
 /// that can't drop anything.
 #[instrument(level = "trace", skip(body, flow_inits), ret)]
-fn compute_dead_unwinds<'mir, 'tcx>(
-    body: &'mir Body<'tcx>,
-    flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
+fn compute_dead_unwinds<'a, 'tcx>(
+    body: &'a Body<'tcx>,
+    flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
 ) -> BitSet<BasicBlock> {
     // We only need to do this pass once, because unwind edges can only
     // reach cleanup blocks, which can't have unwind edges themselves.
@@ -121,12 +121,12 @@ fn compute_dead_unwinds<'mir, 'tcx>(
     dead_unwinds
 }
 
-struct InitializationData<'a, 'mir, 'tcx> {
-    inits: ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'a, 'mir, 'tcx>>,
-    uninits: ResultsCursor<'mir, 'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>,
+struct InitializationData<'a, 'tcx> {
+    inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
+    uninits: ResultsCursor<'a, 'tcx, MaybeUninitializedPlaces<'a, 'tcx>>,
 }
 
-impl InitializationData<'_, '_, '_> {
+impl InitializationData<'_, '_> {
     fn seek_before(&mut self, loc: Location) {
         self.inits.seek_before_primary_effect(loc);
         self.uninits.seek_before_primary_effect(loc);
@@ -137,45 +137,35 @@ fn maybe_live_dead(&self, path: MovePathIndex) -> (bool, bool) {
     }
 }
 
-struct Elaborator<'a, 'b, 'mir, 'tcx> {
-    ctxt: &'a mut ElaborateDropsCtxt<'b, 'mir, 'tcx>,
-}
-
-impl fmt::Debug for Elaborator<'_, '_, '_, '_> {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        Ok(())
-    }
-}
-
-impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, '_, 'tcx> {
+impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> {
     type Path = MovePathIndex;
 
     fn patch(&mut self) -> &mut MirPatch<'tcx> {
-        &mut self.ctxt.patch
+        &mut self.patch
     }
 
     fn body(&self) -> &'a Body<'tcx> {
-        self.ctxt.body
+        self.body
     }
 
     fn tcx(&self) -> TyCtxt<'tcx> {
-        self.ctxt.tcx
+        self.tcx
     }
 
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.ctxt.param_env()
+        self.param_env()
     }
 
     #[instrument(level = "debug", skip(self), ret)]
     fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle {
         let ((maybe_live, maybe_dead), multipart) = match mode {
-            DropFlagMode::Shallow => (self.ctxt.init_data.maybe_live_dead(path), false),
+            DropFlagMode::Shallow => (self.init_data.maybe_live_dead(path), false),
             DropFlagMode::Deep => {
                 let mut some_live = false;
                 let mut some_dead = false;
                 let mut children_count = 0;
-                on_all_children_bits(self.ctxt.move_data(), path, |child| {
-                    let (live, dead) = self.ctxt.init_data.maybe_live_dead(child);
+                on_all_children_bits(self.move_data(), path, |child| {
+                    let (live, dead) = self.init_data.maybe_live_dead(child);
                     debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead));
                     some_live |= live;
                     some_dead |= dead;
@@ -195,25 +185,25 @@ fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle {
     fn clear_drop_flag(&mut self, loc: Location, path: Self::Path, mode: DropFlagMode) {
         match mode {
             DropFlagMode::Shallow => {
-                self.ctxt.set_drop_flag(loc, path, DropFlagState::Absent);
+                self.set_drop_flag(loc, path, DropFlagState::Absent);
             }
             DropFlagMode::Deep => {
-                on_all_children_bits(self.ctxt.move_data(), path, |child| {
-                    self.ctxt.set_drop_flag(loc, child, DropFlagState::Absent)
+                on_all_children_bits(self.move_data(), path, |child| {
+                    self.set_drop_flag(loc, child, DropFlagState::Absent)
                 });
             }
         }
     }
 
     fn field_subpath(&self, path: Self::Path, field: FieldIdx) -> Option<Self::Path> {
-        rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
+        rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| match e {
             ProjectionElem::Field(idx, _) => idx == field,
             _ => false,
         })
     }
 
     fn array_subpath(&self, path: Self::Path, index: u64, size: u64) -> Option<Self::Path> {
-        rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
+        rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| match e {
             ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
                 debug_assert!(size == min_length, "min_length should be exact for arrays");
                 assert!(!from_end, "from_end should not be used for array element ConstantIndex");
@@ -224,34 +214,40 @@ fn array_subpath(&self, path: Self::Path, index: u64, size: u64) -> Option<Self:
     }
 
     fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path> {
-        rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| {
+        rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| {
             e == ProjectionElem::Deref
         })
     }
 
     fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option<Self::Path> {
-        rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
+        rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| match e {
             ProjectionElem::Downcast(_, idx) => idx == variant,
             _ => false,
         })
     }
 
     fn get_drop_flag(&mut self, path: Self::Path) -> Option<Operand<'tcx>> {
-        self.ctxt.drop_flag(path).map(Operand::Copy)
+        self.drop_flag(path).map(Operand::Copy)
     }
 }
 
-struct ElaborateDropsCtxt<'a, 'mir, 'tcx> {
+struct ElaborateDropsCtxt<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    body: &'mir Body<'tcx>,
+    body: &'a Body<'tcx>,
     env: &'a MoveDataParamEnv<'tcx>,
-    init_data: InitializationData<'a, 'mir, 'tcx>,
+    init_data: InitializationData<'a, 'tcx>,
     drop_flags: IndexVec<MovePathIndex, Option<Local>>,
     patch: MirPatch<'tcx>,
 }
 
-impl<'b, 'mir, 'tcx> ElaborateDropsCtxt<'b, 'mir, 'tcx> {
-    fn move_data(&self) -> &'b MoveData<'tcx> {
+impl fmt::Debug for ElaborateDropsCtxt<'_, '_> {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        Ok(())
+    }
+}
+
+impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
+    fn move_data(&self) -> &'a MoveData<'tcx> {
         &self.env.move_data
     }
 
@@ -370,15 +366,7 @@ fn elaborate_drops(&mut self) {
                         }
                     };
                     self.init_data.seek_before(self.body.terminator_loc(bb));
-                    elaborate_drop(
-                        &mut Elaborator { ctxt: self },
-                        terminator.source_info,
-                        place,
-                        path,
-                        target,
-                        unwind,
-                        bb,
-                    )
+                    elaborate_drop(self, terminator.source_info, place, path, target, unwind, bb)
                 }
                 LookupResult::Parent(None) => {}
                 LookupResult::Parent(Some(_)) => {
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index 2703dc5..9a93c3a 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -64,7 +64,7 @@ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
 }
 
 impl AssertLintKind {
-    pub fn lint(&self) -> &'static Lint {
+    pub(crate) fn lint(&self) -> &'static Lint {
         match self {
             AssertLintKind::ArithmeticOverflow => lint::builtin::ARITHMETIC_OVERFLOW,
             AssertLintKind::UnconditionalPanic => lint::builtin::UNCONDITIONAL_PANIC,
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 199fd0f..0efaa17 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -11,7 +11,7 @@
 
 use crate::errors;
 
-pub struct FunctionItemReferences;
+pub(super) struct FunctionItemReferences;
 
 impl<'tcx> crate::MirLint<'tcx> for FunctionItemReferences {
     fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index df0fcc4..e5d2b13 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -109,7 +109,7 @@
 
 use crate::ssa::{AssignedValue, SsaLocals};
 
-pub struct GVN;
+pub(super) struct GVN;
 
 impl<'tcx> crate::MirPass<'tcx> for GVN {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 6cc7e0e..03ef808 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -32,9 +32,11 @@
 
 const TOP_DOWN_DEPTH_LIMIT: usize = 5;
 
+// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden
+// by custom rustc drivers, running all the steps by themselves. See #114628.
 pub struct Inline;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Clone, Debug)]
 struct CallSite<'tcx> {
     callee: Instance<'tcx>,
     fn_sig: ty::PolyFnSig<'tcx>,
@@ -156,7 +158,6 @@ fn process_blocks(&mut self, caller_body: &mut Body<'tcx>, blocks: Range<BasicBl
             match self.try_inlining(caller_body, &callsite) {
                 Err(reason) => {
                     debug!("not-inlined {} [{}]", callsite.callee, reason);
-                    continue;
                 }
                 Ok(new_blocks) => {
                     debug!("inlined {}", callsite.callee);
@@ -638,7 +639,7 @@ fn dest_needs_borrow(place: Place<'_>) -> bool {
             );
             let dest_ty = dest.ty(caller_body, self.tcx);
             let temp =
-                Place::from(self.new_call_temp(caller_body, &callsite, dest_ty, return_block));
+                Place::from(self.new_call_temp(caller_body, callsite, dest_ty, return_block));
             caller_body[callsite.block].statements.push(Statement {
                 source_info: callsite.source_info,
                 kind: StatementKind::Assign(Box::new((temp, dest))),
@@ -657,7 +658,7 @@ fn dest_needs_borrow(place: Place<'_>) -> bool {
                 true,
                 self.new_call_temp(
                     caller_body,
-                    &callsite,
+                    callsite,
                     destination.ty(caller_body, self.tcx).ty,
                     return_block,
                 ),
@@ -665,7 +666,7 @@ fn dest_needs_borrow(place: Place<'_>) -> bool {
         };
 
         // Copy the arguments if needed.
-        let args = self.make_call_args(args, &callsite, caller_body, &callee_body, return_block);
+        let args = self.make_call_args(args, callsite, caller_body, &callee_body, return_block);
 
         let mut integrator = Integrator {
             args: &args,
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 4fbfa74..a9591bf 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -13,13 +13,13 @@
 use crate::simplify::simplify_duplicate_switch_targets;
 use crate::take_array;
 
-pub enum InstSimplify {
+pub(super) enum InstSimplify {
     BeforeInline,
     AfterSimplifyCfg,
 }
 
 impl InstSimplify {
-    pub fn name(&self) -> &'static str {
+    fn name(&self) -> &'static str {
         match self {
             InstSimplify::BeforeInline => "InstSimplify-before-inline",
             InstSimplify::AfterSimplifyCfg => "InstSimplify-after-simplifycfg",
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index 02dd56e..e950c2c 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -55,7 +55,7 @@
 
 use crate::cost_checker::CostChecker;
 
-pub struct JumpThreading;
+pub(super) struct JumpThreading;
 
 const MAX_BACKTRACK: usize = 5;
 const MAX_COST: usize = 100;
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 61405fb..e964310 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -26,7 +26,7 @@
 
 use crate::errors::{AssertLint, AssertLintKind};
 
-pub struct KnownPanicsLint;
+pub(super) struct KnownPanicsLint;
 
 impl<'tcx> crate::MirLint<'tcx> for KnownPanicsLint {
     fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
@@ -852,7 +852,7 @@ fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'t
 
 /// The mode that `ConstProp` is allowed to run in for a given `Local`.
 #[derive(Clone, Copy, Debug, PartialEq)]
-pub enum ConstPropMode {
+enum ConstPropMode {
     /// The `Local` can be propagated into and reads of this `Local` can also be propagated.
     FullConstProp,
     /// The `Local` can only be propagated into and from its own block.
@@ -864,7 +864,7 @@ pub enum ConstPropMode {
 
 /// A visitor that determines locals in a MIR body
 /// that can be const propagated
-pub struct CanConstProp {
+struct CanConstProp {
     can_const_prop: IndexVec<Local, ConstPropMode>,
     // False at the beginning. Once set, no more assignments are allowed to that local.
     found_assignment: BitSet<Local>,
@@ -872,7 +872,7 @@ pub struct CanConstProp {
 
 impl CanConstProp {
     /// Returns true if `local` can be propagated
-    pub fn check<'tcx>(
+    fn check<'tcx>(
         tcx: TyCtxt<'tcx>,
         param_env: ParamEnv<'tcx>,
         body: &Body<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index f02ba71..f61cf23 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -23,7 +23,7 @@
 /// In summary, what this does is at runtime determine which enum variant is active,
 /// and instead of copying all the bytes of the largest possible variant,
 /// copy only the bytes for the currently active variant.
-pub struct EnumSizeOpt {
+pub(super) struct EnumSizeOpt {
     pub(crate) discrepancy: u64,
 }
 
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 62e73ba..0bbbf04 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -11,6 +11,7 @@
 #![feature(round_char_boundary)]
 #![feature(try_blocks)]
 #![feature(yeet_expr)]
+#![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
 use hir::ConstContext;
@@ -72,6 +73,8 @@
 mod ffi_unwind_calls;
 mod function_item_references;
 mod gvn;
+// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden
+// by custom rustc drivers, running all the steps by themselves. See #114628.
 pub mod inline;
 mod instsimplify;
 mod jump_threading;
@@ -459,8 +462,8 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
     tcx.alloc_steal_mir(body)
 }
 
-// Made public such that `mir_drops_elaborated_and_const_checked` can be overridden
-// by custom rustc drivers, running all the steps by themselves.
+// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden
+// by custom rustc drivers, running all the steps by themselves. See #114628.
 pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     assert!(body.phase == MirPhase::Analysis(AnalysisPhase::Initial));
     let did = body.source.def_id();
diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs
index 7460680..2373399 100644
--- a/compiler/rustc_mir_transform/src/lint.rs
+++ b/compiler/rustc_mir_transform/src/lint.rs
@@ -13,7 +13,7 @@
 use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_mir_dataflow::{Analysis, ResultsCursor};
 
-pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
+pub(super) fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
     let always_live_locals = &always_storage_live_locals(body);
 
     let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals))
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 55eec33..6d63560 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -7,7 +7,7 @@
 
 use crate::take_array;
 
-pub struct LowerIntrinsics;
+pub(super) struct LowerIntrinsics;
 
 impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
@@ -35,20 +35,19 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                         terminator.kind = TerminatorKind::Goto { target };
                     }
                     sym::forget => {
-                        if let Some(target) = *target {
-                            block.statements.push(Statement {
-                                source_info: terminator.source_info,
-                                kind: StatementKind::Assign(Box::new((
-                                    *destination,
-                                    Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
-                                        span: terminator.source_info.span,
-                                        user_ty: None,
-                                        const_: Const::zero_sized(tcx.types.unit),
-                                    }))),
-                                ))),
-                            });
-                            terminator.kind = TerminatorKind::Goto { target };
-                        }
+                        let target = target.unwrap();
+                        block.statements.push(Statement {
+                            source_info: terminator.source_info,
+                            kind: StatementKind::Assign(Box::new((
+                                *destination,
+                                Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
+                                    span: terminator.source_info.span,
+                                    user_ty: None,
+                                    const_: Const::zero_sized(tcx.types.unit),
+                                }))),
+                            ))),
+                        });
+                        terminator.kind = TerminatorKind::Goto { target };
                     }
                     sym::copy_nonoverlapping => {
                         let target = target.unwrap();
@@ -121,43 +120,41 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                         terminator.kind = TerminatorKind::Goto { target };
                     }
                     sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
-                        if let Some(target) = *target {
-                            let Ok([lhs, rhs]) = take_array(args) else {
-                                bug!("Wrong arguments for {} intrinsic", intrinsic.name);
-                            };
-                            let bin_op = match intrinsic.name {
-                                sym::add_with_overflow => BinOp::AddWithOverflow,
-                                sym::sub_with_overflow => BinOp::SubWithOverflow,
-                                sym::mul_with_overflow => BinOp::MulWithOverflow,
-                                _ => bug!("unexpected intrinsic"),
-                            };
-                            block.statements.push(Statement {
-                                source_info: terminator.source_info,
-                                kind: StatementKind::Assign(Box::new((
-                                    *destination,
-                                    Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))),
-                                ))),
-                            });
-                            terminator.kind = TerminatorKind::Goto { target };
-                        }
+                        let target = target.unwrap();
+                        let Ok([lhs, rhs]) = take_array(args) else {
+                            bug!("Wrong arguments for {} intrinsic", intrinsic.name);
+                        };
+                        let bin_op = match intrinsic.name {
+                            sym::add_with_overflow => BinOp::AddWithOverflow,
+                            sym::sub_with_overflow => BinOp::SubWithOverflow,
+                            sym::mul_with_overflow => BinOp::MulWithOverflow,
+                            _ => bug!("unexpected intrinsic"),
+                        };
+                        block.statements.push(Statement {
+                            source_info: terminator.source_info,
+                            kind: StatementKind::Assign(Box::new((
+                                *destination,
+                                Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))),
+                            ))),
+                        });
+                        terminator.kind = TerminatorKind::Goto { target };
                     }
                     sym::size_of | sym::min_align_of => {
-                        if let Some(target) = *target {
-                            let tp_ty = generic_args.type_at(0);
-                            let null_op = match intrinsic.name {
-                                sym::size_of => NullOp::SizeOf,
-                                sym::min_align_of => NullOp::AlignOf,
-                                _ => bug!("unexpected intrinsic"),
-                            };
-                            block.statements.push(Statement {
-                                source_info: terminator.source_info,
-                                kind: StatementKind::Assign(Box::new((
-                                    *destination,
-                                    Rvalue::NullaryOp(null_op, tp_ty),
-                                ))),
-                            });
-                            terminator.kind = TerminatorKind::Goto { target };
-                        }
+                        let target = target.unwrap();
+                        let tp_ty = generic_args.type_at(0);
+                        let null_op = match intrinsic.name {
+                            sym::size_of => NullOp::SizeOf,
+                            sym::min_align_of => NullOp::AlignOf,
+                            _ => bug!("unexpected intrinsic"),
+                        };
+                        block.statements.push(Statement {
+                            source_info: terminator.source_info,
+                            kind: StatementKind::Assign(Box::new((
+                                *destination,
+                                Rvalue::NullaryOp(null_op, tp_ty),
+                            ))),
+                        });
+                        terminator.kind = TerminatorKind::Goto { target };
                     }
                     sym::read_via_copy => {
                         let Ok([arg]) = take_array(args) else {
@@ -219,17 +216,23 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                         terminator.kind = TerminatorKind::Goto { target };
                     }
                     sym::discriminant_value => {
-                        if let (Some(target), Some(arg)) = (*target, args[0].node.place()) {
-                            let arg = tcx.mk_place_deref(arg);
-                            block.statements.push(Statement {
-                                source_info: terminator.source_info,
-                                kind: StatementKind::Assign(Box::new((
-                                    *destination,
-                                    Rvalue::Discriminant(arg),
-                                ))),
-                            });
-                            terminator.kind = TerminatorKind::Goto { target };
-                        }
+                        let target = target.unwrap();
+                        let Ok([arg]) = take_array(args) else {
+                            span_bug!(
+                                terminator.source_info.span,
+                                "Wrong arguments for discriminant_value intrinsic"
+                            );
+                        };
+                        let arg = arg.node.place().unwrap();
+                        let arg = tcx.mk_place_deref(arg);
+                        block.statements.push(Statement {
+                            source_info: terminator.source_info,
+                            kind: StatementKind::Assign(Box::new((
+                                *destination,
+                                Rvalue::Discriminant(arg),
+                            ))),
+                        });
+                        terminator.kind = TerminatorKind::Goto { target };
                     }
                     sym::offset => {
                         let target = target.unwrap();
@@ -267,7 +270,6 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                                 Rvalue::Cast(CastKind::Transmute, arg.node, dst_ty),
                             ))),
                         });
-
                         if let Some(target) = *target {
                             terminator.kind = TerminatorKind::Goto { target };
                         } else {
@@ -299,7 +301,6 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                                 Rvalue::Aggregate(Box::new(kind), fields.into()),
                             ))),
                         });
-
                         terminator.kind = TerminatorKind::Goto { target };
                     }
                     sym::ptr_metadata => {
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index 555309a..ca59d4d 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -5,7 +5,7 @@
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
-pub struct LowerSliceLenCalls;
+pub(super) struct LowerSliceLenCalls;
 
 impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
@@ -17,7 +17,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     }
 }
 
-pub fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let language_items = tcx.lang_items();
     let Some(slice_len_fn_item_def_id) = language_items.slice_len_fn() else {
         // there is no lang item to compare to :)
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 233b39f..2a2616b 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -10,7 +10,7 @@
 
 use super::simplify::simplify_cfg;
 
-pub struct MatchBranchSimplification;
+pub(super) struct MatchBranchSimplification;
 
 impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs
index 41ce03c..7f9d0a5 100644
--- a/compiler/rustc_mir_transform/src/mentioned_items.rs
+++ b/compiler/rustc_mir_transform/src/mentioned_items.rs
@@ -5,7 +5,7 @@
 use rustc_session::Session;
 use rustc_span::source_map::Spanned;
 
-pub struct MentionedItems;
+pub(super) struct MentionedItems;
 
 struct MentionedItemsVisitor<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
index 1b4972d..b6d6ef5 100644
--- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
+++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
@@ -7,7 +7,7 @@
 
 use crate::simplify;
 
-pub struct MultipleReturnTerminators;
+pub(super) struct MultipleReturnTerminators;
 
 impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs
index 94573a9..98fa149 100644
--- a/compiler/rustc_mir_transform/src/nrvo.rs
+++ b/compiler/rustc_mir_transform/src/nrvo.rs
@@ -30,7 +30,7 @@
 ///
 /// [#47954]: https://github.com/rust-lang/rust/pull/47954
 /// [#71003]: https://github.com/rust-lang/rust/pull/71003
-pub struct RenameReturnPlace;
+pub(super) struct RenameReturnPlace;
 
 impl<'tcx> crate::MirPass<'tcx> for RenameReturnPlace {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index 28d4e1a..60ece5e 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -269,12 +269,7 @@ pub(super) fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when
     validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body);
 }
 
-pub(super) fn dump_mir_for_pass<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &Body<'tcx>,
-    pass_name: &str,
-    is_after: bool,
-) {
+fn dump_mir_for_pass<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, pass_name: &str, is_after: bool) {
     mir::dump_mir(
         tcx,
         true,
diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs
index ad71c62..ef011d2 100644
--- a/compiler/rustc_mir_transform/src/prettify.rs
+++ b/compiler/rustc_mir_transform/src/prettify.rs
@@ -15,7 +15,7 @@
 ///
 /// Thus after this pass, all the successors of a block are later than it in the
 /// `IndexVec`, unless that successor is a back-edge (such as from a loop).
-pub struct ReorderBasicBlocks;
+pub(super) struct ReorderBasicBlocks;
 
 impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks {
     fn is_enabled(&self, _session: &Session) -> bool {
@@ -43,7 +43,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 /// assigned or referenced will have a smaller number.
 ///
 /// (Does not reorder arguments nor the [`RETURN_PLACE`].)
-pub struct ReorderLocals;
+pub(super) struct ReorderLocals;
 
 impl<'tcx> crate::MirPass<'tcx> for ReorderLocals {
     fn is_enabled(&self, _session: &Session) -> bool {
@@ -135,8 +135,8 @@ fn visit_local(&mut self, l: Local, context: PlaceContext, _location: Location)
 }
 
 struct LocalUpdater<'tcx> {
-    pub map: IndexVec<Local, Local>,
-    pub tcx: TyCtxt<'tcx>,
+    map: IndexVec<Local, Local>,
+    tcx: TyCtxt<'tcx>,
 }
 
 impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index cf0a569..65309f6 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -37,7 +37,7 @@
 /// After this pass is run, `promoted_fragments` will hold the MIR body corresponding to each
 /// newly created `Constant`.
 #[derive(Default)]
-pub struct PromoteTemps<'tcx> {
+pub(super) struct PromoteTemps<'tcx> {
     pub promoted_fragments: Cell<IndexVec<Promoted, Body<'tcx>>>,
 }
 
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index 4a447d2..25b9878 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -70,7 +70,7 @@
 ///
 /// For immutable borrows, we do not need to preserve such uniqueness property,
 /// so we perform all the possible instantiations without removing the `_1 = &_2` statement.
-pub struct ReferencePropagation;
+pub(super) struct ReferencePropagation;
 
 impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
index ccba8d0..37197c3 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -8,7 +8,7 @@
 /// A pass that removes noop landing pads and replaces jumps to them with
 /// `UnwindAction::Continue`. This is important because otherwise LLVM generates
 /// terrible code for these.
-pub struct RemoveNoopLandingPads;
+pub(super) struct RemoveNoopLandingPads;
 
 impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs
index 5801fde..71399eb 100644
--- a/compiler/rustc_mir_transform/src/remove_place_mention.rs
+++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs
@@ -4,7 +4,7 @@
 use rustc_middle::ty::TyCtxt;
 use tracing::trace;
 
-pub struct RemovePlaceMention;
+pub(super) struct RemovePlaceMention;
 
 impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs
index 329b30d..3ecb4a8 100644
--- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs
+++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs
@@ -4,7 +4,7 @@
 use rustc_middle::ty::TyCtxt;
 use tracing::trace;
 
-pub struct RemoveStorageMarkers;
+pub(super) struct RemoveStorageMarkers;
 
 impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
index aafe971..c58f492 100644
--- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
@@ -14,7 +14,7 @@
 /// like [#90770].
 ///
 /// [#90770]: https://github.com/rust-lang/rust/issues/90770
-pub struct RemoveUninitDrops;
+pub(super) struct RemoveUninitDrops;
 
 impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
index 43109aa..28925ba 100644
--- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
@@ -10,7 +10,7 @@
 
 use super::simplify::simplify_cfg;
 
-pub struct RemoveUnneededDrops;
+pub(super) struct RemoveUnneededDrops;
 
 impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index 9aa46bd..f13bb1c 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -4,7 +4,7 @@
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
-pub struct RemoveZsts;
+pub(super) struct RemoveZsts;
 
 impl<'tcx> crate::MirPass<'tcx> for RemoveZsts {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs
index 50637e2..ebcf5b5 100644
--- a/compiler/rustc_mir_transform/src/required_consts.rs
+++ b/compiler/rustc_mir_transform/src/required_consts.rs
@@ -1,7 +1,7 @@
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::{traversal, Body, ConstOperand, Location};
 
-pub struct RequiredConstsVisitor<'a, 'tcx> {
+pub(super) struct RequiredConstsVisitor<'a, 'tcx> {
     required_consts: &'a mut Vec<ConstOperand<'tcx>>,
 }
 
@@ -10,7 +10,7 @@ fn new(required_consts: &'a mut Vec<ConstOperand<'tcx>>) -> Self {
         RequiredConstsVisitor { required_consts }
     }
 
-    pub fn compute_required_consts(body: &mut Body<'tcx>) {
+    pub(super) fn compute_required_consts(body: &mut Body<'tcx>) {
         let mut required_consts = Vec::new();
         let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts);
         for (bb, bb_data) in traversal::reverse_postorder(&body) {
diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs
index 29312a9..3db962b 100644
--- a/compiler/rustc_mir_transform/src/reveal_all.rs
+++ b/compiler/rustc_mir_transform/src/reveal_all.rs
@@ -4,7 +4,7 @@
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
-pub struct RevealAll;
+pub(super) struct RevealAll;
 
 impl<'tcx> crate::MirPass<'tcx> for RevealAll {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 8c70e42..cf8ef58 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -26,7 +26,7 @@
 
 mod async_destructor_ctor;
 
-pub fn provide(providers: &mut Providers) {
+pub(super) fn provide(providers: &mut Providers) {
     providers.mir_shims = make_shim;
 }
 
@@ -331,7 +331,7 @@ fn new_body<'tcx>(
     body
 }
 
-pub struct DropShimElaborator<'a, 'tcx> {
+pub(super) struct DropShimElaborator<'a, 'tcx> {
     pub body: &'a Body<'tcx>,
     pub patch: MirPatch<'tcx>,
     pub tcx: TyCtxt<'tcx>,
@@ -913,7 +913,7 @@ fn build_call_shim<'tcx>(
     body
 }
 
-pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
+pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
     debug_assert!(tcx.is_constructor(ctor_id));
 
     let param_env = tcx.param_env_reveal_all_normalized(ctor_id);
diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
index 50810f2..c88953a 100644
--- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
+++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
@@ -23,7 +23,7 @@
 
 use super::{local_decls_for_sig, new_body};
 
-pub fn build_async_destructor_ctor_shim<'tcx>(
+pub(super) fn build_async_destructor_ctor_shim<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
     ty: Option<Ty<'tcx>>,
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 1478b86..cb8e1df 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -35,7 +35,7 @@
 use smallvec::SmallVec;
 use tracing::{debug, trace};
 
-pub enum SimplifyCfg {
+pub(super) enum SimplifyCfg {
     Initial,
     PromoteConsts,
     RemoveFalseEdges,
@@ -50,7 +50,7 @@ pub enum SimplifyCfg {
 }
 
 impl SimplifyCfg {
-    pub fn name(&self) -> &'static str {
+    fn name(&self) -> &'static str {
         match self {
             SimplifyCfg::Initial => "SimplifyCfg-initial",
             SimplifyCfg::PromoteConsts => "SimplifyCfg-promote-consts",
@@ -66,7 +66,7 @@ pub fn name(&self) -> &'static str {
     }
 }
 
-pub(crate) fn simplify_cfg(body: &mut Body<'_>) {
+pub(super) fn simplify_cfg(body: &mut Body<'_>) {
     CfgSimplifier::new(body).simplify();
     remove_dead_blocks(body);
 
@@ -85,13 +85,13 @@ fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     }
 }
 
-pub struct CfgSimplifier<'a, 'tcx> {
+struct CfgSimplifier<'a, 'tcx> {
     basic_blocks: &'a mut IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
     pred_count: IndexVec<BasicBlock, u32>,
 }
 
 impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
-    pub fn new(body: &'a mut Body<'tcx>) -> Self {
+    fn new(body: &'a mut Body<'tcx>) -> Self {
         let mut pred_count = IndexVec::from_elem(0u32, &body.basic_blocks);
 
         // we can't use mir.predecessors() here because that counts
@@ -111,7 +111,7 @@ pub fn new(body: &'a mut Body<'tcx>) -> Self {
         CfgSimplifier { basic_blocks, pred_count }
     }
 
-    pub fn simplify(mut self) {
+    fn simplify(mut self) {
         self.strip_nops();
 
         // Vec of the blocks that should be merged. We store the indices here, instead of the
@@ -280,7 +280,7 @@ fn strip_nops(&mut self) {
     }
 }
 
-pub fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) {
+pub(super) fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) {
     if let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind {
         let otherwise = targets.otherwise();
         if targets.iter().any(|t| t.1 == otherwise) {
@@ -292,7 +292,7 @@ pub fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) {
     }
 }
 
-pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
+pub(super) fn remove_dead_blocks(body: &mut Body<'_>) {
     let should_deduplicate_unreachable = |bbdata: &BasicBlockData<'_>| {
         // CfgSimplifier::simplify leaves behind some unreachable basic blocks without a
         // terminator. Those blocks will be deleted by remove_dead_blocks, but we run just
@@ -360,7 +360,7 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
     }
 }
 
-pub enum SimplifyLocals {
+pub(super) enum SimplifyLocals {
     BeforeConstProp,
     AfterGVN,
     Final,
@@ -385,7 +385,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     }
 }
 
-pub fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
+pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
     // First, we're going to get a count of *actual* uses for every `Local`.
     let mut used_locals = UsedLocals::new(body);
 
@@ -397,7 +397,7 @@ pub fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
     remove_unused_definitions_helper(&mut used_locals, body);
 }
 
-pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
+fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
     // First, we're going to get a count of *actual* uses for every `Local`.
     let mut used_locals = UsedLocals::new(body);
 
diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs
index 5a014bb..e83b472 100644
--- a/compiler/rustc_mir_transform/src/simplify_branches.rs
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -2,10 +2,11 @@
 use rustc_middle::ty::TyCtxt;
 use tracing::trace;
 
-pub enum SimplifyConstCondition {
+pub(super) enum SimplifyConstCondition {
     AfterConstProp,
     Final,
 }
+
 /// A pass that replaces a branch with a goto when its condition is known.
 impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
     fn name(&self) -> &'static str {
diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
index bd30ecc..644bcb5 100644
--- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
@@ -23,7 +23,7 @@
 /// ```ignore (MIR)
 /// switchInt(_4) -> [43i32: bb3, otherwise: bb2];
 /// ```
-pub struct SimplifyComparisonIntegral;
+pub(super) struct SimplifyComparisonIntegral;
 
 impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs
index 64a9287..2605926 100644
--- a/compiler/rustc_mir_transform/src/single_use_consts.rs
+++ b/compiler/rustc_mir_transform/src/single_use_consts.rs
@@ -19,7 +19,7 @@
 ///
 /// It also removes *never*-used constants, since it had all the information
 /// needed to do that too, including updating the debug info.
-pub struct SingleUseConsts;
+pub(super) struct SingleUseConsts;
 
 impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 3c5ccc0..e6dd2cf 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -11,7 +11,7 @@
 use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
 use tracing::{debug, instrument};
 
-pub struct ScalarReplacementOfAggregates;
+pub(super) struct ScalarReplacementOfAggregates;
 
 impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index c125476..cf8622c 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -16,7 +16,7 @@
 use rustc_middle::ty::{ParamEnv, TyCtxt};
 use tracing::{debug, instrument, trace};
 
-pub struct SsaLocals {
+pub(super) struct SsaLocals {
     /// Assignments to each local. This defines whether the local is SSA.
     assignments: IndexVec<Local, Set1<DefLocation>>,
     /// We visit the body in reverse postorder, to ensure each local is assigned before it is used.
@@ -32,14 +32,18 @@ pub struct SsaLocals {
     borrowed_locals: BitSet<Local>,
 }
 
-pub enum AssignedValue<'a, 'tcx> {
+pub(super) enum AssignedValue<'a, 'tcx> {
     Arg,
     Rvalue(&'a mut Rvalue<'tcx>),
     Terminator,
 }
 
 impl SsaLocals {
-    pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ParamEnv<'tcx>) -> SsaLocals {
+    pub(super) fn new<'tcx>(
+        tcx: TyCtxt<'tcx>,
+        body: &Body<'tcx>,
+        param_env: ParamEnv<'tcx>,
+    ) -> SsaLocals {
         let assignment_order = Vec::with_capacity(body.local_decls.len());
 
         let assignments = IndexVec::from_elem(Set1::Empty, &body.local_decls);
@@ -101,25 +105,25 @@ pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ParamEnv<'tcx>
         ssa
     }
 
-    pub fn num_locals(&self) -> usize {
+    pub(super) fn num_locals(&self) -> usize {
         self.assignments.len()
     }
 
-    pub fn locals(&self) -> impl Iterator<Item = Local> {
+    pub(super) fn locals(&self) -> impl Iterator<Item = Local> {
         self.assignments.indices()
     }
 
-    pub fn is_ssa(&self, local: Local) -> bool {
+    pub(super) fn is_ssa(&self, local: Local) -> bool {
         matches!(self.assignments[local], Set1::One(_))
     }
 
     /// Return the number of uses if a local that are not "Deref".
-    pub fn num_direct_uses(&self, local: Local) -> u32 {
+    pub(super) fn num_direct_uses(&self, local: Local) -> u32 {
         self.direct_uses[local]
     }
 
     #[inline]
-    pub fn assignment_dominates(
+    pub(super) fn assignment_dominates(
         &self,
         dominators: &Dominators<BasicBlock>,
         local: Local,
@@ -131,7 +135,7 @@ pub fn assignment_dominates(
         }
     }
 
-    pub fn assignments<'a, 'tcx>(
+    pub(super) fn assignments<'a, 'tcx>(
         &'a self,
         body: &'a Body<'tcx>,
     ) -> impl Iterator<Item = (Local, &'a Rvalue<'tcx>, Location)> + 'a {
@@ -148,7 +152,7 @@ pub fn assignments<'a, 'tcx>(
         })
     }
 
-    pub fn for_each_assignment_mut<'tcx>(
+    pub(super) fn for_each_assignment_mut<'tcx>(
         &self,
         basic_blocks: &mut IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
         mut f: impl FnMut(Local, AssignedValue<'_, 'tcx>, Location),
@@ -194,17 +198,17 @@ pub fn for_each_assignment_mut<'tcx>(
     ///   _d => _a // transitively through _c
     ///
     /// Exception: we do not see through the return place, as it cannot be instantiated.
-    pub fn copy_classes(&self) -> &IndexSlice<Local, Local> {
+    pub(super) fn copy_classes(&self) -> &IndexSlice<Local, Local> {
         &self.copy_classes
     }
 
     /// Set of SSA locals that are immutably borrowed.
-    pub fn borrowed_locals(&self) -> &BitSet<Local> {
+    pub(super) fn borrowed_locals(&self) -> &BitSet<Local> {
         &self.borrowed_locals
     }
 
     /// Make a property uniform on a copy equivalence class by removing elements.
-    pub fn meet_copy_equivalence(&self, property: &mut BitSet<Local>) {
+    pub(super) fn meet_copy_equivalence(&self, property: &mut BitSet<Local>) {
         // Consolidate to have a local iff all its copies are.
         //
         // `copy_classes` defines equivalence classes between locals. The `local`s that recursively
diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
index 51a3226..6957394 100644
--- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
@@ -12,7 +12,7 @@
 use rustc_target::abi::{Abi, Variants};
 use tracing::trace;
 
-pub struct UnreachableEnumBranching;
+pub(super) struct UnreachableEnumBranching;
 
 fn get_discriminant_local(terminator: &TerminatorKind<'_>) -> Option<Local> {
     if let TerminatorKind::SwitchInt { discr: Operand::Move(p), .. } = terminator {
diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs
index b8da86f..c60cbae 100644
--- a/compiler/rustc_mir_transform/src/unreachable_prop.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs
@@ -10,7 +10,7 @@
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_target::abi::Size;
 
-pub struct UnreachablePropagation;
+pub(super) struct UnreachablePropagation;
 
 impl crate::MirPass<'_> for UnreachablePropagation {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 69e2592..18865c7 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -1,6 +1,7 @@
 //! Validates the MIR to ensure that invariants are upheld.
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir as hir;
 use rustc_hir::LangItem;
 use rustc_index::bit_set::BitSet;
 use rustc_index::IndexVec;
@@ -25,7 +26,7 @@ enum EdgeKind {
     Normal,
 }
 
-pub struct Validator {
+pub(super) struct Validator {
     /// Describes at which point in the pipeline this validation is happening.
     pub when: String,
     /// The phase for which we are upholding the dialect. If the given phase forbids a specific
@@ -530,7 +531,7 @@ fn visit_source_scope(&mut self, scope: SourceScope) {
 ///
 /// `caller_body` is used to detect cycles in MIR inlining and MIR validation before
 /// `optimized_mir` is available.
-pub fn validate_types<'tcx>(
+pub(super) fn validate_types<'tcx>(
     tcx: TyCtxt<'tcx>,
     mir_phase: MirPhase,
     param_env: ty::ParamEnv<'tcx>,
@@ -714,7 +715,17 @@ fn visit_projection_elem(
                             // since we may be in the process of computing this MIR in the
                             // first place.
                             let layout = if def_id == self.caller_body.source.def_id() {
-                                // FIXME: This is not right for async closures.
+                                self.caller_body.coroutine_layout_raw()
+                            } else if let Some(hir::CoroutineKind::Desugared(
+                                _,
+                                hir::CoroutineSource::Closure,
+                            )) = self.tcx.coroutine_kind(def_id)
+                                && let ty::ClosureKind::FnOnce =
+                                    args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap()
+                                && self.caller_body.source.def_id()
+                                    == self.tcx.coroutine_by_move_body_def_id(def_id)
+                            {
+                                // Same if this is the by-move body of a coroutine-closure.
                                 self.caller_body.coroutine_layout_raw()
                             } else {
                                 self.tcx.coroutine_layout(def_id, args.as_coroutine().kind_ty())
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 8515ab4..093697a 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1041,8 +1041,11 @@ fn find_vtable_types_for_unsizing<'tcx>(
     match (source_ty.kind(), target_ty.kind()) {
         (&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _))
         | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(a, b),
-        (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
-            ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty())
+        (_, _)
+            if let Some(source_boxed) = source_ty.boxed_ty()
+                && let Some(target_boxed) = target_ty.boxed_ty() =>
+        {
+            ptr_vtable(source_boxed, target_boxed)
         }
 
         // T as dyn* Trait
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index b22e8e3..91101dd 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -1,5 +1,7 @@
 // tidy-alphabetical-start
 #![feature(array_windows)]
+#![feature(if_let_guard)]
+#![feature(let_chains)]
 #![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index c7a9846..17b6ec7 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -3,7 +3,7 @@
 mod opaque_types;
 mod weak_types;
 
-use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_type_ir::fast_reject::DeepRejectCtxt;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
 use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _};
@@ -106,6 +106,12 @@ fn probe_and_match_goal_against_assumption(
         if let Some(projection_pred) = assumption.as_projection_clause() {
             if projection_pred.projection_def_id() == goal.predicate.def_id() {
                 let cx = ecx.cx();
+                if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
+                    goal.predicate.alias.args,
+                    projection_pred.skip_binder().projection_term.args,
+                ) {
+                    return Err(NoSolution);
+                }
                 ecx.probe_trait_candidate(source).enter(|ecx| {
                     let assumption_projection_pred =
                         ecx.instantiate_binder_with_infer(projection_pred);
@@ -144,7 +150,7 @@ fn consider_impl_candidate(
 
         let goal_trait_ref = goal.predicate.alias.trait_ref(cx);
         let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
-        if !DeepRejectCtxt::new(ecx.cx(), TreatParams::ForLookup).args_may_unify(
+        if !DeepRejectCtxt::relate_rigid_infer(ecx.cx()).args_may_unify(
             goal.predicate.alias.trait_ref(cx).args,
             impl_trait_ref.skip_binder().args,
         ) {
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 67b001d..683d8da 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -2,7 +2,7 @@
 
 use rustc_ast_ir::Movability;
 use rustc_type_ir::data_structures::IndexSet;
-use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_type_ir::fast_reject::DeepRejectCtxt;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
 use rustc_type_ir::visit::TypeVisitableExt as _;
@@ -47,7 +47,7 @@ fn consider_impl_candidate(
         let cx = ecx.cx();
 
         let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
-        if !DeepRejectCtxt::new(ecx.cx(), TreatParams::ForLookup)
+        if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
             .args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
         {
             return Err(NoSolution);
@@ -124,6 +124,13 @@ fn probe_and_match_goal_against_assumption(
             if trait_clause.def_id() == goal.predicate.def_id()
                 && trait_clause.polarity() == goal.predicate.polarity
             {
+                if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
+                    goal.predicate.trait_ref.args,
+                    trait_clause.skip_binder().trait_ref.args,
+                ) {
+                    return Err(NoSolution);
+                }
+
                 ecx.probe_trait_candidate(source).enter(|ecx| {
                     let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
                     ecx.eq(
diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml
index b338961..c59ae48 100644
--- a/compiler/rustc_parse/Cargo.toml
+++ b/compiler/rustc_parse/Cargo.toml
@@ -12,6 +12,7 @@
 rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_index = { path = "../rustc_index" }
 rustc_lexer = { path = "../rustc_lexer" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 8e8d91c..ec9a676 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -381,6 +381,7 @@
     *[false] unicode
     } escape
 
+
 parse_invalid_comparison_operator = invalid comparison operator `{$invalid}`
     .use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}`
     .spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering`
@@ -581,6 +582,11 @@
     .suggestion_add_trait = add a trait here
     .suggestion_remove_for = for an inherent impl, drop this `for`
 
+parse_misspelled_kw = {$is_incorrect_case ->
+                    [true] write keyword `{$similar_kw}` in lowercase
+                    *[false] there is a keyword `{$similar_kw}` with a similar name
+}
+
 parse_modifier_lifetime = `{$modifier}` may only modify trait bounds, not lifetime bounds
     .suggestion = remove the `{$modifier}`
 
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index f309390..b7232ff 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -13,7 +13,6 @@
 };
 use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::parse::ParseSess;
-use rustc_span::edition::Edition;
 use rustc_span::symbol::Symbol;
 use rustc_span::{BytePos, Pos, Span};
 use tracing::debug;
@@ -188,9 +187,7 @@ fn next_token(&mut self) -> (Token, bool) {
                     preceded_by_whitespace = true;
                     continue;
                 }
-                rustc_lexer::TokenKind::Ident => {
-                    self.ident(start)
-                }
+                rustc_lexer::TokenKind::Ident => self.ident(start),
                 rustc_lexer::TokenKind::RawIdent => {
                     let sym = nfc_normalize(self.str_from(start + BytePos(2)));
                     let span = self.mk_sp(start, self.pos);
@@ -205,20 +202,31 @@ fn next_token(&mut self) -> (Token, bool) {
                     self.report_unknown_prefix(start);
                     self.ident(start)
                 }
-                rustc_lexer::TokenKind::InvalidIdent
-                | rustc_lexer::TokenKind::InvalidPrefix
+                rustc_lexer::TokenKind::UnknownPrefixLifetime => {
+                    self.report_unknown_prefix(start);
+                    // Include the leading `'` in the real identifier, for macro
+                    // expansion purposes. See #12512 for the gory details of why
+                    // this is necessary.
+                    let lifetime_name = self.str_from(start);
+                    self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
+                    let ident = Symbol::intern(lifetime_name);
+                    token::Lifetime(ident, IdentIsRaw::No)
+                }
+                rustc_lexer::TokenKind::InvalidIdent | rustc_lexer::TokenKind::InvalidPrefix
                     // Do not recover an identifier with emoji if the codepoint is a confusable
                     // with a recoverable substitution token, like `➖`.
-                    if !UNICODE_ARRAY
-                        .iter()
-                        .any(|&(c, _, _)| {
-                            let sym = self.str_from(start);
-                            sym.chars().count() == 1 && c == sym.chars().next().unwrap()
-                        }) =>
+                    if !UNICODE_ARRAY.iter().any(|&(c, _, _)| {
+                        let sym = self.str_from(start);
+                        sym.chars().count() == 1 && c == sym.chars().next().unwrap()
+                    }) =>
                 {
                     let sym = nfc_normalize(self.str_from(start));
                     let span = self.mk_sp(start, self.pos);
-                    self.psess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default()
+                    self.psess
+                        .bad_unicode_identifiers
+                        .borrow_mut()
+                        .entry(sym)
+                        .or_default()
                         .push(span);
                     token::Ident(sym, IdentIsRaw::No)
                 }
@@ -249,9 +257,9 @@ fn next_token(&mut self) -> (Token, bool) {
                     let suffix = if suffix_start < self.pos {
                         let string = self.str_from(suffix_start);
                         if string == "_" {
-                            self
-                                .dcx()
-                                .emit_err(errors::UnderscoreLiteralSuffix { span: self.mk_sp(suffix_start, self.pos) });
+                            self.dcx().emit_err(errors::UnderscoreLiteralSuffix {
+                                span: self.mk_sp(suffix_start, self.pos),
+                            });
                             None
                         } else {
                             Some(Symbol::intern(string))
@@ -269,12 +277,47 @@ fn next_token(&mut self) -> (Token, bool) {
                     self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
                     if starts_with_number {
                         let span = self.mk_sp(start, self.pos);
-                        self.dcx().struct_err("lifetimes cannot start with a number")
+                        self.dcx()
+                            .struct_err("lifetimes cannot start with a number")
                             .with_span(span)
                             .stash(span, StashKey::LifetimeIsChar);
                     }
                     let ident = Symbol::intern(lifetime_name);
-                    token::Lifetime(ident)
+                    token::Lifetime(ident, IdentIsRaw::No)
+                }
+                rustc_lexer::TokenKind::RawLifetime => {
+                    self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
+
+                    let ident_start = start + BytePos(3);
+                    let prefix_span = self.mk_sp(start, ident_start);
+
+                    if prefix_span.at_least_rust_2021() {
+                        let lifetime_name_without_tick = self.str_from(ident_start);
+                        // Put the `'` back onto the lifetime name.
+                        let mut lifetime_name = String::with_capacity(lifetime_name_without_tick.len() + 1);
+                        lifetime_name.push('\'');
+                        lifetime_name += lifetime_name_without_tick;
+                        let sym = Symbol::intern(&lifetime_name);
+
+                        token::Lifetime(sym, IdentIsRaw::Yes)
+                    } else {
+                        // Otherwise, this should be parsed like `'r`. Warn about it though.
+                        self.psess.buffer_lint(
+                            RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
+                            prefix_span,
+                            ast::CRATE_NODE_ID,
+                            BuiltinLintDiag::RawPrefix(prefix_span),
+                        );
+
+                        // Reset the state so we just lex the `'r`.
+                        let lt_start = start + BytePos(2);
+                        self.pos = lt_start;
+                        self.cursor = Cursor::new(&str_before[2 as usize..]);
+
+                        let lifetime_name = self.str_from(start);
+                        let ident = Symbol::intern(lifetime_name);
+                        token::Lifetime(ident, IdentIsRaw::No)
+                    }
                 }
                 rustc_lexer::TokenKind::Semi => token::Semi,
                 rustc_lexer::TokenKind::Comma => token::Comma,
@@ -331,16 +374,19 @@ fn next_token(&mut self) -> (Token, bool) {
                     // first remove compound tokens like `<<` from `rustc_lexer`, and then add
                     // fancier error recovery to it, as there will be less overall work to do this
                     // way.
-                    let (token, sugg) = unicode_chars::check_for_substitution(self, start, c, repeats+1);
+                    let (token, sugg) =
+                        unicode_chars::check_for_substitution(self, start, c, repeats + 1);
                     self.dcx().emit_err(errors::UnknownTokenStart {
                         span: self.mk_sp(start, self.pos + Pos::from_usize(repeats * c.len_utf8())),
                         escaped: escaped_char(c),
                         sugg,
-                        null: if c == '\x00' {Some(errors::UnknownTokenNull)} else {None},
+                        null: if c == '\x00' { Some(errors::UnknownTokenNull) } else { None },
                         repeat: if repeats > 0 {
                             swallow_next_invalid = repeats;
                             Some(errors::UnknownTokenRepeat { repeats })
-                        } else {None}
+                        } else {
+                            None
+                        },
                     });
 
                     if let Some(token) = token {
@@ -699,7 +745,7 @@ fn report_unknown_prefix(&self, start: BytePos) {
 
         let expn_data = prefix_span.ctxt().outer_expn_data();
 
-        if expn_data.edition >= Edition::Edition2021 {
+        if expn_data.edition.at_least_rust_2021() {
             // In Rust 2021, this is a hard error.
             let sugg = if prefix == "rb" {
                 Some(errors::UnknownPrefixSugg::UseBr(prefix_span))
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 49df281..205cca8 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -1,3 +1,4 @@
+use std::borrow::Cow;
 use std::{iter, mem};
 
 use rustc_ast::token::{Delimiter, Token, TokenKind};
@@ -6,6 +7,7 @@
     Spacing, ToAttrTokenStream,
 };
 use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, HasTokens};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::PResult;
 use rustc_session::parse::ParseSess;
 use rustc_span::{sym, Span, DUMMY_SP};
@@ -134,9 +136,8 @@ fn to_attr_token_stream(&self) -> AttrTokenStream {
                 node_replacements.array_windows()
             {
                 assert!(
-                    node_range.0.end <= next_node_range.0.start
-                        || node_range.0.end >= next_node_range.0.end,
-                    "Node ranges should be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})",
+                    node_range.0.end <= next_node_range.0.start,
+                    "Node ranges should be disjoint: ({:?}, {:?}) ({:?}, {:?})",
                     node_range,
                     tokens,
                     next_node_range,
@@ -144,20 +145,8 @@ fn to_attr_token_stream(&self) -> AttrTokenStream {
                 );
             }
 
-            // Process the replace ranges, starting from the highest start
-            // position and working our way back. If have tokens like:
-            //
-            // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
-            //
-            // Then we will generate replace ranges for both
-            // the `#[cfg(FALSE)] field: bool` and the entire
-            // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
-            //
-            // By starting processing from the replace range with the greatest
-            // start position, we ensure that any (outer) replace range which
-            // encloses another (inner) replace range will fully overwrite the
-            // inner range's replacement.
-            for (node_range, target) in node_replacements.into_iter().rev() {
+            // Process the replace ranges.
+            for (node_range, target) in node_replacements.into_iter() {
                 assert!(
                     !node_range.0.is_empty(),
                     "Cannot replace an empty node range: {:?}",
@@ -234,6 +223,8 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
         force_collect: ForceCollect,
         f: impl FnOnce(&mut Self, AttrVec) -> PResult<'a, (R, Trailing, UsePreAttrPos)>,
     ) -> PResult<'a, R> {
+        let possible_capture_mode = self.capture_cfg;
+
         // We must collect if anything could observe the collected tokens, i.e.
         // if any of the following conditions hold.
         // - We are force collecting tokens (because force collection requires
@@ -244,9 +235,9 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
             // - Our target supports custom inner attributes (custom
             //   inner attribute invocation might require token capturing).
             || R::SUPPORTS_CUSTOM_INNER_ATTRS
-            // - We are in `capture_cfg` mode (which requires tokens if
+            // - We are in "possible capture mode" (which requires tokens if
             //   the parsed node has `#[cfg]` or `#[cfg_attr]` attributes).
-            || self.capture_cfg;
+            || possible_capture_mode;
         if !needs_collection {
             return Ok(f(self, attrs.attrs)?.0);
         }
@@ -267,18 +258,48 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
             res?
         };
 
-        // When we're not in `capture_cfg` mode, then skip collecting and
-        // return early if either of the following conditions hold.
         // - `None`: Our target doesn't support tokens at all (e.g. `NtIdent`).
+        // - `Some(None)`: Our target supports tokens and has none.
         // - `Some(Some(_))`: Our target already has tokens set (e.g. we've
-        //   parsed something like `#[my_attr] $item`). The actual parsing code
-        //   takes care of prepending any attributes to the nonterminal, so we
-        //   don't need to modify the already captured tokens.
+        //   parsed something like `#[my_attr] $item`).
+        let ret_can_hold_tokens = matches!(ret.tokens_mut(), Some(None));
+
+        // Ignore any attributes we've previously processed. This happens when
+        // an inner call to `collect_tokens` returns an AST node and then an
+        // outer call ends up with the same AST node without any additional
+        // wrapping layer.
+        let mut seen_indices = FxHashSet::default();
+        for (i, attr) in ret.attrs().iter().enumerate() {
+            let is_unseen = self.capture_state.seen_attrs.insert(attr.id);
+            if !is_unseen {
+                seen_indices.insert(i);
+            }
+        }
+        let ret_attrs: Cow<'_, [Attribute]> =
+            if seen_indices.is_empty() {
+                Cow::Borrowed(ret.attrs())
+            } else {
+                let ret_attrs =
+                    ret.attrs()
+                        .iter()
+                        .enumerate()
+                        .filter_map(|(i, attr)| {
+                            if seen_indices.contains(&i) { None } else { Some(attr.clone()) }
+                        })
+                        .collect();
+                Cow::Owned(ret_attrs)
+            };
+
+        // When we're not in "definite capture mode", then skip collecting and
+        // return early if `ret` doesn't support tokens or already has some.
         //
         // Note that this check is independent of `force_collect`. There's no
         // need to collect tokens when we don't support tokens or already have
         // tokens.
-        if !self.capture_cfg && matches!(ret.tokens_mut(), None | Some(Some(_))) {
+        let definite_capture_mode = self.capture_cfg
+            && matches!(self.capture_state.capturing, Capturing::Yes)
+            && has_cfg_or_cfg_attr(&ret_attrs);
+        if !definite_capture_mode && !ret_can_hold_tokens {
             return Ok(ret);
         }
 
@@ -297,12 +318,12 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
             //   outer and inner attributes. So this check is more precise than
             //   the earlier `needs_tokens` check, and we don't need to
             //   check `R::SUPPORTS_CUSTOM_INNER_ATTRS`.)
-            || needs_tokens(ret.attrs())
-            // - We are in `capture_cfg` mode and there are `#[cfg]` or
-            //   `#[cfg_attr]` attributes. (During normal non-`capture_cfg`
-            //   parsing, we don't need any special capturing for those
-            //   attributes, because they're builtin.)
-            || (self.capture_cfg && has_cfg_or_cfg_attr(ret.attrs()));
+            || needs_tokens(&ret_attrs)
+            // - We are in "definite capture mode", which requires that there
+            //   are `#[cfg]` or `#[cfg_attr]` attributes. (During normal
+            //   non-`capture_cfg` parsing, we don't need any special capturing
+            //   for those attributes, because they're builtin.)
+            || definite_capture_mode;
         if !needs_collection {
             return Ok(ret);
         }
@@ -336,7 +357,7 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
         // `Parser::parse_inner_attributes`, and pair them in a `ParserReplacement` with `None`,
         // which means the relevant tokens will be removed. (More details below.)
         let mut inner_attr_parser_replacements = Vec::new();
-        for attr in ret.attrs() {
+        for attr in ret_attrs.iter() {
             if attr.style == ast::AttrStyle::Inner {
                 if let Some(inner_attr_parser_range) =
                     self.capture_state.inner_attr_parser_ranges.remove(&attr.id)
@@ -359,11 +380,10 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
             // from `ParserRange` form to `NodeRange` form. We will perform the actual
             // replacement only when we convert the `LazyAttrTokenStream` to an
             // `AttrTokenStream`.
-            self.capture_state.parser_replacements
-                [parser_replacements_start..parser_replacements_end]
-                .iter()
-                .cloned()
-                .chain(inner_attr_parser_replacements.iter().cloned())
+            self.capture_state
+                .parser_replacements
+                .drain(parser_replacements_start..parser_replacements_end)
+                .chain(inner_attr_parser_replacements.into_iter())
                 .map(|(parser_range, data)| {
                     (NodeRange::new(parser_range, collect_pos.start_pos), data)
                 })
@@ -399,20 +419,12 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
             break_last_token: self.break_last_token,
             node_replacements,
         });
+        let mut tokens_used = false;
 
-        // If we support tokens and don't already have them, store the newly captured tokens.
-        if let Some(target_tokens @ None) = ret.tokens_mut() {
-            *target_tokens = Some(tokens.clone());
-        }
-
-        // If `capture_cfg` is set and we're inside a recursive call to
-        // `collect_tokens`, then we need to register a replace range if we
-        // have `#[cfg]` or `#[cfg_attr]`. This allows us to run eager
-        // cfg-expansion on the captured token stream.
-        if self.capture_cfg
-            && matches!(self.capture_state.capturing, Capturing::Yes)
-            && has_cfg_or_cfg_attr(ret.attrs())
-        {
+        // If in "definite capture mode" we need to register a replace range
+        // for the `#[cfg]` and/or `#[cfg_attr]` attrs. This allows us to run
+        // eager cfg-expansion on the captured token stream.
+        if definite_capture_mode {
             assert!(!self.break_last_token, "Should not have unglued last token with cfg attr");
 
             // What is the status here when parsing the example code at the top of this method?
@@ -429,7 +441,9 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
             // cfg-expand this AST node.
             let start_pos =
                 if has_outer_attrs { attrs.start_pos.unwrap() } else { collect_pos.start_pos };
-            let target = AttrsTarget { attrs: ret.attrs().iter().cloned().collect(), tokens };
+            let target =
+                AttrsTarget { attrs: ret_attrs.iter().cloned().collect(), tokens: tokens.clone() };
+            tokens_used = true;
             self.capture_state
                 .parser_replacements
                 .push((ParserRange(start_pos..end_pos), Some(target)));
@@ -438,7 +452,16 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
             // the outermost call to this method.
             self.capture_state.parser_replacements.clear();
             self.capture_state.inner_attr_parser_ranges.clear();
+            self.capture_state.seen_attrs.clear();
         }
+
+        // If we support tokens and don't already have them, store the newly captured tokens.
+        if let Some(target_tokens @ None) = ret.tokens_mut() {
+            tokens_used = true;
+            *target_tokens = Some(tokens);
+        }
+
+        assert!(tokens_used); // check we didn't create `tokens` unnecessarily
         Ok(ret)
     }
 }
@@ -510,9 +533,11 @@ struct FrameData {
 }
 
 /// Tokens are needed if:
-/// - any non-single-segment attributes (other than doc comments) are present; or
-/// - any `cfg_attr` attributes are present;
-/// - any single-segment, non-builtin attributes are present.
+/// - any non-single-segment attributes (other than doc comments) are present,
+///   e.g. `rustfmt::skip`; or
+/// - any `cfg_attr` attributes are present; or
+/// - any single-segment, non-builtin attributes are present, e.g. `derive`,
+///   `test`, `global_allocator`.
 fn needs_tokens(attrs: &[ast::Attribute]) -> bool {
     attrs.iter().any(|attr| match attr.ident() {
         None => !attr.is_doc_comment(),
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index fcdc10c..f6f6682 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -19,8 +19,9 @@
     Subdiagnostic,
 };
 use rustc_session::errors::ExprParenthesesNeeded;
+use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{kw, sym, Ident};
+use rustc_span::symbol::{kw, sym, AllKeywords, Ident};
 use rustc_span::{BytePos, Span, SpanSnippetError, Symbol, DUMMY_SP};
 use thin_vec::{thin_vec, ThinVec};
 use tracing::{debug, trace};
@@ -203,6 +204,37 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     }
 }
 
+#[derive(Debug, rustc_macros::Subdiagnostic)]
+#[suggestion(
+    parse_misspelled_kw,
+    applicability = "machine-applicable",
+    code = "{similar_kw}",
+    style = "verbose"
+)]
+struct MisspelledKw {
+    similar_kw: String,
+    #[primary_span]
+    span: Span,
+    is_incorrect_case: bool,
+}
+
+/// Checks if the given `lookup` identifier is similar to any keyword symbol in `candidates`.
+fn find_similar_kw(lookup: Ident, candidates: &[Symbol]) -> Option<MisspelledKw> {
+    let lowercase = lookup.name.as_str().to_lowercase();
+    let lowercase_sym = Symbol::intern(&lowercase);
+    if candidates.contains(&lowercase_sym) {
+        Some(MisspelledKw { similar_kw: lowercase, span: lookup.span, is_incorrect_case: true })
+    } else if let Some(similar_sym) = find_best_match_for_name(candidates, lookup.name, None) {
+        Some(MisspelledKw {
+            similar_kw: similar_sym.to_string(),
+            span: lookup.span,
+            is_incorrect_case: false,
+        })
+    } else {
+        None
+    }
+}
+
 struct MultiSugg {
     msg: String,
     patches: Vec<(Span, String)>,
@@ -638,9 +670,9 @@ fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
             let concat = Symbol::intern(&format!("{prev}{cur}"));
             let ident = Ident::new(concat, DUMMY_SP);
             if ident.is_used_keyword() || ident.is_reserved() || ident.is_raw_guess() {
-                let span = self.prev_token.span.to(self.token.span);
+                let concat_span = self.prev_token.span.to(self.token.span);
                 err.span_suggestion_verbose(
-                    span,
+                    concat_span,
                     format!("consider removing the space to spell keyword `{concat}`"),
                     concat,
                     Applicability::MachineApplicable,
@@ -741,9 +773,55 @@ fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
             err.span_label(sp, label_exp);
             err.span_label(self.token.span, "unexpected token");
         }
+
+        // Check for misspelled keywords if there are no suggestions added to the diagnostic.
+        if err.suggestions.as_ref().is_ok_and(|code_suggestions| code_suggestions.is_empty()) {
+            self.check_for_misspelled_kw(&mut err, &expected);
+        }
         Err(err)
     }
 
+    /// Checks if the current token or the previous token are misspelled keywords
+    /// and adds a helpful suggestion.
+    fn check_for_misspelled_kw(&self, err: &mut Diag<'_>, expected: &[TokenType]) {
+        let Some((curr_ident, _)) = self.token.ident() else {
+            return;
+        };
+        let expected_tokens: &[TokenType] =
+            expected.len().checked_sub(10).map_or(&expected, |index| &expected[index..]);
+        let expected_keywords: Vec<Symbol> = expected_tokens
+            .iter()
+            .filter_map(|token| if let TokenType::Keyword(kw) = token { Some(*kw) } else { None })
+            .collect();
+
+        // When there are a few keywords in the last ten elements of `self.expected_tokens` and the current
+        // token is an identifier, it's probably a misspelled keyword.
+        // This handles code like `async Move {}`, misspelled `if` in match guard, misspelled `else` in `if`-`else`
+        // and mispelled `where` in a where clause.
+        if !expected_keywords.is_empty()
+            && !curr_ident.is_used_keyword()
+            && let Some(misspelled_kw) = find_similar_kw(curr_ident, &expected_keywords)
+        {
+            err.subdiagnostic(misspelled_kw);
+        } else if let Some((prev_ident, _)) = self.prev_token.ident()
+            && !prev_ident.is_used_keyword()
+        {
+            // We generate a list of all keywords at runtime rather than at compile time
+            // so that it gets generated only when the diagnostic needs it.
+            // Also, it is unlikely that this list is generated multiple times because the
+            // parser halts after execution hits this path.
+            let all_keywords = AllKeywords::new().collect_used(|| prev_ident.span.edition());
+
+            // Otherwise, check the previous token with all the keywords as possible candidates.
+            // This handles code like `Struct Human;` and `While a < b {}`.
+            // We check the previous token only when the current token is an identifier to avoid false
+            // positives like suggesting keyword `for` for `extern crate foo {}`.
+            if let Some(misspelled_kw) = find_similar_kw(prev_ident, &all_keywords) {
+                err.subdiagnostic(misspelled_kw);
+            }
+        }
+    }
+
     /// The user has written `#[attr] expr` which is unsupported. (#106020)
     pub(super) fn attr_on_non_tail_expr(&self, expr: &Expr) -> ErrorGuaranteed {
         // Missing semicolon typo error.
@@ -846,6 +924,7 @@ pub(super) fn attr_on_non_tail_expr(&self, expr: &Expr) -> ErrorGuaranteed {
                 );
             }
         }
+
         err.emit()
     }
 
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 84684e8..ecc4cd9 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2050,7 +2050,7 @@ fn handle_missing_lit<L>(
         };
         // On an error path, eagerly consider a lifetime to be an unclosed character lit, if that
         // makes sense.
-        if let Some(ident) = self.token.lifetime()
+        if let Some((ident, IdentIsRaw::No)) = self.token.lifetime()
             && could_be_unclosed_char_literal(ident)
         {
             let lt = self.expect_lifetime();
@@ -2925,9 +2925,9 @@ fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a,
     }
 
     pub(crate) fn eat_label(&mut self) -> Option<Label> {
-        if let Some(ident) = self.token.lifetime() {
+        if let Some((ident, is_raw)) = self.token.lifetime() {
             // Disallow `'fn`, but with a better error message than `expect_lifetime`.
-            if ident.without_first_quote().is_reserved() {
+            if matches!(is_raw, IdentIsRaw::No) && ident.without_first_quote().is_reserved() {
                 self.dcx().emit_err(errors::InvalidLabel { span: ident.span, name: ident.name });
             }
 
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 61e3fa2..3ee6e74 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -35,6 +35,7 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, Diag, FatalError, MultiSpan, PResult};
+use rustc_index::interval::IntervalSet;
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -183,7 +184,7 @@ pub struct Parser<'a> {
 // This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
 // it doesn't unintentionally get bigger.
 #[cfg(target_pointer_width = "64")]
-rustc_data_structures::static_assert_size!(Parser<'_>, 256);
+rustc_data_structures::static_assert_size!(Parser<'_>, 288);
 
 /// Stores span information about a closure.
 #[derive(Clone, Debug)]
@@ -238,7 +239,8 @@ impl NodeRange {
     // is the position of the function's start token. This gives
     // `NodeRange(10..15)`.
     fn new(ParserRange(parser_range): ParserRange, start_pos: u32) -> NodeRange {
-        assert!(parser_range.start >= start_pos && parser_range.end >= start_pos);
+        assert!(!parser_range.is_empty());
+        assert!(parser_range.start >= start_pos);
         NodeRange((parser_range.start - start_pos)..(parser_range.end - start_pos))
     }
 }
@@ -260,6 +262,9 @@ struct CaptureState {
     capturing: Capturing,
     parser_replacements: Vec<ParserReplacement>,
     inner_attr_parser_ranges: FxHashMap<AttrId, ParserRange>,
+    // `IntervalSet` is good for perf because attrs are mostly added to this
+    // set in contiguous ranges.
+    seen_attrs: IntervalSet<AttrId>,
 }
 
 /// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that
@@ -457,6 +462,7 @@ pub fn new(
                 capturing: Capturing::No,
                 parser_replacements: Vec::new(),
                 inner_attr_parser_ranges: Default::default(),
+                seen_attrs: IntervalSet::new(u32::MAX as usize),
             },
             current_closure: None,
             recovery: Recovery::Allowed,
@@ -1666,7 +1672,7 @@ enum FlatToken {
 pub enum ParseNtResult {
     Tt(TokenTree),
     Ident(Ident, IdentIsRaw),
-    Lifetime(Ident),
+    Lifetime(Ident, IdentIsRaw),
 
     /// This case will eventually be removed, along with `Token::Interpolate`.
     Nt(Lrc<Nonterminal>),
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index e66d0df..44b169c 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -88,7 +88,7 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool {
             },
             NonterminalKind::Pat(pat_kind) => token.can_begin_pattern(pat_kind),
             NonterminalKind::Lifetime => match &token.kind {
-                token::Lifetime(_) | token::NtLifetime(..) => true,
+                token::Lifetime(..) | token::NtLifetime(..) => true,
                 _ => false,
             },
             NonterminalKind::TT | NonterminalKind::Item | NonterminalKind::Stmt => {
@@ -171,9 +171,9 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseN
             NonterminalKind::Lifetime => {
                 // We want to keep `'keyword` parsing, just like `keyword` is still
                 // an ident for nonterminal purposes.
-                return if let Some(ident) = self.token.lifetime() {
+                return if let Some((ident, is_raw)) = self.token.lifetime() {
                     self.bump();
-                    Ok(ParseNtResult::Lifetime(ident))
+                    Ok(ParseNtResult::Lifetime(ident, is_raw))
                 } else {
                     Err(self.dcx().create_err(UnexpectedNonterminal::Lifetime {
                         span: self.token.span,
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index f87b564..cbd35ff 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1,6 +1,6 @@
 use rustc_ast::mut_visit::{walk_pat, MutVisitor};
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, BinOpToken, Delimiter, Token};
+use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token};
 use rustc_ast::{
     self as ast, AttrVec, BindingMode, ByRef, Expr, ExprKind, MacCall, Mutability, Pat, PatField,
     PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
@@ -548,7 +548,7 @@ fn parse_pat_with_range_pat(
                     None => PatKind::Path(qself, path),
                 }
             }
-        } else if let Some(lt) = self.token.lifetime()
+        } else if let Some((lt, IdentIsRaw::No)) = self.token.lifetime()
             // In pattern position, we're totally fine with using "next token isn't colon"
             // as a heuristic. We could probably just always try to recover if it's a lifetime,
             // because we never have `'a: label {}` in a pattern position anyways, but it does
@@ -689,7 +689,7 @@ fn ban_pat_range_if_ambiguous(&self, pat: &Pat) {
     /// Parse `&pat` / `&mut pat`.
     fn parse_pat_deref(&mut self, expected: Option<Expected>) -> PResult<'a, PatKind> {
         self.expect_and()?;
-        if let Some(lifetime) = self.token.lifetime() {
+        if let Some((lifetime, _)) = self.token.lifetime() {
             self.bump(); // `'a`
 
             self.dcx().emit_err(UnexpectedLifetimeInPattern {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 52f0b1c..dd1cc75 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -1,5 +1,5 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, BinOpToken, Delimiter, Token, TokenKind};
+use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token, TokenKind};
 use rustc_ast::util::case::Case;
 use rustc_ast::{
     self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound,
@@ -1285,8 +1285,9 @@ pub(super) fn check_lifetime(&mut self) -> bool {
 
     /// Parses a single lifetime `'a` or panics.
     pub(super) fn expect_lifetime(&mut self) -> Lifetime {
-        if let Some(ident) = self.token.lifetime() {
-            if ident.without_first_quote().is_reserved()
+        if let Some((ident, is_raw)) = self.token.lifetime() {
+            if matches!(is_raw, IdentIsRaw::No)
+                && ident.without_first_quote().is_reserved()
                 && ![kw::UnderscoreLifetime, kw::StaticLifetime].contains(&ident.name)
             {
                 self.dcx().emit_err(errors::KeywordLifetime { span: ident.span });
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 21478a4..e41f89a 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -125,7 +125,9 @@ fn check_attributes(
                 [sym::inline, ..] => self.check_inline(hir_id, attr, span, target),
                 [sym::coverage, ..] => self.check_coverage(attr, span, target),
                 [sym::optimize, ..] => self.check_optimize(hir_id, attr, target),
-                [sym::no_sanitize, ..] => self.check_no_sanitize(hir_id, attr, span, target),
+                [sym::no_sanitize, ..] => {
+                    self.check_applied_to_fn_or_method(hir_id, attr, span, target)
+                }
                 [sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target),
                 [sym::marker, ..] => self.check_marker(hir_id, attr, span, target),
                 [sym::target_feature, ..] => {
@@ -166,10 +168,13 @@ fn check_attributes(
                     self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item)
                 }
                 [sym::rustc_lint_query_instability, ..] => {
-                    self.check_rustc_lint_query_instability(hir_id, attr, span, target)
+                    self.check_applied_to_fn_or_method(hir_id, attr, span, target)
+                }
+                [sym::rustc_lint_untracked_query_information, ..] => {
+                    self.check_applied_to_fn_or_method(hir_id, attr, span, target)
                 }
                 [sym::rustc_lint_diagnostics, ..] => {
-                    self.check_rustc_lint_diagnostics(hir_id, attr, span, target)
+                    self.check_applied_to_fn_or_method(hir_id, attr, span, target)
                 }
                 [sym::rustc_lint_opt_ty, ..] => self.check_rustc_lint_opt_ty(attr, span, target),
                 [sym::rustc_lint_opt_deny_field_access, ..] => {
@@ -452,11 +457,6 @@ fn check_optimize(&self, hir_id: HirId, attr: &Attribute, target: Target) {
         }
     }
 
-    /// Checks that `#[no_sanitize(..)]` is applied to a function or method.
-    fn check_no_sanitize(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
-        self.check_applied_to_fn_or_method(hir_id, attr, span, target)
-    }
-
     fn check_generic_attr(
         &self,
         hir_id: HirId,
@@ -1635,30 +1635,6 @@ fn check_applied_to_fn_or_method(
         }
     }
 
-    /// Checks that the `#[rustc_lint_query_instability]` attribute is only applied to a function
-    /// or method.
-    fn check_rustc_lint_query_instability(
-        &self,
-        hir_id: HirId,
-        attr: &Attribute,
-        span: Span,
-        target: Target,
-    ) {
-        self.check_applied_to_fn_or_method(hir_id, attr, span, target)
-    }
-
-    /// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or
-    /// method.
-    fn check_rustc_lint_diagnostics(
-        &self,
-        hir_id: HirId,
-        attr: &Attribute,
-        span: Span,
-        target: Target,
-    ) {
-        self.check_applied_to_fn_or_method(hir_id, attr, span, target)
-    }
-
     /// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct.
     fn check_rustc_lint_opt_ty(&self, attr: &Attribute, span: Span, target: Target) {
         match target {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 79c4245..917cb81 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2062,7 +2062,10 @@ fn record_lifetime_res(
                                 lint::builtin::ELIDED_NAMED_LIFETIMES,
                                 missing.id_for_lint,
                                 missing.span,
-                                BuiltinLintDiag::ElidedIsStatic { elided: missing.span },
+                                BuiltinLintDiag::ElidedNamedLifetimes {
+                                    elided: (missing.span, missing.kind),
+                                    resolution: lint::ElidedLifetimeResolution::Static,
+                                },
                             );
                         }
                     }
@@ -2072,9 +2075,12 @@ fn record_lifetime_res(
                             lint::builtin::ELIDED_NAMED_LIFETIMES,
                             missing.id_for_lint,
                             missing.span,
-                            BuiltinLintDiag::ElidedIsParam {
-                                elided: missing.span,
-                                param: (tcx.item_name(param.into()), tcx.source_span(param)),
+                            BuiltinLintDiag::ElidedNamedLifetimes {
+                                elided: (missing.span, missing.kind),
+                                resolution: lint::ElidedLifetimeResolution::Param(
+                                    tcx.item_name(param.into()),
+                                    tcx.source_span(param),
+                                ),
                             },
                         );
                     }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 908d50a..f3e3b36 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -842,6 +842,11 @@ pub struct NextSolverConfig {
     /// This is only `true` if `coherence` is also enabled.
     pub globally: bool,
 }
+impl Default for NextSolverConfig {
+    fn default() -> Self {
+        NextSolverConfig { coherence: true, globally: false }
+    }
+}
 
 #[derive(Clone)]
 pub enum Input {
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 45339c2..a57dc80 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -403,7 +403,7 @@ mod desc {
     pub(crate) const parse_unpretty: &str = "`string` or `string=string`";
     pub(crate) const parse_treat_err_as_bug: &str = "either no value or a non-negative number";
     pub(crate) const parse_next_solver_config: &str =
-        "a comma separated list of solver configurations: `globally` (default), and `coherence`";
+        "either `globally` (when used without an argument), `coherence` (default) or `no`";
     pub(crate) const parse_lto: &str =
         "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted";
     pub(crate) const parse_linker_plugin_lto: &str =
@@ -1105,27 +1105,16 @@ pub(crate) fn parse_treat_err_as_bug(
         }
     }
 
-    pub(crate) fn parse_next_solver_config(
-        slot: &mut Option<NextSolverConfig>,
-        v: Option<&str>,
-    ) -> bool {
+    pub(crate) fn parse_next_solver_config(slot: &mut NextSolverConfig, v: Option<&str>) -> bool {
         if let Some(config) = v {
-            let mut coherence = false;
-            let mut globally = true;
-            for c in config.split(',') {
-                match c {
-                    "globally" => globally = true,
-                    "coherence" => {
-                        globally = false;
-                        coherence = true;
-                    }
-                    _ => return false,
-                }
-            }
-
-            *slot = Some(NextSolverConfig { coherence: coherence || globally, globally });
+            *slot = match config {
+                "no" => NextSolverConfig { coherence: false, globally: false },
+                "coherence" => NextSolverConfig { coherence: true, globally: false },
+                "globally" => NextSolverConfig { coherence: true, globally: true },
+                _ => return false,
+            };
         } else {
-            *slot = Some(NextSolverConfig { coherence: true, globally: true });
+            *slot = NextSolverConfig { coherence: true, globally: true };
         }
 
         true
@@ -1878,7 +1867,7 @@ pub(crate) fn parse_mir_include_spans(slot: &mut MirIncludeSpans, v: Option<&str
         "the size at which the `large_assignments` lint starts to be emitted"),
     mutable_noalias: bool = (true, parse_bool, [TRACKED],
         "emit noalias metadata for mutable references (default: yes)"),
-    next_solver: Option<NextSolverConfig> = (None, parse_next_solver_config, [TRACKED],
+    next_solver: NextSolverConfig = (NextSolverConfig::default(), parse_next_solver_config, [TRACKED],
         "enable and configure the next generation trait solver used by rustc"),
     nll_facts: bool = (false, parse_bool, [UNTRACKED],
         "dump facts from NLL analysis into side files (default: no)"),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index db4f44e..d5240a0 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -20,7 +20,8 @@
 
 // The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`.
 symbols! {
-    // If you modify this list, adjust `is_special` and `is_used_keyword`/`is_unused_keyword`.
+    // If you modify this list, adjust `is_special`, `is_used_keyword`/`is_unused_keyword`
+    // and `AllKeywords`.
     // But this should rarely be necessary if the keywords are kept in alphabetic order.
     Keywords {
         // Special reserved identifiers used internally for elided lifetimes,
@@ -1255,6 +1256,7 @@
         mut_preserve_binding_mode_2024,
         mut_ref,
         naked,
+        naked_asm,
         naked_functions,
         name,
         names,
@@ -1655,6 +1657,7 @@
         rustc_lint_opt_deny_field_access,
         rustc_lint_opt_ty,
         rustc_lint_query_instability,
+        rustc_lint_untracked_query_information,
         rustc_macro_transparency,
         rustc_main,
         rustc_mir,
@@ -2579,3 +2582,42 @@ pub fn is_raw_guess(self) -> bool {
         self.name.can_be_raw() && self.is_reserved()
     }
 }
+
+/// An iterator over all the keywords in Rust.
+#[derive(Copy, Clone)]
+pub struct AllKeywords {
+    curr_idx: u32,
+    end_idx: u32,
+}
+
+impl AllKeywords {
+    /// Initialize a new iterator over all the keywords.
+    ///
+    /// *Note:* Please update this if a new keyword is added beyond the current
+    /// range.
+    pub fn new() -> Self {
+        AllKeywords { curr_idx: kw::Empty.as_u32(), end_idx: kw::Yeet.as_u32() }
+    }
+
+    /// Collect all the keywords in a given edition into a vector.
+    pub fn collect_used(&self, edition: impl Copy + FnOnce() -> Edition) -> Vec<Symbol> {
+        self.filter(|&keyword| {
+            keyword.is_used_keyword_always() || keyword.is_used_keyword_conditional(edition)
+        })
+        .collect()
+    }
+}
+
+impl Iterator for AllKeywords {
+    type Item = Symbol;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.curr_idx <= self.end_idx {
+            let keyword = Symbol::new(self.curr_idx);
+            self.curr_idx += 1;
+            Some(keyword)
+        } else {
+            None
+        }
+    }
+}
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index d7c66d6..2121c41 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -9,7 +9,6 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
-#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index b752a34..b1fe49f 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -1,5 +1,6 @@
 use std::borrow::Cow;
 use std::env;
+use std::num::ParseIntError;
 
 use crate::spec::{
     add_link_args, add_link_args_iter, cvs, Cc, DebuginfoKind, FramePointer, LinkArgs,
@@ -39,6 +40,25 @@ fn target_name(self) -> &'static str {
         }
     }
 
+    /// The architecture name to forward to the linker.
+    fn ld_arch(self) -> &'static str {
+        // Supported architecture names can be found in the source:
+        // https://github.com/apple-oss-distributions/ld64/blob/ld64-951.9/src/abstraction/MachOFileAbstraction.hpp#L578-L648
+        match self {
+            Armv7k => "armv7k",
+            Armv7s => "armv7s",
+            Arm64 => "arm64",
+            Arm64e => "arm64e",
+            Arm64_32 => "arm64_32",
+            // ld64 doesn't understand i686, so fall back to i386 instead
+            //
+            // Same story when linking with cc, since that ends up invoking ld64.
+            I386 | I686 => "i386",
+            X86_64 => "x86_64",
+            X86_64h => "x86_64h",
+        }
+    }
+
     pub(crate) fn target_arch(self) -> Cow<'static, str> {
         Cow::Borrowed(match self {
             Armv7k | Armv7s => "arm",
@@ -97,53 +117,85 @@ fn target_abi(self) -> &'static str {
 }
 
 fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs {
+    // From the man page for ld64 (`man ld`):
+    // > The linker accepts universal (multiple-architecture) input files,
+    // > but always creates a "thin" (single-architecture), standard Mach-O
+    // > output file. The architecture for the output file is specified using
+    // > the -arch option.
+    //
+    // The linker has heuristics to determine the desired architecture, but to
+    // be safe, and to avoid a warning, we set the architecture explicitly.
+    let mut args =
+        TargetOptions::link_args(LinkerFlavor::Darwin(Cc::No, Lld::No), &["-arch", arch.ld_arch()]);
+
+    // From the man page for ld64 (`man ld`):
+    // > This is set to indicate the platform, oldest supported version of
+    // > that platform that output is to be used on, and the SDK that the
+    // > output was built against. platform [...] may be one of the following
+    // > strings:
+    // > - macos
+    // > - ios
+    // > - tvos
+    // > - watchos
+    // > - bridgeos
+    // > - visionos
+    // > - xros
+    // > - mac-catalyst
+    // > - ios-simulator
+    // > - tvos-simulator
+    // > - watchos-simulator
+    // > - visionos-simulator
+    // > - xros-simulator
+    // > - driverkit
+    //
+    // Like with `-arch`, the linker can figure out the platform versions
+    // itself from the binaries being linked, but to be safe, we specify the
+    // desired versions here explicitly.
     let platform_name: StaticCow<str> = match abi {
         TargetAbi::Normal => os.into(),
         TargetAbi::Simulator => format!("{os}-simulator").into(),
         TargetAbi::MacCatalyst => "mac-catalyst".into(),
     };
-
     let min_version: StaticCow<str> = {
-        let (major, minor) = match os {
-            "ios" => ios_deployment_target(arch, abi.target_abi()),
-            "tvos" => tvos_deployment_target(),
-            "watchos" => watchos_deployment_target(),
-            "visionos" => visionos_deployment_target(),
-            "macos" => macos_deployment_target(arch),
-            _ => unreachable!(),
-        };
-        format!("{major}.{minor}").into()
+        let (major, minor, patch) = deployment_target(os, arch, abi);
+        format!("{major}.{minor}.{patch}").into()
     };
+    // Lie about the SDK version, we don't know it here
     let sdk_version = min_version.clone();
-
-    let mut args = TargetOptions::link_args(
-        LinkerFlavor::Darwin(Cc::No, Lld::No),
-        &["-arch", arch.target_name(), "-platform_version"],
-    );
     add_link_args_iter(
         &mut args,
         LinkerFlavor::Darwin(Cc::No, Lld::No),
-        [platform_name, min_version, sdk_version].into_iter(),
+        ["-platform_version".into(), platform_name, min_version, sdk_version].into_iter(),
     );
+
     if abi != TargetAbi::MacCatalyst {
+        // CC forwards the `-arch` to the linker, so we use the same value
+        // here intentionally.
         add_link_args(
             &mut args,
             LinkerFlavor::Darwin(Cc::Yes, Lld::No),
-            &["-arch", arch.target_name()],
+            &["-arch", arch.ld_arch()],
         );
     } else {
         add_link_args_iter(
             &mut args,
             LinkerFlavor::Darwin(Cc::Yes, Lld::No),
-            ["-target".into(), mac_catalyst_llvm_target(arch).into()].into_iter(),
+            ["-target".into(), llvm_target(os, arch, abi)].into_iter(),
         );
     }
 
     args
 }
 
-pub(crate) fn opts(os: &'static str, arch: Arch, abi: TargetAbi) -> TargetOptions {
-    TargetOptions {
+/// Get the base target options, LLVM target and `target_arch` from the three
+/// things that uniquely identify Rust's Apple targets: The OS, the
+/// architecture, and the ABI.
+pub(crate) fn base(
+    os: &'static str,
+    arch: Arch,
+    abi: TargetAbi,
+) -> (TargetOptions, StaticCow<str>, StaticCow<str>) {
+    let opts = TargetOptions {
         abi: abi.target_abi().into(),
         os: os.into(),
         cpu: arch.target_cpu(abi).into(),
@@ -193,10 +245,11 @@ pub(crate) fn opts(os: &'static str, arch: Arch, abi: TargetAbi) -> TargetOption
         link_env: Cow::Borrowed(&[(Cow::Borrowed("ZERO_AR_DATE"), Cow::Borrowed("1"))]),
 
         ..Default::default()
-    }
+    };
+    (opts, llvm_target(os, arch, abi), arch.target_arch())
 }
 
-pub fn sdk_version(platform: u32) -> Option<(u32, u32)> {
+pub fn sdk_version(platform: u32) -> Option<(u16, u8)> {
     // NOTE: These values are from an arbitrary point in time but shouldn't make it into the final
     // binary since the final link command will have the current SDK version passed to it.
     match platform {
@@ -230,58 +283,108 @@ pub fn platform(target: &Target) -> Option<u32> {
     })
 }
 
-pub fn deployment_target(target: &Target) -> Option<(u32, u32)> {
-    let (major, minor) = match &*target.os {
-        "macos" => {
-            // This does not need to be specific. It just needs to handle x86 vs M1.
-            let arch = match target.arch.as_ref() {
-                "x86" | "x86_64" => X86_64,
-                "arm64e" => Arm64e,
-                _ => Arm64,
-            };
-            macos_deployment_target(arch)
-        }
-        "ios" => {
-            let arch = match target.arch.as_ref() {
-                "arm64e" => Arm64e,
-                _ => Arm64,
-            };
-            ios_deployment_target(arch, &target.abi)
-        }
-        "watchos" => watchos_deployment_target(),
-        "tvos" => tvos_deployment_target(),
-        "visionos" => visionos_deployment_target(),
-        _ => return None,
+/// Hack for calling `deployment_target` outside of this module.
+pub fn deployment_target_for_target(target: &Target) -> (u16, u8, u8) {
+    let arch = if target.llvm_target.starts_with("arm64e") {
+        Arch::Arm64e
+    } else if target.arch == "aarch64" {
+        Arch::Arm64
+    } else {
+        // Dummy architecture, only used by `deployment_target` anyhow
+        Arch::X86_64
+    };
+    let abi = match &*target.abi {
+        "macabi" => TargetAbi::MacCatalyst,
+        "sim" => TargetAbi::Simulator,
+        "" => TargetAbi::Normal,
+        abi => unreachable!("invalid abi '{abi}' for Apple target"),
+    };
+    deployment_target(&target.os, arch, abi)
+}
+
+/// Get the deployment target based on the standard environment variables, or
+/// fall back to a sane default.
+fn deployment_target(os: &str, arch: Arch, abi: TargetAbi) -> (u16, u8, u8) {
+    // When bumping a version in here, remember to update the platform-support
+    // docs too.
+    //
+    // NOTE: If you are looking for the default deployment target, prefer
+    // `rustc --print deployment-target`, as the default here may change in
+    // future `rustc` versions.
+
+    // Minimum operating system versions currently supported by `rustc`.
+    let os_min = match os {
+        "macos" => (10, 12, 0),
+        "ios" => (10, 0, 0),
+        "tvos" => (10, 0, 0),
+        "watchos" => (5, 0, 0),
+        "visionos" => (1, 0, 0),
+        _ => unreachable!("tried to get deployment target for non-Apple platform"),
     };
 
-    Some((major, minor))
-}
+    // On certain targets it makes sense to raise the minimum OS version.
+    let min = match (os, arch, abi) {
+        // Use 11.0 on Aarch64 as that's the earliest version with M1 support.
+        ("macos", Arch::Arm64 | Arch::Arm64e, _) => (11, 0, 0),
+        ("ios", Arch::Arm64e, _) => (14, 0, 0),
+        // Mac Catalyst defaults to 13.1 in Clang.
+        ("ios", _, TargetAbi::MacCatalyst) => (13, 1, 0),
+        _ => os_min,
+    };
 
-fn from_set_deployment_target(var_name: &str) -> Option<(u32, u32)> {
-    let deployment_target = env::var(var_name).ok()?;
-    let (unparsed_major, unparsed_minor) = deployment_target.split_once('.')?;
-    let (major, minor) = (unparsed_major.parse().ok()?, unparsed_minor.parse().ok()?);
+    // The environment variable used to fetch the deployment target.
+    let env_var = match os {
+        "macos" => "MACOSX_DEPLOYMENT_TARGET",
+        "ios" => "IPHONEOS_DEPLOYMENT_TARGET",
+        "watchos" => "WATCHOS_DEPLOYMENT_TARGET",
+        "tvos" => "TVOS_DEPLOYMENT_TARGET",
+        "visionos" => "XROS_DEPLOYMENT_TARGET",
+        _ => unreachable!("tried to get deployment target env var for non-Apple platform"),
+    };
 
-    Some((major, minor))
-}
-
-fn macos_default_deployment_target(arch: Arch) -> (u32, u32) {
-    match arch {
-        Arm64 | Arm64e => (11, 0),
-        _ => (10, 12),
+    if let Ok(deployment_target) = env::var(env_var) {
+        match parse_version(&deployment_target) {
+            // It is common that the deployment target is set too low, e.g. on
+            // macOS Aarch64 to also target older x86_64, the user may set a
+            // lower deployment target than supported.
+            //
+            // To avoid such issues, we silently raise the deployment target
+            // here.
+            // FIXME: We want to show a warning when `version < os_min`.
+            Ok(version) => version.max(min),
+            // FIXME: Report erroneous environment variable to user.
+            Err(_) => min,
+        }
+    } else {
+        min
     }
 }
 
-fn macos_deployment_target(arch: Arch) -> (u32, u32) {
-    // If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
-    // Note: If bumping this version, remember to update it in the rustc/platform-support docs.
-    from_set_deployment_target("MACOSX_DEPLOYMENT_TARGET")
-        .unwrap_or_else(|| macos_default_deployment_target(arch))
-}
-
-pub(crate) fn macos_llvm_target(arch: Arch) -> String {
-    let (major, minor) = macos_deployment_target(arch);
-    format!("{}-apple-macosx{}.{}.0", arch.target_name(), major, minor)
+/// Generate the target triple that we need to pass to LLVM and/or Clang.
+fn llvm_target(os: &str, arch: Arch, abi: TargetAbi) -> StaticCow<str> {
+    // The target triple depends on the deployment target, and is required to
+    // enable features such as cross-language LTO, and for picking the right
+    // Mach-O commands.
+    //
+    // Certain optimizations also depend on the deployment target.
+    let (major, minor, patch) = deployment_target(os, arch, abi);
+    let arch = arch.target_name();
+    // Convert to the "canonical" OS name used by LLVM:
+    // https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L236-L282
+    let os = match os {
+        "macos" => "macosx",
+        "ios" => "ios",
+        "watchos" => "watchos",
+        "tvos" => "tvos",
+        "visionos" => "xros",
+        _ => unreachable!("tried to get LLVM target OS for non-Apple platform"),
+    };
+    let environment = match abi {
+        TargetAbi::Normal => "",
+        TargetAbi::MacCatalyst => "-macabi",
+        TargetAbi::Simulator => "-simulator",
+    };
+    format!("{arch}-apple-{os}{major}.{minor}.{patch}{environment}").into()
 }
 
 fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow<str>]> {
@@ -321,83 +424,19 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow<str>]> {
     }
 }
 
-fn ios_deployment_target(arch: Arch, abi: &str) -> (u32, u32) {
-    // If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
-    // Note: If bumping this version, remember to update it in the rustc/platform-support docs.
-    let (major, minor) = match (arch, abi) {
-        (Arm64e, _) => (14, 0),
-        // Mac Catalyst defaults to 13.1 in Clang.
-        (_, "macabi") => (13, 1),
-        _ => (10, 0),
-    };
-    from_set_deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((major, minor))
-}
-
-pub(crate) fn ios_llvm_target(arch: Arch) -> String {
-    // Modern iOS tooling extracts information about deployment target
-    // from LC_BUILD_VERSION. This load command will only be emitted when
-    // we build with a version specific `llvm_target`, with the version
-    // set high enough. Luckily one LC_BUILD_VERSION is enough, for Xcode
-    // to pick it up (since std and core are still built with the fallback
-    // of version 7.0 and hence emit the old LC_IPHONE_MIN_VERSION).
-    let (major, minor) = ios_deployment_target(arch, "");
-    format!("{}-apple-ios{}.{}.0", arch.target_name(), major, minor)
-}
-
-pub(crate) fn mac_catalyst_llvm_target(arch: Arch) -> String {
-    let (major, minor) = ios_deployment_target(arch, "macabi");
-    format!("{}-apple-ios{}.{}.0-macabi", arch.target_name(), major, minor)
-}
-
-pub(crate) fn ios_sim_llvm_target(arch: Arch) -> String {
-    let (major, minor) = ios_deployment_target(arch, "sim");
-    format!("{}-apple-ios{}.{}.0-simulator", arch.target_name(), major, minor)
-}
-
-fn tvos_deployment_target() -> (u32, u32) {
-    // If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
-    // Note: If bumping this version, remember to update it in the rustc platform-support docs.
-    from_set_deployment_target("TVOS_DEPLOYMENT_TARGET").unwrap_or((10, 0))
-}
-
-pub(crate) fn tvos_llvm_target(arch: Arch) -> String {
-    let (major, minor) = tvos_deployment_target();
-    format!("{}-apple-tvos{}.{}.0", arch.target_name(), major, minor)
-}
-
-pub(crate) fn tvos_sim_llvm_target(arch: Arch) -> String {
-    let (major, minor) = tvos_deployment_target();
-    format!("{}-apple-tvos{}.{}.0-simulator", arch.target_name(), major, minor)
-}
-
-fn watchos_deployment_target() -> (u32, u32) {
-    // If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
-    // Note: If bumping this version, remember to update it in the rustc platform-support docs.
-    from_set_deployment_target("WATCHOS_DEPLOYMENT_TARGET").unwrap_or((5, 0))
-}
-
-pub(crate) fn watchos_llvm_target(arch: Arch) -> String {
-    let (major, minor) = watchos_deployment_target();
-    format!("{}-apple-watchos{}.{}.0", arch.target_name(), major, minor)
-}
-
-pub(crate) fn watchos_sim_llvm_target(arch: Arch) -> String {
-    let (major, minor) = watchos_deployment_target();
-    format!("{}-apple-watchos{}.{}.0-simulator", arch.target_name(), major, minor)
-}
-
-fn visionos_deployment_target() -> (u32, u32) {
-    // If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
-    // Note: If bumping this version, remember to update it in the rustc platform-support docs.
-    from_set_deployment_target("XROS_DEPLOYMENT_TARGET").unwrap_or((1, 0))
-}
-
-pub(crate) fn visionos_llvm_target(arch: Arch) -> String {
-    let (major, minor) = visionos_deployment_target();
-    format!("{}-apple-visionos{}.{}.0", arch.target_name(), major, minor)
-}
-
-pub(crate) fn visionos_sim_llvm_target(arch: Arch) -> String {
-    let (major, minor) = visionos_deployment_target();
-    format!("{}-apple-visionos{}.{}.0-simulator", arch.target_name(), major, minor)
+/// Parse an OS version triple (SDK version or deployment target).
+///
+/// The size of the returned numbers here are limited by Mach-O's
+/// `LC_BUILD_VERSION`.
+fn parse_version(version: &str) -> Result<(u16, u8, u8), ParseIntError> {
+    if let Some((major, minor)) = version.split_once('.') {
+        let major = major.parse()?;
+        if let Some((minor, patch)) = minor.split_once('.') {
+            Ok((major, minor.parse()?, patch.parse()?))
+        } else {
+            Ok((major, minor.parse()?, 0))
+        }
+    } else {
+        Ok((version.parse()?, 0, 0))
+    }
 }
diff --git a/compiler/rustc_target/src/spec/base/apple/tests.rs b/compiler/rustc_target/src/spec/base/apple/tests.rs
index 7a985ad..d55b44e 100644
--- a/compiler/rustc_target/src/spec/base/apple/tests.rs
+++ b/compiler/rustc_target/src/spec/base/apple/tests.rs
@@ -1,3 +1,4 @@
+use super::parse_version;
 use crate::spec::targets::{
     aarch64_apple_darwin, aarch64_apple_ios_sim, aarch64_apple_visionos_sim,
     aarch64_apple_watchos_sim, i686_apple_darwin, x86_64_apple_darwin, x86_64_apple_ios,
@@ -42,3 +43,11 @@ fn macos_link_environment_unmodified() {
         );
     }
 }
+
+#[test]
+fn test_parse_version() {
+    assert_eq!(parse_version("10"), Ok((10, 0, 0)));
+    assert_eq!(parse_version("10.12"), Ok((10, 12, 0)));
+    assert_eq!(parse_version("10.12.6"), Ok((10, 12, 6)));
+    assert_eq!(parse_version("9999.99.99"), Ok((9999, 99, 99)));
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 6abd8a0..c3e7f74 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -60,8 +60,8 @@
 
 mod base;
 pub use base::apple::{
-    deployment_target as current_apple_deployment_target, platform as current_apple_platform,
-    sdk_version as current_apple_sdk_version,
+    deployment_target_for_target as current_apple_deployment_target,
+    platform as current_apple_platform, sdk_version as current_apple_sdk_version,
 };
 pub use base::avr_gnu::ef_avr_arch;
 
@@ -1645,6 +1645,7 @@ fn $module() {
     ("x86_64-unknown-haiku", x86_64_unknown_haiku),
 
     ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu),
+    ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu),
 
     ("aarch64-apple-darwin", aarch64_apple_darwin),
     ("arm64e-apple-darwin", arm64e_apple_darwin),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
index 912392c..1061633 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
@@ -1,20 +1,10 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Arm64;
-    let mut base = opts("macos", arch, TargetAbi::Normal);
-    base.cpu = "apple-m1".into();
-    base.max_atomic_width = Some(128);
-
-    // FIXME: The leak sanitizer currently fails the tests, see #88132.
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
-
+    let (opts, llvm_target, arch) = base("macos", Arch::Arm64, TargetAbi::Normal);
     Target {
-        // Clang automatically chooses a more specific target based on
-        // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
-        // correctly, we do too.
-        llvm_target: macos_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("ARM64 macOS (11.0+, Big Sur+)".into()),
             tier: Some(1),
@@ -23,11 +13,15 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
-        arch: arch.target_arch(),
+        arch,
         options: TargetOptions {
             mcount: "\u{1}mcount".into(),
             frame_pointer: FramePointer::NonLeaf,
-            ..base
+            cpu: "apple-m1".into(),
+            max_atomic_width: Some(128),
+            // FIXME: The leak sanitizer currently fails the tests, see #88132.
+            supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD,
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
index 7f3a86f..caeb9a1 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
@@ -1,17 +1,10 @@
-use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Arm64;
-    let mut base = opts("ios", arch, TargetAbi::Normal);
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
-
+    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Normal);
     Target {
-        // Clang automatically chooses a more specific target based on
-        // IPHONEOS_DEPLOYMENT_TARGET.
-        // This is required for the target to pick the right
-        // MACH-O commands, so we do too.
-        llvm_target: ios_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("ARM64 iOS".into()),
             tier: Some(2),
@@ -20,12 +13,13 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
-        arch: arch.target_arch(),
+        arch,
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             frame_pointer: FramePointer::NonLeaf,
-            ..base
+            supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
index e60eeda..eee9eca 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
@@ -1,13 +1,10 @@
-use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Arm64;
-    let mut base = opts("ios", arch, TargetAbi::MacCatalyst);
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
-
+    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::MacCatalyst);
     Target {
-        llvm_target: mac_catalyst_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("Apple Catalyst on ARM64".into()),
             tier: Some(2),
@@ -16,12 +13,13 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
-        arch: arch.target_arch(),
+        arch,
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a12".into(),
             max_atomic_width: Some(128),
             frame_pointer: FramePointer::NonLeaf,
-            ..base
+            supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD,
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
index d605e22..ee58038 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
@@ -1,17 +1,10 @@
-use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Arm64;
-    let mut base = opts("ios", arch, TargetAbi::Simulator);
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
-
+    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Simulator);
     Target {
-        // Clang automatically chooses a more specific target based on
-        // IPHONEOS_DEPLOYMENT_TARGET.
-        // This is required for the simulator target to pick the right
-        // MACH-O commands, so we do too.
-        llvm_target: ios_sim_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("Apple iOS Simulator on ARM64".into()),
             tier: Some(2),
@@ -20,12 +13,13 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
-        arch: arch.target_arch(),
+        arch,
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             frame_pointer: FramePointer::NonLeaf,
-            ..base
+            supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
index fc774ab..baca863 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{opts, tvos_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Arm64;
+    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Normal);
     Target {
-        llvm_target: tvos_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("ARM64 tvOS".into()),
             tier: Some(3),
@@ -13,12 +13,12 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
-        arch: arch.target_arch(),
+        arch,
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             frame_pointer: FramePointer::NonLeaf,
-            ..opts("tvos", arch, TargetAbi::Normal)
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
index 8e8bb1e..1a48f8c 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Arm64;
+    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Simulator);
     Target {
-        llvm_target: tvos_sim_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("ARM64 tvOS Simulator".into()),
             tier: Some(3),
@@ -13,12 +13,12 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
-        arch: arch.target_arch(),
+        arch,
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             frame_pointer: FramePointer::NonLeaf,
-            ..opts("tvos", arch, TargetAbi::Simulator)
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
index 16c7d72..1424126 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
@@ -1,13 +1,10 @@
-use crate::spec::base::apple::{opts, visionos_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Arm64;
-    let mut base = opts("visionos", arch, TargetAbi::Normal);
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
-
+    let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Normal);
     Target {
-        llvm_target: visionos_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("ARM64 Apple visionOS".into()),
             tier: Some(3),
@@ -16,12 +13,13 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
-        arch: arch.target_arch(),
+        arch,
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a16".into(),
             max_atomic_width: Some(128),
             frame_pointer: FramePointer::NonLeaf,
-            ..base
+            supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
index 42973e0..d7226e0 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
@@ -1,13 +1,10 @@
-use crate::spec::base::apple::{opts, visionos_sim_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Arm64;
-    let mut base = opts("visionos", arch, TargetAbi::Simulator);
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
-
+    let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Simulator);
     Target {
-        llvm_target: visionos_sim_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("ARM64 Apple visionOS simulator".into()),
             tier: Some(3),
@@ -16,12 +13,13 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
-        arch: arch.target_arch(),
+        arch,
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a16".into(),
             max_atomic_width: Some(128),
             frame_pointer: FramePointer::NonLeaf,
-            ..base
+            supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
index 03fc251..1940a56 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let base = opts("watchos", Arch::Arm64, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Normal);
     Target {
-        llvm_target: "aarch64-apple-watchos".into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("ARM64 Apple WatchOS".into()),
             tier: Some(3),
@@ -13,13 +13,13 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
-        arch: "aarch64".into(),
+        arch,
         options: TargetOptions {
             features: "+v8a,+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             dynamic_linking: false,
             position_independent_executables: true,
-            ..base
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
index 13e2b96..6beef11 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
@@ -1,14 +1,10 @@
-use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{FramePointer, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Arm64;
+    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Simulator);
     Target {
-        // Clang automatically chooses a more specific target based on
-        // WATCHOS_DEPLOYMENT_TARGET.
-        // This is required for the simulator target to pick the right
-        // MACH-O commands, so we do too.
-        llvm_target: watchos_sim_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("ARM64 Apple WatchOS Simulator".into()),
             tier: Some(3),
@@ -17,12 +13,12 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
-        arch: arch.target_arch(),
+        arch,
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             frame_pointer: FramePointer::NonLeaf,
-            ..opts("watchos", arch, TargetAbi::Simulator)
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
index f292ee7..e9f4d93 100644
--- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
@@ -1,11 +1,10 @@
-use crate::spec::base::apple::{opts, watchos_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Arm64_32;
-    let base = opts("watchos", arch, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64_32, TargetAbi::Normal);
     Target {
-        llvm_target: watchos_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("Arm Apple WatchOS 64-bit with 32-bit pointers".into()),
             tier: Some(3),
@@ -14,13 +13,13 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
-        arch: "aarch64".into(),
+        arch,
         options: TargetOptions {
             features: "+v8a,+neon,+fp-armv8,+apple-a7".into(),
             max_atomic_width: Some(128),
             dynamic_linking: false,
             position_independent_executables: true,
-            ..base
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
index e86b835..4f7c945 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
@@ -1,20 +1,10 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Arm64e;
-    let mut base = opts("macos", arch, TargetAbi::Normal);
-    base.cpu = "apple-m1".into();
-    base.max_atomic_width = Some(128);
-
-    // FIXME: The leak sanitizer currently fails the tests, see #88132.
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
-
+    let (opts, llvm_target, arch) = base("macos", Arch::Arm64e, TargetAbi::Normal);
     Target {
-        // Clang automatically chooses a more specific target based on
-        // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
-        // correctly, we do too.
-        llvm_target: macos_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("ARM64e Apple Darwin".into()),
             tier: Some(3),
@@ -23,11 +13,15 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
-        arch: arch.target_arch(),
+        arch,
         options: TargetOptions {
             mcount: "\u{1}mcount".into(),
             frame_pointer: FramePointer::NonLeaf,
-            ..base
+            cpu: "apple-m1".into(),
+            max_atomic_width: Some(128),
+            // FIXME: The leak sanitizer currently fails the tests, see #88132.
+            supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD,
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
index fcb850f..8f192fe 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
@@ -1,17 +1,10 @@
-use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Arm64e;
-    let mut base = opts("ios", arch, TargetAbi::Normal);
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
-
+    let (opts, llvm_target, arch) = base("ios", Arch::Arm64e, TargetAbi::Normal);
     Target {
-        // Clang automatically chooses a more specific target based on
-        // IPHONEOS_DEPLOYMENT_TARGET.
-        // This is required for the target to pick the right
-        // MACH-O commands, so we do too.
-        llvm_target: ios_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("ARM64e Apple iOS".into()),
             tier: Some(3),
@@ -20,12 +13,13 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
-        arch: arch.target_arch(),
+        arch,
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(),
             max_atomic_width: Some(128),
             frame_pointer: FramePointer::NonLeaf,
-            ..base
+            supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
index 35de6b3..8fe27f6 100644
--- a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Armv7k;
+    let (opts, llvm_target, arch) = base("watchos", Arch::Armv7k, TargetAbi::Normal);
     Target {
-        llvm_target: "armv7k-apple-watchos".into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("Armv7-A Apple WatchOS".into()),
             tier: Some(3),
@@ -13,13 +13,13 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128".into(),
-        arch: arch.target_arch(),
+        arch,
         options: TargetOptions {
             features: "+v7,+vfp4,+neon".into(),
             max_atomic_width: Some(64),
             dynamic_linking: false,
             position_independent_executables: true,
-            ..opts("watchos", arch, TargetAbi::Normal)
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
index 41eaa79..deee698 100644
--- a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::Armv7s;
+    let (opts, llvm_target, arch) = base("ios", Arch::Armv7s, TargetAbi::Normal);
     Target {
-        llvm_target: ios_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("Armv7-A Apple-A6 Apple iOS".into()),
             tier: Some(3),
@@ -13,11 +13,11 @@ pub(crate) fn target() -> Target {
         },
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(),
-        arch: arch.target_arch(),
+        arch,
         options: TargetOptions {
             features: "+v7,+vfp4,+neon".into(),
             max_atomic_width: Some(64),
-            ..opts("ios", arch, TargetAbi::Normal)
+            ..opts
         },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
index 263393f..dc14cb3 100644
--- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
@@ -1,17 +1,12 @@
-use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::I386;
     // i386-apple-ios is a simulator target, even though it isn't declared
     // that way in the target name like the other ones...
-    let abi = TargetAbi::Simulator;
+    let (opts, llvm_target, arch) = base("ios", Arch::I386, TargetAbi::Simulator);
     Target {
-        // Clang automatically chooses a more specific target based on
-        // IPHONEOS_DEPLOYMENT_TARGET.
-        // This is required for the target to pick the right
-        // MACH-O commands, so we do too.
-        llvm_target: ios_sim_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("32-bit x86 iOS".into()),
             tier: Some(3),
@@ -22,7 +17,7 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:128-n8:16:32-S128"
             .into(),
-        arch: arch.target_arch(),
-        options: TargetOptions { max_atomic_width: Some(64), ..opts("ios", arch, abi) },
+        arch,
+        options: TargetOptions { max_atomic_width: Some(64), ..opts },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
index f173e8b..67afe35 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -1,21 +1,12 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    // ld64 only understands i386 and not i686
-    let arch = Arch::I386;
-    let mut base = opts("macos", arch, TargetAbi::Normal);
-    base.max_atomic_width = Some(64);
-    base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]);
-    base.frame_pointer = FramePointer::Always;
+    let (mut opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
+    opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]);
 
     Target {
-        // Clang automatically chooses a more specific target based on
-        // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
-        // correctly, we do too.
-        //
-        // While ld64 doesn't understand i686, LLVM does.
-        llvm_target: macos_llvm_target(Arch::I686).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("32-bit macOS (10.12+, Sierra+)".into()),
             tier: Some(3),
@@ -26,7 +17,12 @@ pub(crate) fn target() -> Target {
         data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:128-n8:16:32-S128"
             .into(),
-        arch: arch.target_arch(),
-        options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
+        arch,
+        options: TargetOptions {
+            mcount: "\u{1}mcount".into(),
+            max_atomic_width: Some(64),
+            frame_pointer: FramePointer::Always,
+            ..opts
+        },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
index 40f026c..876aa70 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
@@ -1,6 +1,6 @@
 //! The `wasm32-wasip2` target is the next evolution of the
 //! wasm32-wasi target. While the wasi specification is still under
-//! active development, the {review 2 iteration is considered an "island
+//! active development, the preview 2 iteration is considered an "island
 //! of stability" that should allow users to rely on it indefinitely.
 //!
 //! The `wasi` target is a proposal to define a standardized set of WebAssembly
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index 7bf1802..e7f14aa 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -1,20 +1,11 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::X86_64;
-    let mut base = opts("macos", arch, TargetAbi::Normal);
-    base.max_atomic_width = Some(128); // penryn+ supports cmpxchg16b
-    base.frame_pointer = FramePointer::Always;
-    base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
-    base.supported_sanitizers =
-        SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
-
+    let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
+    opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
     Target {
-        // Clang automatically chooses a more specific target based on
-        // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
-        // correctly, we do too.
-        llvm_target: macos_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("64-bit macOS (10.12+, Sierra+)".into()),
             tier: Some(1),
@@ -24,7 +15,16 @@ pub(crate) fn target() -> Target {
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
-        arch: arch.target_arch(),
-        options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
+        arch,
+        options: TargetOptions {
+            mcount: "\u{1}mcount".into(),
+            max_atomic_width: Some(128), // penryn+ supports cmpxchg16b
+            frame_pointer: FramePointer::Always,
+            supported_sanitizers: SanitizerSet::ADDRESS
+                | SanitizerSet::CFI
+                | SanitizerSet::LEAK
+                | SanitizerSet::THREAD,
+            ..opts
+        },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
index 76a0bb1..847c4f0 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
@@ -1,15 +1,12 @@
-use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::X86_64;
     // x86_64-apple-ios is a simulator target, even though it isn't declared
     // that way in the target name like the other ones...
-    let mut base = opts("ios", arch, TargetAbi::Simulator);
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
-
+    let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetAbi::Simulator);
     Target {
-        llvm_target: ios_sim_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("64-bit x86 iOS".into()),
             tier: Some(2),
@@ -19,7 +16,11 @@ pub(crate) fn target() -> Target {
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
-        arch: arch.target_arch(),
-        options: TargetOptions { max_atomic_width: Some(128), ..base },
+        arch,
+        options: TargetOptions {
+            max_atomic_width: Some(128),
+            supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
+            ..opts
+        },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
index f66efbb..042079f 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
@@ -1,13 +1,10 @@
-use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::X86_64;
-    let mut base = opts("ios", arch, TargetAbi::MacCatalyst);
-    base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
-
+    let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetAbi::MacCatalyst);
     Target {
-        llvm_target: mac_catalyst_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("Apple Catalyst on x86_64".into()),
             tier: Some(2),
@@ -17,7 +14,11 @@ pub(crate) fn target() -> Target {
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
-        arch: arch.target_arch(),
-        options: TargetOptions { max_atomic_width: Some(128), ..base },
+        arch,
+        options: TargetOptions {
+            max_atomic_width: Some(128),
+            supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD,
+            ..opts
+        },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
index f9d5f6e..9470860 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
@@ -1,13 +1,12 @@
-use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::X86_64;
     // x86_64-apple-tvos is a simulator target, even though it isn't declared
     // that way in the target name like the other ones...
-    let abi = TargetAbi::Simulator;
+    let (opts, llvm_target, arch) = base("tvos", Arch::X86_64, TargetAbi::Simulator);
     Target {
-        llvm_target: tvos_sim_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("x86 64-bit tvOS".into()),
             tier: Some(3),
@@ -17,7 +16,7 @@ pub(crate) fn target() -> Target {
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
-        arch: arch.target_arch(),
-        options: TargetOptions { max_atomic_width: Some(128), ..opts("tvos", arch, abi) },
+        arch,
+        options: TargetOptions { max_atomic_width: Some(128), ..opts },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
index 1fced10..1dab959 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::X86_64;
+    let (opts, llvm_target, arch) = base("watchos", Arch::X86_64, TargetAbi::Simulator);
     Target {
-        llvm_target: watchos_sim_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("x86 64-bit Apple WatchOS simulator".into()),
             tier: Some(3),
@@ -14,10 +14,7 @@ pub(crate) fn target() -> Target {
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
-        arch: arch.target_arch(),
-        options: TargetOptions {
-            max_atomic_width: Some(128),
-            ..opts("watchos", arch, TargetAbi::Simulator)
-        },
+        arch,
+        options: TargetOptions { max_atomic_width: Some(128), ..opts },
     }
 }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs
new file mode 100644
index 0000000..6461ece
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs
@@ -0,0 +1,26 @@
+use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target};
+
+pub(crate) fn target() -> Target {
+    let mut base = base::hurd_gnu::opts();
+    base.cpu = "x86-64".into();
+    base.plt_by_default = false;
+    base.max_atomic_width = Some(64);
+    base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+    base.stack_probes = StackProbeType::Inline;
+    base.supports_xray = true;
+
+    Target {
+        llvm_target: "x86_64-unknown-hurd-gnu".into(),
+        metadata: crate::spec::TargetMetadata {
+            description: Some("64-bit GNU/Hurd".into()),
+            tier: Some(3),
+            host_tools: Some(true),
+            std: Some(true),
+        },
+        pointer_width: 64,
+        data_layout:
+            "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
+        arch: "x86_64".into(),
+        options: base,
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
index 9b9ffe4..f44bc66 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
@@ -1,13 +1,12 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
 use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let arch = Arch::X86_64h;
-    let mut base = opts("macos", arch, TargetAbi::Normal);
-    base.max_atomic_width = Some(128);
-    base.frame_pointer = FramePointer::Always;
-    base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
-    base.supported_sanitizers =
+    let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal);
+    opts.max_atomic_width = Some(128);
+    opts.frame_pointer = FramePointer::Always;
+    opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
+    opts.supported_sanitizers =
         SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
 
     // x86_64h is core2-avx without a few of the features which would otherwise
@@ -20,19 +19,16 @@ pub(crate) fn target() -> Target {
     // It would be nice if this were not the case, but fixing it seems tricky
     // (and given that the main use-case for this target is for use in universal
     // binaries, probably not that important).
-    base.features = "-rdrnd,-aes,-pclmul,-rtm,-fsgsbase".into();
+    opts.features = "-rdrnd,-aes,-pclmul,-rtm,-fsgsbase".into();
     // Double-check that the `cpu` is what we expect (if it's not the list above
     // may need updating).
     assert_eq!(
-        base.cpu, "core-avx2",
+        opts.cpu, "core-avx2",
         "you need to adjust the feature list in x86_64h-apple-darwin if you change this",
     );
 
     Target {
-        // Clang automatically chooses a more specific target based on
-        // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
-        // correctly, we do too.
-        llvm_target: macos_llvm_target(arch).into(),
+        llvm_target,
         metadata: crate::spec::TargetMetadata {
             description: Some("macOS with late-gen Intel (at least Haswell)".into()),
             tier: Some(3),
@@ -42,7 +38,7 @@ pub(crate) fn target() -> Target {
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
-        arch: arch.target_arch(),
-        options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
+        arch,
+        options: TargetOptions { mcount: "\u{1}mcount".into(), ..opts },
     }
 }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index bff2a18..65d2151 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -348,8 +348,7 @@ fn note_error_origin(
                     }
                 }
                 if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
-                    && ty.is_box()
-                    && ty.boxed_ty() == found
+                    && ty.boxed_ty() == Some(found)
                     && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
                 {
                     err.span_suggestion(
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index a93b633..cf9891f 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -1296,6 +1296,9 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
             && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
             && self.tecx.tcx.trait_of_item(def_id).is_some()
             && !has_impl_trait(def_id)
+            // FIXME(fn_delegation): In delegation item argument spans are equal to last path
+            // segment. This leads to ICE's when emitting `multipart_suggestion`.
+            && tcx.hir().opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
         {
             let successor =
                 method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
index db71331..7bfc647 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
@@ -4,7 +4,7 @@
 use rustc_hir::def::DefKind;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::print::{FmtPrinter, Printer};
 use rustc_middle::ty::{self, suggest_constraining_type_param, Ty};
 use rustc_span::def_id::DefId;
@@ -317,7 +317,7 @@ fn foo(&self, x: T) -> T { x }
                     {
                         let mut has_matching_impl = false;
                         tcx.for_each_relevant_impl(def_id, values.found, |did| {
-                            if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
+                            if DeepRejectCtxt::relate_rigid_infer(tcx)
                                 .types_may_unify(values.found, tcx.type_of(did).skip_binder())
                             {
                                 has_matching_impl = true;
@@ -338,7 +338,7 @@ fn foo(&self, x: T) -> T { x }
                     {
                         let mut has_matching_impl = false;
                         tcx.for_each_relevant_impl(def_id, values.expected, |did| {
-                            if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
+                            if DeepRejectCtxt::relate_rigid_infer(tcx)
                                 .types_may_unify(values.expected, tcx.type_of(did).skip_binder())
                             {
                                 has_matching_impl = true;
@@ -358,7 +358,7 @@ fn foo(&self, x: T) -> T { x }
                     {
                         let mut has_matching_impl = false;
                         tcx.for_each_relevant_impl(def_id, values.found, |did| {
-                            if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
+                            if DeepRejectCtxt::relate_rigid_infer(tcx)
                                 .types_may_unify(values.found, tcx.type_of(did).skip_binder())
                             {
                                 has_matching_impl = true;
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index e4a4ec1..38d06f5 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -625,11 +625,19 @@ pub(super) fn report_placeholder_failure(
                 if let ObligationCauseCode::WhereClause(_, span)
                 | ObligationCauseCode::WhereClauseInExpr(_, span, ..) =
                     &trace.cause.code().peel_derives()
-                    && !span.is_dummy()
                 {
                     let span = *span;
-                    self.report_concrete_failure(generic_param_scope, placeholder_origin, sub, sup)
-                        .with_span_note(span, "the lifetime requirement is introduced here")
+                    let mut err = self.report_concrete_failure(
+                        generic_param_scope,
+                        placeholder_origin,
+                        sub,
+                        sup,
+                    );
+                    if !span.is_dummy() {
+                        err =
+                            err.with_span_note(span, "the lifetime requirement is introduced here");
+                    }
+                    err
                 } else {
                     unreachable!(
                         "control flow ensures we have a `BindingObligation` or `WhereClauseInExpr` here..."
@@ -844,18 +852,7 @@ struct LifetimeReplaceVisitor<'tcx, 'a> {
         impl<'hir, 'tcx> hir::intravisit::Visitor<'hir> for LifetimeReplaceVisitor<'tcx, '_> {
             fn visit_lifetime(&mut self, lt: &'hir hir::Lifetime) {
                 if lt.res == self.needle {
-                    let (pos, span) = lt.suggestion_position();
-                    let new_lt = &self.new_lt;
-                    let sugg = match pos {
-                        hir::LifetimeSuggestionPosition::Normal => format!("{new_lt}"),
-                        hir::LifetimeSuggestionPosition::Ampersand => format!("{new_lt} "),
-                        hir::LifetimeSuggestionPosition::ElidedPath => format!("<{new_lt}>"),
-                        hir::LifetimeSuggestionPosition::ElidedPathArgument => {
-                            format!("{new_lt}, ")
-                        }
-                        hir::LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lt}"),
-                    };
-                    self.add_lt_suggs.push((span, sugg));
+                    self.add_lt_suggs.push(lt.suggestion(self.new_lt));
                 }
             }
 
@@ -1018,7 +1015,7 @@ fn report_inference_failure(&self, var_origin: RegionVariableOrigin) -> Diag<'_>
         let var_description = match var_origin {
             infer::MiscVariable(_) => String::new(),
             infer::PatternRegion(_) => " for pattern".to_string(),
-            infer::AddrOfRegion(_) => " for borrow expression".to_string(),
+            infer::BorrowRegion(_) => " for borrow expression".to_string(),
             infer::Autoref(_) => " for autoref".to_string(),
             infer::Coercion(_) => " for automatic coercion".to_string(),
             infer::BoundRegion(_, br, infer::FnCall) => {
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 8b55f84..bafe1ff 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -15,7 +15,7 @@
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
 use rustc_middle::traits::specialization_graph::OverlapMode;
-use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 pub use rustc_next_trait_solver::coherence::*;
@@ -96,7 +96,7 @@ pub fn overlapping_impls(
     // Before doing expensive operations like entering an inference context, do
     // a quick check via fast_reject to tell if the impl headers could possibly
     // unify.
-    let drcx = DeepRejectCtxt::new(tcx, TreatParams::AsCandidateKey);
+    let drcx = DeepRejectCtxt::relate_infer_infer(tcx);
     let impl1_ref = tcx.impl_trait_ref(impl1_def_id);
     let impl2_ref = tcx.impl_trait_ref(impl2_def_id);
     let may_overlap = match (impl1_ref, impl2_ref) {
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index de1d4ef..c8811bc 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -35,10 +35,8 @@ fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> {
         if infcx.next_trait_solver() {
             Box::new(NextFulfillmentCtxt::new(infcx))
         } else {
-            let new_solver_globally =
-                infcx.tcx.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally);
             assert!(
-                !new_solver_globally,
+                !infcx.tcx.next_trait_solver_globally(),
                 "using old solver even though new solver is enabled globally"
             );
             Box::new(FulfillmentContext::new(infcx))
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 4702fd8..630acc9 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -13,6 +13,7 @@
 use rustc_middle::traits::select::OverflowError;
 pub use rustc_middle::traits::Reveal;
 use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData};
+use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::{self, Term, Ty, TyCtxt, Upcast};
@@ -886,6 +887,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
     potentially_unnormalized_candidates: bool,
 ) {
     let infcx = selcx.infcx;
+    let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
     for predicate in env_predicates {
         let bound_predicate = predicate.kind();
         if let ty::ClauseKind::Projection(data) = predicate.kind().skip_binder() {
@@ -894,6 +896,12 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
                 continue;
             }
 
+            if !drcx
+                .args_may_unify(obligation.predicate.args, data.skip_binder().projection_term.args)
+            {
+                continue;
+            }
+
             let is_match = infcx.probe(|_| {
                 selcx.match_projection_projections(
                     obligation,
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 96faa52..77efc2f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -13,7 +13,7 @@
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_hir as hir;
 use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation, SelectionError};
-use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt};
 use rustc_middle::{bug, span_bug};
 use tracing::{debug, instrument, trace};
@@ -248,11 +248,17 @@ fn assemble_candidates_from_caller_bounds<'o>(
             .filter(|p| p.def_id() == stack.obligation.predicate.def_id())
             .filter(|p| p.polarity() == stack.obligation.predicate.polarity());
 
+        let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
+        let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args;
         // Keep only those bounds which may apply, and propagate overflow if it occurs.
         for bound in bounds {
+            let bound_trait_ref = bound.map_bound(|t| t.trait_ref);
+            if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) {
+                continue;
+            }
             // FIXME(oli-obk): it is suspicious that we are dropping the constness and
             // polarity here.
-            let wc = self.where_clause_may_apply(stack, bound.map_bound(|t| t.trait_ref))?;
+            let wc = self.where_clause_may_apply(stack, bound_trait_ref)?;
             if wc.may_apply() {
                 candidates.vec.push(ParamCandidate(bound));
             }
@@ -581,7 +587,7 @@ fn assemble_candidates_from_impls(
             return;
         }
 
-        let drcx = DeepRejectCtxt::new(self.tcx(), TreatParams::ForLookup);
+        let drcx = DeepRejectCtxt::relate_rigid_infer(self.tcx());
         let obligation_args = obligation.predicate.skip_binder().trait_ref.args;
         self.tcx().for_each_relevant_impl(
             obligation.predicate.def_id(),
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
index 0fdaf40..13620f4 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -41,7 +41,7 @@ impl<'tcx> Children {
     fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
         if let Some(st) =
-            fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey)
+            fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer)
         {
             debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
             self.non_blanket_impls.entry(st).or_default().push(impl_def_id)
@@ -58,7 +58,7 @@ fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
         let vec: &mut Vec<DefId>;
         if let Some(st) =
-            fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey)
+            fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer)
         {
             debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
             vec = self.non_blanket_impls.get_mut(&st).unwrap();
@@ -279,7 +279,7 @@ fn insert(
         let mut parent = trait_def_id;
         let mut last_lint = None;
         let simplified =
-            fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey);
+            fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer);
 
         // Descend the specialization tree, where `parent` is the current parent node.
         loop {
diff --git a/compiler/rustc_transmute/src/layout/nfa.rs b/compiler/rustc_transmute/src/layout/nfa.rs
index 5db5a8f..3b49c59 100644
--- a/compiler/rustc_transmute/src/layout/nfa.rs
+++ b/compiler/rustc_transmute/src/layout/nfa.rs
@@ -87,8 +87,6 @@ pub(crate) fn from_ref(r: R) -> Self {
     pub(crate) fn from_tree(tree: Tree<!, R>) -> Result<Self, Uninhabited> {
         Ok(match tree {
             Tree::Byte(b) => Self::from_byte(b),
-            #[cfg(bootstrap)]
-            Tree::Def(..) => unreachable!(),
             Tree::Ref(r) => Self::from_ref(r),
             Tree::Alt(alts) => {
                 let mut alts = alts.into_iter().map(Self::from_tree);
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 234e1a6..c23a7fe 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -1001,7 +1001,13 @@ fn coroutine_layout<'tcx>(
         },
         fields: outer_fields,
         abi,
-        largest_niche: prefix.largest_niche,
+        // Suppress niches inside coroutines. If the niche is inside a field that is aliased (due to
+        // self-referentiality), getting the discriminant can cause aliasing violations.
+        // `UnsafeCell` blocks niches for the same reason, but we don't yet have `UnsafePinned` that
+        // would do the same for us here.
+        // See <https://github.com/rust-lang/rust/issues/63818>, <https://github.com/rust-lang/miri/issues/3780>.
+        // FIXME: Remove when <https://github.com/rust-lang/rust/issues/125735> is implemented and aliased coroutine fields are wrapped in `UnsafePinned`.
+        largest_niche: None,
         size,
         align,
         max_repr_align: None,
diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs
index 433c444..f30419c 100644
--- a/compiler/rustc_type_ir/src/elaborate.rs
+++ b/compiler/rustc_type_ir/src/elaborate.rs
@@ -237,7 +237,7 @@ pub fn supertrait_def_ids<I: Interner>(
     cx: I,
     trait_def_id: I::DefId,
 ) -> impl Iterator<Item = I::DefId> {
-    let mut set: HashSet<I::DefId> = HashSet::default();
+    let mut set = HashSet::default();
     let mut stack = vec![trait_def_id];
 
     set.insert(trait_def_id);
diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs
index fab4a09..2c8e47b 100644
--- a/compiler/rustc_type_ir/src/fast_reject.rs
+++ b/compiler/rustc_type_ir/src/fast_reject.rs
@@ -74,13 +74,13 @@ fn to_stable_hash_key(&self, hcx: &HCX) -> Fingerprint {
 pub enum TreatParams {
     /// Treat parameters as infer vars. This is the correct mode for caching
     /// an impl's type for lookup.
-    AsCandidateKey,
+    InstantiateWithInfer,
     /// Treat parameters as placeholders in the given environment. This is the
     /// correct mode for *lookup*, as during candidate selection.
     ///
     /// This also treats projections with inference variables as infer vars
     /// since they could be further normalized.
-    ForLookup,
+    AsRigid,
 }
 
 /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
@@ -140,18 +140,16 @@ pub fn simplify_type<I: Interner>(
         }
         ty::Placeholder(..) => Some(SimplifiedType::Placeholder),
         ty::Param(_) => match treat_params {
-            TreatParams::ForLookup => Some(SimplifiedType::Placeholder),
-            TreatParams::AsCandidateKey => None,
+            TreatParams::AsRigid => Some(SimplifiedType::Placeholder),
+            TreatParams::InstantiateWithInfer => None,
         },
         ty::Alias(..) => match treat_params {
             // When treating `ty::Param` as a placeholder, projections also
             // don't unify with anything else as long as they are fully normalized.
             // FIXME(-Znext-solver): Can remove this `if` and always simplify to `Placeholder`
             // when the new solver is enabled by default.
-            TreatParams::ForLookup if !ty.has_non_region_infer() => {
-                Some(SimplifiedType::Placeholder)
-            }
-            TreatParams::ForLookup | TreatParams::AsCandidateKey => None,
+            TreatParams::AsRigid if !ty.has_non_region_infer() => Some(SimplifiedType::Placeholder),
+            TreatParams::AsRigid | TreatParams::InstantiateWithInfer => None,
         },
         ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)),
         ty::Error(_) => Some(SimplifiedType::Error),
@@ -173,29 +171,49 @@ pub fn def(self) -> Option<DefId> {
     }
 }
 
-/// Given generic arguments from an obligation and an impl,
-/// could these two be unified after replacing parameters in the
-/// the impl with inference variables.
+/// Given generic arguments, could they be unified after
+/// replacing parameters with inference variables or placeholders.
+/// This behavior is toggled using the const generics.
 ///
-/// For obligations, parameters won't be replaced by inference
-/// variables and only unify with themselves. We treat them
-/// the same way we treat placeholders.
+/// We use this to quickly reject impl/wc candidates without needing
+/// to instantiate generic arguments/having to enter a probe.
 ///
 /// We also use this function during coherence. For coherence the
 /// impls only have to overlap for some value, so we treat parameters
-/// on both sides like inference variables. This behavior is toggled
-/// using the `treat_obligation_params` field.
+/// on both sides like inference variables.
 #[derive(Debug, Clone, Copy)]
-pub struct DeepRejectCtxt<I: Interner> {
-    treat_obligation_params: TreatParams,
+pub struct DeepRejectCtxt<
+    I: Interner,
+    const INSTANTIATE_LHS_WITH_INFER: bool,
+    const INSTANTIATE_RHS_WITH_INFER: bool,
+> {
     _interner: PhantomData<I>,
 }
 
-impl<I: Interner> DeepRejectCtxt<I> {
-    pub fn new(_interner: I, treat_obligation_params: TreatParams) -> Self {
-        DeepRejectCtxt { treat_obligation_params, _interner: PhantomData }
+impl<I: Interner> DeepRejectCtxt<I, false, false> {
+    /// Treat parameters in both the lhs and the rhs as rigid.
+    pub fn relate_rigid_rigid(_interner: I) -> DeepRejectCtxt<I, false, false> {
+        DeepRejectCtxt { _interner: PhantomData }
     }
+}
 
+impl<I: Interner> DeepRejectCtxt<I, true, true> {
+    /// Treat parameters in both the lhs and the rhs as infer vars.
+    pub fn relate_infer_infer(_interner: I) -> DeepRejectCtxt<I, true, true> {
+        DeepRejectCtxt { _interner: PhantomData }
+    }
+}
+
+impl<I: Interner> DeepRejectCtxt<I, false, true> {
+    /// Treat parameters in the lhs as rigid, and in rhs as infer vars.
+    pub fn relate_rigid_infer(_interner: I) -> DeepRejectCtxt<I, false, true> {
+        DeepRejectCtxt { _interner: PhantomData }
+    }
+}
+
+impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_WITH_INFER: bool>
+    DeepRejectCtxt<I, INSTANTIATE_LHS_WITH_INFER, INSTANTIATE_RHS_WITH_INFER>
+{
     pub fn args_may_unify(
         self,
         obligation_args: I::GenericArgs,
@@ -216,11 +234,18 @@ pub fn args_may_unify(
         })
     }
 
-    pub fn types_may_unify(self, obligation_ty: I::Ty, impl_ty: I::Ty) -> bool {
-        match impl_ty.kind() {
-            // Start by checking whether the type in the impl may unify with
+    pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool {
+        match rhs.kind() {
+            // Start by checking whether the `rhs` type may unify with
             // pretty much everything. Just return `true` in that case.
-            ty::Param(_) | ty::Error(_) | ty::Alias(..) => return true,
+            ty::Param(_) => {
+                if INSTANTIATE_RHS_WITH_INFER {
+                    return true;
+                }
+            }
+            ty::Error(_) | ty::Alias(..) | ty::Bound(..) => return true,
+            ty::Infer(var) => return self.var_and_ty_may_unify(var, lhs),
+
             // These types only unify with inference variables or their own
             // variant.
             ty::Bool
@@ -238,108 +263,48 @@ pub fn types_may_unify(self, obligation_ty: I::Ty, impl_ty: I::Ty) -> bool {
             | ty::Ref(..)
             | ty::Never
             | ty::Tuple(..)
+            | ty::FnDef(..)
             | ty::FnPtr(..)
-            | ty::Foreign(..) => debug_assert!(impl_ty.is_known_rigid()),
-            ty::FnDef(..)
             | ty::Closure(..)
             | ty::CoroutineClosure(..)
             | ty::Coroutine(..)
             | ty::CoroutineWitness(..)
-            | ty::Placeholder(..)
-            | ty::Bound(..)
-            | ty::Infer(_) => panic!("unexpected impl_ty: {impl_ty:?}"),
-        }
+            | ty::Foreign(_)
+            | ty::Placeholder(_) => {}
+        };
 
-        let k = impl_ty.kind();
-        match obligation_ty.kind() {
-            // Purely rigid types, use structural equivalence.
-            ty::Bool
-            | ty::Char
-            | ty::Int(_)
-            | ty::Uint(_)
-            | ty::Float(_)
-            | ty::Str
-            | ty::Never
-            | ty::Foreign(_) => obligation_ty == impl_ty,
-            ty::Ref(_, obl_ty, obl_mutbl) => match k {
-                ty::Ref(_, impl_ty, impl_mutbl) => {
-                    obl_mutbl == impl_mutbl && self.types_may_unify(obl_ty, impl_ty)
+        // For purely rigid types, use structural equivalence.
+        match lhs.kind() {
+            ty::Ref(_, lhs_ty, lhs_mutbl) => match rhs.kind() {
+                ty::Ref(_, rhs_ty, rhs_mutbl) => {
+                    lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty)
                 }
                 _ => false,
             },
-            ty::Adt(obl_def, obl_args) => match k {
-                ty::Adt(impl_def, impl_args) => {
-                    obl_def == impl_def && self.args_may_unify(obl_args, impl_args)
+
+            ty::Adt(lhs_def, lhs_args) => match rhs.kind() {
+                ty::Adt(rhs_def, rhs_args) => {
+                    lhs_def == rhs_def && self.args_may_unify(lhs_args, rhs_args)
                 }
                 _ => false,
             },
-            ty::Pat(obl_ty, _) => {
-                // FIXME(pattern_types): take pattern into account
-                matches!(k, ty::Pat(impl_ty, _) if self.types_may_unify(obl_ty, impl_ty))
+
+            // Depending on the value of const generics, we either treat generic parameters
+            // like placeholders or like inference variables.
+            ty::Param(lhs) => {
+                INSTANTIATE_LHS_WITH_INFER
+                    || match rhs.kind() {
+                        ty::Param(rhs) => lhs == rhs,
+                        _ => false,
+                    }
             }
-            ty::Slice(obl_ty) => {
-                matches!(k, ty::Slice(impl_ty) if self.types_may_unify(obl_ty, impl_ty))
+
+            // Placeholder types don't unify with anything on their own.
+            ty::Placeholder(lhs) => {
+                matches!(rhs.kind(), ty::Placeholder(rhs) if lhs == rhs)
             }
-            ty::Array(obl_ty, obl_len) => match k {
-                ty::Array(impl_ty, impl_len) => {
-                    self.types_may_unify(obl_ty, impl_ty)
-                        && self.consts_may_unify(obl_len, impl_len)
-                }
-                _ => false,
-            },
-            ty::Tuple(obl) => match k {
-                ty::Tuple(imp) => {
-                    obl.len() == imp.len()
-                        && iter::zip(obl.iter(), imp.iter())
-                            .all(|(obl, imp)| self.types_may_unify(obl, imp))
-                }
-                _ => false,
-            },
-            ty::RawPtr(obl_ty, obl_mutbl) => match k {
-                ty::RawPtr(imp_ty, imp_mutbl) => {
-                    obl_mutbl == imp_mutbl && self.types_may_unify(obl_ty, imp_ty)
-                }
-                _ => false,
-            },
-            ty::Dynamic(obl_preds, ..) => {
-                // Ideally we would walk the existential predicates here or at least
-                // compare their length. But considering that the relevant `Relate` impl
-                // actually sorts and deduplicates these, that doesn't work.
-                matches!(k, ty::Dynamic(impl_preds, ..) if
-                    obl_preds.principal_def_id() == impl_preds.principal_def_id()
-                )
-            }
-            ty::FnPtr(obl_sig_tys, obl_hdr) => match k {
-                ty::FnPtr(impl_sig_tys, impl_hdr) => {
-                    let obl_sig_tys = obl_sig_tys.skip_binder().inputs_and_output;
-                    let impl_sig_tys = impl_sig_tys.skip_binder().inputs_and_output;
 
-                    obl_hdr == impl_hdr
-                        && obl_sig_tys.len() == impl_sig_tys.len()
-                        && iter::zip(obl_sig_tys.iter(), impl_sig_tys.iter())
-                            .all(|(obl, imp)| self.types_may_unify(obl, imp))
-                }
-                _ => false,
-            },
-
-            // Impls cannot contain these types as these cannot be named directly.
-            ty::FnDef(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) => false,
-
-            // Placeholder types don't unify with anything on their own
-            ty::Placeholder(..) | ty::Bound(..) => false,
-
-            // Depending on the value of `treat_obligation_params`, we either
-            // treat generic parameters like placeholders or like inference variables.
-            ty::Param(_) => match self.treat_obligation_params {
-                TreatParams::ForLookup => false,
-                TreatParams::AsCandidateKey => true,
-            },
-
-            ty::Infer(ty::IntVar(_)) => impl_ty.is_integral(),
-
-            ty::Infer(ty::FloatVar(_)) => impl_ty.is_floating_point(),
-
-            ty::Infer(_) => true,
+            ty::Infer(var) => self.var_and_ty_may_unify(var, rhs),
 
             // As we're walking the whole type, it may encounter projections
             // inside of binders and what not, so we're just going to assume that
@@ -348,49 +313,167 @@ pub fn types_may_unify(self, obligation_ty: I::Ty, impl_ty: I::Ty) -> bool {
             // Looking forward to lazy normalization this is the safer strategy anyways.
             ty::Alias(..) => true,
 
-            ty::Error(_) => true,
+            ty::Int(_)
+            | ty::Uint(_)
+            | ty::Float(_)
+            | ty::Str
+            | ty::Bool
+            | ty::Char
+            | ty::Never
+            | ty::Foreign(_) => lhs == rhs,
 
-            ty::CoroutineWitness(..) => {
-                panic!("unexpected obligation type: {:?}", obligation_ty)
+            ty::Tuple(lhs) => match rhs.kind() {
+                ty::Tuple(rhs) => {
+                    lhs.len() == rhs.len()
+                        && iter::zip(lhs.iter(), rhs.iter())
+                            .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs))
+                }
+                _ => false,
+            },
+
+            ty::Array(lhs_ty, lhs_len) => match rhs.kind() {
+                ty::Array(rhs_ty, rhs_len) => {
+                    self.types_may_unify(lhs_ty, rhs_ty) && self.consts_may_unify(lhs_len, rhs_len)
+                }
+                _ => false,
+            },
+
+            ty::RawPtr(lhs_ty, lhs_mutbl) => match rhs.kind() {
+                ty::RawPtr(rhs_ty, rhs_mutbl) => {
+                    lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty)
+                }
+                _ => false,
+            },
+
+            ty::Slice(lhs_ty) => {
+                matches!(rhs.kind(), ty::Slice(rhs_ty) if self.types_may_unify(lhs_ty, rhs_ty))
             }
+
+            ty::Dynamic(lhs_preds, ..) => {
+                // Ideally we would walk the existential predicates here or at least
+                // compare their length. But considering that the relevant `Relate` impl
+                // actually sorts and deduplicates these, that doesn't work.
+                matches!(rhs.kind(), ty::Dynamic(rhs_preds, ..) if
+                    lhs_preds.principal_def_id() == rhs_preds.principal_def_id()
+                )
+            }
+
+            ty::FnPtr(lhs_sig_tys, lhs_hdr) => match rhs.kind() {
+                ty::FnPtr(rhs_sig_tys, rhs_hdr) => {
+                    let lhs_sig_tys = lhs_sig_tys.skip_binder().inputs_and_output;
+                    let rhs_sig_tys = rhs_sig_tys.skip_binder().inputs_and_output;
+
+                    lhs_hdr == rhs_hdr
+                        && lhs_sig_tys.len() == rhs_sig_tys.len()
+                        && iter::zip(lhs_sig_tys.iter(), rhs_sig_tys.iter())
+                            .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs))
+                }
+                _ => false,
+            },
+
+            ty::Bound(..) => true,
+
+            ty::FnDef(lhs_def_id, lhs_args) => match rhs.kind() {
+                ty::FnDef(rhs_def_id, rhs_args) => {
+                    lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
+                }
+                _ => false,
+            },
+
+            ty::Closure(lhs_def_id, lhs_args) => match rhs.kind() {
+                ty::Closure(rhs_def_id, rhs_args) => {
+                    lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
+                }
+                _ => false,
+            },
+
+            ty::CoroutineClosure(lhs_def_id, lhs_args) => match rhs.kind() {
+                ty::CoroutineClosure(rhs_def_id, rhs_args) => {
+                    lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
+                }
+                _ => false,
+            },
+
+            ty::Coroutine(lhs_def_id, lhs_args) => match rhs.kind() {
+                ty::Coroutine(rhs_def_id, rhs_args) => {
+                    lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
+                }
+                _ => false,
+            },
+
+            ty::CoroutineWitness(lhs_def_id, lhs_args) => match rhs.kind() {
+                ty::CoroutineWitness(rhs_def_id, rhs_args) => {
+                    lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
+                }
+                _ => false,
+            },
+
+            ty::Pat(lhs_ty, _) => {
+                // FIXME(pattern_types): take pattern into account
+                matches!(rhs.kind(), ty::Pat(rhs_ty, _) if self.types_may_unify(lhs_ty, rhs_ty))
+            }
+
+            ty::Error(..) => true,
         }
     }
 
-    pub fn consts_may_unify(self, obligation_ct: I::Const, impl_ct: I::Const) -> bool {
-        let impl_val = match impl_ct.kind() {
+    pub fn consts_may_unify(self, lhs: I::Const, rhs: I::Const) -> bool {
+        match rhs.kind() {
+            ty::ConstKind::Param(_) => {
+                if INSTANTIATE_RHS_WITH_INFER {
+                    return true;
+                }
+            }
+
             ty::ConstKind::Expr(_)
-            | ty::ConstKind::Param(_)
             | ty::ConstKind::Unevaluated(_)
-            | ty::ConstKind::Error(_) => {
+            | ty::ConstKind::Error(_)
+            | ty::ConstKind::Infer(_)
+            | ty::ConstKind::Bound(..) => {
                 return true;
             }
-            ty::ConstKind::Value(_, impl_val) => impl_val,
-            ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
-                panic!("unexpected impl arg: {:?}", impl_ct)
-            }
+
+            ty::ConstKind::Value(..) | ty::ConstKind::Placeholder(_) => {}
         };
 
-        match obligation_ct.kind() {
-            ty::ConstKind::Param(_) => match self.treat_obligation_params {
-                TreatParams::ForLookup => false,
-                TreatParams::AsCandidateKey => true,
+        match lhs.kind() {
+            ty::ConstKind::Value(_, lhs_val) => match rhs.kind() {
+                ty::ConstKind::Value(_, rhs_val) => lhs_val == rhs_val,
+                _ => false,
             },
 
+            ty::ConstKind::Param(lhs) => {
+                INSTANTIATE_LHS_WITH_INFER
+                    || match rhs.kind() {
+                        ty::ConstKind::Param(rhs) => lhs == rhs,
+                        _ => false,
+                    }
+            }
+
             // Placeholder consts don't unify with anything on their own
-            ty::ConstKind::Placeholder(_) => false,
+            ty::ConstKind::Placeholder(lhs) => {
+                matches!(rhs.kind(), ty::ConstKind::Placeholder(rhs) if lhs == rhs)
+            }
 
             // As we don't necessarily eagerly evaluate constants,
             // they might unify with any value.
             ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => {
                 true
             }
-            ty::ConstKind::Value(_, obl_val) => obl_val == impl_val,
 
-            ty::ConstKind::Infer(_) => true,
+            ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) => true,
+        }
+    }
 
-            ty::ConstKind::Bound(..) => {
-                panic!("unexpected obl const: {:?}", obligation_ct)
-            }
+    fn var_and_ty_may_unify(self, var: ty::InferTy, ty: I::Ty) -> bool {
+        if !ty.is_known_rigid() {
+            return true;
+        }
+
+        match var {
+            ty::IntVar(_) => ty.is_integral(),
+            ty::FloatVar(_) => ty.is_floating_point(),
+            _ => true,
         }
     }
 }
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index f49aa34..64ce6fd 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -91,8 +91,6 @@ pub trait TypeFoldable<I: Interner>: TypeVisitable<I> {
     fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
         match self.try_fold_with(folder) {
             Ok(t) => t,
-            #[cfg(bootstrap)]
-            Err(e) => match e {},
         }
     }
 }
@@ -116,8 +114,6 @@ fn try_super_fold_with<F: FallibleTypeFolder<I>>(
     fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
         match self.try_super_fold_with(folder) {
             Ok(t) => t,
-            #[cfg(bootstrap)]
-            Err(e) => match e {},
         }
     }
 }
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index f2492ed..8dec213 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -137,6 +137,8 @@ fn with_global_cache<R>(
         f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R,
     ) -> R;
 
+    fn evaluation_is_concurrent(&self) -> bool;
+
     fn expand_abstract_consts<T: TypeFoldable<Self>>(self, t: T) -> T;
 
     type GenericsOf: GenericsOf<Self>;
@@ -404,4 +406,7 @@ fn with_global_cache<R>(
     ) -> R {
         I::with_global_cache(self, mode, f)
     }
+    fn evaluation_is_concurrent(&self) -> bool {
+        self.evaluation_is_concurrent()
+    }
 }
diff --git a/compiler/rustc_type_ir/src/search_graph/global_cache.rs b/compiler/rustc_type_ir/src/search_graph/global_cache.rs
index 47f7cef..0ce927b 100644
--- a/compiler/rustc_type_ir/src/search_graph/global_cache.rs
+++ b/compiler/rustc_type_ir/src/search_graph/global_cache.rs
@@ -44,22 +44,28 @@ pub(super) fn insert(
         cx: X,
         input: X::Input,
 
-        result: X::Result,
+        origin_result: X::Result,
         dep_node: X::DepNodeIndex,
 
         additional_depth: usize,
         encountered_overflow: bool,
         nested_goals: NestedGoals<X>,
     ) {
-        let result = cx.mk_tracked(result, dep_node);
+        let result = cx.mk_tracked(origin_result, dep_node);
         let entry = self.map.entry(input).or_default();
         if encountered_overflow {
             let with_overflow = WithOverflow { nested_goals, result };
             let prev = entry.with_overflow.insert(additional_depth, with_overflow);
-            assert!(prev.is_none());
+            if let Some(prev) = &prev {
+                assert!(cx.evaluation_is_concurrent());
+                assert_eq!(cx.get_tracked(&prev.result), origin_result);
+            }
         } else {
             let prev = entry.success.replace(Success { additional_depth, nested_goals, result });
-            assert!(prev.is_none());
+            if let Some(prev) = &prev {
+                assert!(cx.evaluation_is_concurrent());
+                assert_eq!(cx.get_tracked(&prev.result), origin_result);
+            }
         }
     }
 
diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs
index 418139c..ac4d079 100644
--- a/compiler/rustc_type_ir/src/search_graph/mod.rs
+++ b/compiler/rustc_type_ir/src/search_graph/mod.rs
@@ -53,6 +53,8 @@ fn with_global_cache<R>(
         mode: SolverMode,
         f: impl FnOnce(&mut GlobalCache<Self>) -> R,
     ) -> R;
+
+    fn evaluation_is_concurrent(&self) -> bool;
 }
 
 pub trait Delegate {
diff --git a/config.example.toml b/config.example.toml
index 13f7693..2b5e9ae 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -42,6 +42,9 @@
 # Unless you're developing for a target where Rust CI doesn't build a compiler
 # toolchain or changing LLVM locally, you probably want to leave this enabled.
 #
+# Set this to `true` to download if CI llvm available otherwise it builds
+# from `src/llvm-project`.
+#
 # Set this to `"if-unchanged"` to download only if the llvm-project has not
 # been modified. You can also use this if you are unsure whether you're on a
 # tier 1 target. All tier 1 targets are currently supported.
@@ -78,6 +81,9 @@
 # Indicates whether the LLVM plugin is enabled or not
 #plugins = false
 
+# Wheter to build Enzyme as AutoDiff backend.
+#enzyme = false
+
 # Indicates whether ccache is used when building LLVM. Set to `true` to use the first `ccache` in
 # PATH, or set an absolute path to use a specific version.
 #ccache = false
@@ -233,7 +239,7 @@
 # Instead of downloading the src/stage0 version of cargo-clippy specified,
 # use this cargo-clippy binary instead as the stage0 snapshot cargo-clippy.
 #
-# Note that this option should be used with the same toolchain as the `rustc` option above. 
+# Note that this option should be used with the same toolchain as the `rustc` option above.
 # Otherwise, clippy is likely to fail due to a toolchain conflict.
 #cargo-clippy = "/path/to/cargo-clippy"
 
@@ -638,7 +644,7 @@
 #stack-protector = "none"
 
 # Prints each test name as it is executed, to help debug issues in the test harness itself.
-#verbose-tests = false
+#verbose-tests = if is_verbose { true } else { false }
 
 # Flag indicating whether tests are compiled with optimizations (the -O flag).
 #optimize-tests = true
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index a924fea..6dc7547 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -272,7 +272,7 @@ pub fn new(x: T) -> Self {
     /// assert_eq!(*five, 5)
     /// ```
     #[cfg(not(no_global_oom_handling))]
-    #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "new_uninit", since = "1.82.0")]
     #[must_use]
     #[inline]
     pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
@@ -663,7 +663,7 @@ impl<T> Box<[T]> {
     /// assert_eq!(*values, [1, 2, 3])
     /// ```
     #[cfg(not(no_global_oom_handling))]
-    #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "new_uninit", since = "1.82.0")]
     #[must_use]
     pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
         unsafe { RawVec::with_capacity(len).into_box(len) }
@@ -930,7 +930,7 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
     ///
     /// assert_eq!(*five, 5)
     /// ```
-    #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "new_uninit", since = "1.82.0")]
     #[inline]
     pub unsafe fn assume_init(self) -> Box<T, A> {
         let (raw, alloc) = Box::into_raw_with_allocator(self);
@@ -1003,7 +1003,7 @@ impl<T, A: Allocator> Box<[mem::MaybeUninit<T>], A> {
     ///
     /// assert_eq!(*values, [1, 2, 3])
     /// ```
-    #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "new_uninit", since = "1.82.0")]
     #[inline]
     pub unsafe fn assume_init(self) -> Box<[T], A> {
         let (raw, alloc) = Box::into_raw_with_allocator(self);
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index 8870137..fe9f101 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -1433,7 +1433,7 @@ pub struct Iter<'a, T: 'a> {
     iter: slice::Iter<'a, T>,
 }
 
-#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "default_iters_sequel", since = "1.82.0")]
 impl<T> Default for Iter<'_, T> {
     /// Creates an empty `binary_heap::Iter`.
     ///
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index c790857..60e08b4 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -2016,7 +2016,7 @@ fn default() -> Self {
     }
 }
 
-#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "default_iters_sequel", since = "1.82.0")]
 impl<K, V> Default for RangeMut<'_, K, V> {
     /// Creates an empty `btree_map::RangeMut`.
     ///
@@ -2064,7 +2064,7 @@ fn len(&self) -> usize {
 #[stable(feature = "fused", since = "1.26.0")]
 impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
 
-#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "default_iters_sequel", since = "1.82.0")]
 impl<K, V> Default for ValuesMut<'_, K, V> {
     /// Creates an empty `btree_map::ValuesMut`.
     ///
diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs
index 7be3de1..2b09a5e 100644
--- a/library/alloc/src/collections/vec_deque/into_iter.rs
+++ b/library/alloc/src/collections/vec_deque/into_iter.rs
@@ -121,8 +121,6 @@ fn fold<B, F>(mut self, init: B, mut f: F) -> B
     {
         match self.try_fold(init, |b, item| Ok::<B, !>(f(b, item))) {
             Ok(b) => b,
-            #[cfg(bootstrap)]
-            Err(e) => match e {},
         }
     }
 
@@ -243,8 +241,6 @@ fn rfold<B, F>(mut self, init: B, mut f: F) -> B
     {
         match self.try_rfold(init, |b, item| Ok::<B, !>(f(b, item))) {
             Ok(b) => b,
-            #[cfg(bootstrap)]
-            Err(e) => match e {},
         }
     }
 }
diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs
index 67b5b91..6922ea9 100644
--- a/library/alloc/src/collections/vec_deque/iter.rs
+++ b/library/alloc/src/collections/vec_deque/iter.rs
@@ -28,7 +28,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "default_iters_sequel", since = "1.82.0")]
 impl<T> Default for Iter<'_, T> {
     /// Creates an empty `vec_deque::Iter`.
     ///
@@ -73,7 +73,7 @@ fn next(&mut self) -> Option<&'a T> {
     fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
         let remaining = self.i1.advance_by(n);
         match remaining {
-            Ok(()) => return Ok(()),
+            Ok(()) => Ok(()),
             Err(n) => {
                 mem::swap(&mut self.i1, &mut self.i2);
                 self.i1.advance_by(n.get())
@@ -144,7 +144,7 @@ fn next_back(&mut self) -> Option<&'a T> {
 
     fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
         match self.i2.advance_back_by(n) {
-            Ok(()) => return Ok(()),
+            Ok(()) => Ok(()),
             Err(n) => {
                 mem::swap(&mut self.i1, &mut self.i2);
                 self.i2.advance_back_by(n.get())
diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs
index 2726e3e..84b7410 100644
--- a/library/alloc/src/collections/vec_deque/iter_mut.rs
+++ b/library/alloc/src/collections/vec_deque/iter_mut.rs
@@ -28,7 +28,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "default_iters_sequel", since = "1.82.0")]
 impl<T> Default for IterMut<'_, T> {
     /// Creates an empty `vec_deque::IterMut`.
     ///
@@ -64,7 +64,7 @@ fn next(&mut self) -> Option<&'a mut T> {
 
     fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
         match self.i1.advance_by(n) {
-            Ok(()) => return Ok(()),
+            Ok(()) => Ok(()),
             Err(remaining) => {
                 mem::swap(&mut self.i1, &mut self.i2);
                 self.i1.advance_by(remaining.get())
@@ -135,7 +135,7 @@ fn next_back(&mut self) -> Option<&'a mut T> {
 
     fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
         match self.i2.advance_back_by(n) {
-            Ok(()) => return Ok(()),
+            Ok(()) => Ok(()),
             Err(remaining) => {
                 mem::swap(&mut self.i1, &mut self.i2);
                 self.i2.advance_back_by(remaining.get())
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 1b31a78..88c7a12 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -517,7 +517,7 @@ pub fn new_cyclic<F>(data_fn: F) -> Rc<T>
     /// assert_eq!(*five, 5)
     /// ```
     #[cfg(not(no_global_oom_handling))]
-    #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "new_uninit", since = "1.82.0")]
     #[must_use]
     pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> {
         unsafe {
@@ -980,7 +980,7 @@ impl<T> Rc<[T]> {
     /// assert_eq!(*values, [1, 2, 3])
     /// ```
     #[cfg(not(no_global_oom_handling))]
-    #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "new_uninit", since = "1.82.0")]
     #[must_use]
     pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> {
         unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) }
@@ -1127,7 +1127,7 @@ impl<T, A: Allocator> Rc<mem::MaybeUninit<T>, A> {
     ///
     /// assert_eq!(*five, 5)
     /// ```
-    #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "new_uninit", since = "1.82.0")]
     #[inline]
     pub unsafe fn assume_init(self) -> Rc<T, A> {
         let (ptr, alloc) = Rc::into_inner_with_allocator(self);
@@ -1167,7 +1167,7 @@ impl<T, A: Allocator> Rc<[mem::MaybeUninit<T>], A> {
     ///
     /// assert_eq!(*values, [1, 2, 3])
     /// ```
-    #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "new_uninit", since = "1.82.0")]
     #[inline]
     pub unsafe fn assume_init(self) -> Rc<[T], A> {
         let (ptr, alloc) = Rc::into_inner_with_allocator(self);
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 024a794..43684f3 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -520,7 +520,7 @@ pub fn new_cyclic<F>(data_fn: F) -> Arc<T>
     /// ```
     #[cfg(not(no_global_oom_handling))]
     #[inline]
-    #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "new_uninit", since = "1.82.0")]
     #[must_use]
     pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> {
         unsafe {
@@ -1115,7 +1115,7 @@ impl<T> Arc<[T]> {
     /// ```
     #[cfg(not(no_global_oom_handling))]
     #[inline]
-    #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "new_uninit", since = "1.82.0")]
     #[must_use]
     pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
         unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) }
@@ -1262,7 +1262,7 @@ impl<T, A: Allocator> Arc<mem::MaybeUninit<T>, A> {
     ///
     /// assert_eq!(*five, 5)
     /// ```
-    #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "new_uninit", since = "1.82.0")]
     #[must_use = "`self` will be dropped if the result is not used"]
     #[inline]
     pub unsafe fn assume_init(self) -> Arc<T, A> {
@@ -1303,7 +1303,7 @@ impl<T, A: Allocator> Arc<[mem::MaybeUninit<T>], A> {
     ///
     /// assert_eq!(*values, [1, 2, 3])
     /// ```
-    #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "new_uninit", since = "1.82.0")]
     #[must_use = "`self` will be dropped if the result is not used"]
     #[inline]
     pub unsafe fn assume_init(self) -> Arc<[T], A> {
diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs
index d119e6c..ec0ab8e 100644
--- a/library/alloc/src/vec/in_place_collect.rs
+++ b/library/alloc/src/vec/in_place_collect.rs
@@ -208,7 +208,7 @@ const fn needs_realloc<SRC, DEST>(src_cap: usize, dst_cap: usize) -> bool {
 
     // type layouts don't guarantee a fit, so do a runtime check to see if
     // the allocations happen to match
-    return src_cap > 0 && src_cap * mem::size_of::<SRC>() != dst_cap * mem::size_of::<DEST>();
+    src_cap > 0 && src_cap * mem::size_of::<SRC>() != dst_cap * mem::size_of::<DEST>()
 }
 
 /// This provides a shorthand for the source type since local type aliases aren't a thing.
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs
index fad8aba..92c5e36 100644
--- a/library/alloc/src/vec/into_iter.rs
+++ b/library/alloc/src/vec/into_iter.rs
@@ -288,11 +288,11 @@ fn count(self) -> usize {
 
         // Safety: `len` is larger than the array size. Copy a fixed amount here to fully initialize
         // the array.
-        return unsafe {
+        unsafe {
             ptr::copy_nonoverlapping(self.ptr.as_ptr(), raw_ary.as_mut_ptr() as *mut T, N);
             self.ptr = self.ptr.add(N);
             Ok(raw_ary.transpose().assume_init())
-        };
+        }
     }
 
     fn fold<B, F>(mut self, mut accum: B, mut f: F) -> B
diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs
index d681bd1..be734d1 100644
--- a/library/core/src/arch.rs
+++ b/library/core/src/arch.rs
@@ -4,15 +4,6 @@
 #[stable(feature = "simd_arch", since = "1.27.0")]
 pub use crate::core_arch::arch::*;
 
-#[cfg(bootstrap)]
-#[allow(dead_code)]
-#[unstable(feature = "sha512_sm_x86", issue = "126624")]
-fn dummy() {
-    // AArch64 also has a target feature named `sm4`, so we need `#![feature(sha512_sm_x86)]` in lib.rs
-    // But as the bootstrap compiler doesn't know about this feature yet, we need to convert it to a
-    // library feature until bootstrap gets bumped
-}
-
 /// Inline assembly.
 ///
 /// Refer to [Rust By Example] for a usage guide and the [reference] for
@@ -26,6 +17,20 @@ fn dummy() {
     /* compiler built-in */
 }
 
+/// Inline assembly used in combination with `#[naked]` functions.
+///
+/// Refer to [Rust By Example] for a usage guide and the [reference] for
+/// detailed information about the syntax and available options.
+///
+/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html
+/// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html
+#[unstable(feature = "naked_functions", issue = "90957")]
+#[rustc_builtin_macro]
+#[cfg(not(bootstrap))]
+pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) {
+    /* compiler built-in */
+}
+
 /// Module-level inline assembly.
 ///
 /// Refer to [Rust By Example] for a usage guide and the [reference] for
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 5dd9721..a3a471a 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -306,7 +306,7 @@
 /// See the [module-level documentation](self) for more.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[repr(transparent)]
-#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
+#[rustc_pub_transparent]
 pub struct Cell<T: ?Sized> {
     value: UnsafeCell<T>,
 }
@@ -2056,7 +2056,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[lang = "unsafe_cell"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[repr(transparent)]
-#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
+#[rustc_pub_transparent]
 pub struct UnsafeCell<T: ?Sized> {
     value: T,
 }
@@ -2299,7 +2299,7 @@ pub(crate) const fn primitive_into_inner(self) -> *mut T {
 /// See [`UnsafeCell`] for details.
 #[unstable(feature = "sync_unsafe_cell", issue = "95439")]
 #[repr(transparent)]
-#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
+#[rustc_pub_transparent]
 pub struct SyncUnsafeCell<T: ?Sized> {
     value: UnsafeCell<T>,
 }
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 41a1966..113a2d6 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -15,7 +15,6 @@ impl char {
     /// for you:
     ///
     /// ```
-    /// #![feature(char_min)]
     /// let dist = u32::from(char::MAX) - u32::from(char::MIN);
     /// let size = (char::MIN..=char::MAX).count() as u32;
     /// assert!(size < dist);
@@ -29,7 +28,6 @@ impl char {
     /// # Examples
     ///
     /// ```
-    /// #![feature(char_min)]
     /// # fn something_which_returns_char() -> char { 'a' }
     /// let c: char = something_which_returns_char();
     /// assert!(char::MIN <= c);
@@ -37,7 +35,7 @@ impl char {
     /// let value_at_min = u32::from(char::MIN);
     /// assert_eq!(char::from_u32(value_at_min), Some('\0'));
     /// ```
-    #[unstable(feature = "char_min", issue = "114298")]
+    #[stable(feature = "char_min", since = "CURRENT_RUSTC_VERSION")]
     pub const MIN: char = '\0';
 
     /// The highest valid code point a `char` can have, `'\u{10FFFF}'`.
@@ -48,7 +46,6 @@ impl char {
     /// for you:
     ///
     /// ```
-    /// #![feature(char_min)]
     /// let dist = u32::from(char::MAX) - u32::from(char::MIN);
     /// let size = (char::MIN..=char::MAX).count() as u32;
     /// assert!(size < dist);
diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs
index 2150463..c5f8bd7 100644
--- a/library/core/src/clone.rs
+++ b/library/core/src/clone.rs
@@ -161,7 +161,7 @@ pub trait Clone: Sized {
     #[must_use = "cloning is often expensive and is not expected to have side effects"]
     // Clone::clone is special because the compiler generates MIR to implement it for some types.
     // See InstanceKind::CloneShim.
-    #[cfg_attr(not(bootstrap), lang = "clone_fn")]
+    #[lang = "clone_fn"]
     fn clone(&self) -> Self;
 
     /// Performs copy-assignment from `source`.
diff --git a/library/core/src/default.rs b/library/core/src/default.rs
index 5cacedc..4c30290 100644
--- a/library/core/src/default.rs
+++ b/library/core/src/default.rs
@@ -103,7 +103,7 @@
 /// ```
 #[cfg_attr(not(test), rustc_diagnostic_item = "Default")]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
+#[rustc_trivial_field_reads]
 pub trait Default: Sized {
     /// Returns the "default value" for a type.
     ///
diff --git a/library/core/src/future/ready.rs b/library/core/src/future/ready.rs
index 6f6da8c..b562ad4 100644
--- a/library/core/src/future/ready.rs
+++ b/library/core/src/future/ready.rs
@@ -39,7 +39,7 @@ impl<T> Ready<T> {
     /// let a = future::ready(1);
     /// assert_eq!(a.into_inner(), 1);
     /// ```
-    #[stable(feature = "ready_into_inner", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "ready_into_inner", since = "1.82.0")]
     #[must_use]
     #[inline]
     pub fn into_inner(self) -> T {
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 8cb9accd..7870a62 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1020,7 +1020,6 @@ pub const fn unlikely(b: bool) -> bool {
 /// any safety invariants.
 ///
 /// This intrinsic does not have a stable counterpart.
-#[cfg(not(bootstrap))]
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
 #[rustc_nounwind]
@@ -1030,12 +1029,6 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
     if b { true_val } else { false_val }
 }
 
-#[cfg(bootstrap)]
-#[inline]
-pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
-    if b { true_val } else { false_val }
-}
-
 extern "rust-intrinsic" {
     /// Executes a breakpoint trap, for inspection by a debugger.
     ///
diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs
index 4c8f9fe..b96335f 100644
--- a/library/core/src/iter/adapters/take.rs
+++ b/library/core/src/iter/adapters/take.rs
@@ -318,7 +318,7 @@ fn spec_for_each<F: FnMut(Self::Item)>(mut self, mut f: F) {
     }
 }
 
-#[stable(feature = "exact_size_take_repeat", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "exact_size_take_repeat", since = "1.82.0")]
 impl<T: Clone> DoubleEndedIterator for Take<crate::iter::Repeat<T>> {
     #[inline]
     fn next_back(&mut self) -> Option<Self::Item> {
@@ -361,14 +361,14 @@ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
 // because we have no way to return value of nth invocation of repeater followed
 // by n-1st without remembering all results.
 
-#[stable(feature = "exact_size_take_repeat", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "exact_size_take_repeat", since = "1.82.0")]
 impl<T: Clone> ExactSizeIterator for Take<crate::iter::Repeat<T>> {
     fn len(&self) -> usize {
         self.n
     }
 }
 
-#[stable(feature = "exact_size_take_repeat", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "exact_size_take_repeat", since = "1.82.0")]
 impl<F: FnMut() -> A, A> ExactSizeIterator for Take<crate::iter::RepeatWith<F>> {
     fn len(&self) -> usize {
         self.n
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index 5dad9e1..387963d 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -436,7 +436,7 @@ fn $fold<AAA, FFF>(mut self, init: AAA, fold: FFF) -> AAA
 pub use self::sources::{once_with, OnceWith};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::sources::{repeat, Repeat};
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
 pub use self::sources::{repeat_n, RepeatN};
 #[stable(feature = "iterator_repeat_with", since = "1.28.0")]
 pub use self::sources::{repeat_with, RepeatWith};
diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs
index 55901e1..2c726fb 100644
--- a/library/core/src/iter/sources.rs
+++ b/library/core/src/iter/sources.rs
@@ -24,7 +24,7 @@
 pub use self::once_with::{once_with, OnceWith};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::repeat::{repeat, Repeat};
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
 pub use self::repeat_n::{repeat_n, RepeatN};
 #[stable(feature = "iterator_repeat_with", since = "1.28.0")]
 pub use self::repeat_with::{repeat_with, RepeatWith};
diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs
index 2e247a3..9c06219 100644
--- a/library/core/src/iter/sources/repeat_n.rs
+++ b/library/core/src/iter/sources/repeat_n.rs
@@ -56,7 +56,7 @@
 /// assert_eq!(None, it.next());
 /// ```
 #[inline]
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
 pub fn repeat_n<T: Clone>(element: T, count: usize) -> RepeatN<T> {
     let mut element = ManuallyDrop::new(element);
 
@@ -75,7 +75,7 @@ pub fn repeat_n<T: Clone>(element: T, count: usize) -> RepeatN<T> {
 /// This `struct` is created by the [`repeat_n()`] function.
 /// See its documentation for more.
 #[derive(Clone, Debug)]
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
 pub struct RepeatN<A> {
     count: usize,
     // Invariant: has been dropped iff count == 0.
@@ -99,14 +99,14 @@ fn take_element(&mut self) -> Option<A> {
     }
 }
 
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
 impl<A> Drop for RepeatN<A> {
     fn drop(&mut self) {
         self.take_element();
     }
 }
 
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
 impl<A: Clone> Iterator for RepeatN<A> {
     type Item = A;
 
@@ -154,14 +154,14 @@ fn count(self) -> usize {
     }
 }
 
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
 impl<A: Clone> ExactSizeIterator for RepeatN<A> {
     fn len(&self) -> usize {
         self.count
     }
 }
 
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
 impl<A: Clone> DoubleEndedIterator for RepeatN<A> {
     #[inline]
     fn next_back(&mut self) -> Option<A> {
@@ -179,12 +179,12 @@ fn nth_back(&mut self, n: usize) -> Option<A> {
     }
 }
 
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
 impl<A: Clone> FusedIterator for RepeatN<A> {}
 
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<A: Clone> TrustedLen for RepeatN<A> {}
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
 impl<A: Clone> UncheckedIterator for RepeatN<A> {
     #[inline]
     unsafe fn next_unchecked(&mut self) -> Self::Item {
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 50a2d95..8352486 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -3953,7 +3953,7 @@ fn ge<I>(self, other: I) -> bool
     /// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted());
     /// ```
     #[inline]
-    #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "is_sorted", since = "1.82.0")]
     #[rustc_do_not_const_check]
     fn is_sorted(self) -> bool
     where
@@ -3980,7 +3980,7 @@ fn is_sorted(self) -> bool
     /// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| false));
     /// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| true));
     /// ```
-    #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "is_sorted", since = "1.82.0")]
     #[rustc_do_not_const_check]
     fn is_sorted_by<F>(mut self, compare: F) -> bool
     where
@@ -4025,7 +4025,7 @@ fn check<'a, T>(
     /// assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
     /// ```
     #[inline]
-    #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "is_sorted", since = "1.82.0")]
     #[rustc_do_not_const_check]
     fn is_sorted_by_key<F, K>(self, f: F) -> bool
     where
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index e60bcf3..bda38254 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -107,7 +107,6 @@
 //
 // Library features:
 // tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(offset_of_nested))]
 #![feature(array_ptr_get)]
 #![feature(asm_experimental_arch)]
 #![feature(const_align_of_val)]
@@ -122,7 +121,6 @@
 #![feature(const_cell_into_inner)]
 #![feature(const_eval_select)]
 #![feature(const_exact_div)]
-#![feature(const_float_bits_conv)]
 #![feature(const_float_classify)]
 #![feature(const_fmt_arguments_new)]
 #![feature(const_hash)]
@@ -166,6 +164,8 @@
 #![feature(coverage_attribute)]
 #![feature(do_not_recommend)]
 #![feature(duration_consts_float)]
+#![feature(f128_const)]
+#![feature(f16_const)]
 #![feature(internal_impls_macro)]
 #![feature(ip)]
 #![feature(is_ascii_octdigit)]
@@ -192,9 +192,6 @@
 //
 // Language features:
 // tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(asm_const))]
-#![cfg_attr(bootstrap, feature(const_fn_floating_point_arithmetic))]
-#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))]
 #![feature(abi_unadjusted)]
 #![feature(adt_const_params)]
 #![feature(allow_internal_unsafe)]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 5654f5a..fd41b80 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -288,8 +288,19 @@ pub trait StructuralPartialEq {
 /// }
 /// ```
 ///
-/// There is a small difference between the two: the `derive` strategy will also place a `Copy`
-/// bound on type parameters, which isn't always desired.
+/// There is a small difference between the two. The `derive` strategy will also place a `Copy`
+/// bound on type parameters:
+///
+/// ```
+/// #[derive(Clone)]
+/// struct MyStruct<T>(T);
+///
+/// impl<T: Copy> Copy for MyStruct<T> { }
+/// ```
+///
+/// This isn't always desired. For example, shared references (`&T`) can be copied regardless of
+/// whether `T` is `Copy`. Likewise, a generic struct containing markers such as [`PhantomData`]
+/// could potentially be duplicated with a bit-wise copy.
 ///
 /// ## What's the difference between `Copy` and `Clone`?
 ///
@@ -992,7 +1003,7 @@ pub trait ConstParamTy_: UnsizedConstParamTy + StructuralPartialEq + Eq {}
     /* compiler built-in */
 }
 
-#[cfg_attr(not(bootstrap), lang = "unsized_const_param_ty")]
+#[lang = "unsized_const_param_ty"]
 #[unstable(feature = "unsized_const_params", issue = "95174")]
 #[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
 /// A marker for types which can be used as types of `const` generic parameters.
@@ -1002,10 +1013,9 @@ pub trait ConstParamTy_: UnsizedConstParamTy + StructuralPartialEq + Eq {}
 pub trait UnsizedConstParamTy: StructuralPartialEq + Eq {}
 
 /// Derive macro generating an impl of the trait `ConstParamTy`.
-#[cfg(not(bootstrap))]
-#[cfg_attr(not(bootstrap), rustc_builtin_macro)]
-#[cfg_attr(not(bootstrap), allow_internal_unstable(unsized_const_params))]
-#[cfg_attr(not(bootstrap), unstable(feature = "unsized_const_params", issue = "95174"))]
+#[rustc_builtin_macro]
+#[allow_internal_unstable(unsized_const_params)]
+#[unstable(feature = "unsized_const_params", issue = "95174")]
 pub macro UnsizedConstParamTy($item:item) {
     /* compiler built-in */
 }
@@ -1021,14 +1031,6 @@ pub trait UnsizedConstParamTy: StructuralPartialEq + Eq {}
         (),
         {T: ConstParamTy_, const N: usize} [T; N],
 }
-#[cfg(bootstrap)]
-marker_impls! {
-    #[unstable(feature = "adt_const_params", issue = "95174")]
-    ConstParamTy_ for
-        str,
-        {T: ConstParamTy_} [T],
-        {T: ConstParamTy_ + ?Sized} &T,
-}
 
 marker_impls! {
     #[unstable(feature = "unsized_const_params", issue = "95174")]
diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs
index be5cee2..3e47785 100644
--- a/library/core/src/mem/manually_drop.rs
+++ b/library/core/src/mem/manually_drop.rs
@@ -47,7 +47,7 @@
 #[lang = "manually_drop"]
 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[repr(transparent)]
-#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
+#[rustc_pub_transparent]
 pub struct ManuallyDrop<T: ?Sized> {
     value: T,
 }
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index c308def..4be2e5e 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -237,7 +237,7 @@
 #[lang = "maybe_uninit"]
 #[derive(Copy)]
 #[repr(transparent)]
-#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
+#[rustc_pub_transparent]
 pub union MaybeUninit<T> {
     uninit: (),
     value: ManuallyDrop<T>,
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index fed484a..414262f 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -1326,7 +1326,6 @@ impl<T> SizedTypeProperties for T {}
 /// # Examples
 ///
 /// ```
-/// # #![cfg_attr(bootstrap, feature(offset_of_nested))]
 /// #![feature(offset_of_enum)]
 ///
 /// use std::mem;
diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs
index cda999a..7fa3c33 100644
--- a/library/core/src/mem/transmutability.rs
+++ b/library/core/src/mem/transmutability.rs
@@ -43,8 +43,7 @@
 /// conversions that extend the bits of `Src` with trailing padding to fill
 /// trailing uninitialized bytes of `Self`; e.g.:
 ///
-#[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
-#[cfg_attr(not(bootstrap), doc = "```rust")]
+/// ```rust
 /// #![feature(transmutability)]
 ///
 /// use core::mem::{Assume, TransmuteFrom};
@@ -151,8 +150,7 @@ pub struct Assume {
     /// When `false`, [`TransmuteFrom`] is not implemented for transmutations
     /// that might violate the alignment requirements of references; e.g.:
     ///
-    #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
-    #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")]
+    /// ```compile_fail,E0277
     /// #![feature(transmutability)]
     /// use core::mem::{align_of, TransmuteFrom};
     ///
@@ -171,8 +169,7 @@ pub struct Assume {
     /// that references in the transmuted value satisfy the alignment
     /// requirements of their referent types; e.g.:
     ///
-    #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
-    #[cfg_attr(not(bootstrap), doc = "```rust")]
+    /// ```rust
     /// #![feature(pointer_is_aligned_to, transmutability)]
     /// use core::mem::{align_of, Assume, TransmuteFrom};
     ///
@@ -203,8 +200,7 @@ pub struct Assume {
     /// that might violate the library safety invariants of the destination
     /// type; e.g.:
     ///
-    #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
-    #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")]
+    /// ```compile_fail,E0277
     /// #![feature(transmutability)]
     /// use core::mem::TransmuteFrom;
     ///
@@ -225,8 +221,7 @@ pub struct Assume {
     /// that undefined behavior does not arise from using the transmuted value;
     /// e.g.:
     ///
-    #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
-    #[cfg_attr(not(bootstrap), doc = "```rust")]
+    /// ```rust
     /// #![feature(transmutability)]
     /// use core::mem::{Assume, TransmuteFrom};
     ///
@@ -254,8 +249,7 @@ pub struct Assume {
     /// that might violate the language-level bit-validity invariant of the
     /// destination type; e.g.:
     ///
-    #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
-    #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")]
+    /// ```compile_fail,E0277
     /// #![feature(transmutability)]
     /// use core::mem::TransmuteFrom;
     ///
@@ -271,8 +265,7 @@ pub struct Assume {
     /// that the value being transmuted is a bit-valid instance of the
     /// transmuted value; e.g.:
     ///
-    #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
-    #[cfg_attr(not(bootstrap), doc = "```rust")]
+    /// ```rust
     /// #![feature(transmutability)]
     /// use core::mem::{Assume, TransmuteFrom};
     ///
@@ -335,9 +328,7 @@ impl Assume {
     /// This is especially useful for extending [`Assume`] in generic contexts;
     /// e.g.:
     ///
-    #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
-    #[cfg_attr(not(bootstrap), doc = "```rust")]
-    #[unstable(feature = "transmutability", issue = "99571")]
+    /// ```rust
     /// #![feature(
     ///     adt_const_params,
     ///     generic_const_exprs,
@@ -379,6 +370,7 @@ impl Assume {
     ///     try_transmute_ref::<_, _, { Assume::NOTHING }>(src)
     /// };
     ///```
+    #[unstable(feature = "transmutability", issue = "99571")]
     pub const fn and(self, other_assumptions: Self) -> Self {
         Self {
             alignment: self.alignment || other_assumptions.alignment,
@@ -390,8 +382,7 @@ pub const fn and(self, other_assumptions: Self) -> Self {
 
     /// Remove `other_assumptions` the obligations of `self`; e.g.:
     ///
-    #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
-    #[cfg_attr(not(bootstrap), doc = "```rust")]
+    /// ```rust
     /// #![feature(transmutability)]
     /// use core::mem::Assume;
     ///
diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs
index b8e22a8..6ef2fdd 100644
--- a/library/core/src/num/error.rs
+++ b/library/core/src/num/error.rs
@@ -113,7 +113,7 @@ pub enum IntErrorKind {
 impl ParseIntError {
     /// Outputs the detailed cause of parsing an integer failing.
     #[must_use]
-    #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
     #[stable(feature = "int_error_matching", since = "1.55.0")]
     pub const fn kind(&self) -> &IntErrorKind {
         &self.kind
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index d4236e4..1959628 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -914,7 +914,7 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
     /// ```
     #[inline]
     #[unstable(feature = "f128", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub const fn to_bits(self) -> u128 {
         // SAFETY: `u128` is a plain old datatype so we can always transmute to it.
@@ -963,7 +963,7 @@ pub const fn to_bits(self) -> u128 {
     #[inline]
     #[must_use]
     #[unstable(feature = "f128", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
     pub const fn from_bits(v: u128) -> Self {
         // It turns out the safety issues with sNaN were overblown! Hooray!
         // SAFETY: `u128` is a plain old datatype so we can always transmute from it.
@@ -990,7 +990,7 @@ pub const fn from_bits(v: u128) -> Self {
     /// ```
     #[inline]
     #[unstable(feature = "f128", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub const fn to_be_bytes(self) -> [u8; 16] {
         self.to_bits().to_be_bytes()
@@ -1016,7 +1016,7 @@ pub const fn from_bits(v: u128) -> Self {
     /// ```
     #[inline]
     #[unstable(feature = "f128", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub const fn to_le_bytes(self) -> [u8; 16] {
         self.to_bits().to_le_bytes()
@@ -1053,7 +1053,7 @@ pub const fn from_bits(v: u128) -> Self {
     /// ```
     #[inline]
     #[unstable(feature = "f128", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub const fn to_ne_bytes(self) -> [u8; 16] {
         self.to_bits().to_ne_bytes()
@@ -1081,7 +1081,7 @@ pub const fn from_bits(v: u128) -> Self {
     #[inline]
     #[must_use]
     #[unstable(feature = "f128", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
     pub const fn from_be_bytes(bytes: [u8; 16]) -> Self {
         Self::from_bits(u128::from_be_bytes(bytes))
     }
@@ -1108,7 +1108,7 @@ pub const fn from_bits(v: u128) -> Self {
     #[inline]
     #[must_use]
     #[unstable(feature = "f128", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
     pub const fn from_le_bytes(bytes: [u8; 16]) -> Self {
         Self::from_bits(u128::from_le_bytes(bytes))
     }
@@ -1145,7 +1145,7 @@ pub const fn from_bits(v: u128) -> Self {
     #[inline]
     #[must_use]
     #[unstable(feature = "f128", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
     pub const fn from_ne_bytes(bytes: [u8; 16]) -> Self {
         Self::from_bits(u128::from_ne_bytes(bytes))
     }
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index 1e2f841..9252e8c 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -925,7 +925,7 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
     /// ```
     #[inline]
     #[unstable(feature = "f16", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub const fn to_bits(self) -> u16 {
         // SAFETY: `u16` is a plain old datatype so we can always transmute to it.
@@ -973,7 +973,7 @@ pub const fn to_bits(self) -> u16 {
     #[inline]
     #[must_use]
     #[unstable(feature = "f16", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
     pub const fn from_bits(v: u16) -> Self {
         // It turns out the safety issues with sNaN were overblown! Hooray!
         // SAFETY: `u16` is a plain old datatype so we can always transmute from it.
@@ -999,7 +999,7 @@ pub const fn from_bits(v: u16) -> Self {
     /// ```
     #[inline]
     #[unstable(feature = "f16", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub const fn to_be_bytes(self) -> [u8; 2] {
         self.to_bits().to_be_bytes()
@@ -1024,7 +1024,7 @@ pub const fn from_bits(v: u16) -> Self {
     /// ```
     #[inline]
     #[unstable(feature = "f16", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub const fn to_le_bytes(self) -> [u8; 2] {
         self.to_bits().to_le_bytes()
@@ -1062,7 +1062,7 @@ pub const fn from_bits(v: u16) -> Self {
     /// ```
     #[inline]
     #[unstable(feature = "f16", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub const fn to_ne_bytes(self) -> [u8; 2] {
         self.to_bits().to_ne_bytes()
@@ -1086,7 +1086,7 @@ pub const fn from_bits(v: u16) -> Self {
     #[inline]
     #[must_use]
     #[unstable(feature = "f16", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
     pub const fn from_be_bytes(bytes: [u8; 2]) -> Self {
         Self::from_bits(u16::from_be_bytes(bytes))
     }
@@ -1109,7 +1109,7 @@ pub const fn from_bits(v: u16) -> Self {
     #[inline]
     #[must_use]
     #[unstable(feature = "f16", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
     pub const fn from_le_bytes(bytes: [u8; 2]) -> Self {
         Self::from_bits(u16::from_le_bytes(bytes))
     }
@@ -1143,7 +1143,7 @@ pub const fn from_bits(v: u16) -> Self {
     #[inline]
     #[must_use]
     #[unstable(feature = "f16", issue = "116909")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
     pub const fn from_ne_bytes(bytes: [u8; 2]) -> Self {
         Self::from_bits(u16::from_ne_bytes(bytes))
     }
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index c1adcc7..2bc8972 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -1115,7 +1115,7 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn to_bits(self) -> u32 {
         // SAFETY: `u32` is a plain old datatype so we can always transmute to it.
@@ -1159,7 +1159,7 @@ pub const fn to_bits(self) -> u32 {
     /// assert_eq!(v, 12.5);
     /// ```
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[must_use]
     #[inline]
     pub const fn from_bits(v: u32) -> Self {
@@ -1183,7 +1183,7 @@ pub const fn from_bits(v: u32) -> Self {
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn to_be_bytes(self) -> [u8; 4] {
         self.to_bits().to_be_bytes()
@@ -1204,7 +1204,7 @@ pub const fn from_bits(v: u32) -> Self {
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn to_le_bytes(self) -> [u8; 4] {
         self.to_bits().to_le_bytes()
@@ -1238,7 +1238,7 @@ pub const fn from_bits(v: u32) -> Self {
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn to_ne_bytes(self) -> [u8; 4] {
         self.to_bits().to_ne_bytes()
@@ -1256,7 +1256,7 @@ pub const fn from_bits(v: u32) -> Self {
     /// assert_eq!(value, 12.5);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[must_use]
     #[inline]
     pub const fn from_be_bytes(bytes: [u8; 4]) -> Self {
@@ -1275,7 +1275,7 @@ pub const fn from_bits(v: u32) -> Self {
     /// assert_eq!(value, 12.5);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[must_use]
     #[inline]
     pub const fn from_le_bytes(bytes: [u8; 4]) -> Self {
@@ -1305,7 +1305,7 @@ pub const fn from_bits(v: u32) -> Self {
     /// assert_eq!(value, 12.5);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[must_use]
     #[inline]
     pub const fn from_ne_bytes(bytes: [u8; 4]) -> Self {
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index e640677..b3f5be9 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -1111,7 +1111,7 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn to_bits(self) -> u64 {
         // SAFETY: `u64` is a plain old datatype so we can always transmute to it.
@@ -1155,7 +1155,7 @@ pub const fn to_bits(self) -> u64 {
     /// assert_eq!(v, 12.5);
     /// ```
     #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[must_use]
     #[inline]
     pub const fn from_bits(v: u64) -> Self {
@@ -1179,7 +1179,7 @@ pub const fn from_bits(v: u64) -> Self {
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn to_be_bytes(self) -> [u8; 8] {
         self.to_bits().to_be_bytes()
@@ -1200,7 +1200,7 @@ pub const fn from_bits(v: u64) -> Self {
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn to_le_bytes(self) -> [u8; 8] {
         self.to_bits().to_le_bytes()
@@ -1234,7 +1234,7 @@ pub const fn from_bits(v: u64) -> Self {
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn to_ne_bytes(self) -> [u8; 8] {
         self.to_bits().to_ne_bytes()
@@ -1252,7 +1252,7 @@ pub const fn from_bits(v: u64) -> Self {
     /// assert_eq!(value, 12.5);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[must_use]
     #[inline]
     pub const fn from_be_bytes(bytes: [u8; 8]) -> Self {
@@ -1271,7 +1271,7 @@ pub const fn from_bits(v: u64) -> Self {
     /// assert_eq!(value, 12.5);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[must_use]
     #[inline]
     pub const fn from_le_bytes(bytes: [u8; 8]) -> Self {
@@ -1301,7 +1301,7 @@ pub const fn from_bits(v: u64) -> Self {
     /// assert_eq!(value, 12.5);
     /// ```
     #[stable(feature = "float_to_from_bytes", since = "1.40.0")]
-    #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+    #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
     #[must_use]
     #[inline]
     pub const fn from_ne_bytes(bytes: [u8; 8]) -> Self {
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 878a911..7241b3f 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -3023,8 +3023,16 @@ pub const fn rem_euclid(self, rhs: Self) -> Self {
         pub const fn div_floor(self, rhs: Self) -> Self {
             let d = self / rhs;
             let r = self % rhs;
-            if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {
-                d - 1
+
+            // If the remainder is non-zero, we need to subtract one if the
+            // signs of self and rhs differ, as this means we rounded upwards
+            // instead of downwards. We do this branchlessly by creating a mask
+            // which is all-ones iff the signs differ, and 0 otherwise. Then by
+            // adding this mask (which corresponds to the signed value -1), we
+            // get our correction.
+            let correction = (self ^ rhs) >> (Self::BITS - 1);
+            if r != 0 {
+                d + correction
             } else {
                 d
             }
@@ -3059,8 +3067,12 @@ pub const fn div_floor(self, rhs: Self) -> Self {
         pub const fn div_ceil(self, rhs: Self) -> Self {
             let d = self / rhs;
             let r = self % rhs;
-            if (r > 0 && rhs > 0) || (r < 0 && rhs < 0) {
-                d + 1
+
+            // When remainder is non-zero we have a.div_ceil(b) == 1 + a.div_floor(b),
+            // so we can re-use the algorithm from div_floor, just adding 1.
+            let correction = 1 + ((self ^ rhs) >> (Self::BITS - 1));
+            if r != 0 {
+                d + correction
             } else {
                 d
             }
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index e9e5324..37c9db7 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -1385,7 +1385,7 @@ fn from_str(src: &str) -> Result<Self, ParseIntError> {
 #[doc(hidden)]
 #[inline(always)]
 #[unstable(issue = "none", feature = "std_internals")]
-#[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")]
+#[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
 pub const fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool {
     radix <= 16 && digits.len() <= mem::size_of::<T>() * 2 - is_signed_ty as usize
 }
@@ -1435,7 +1435,7 @@ impl $int_ty {
             #[doc = concat!("assert_eq!(", stringify!($int_ty), "::from_str_radix(\"A\", 16), Ok(10));")]
             /// ```
             #[stable(feature = "rust1", since = "1.0.0")]
-            #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")]
+            #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
             pub const fn from_str_radix(src: &str, radix: u32) -> Result<$int_ty, ParseIntError> {
                 use self::IntErrorKind::*;
                 use self::ParseIntError as PIE;
@@ -1565,7 +1565,7 @@ impl $size {
         #[doc = concat!("assert_eq!(", stringify!($size), "::from_str_radix(\"A\", 16), Ok(10));")]
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
-        #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")]
+        #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
         pub const fn from_str_radix(src: &str, radix: u32) -> Result<$size, ParseIntError> {
             match <$t>::from_str_radix(src, radix) {
                 Ok(x) => Ok(x as $size),
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 50cb22b7..ff48575 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -667,7 +667,7 @@ pub const fn is_none(&self) -> bool {
     /// ```
     #[must_use]
     #[inline]
-    #[stable(feature = "is_none_or", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "is_none_or", since = "1.82.0")]
     pub fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool {
         match self {
             None => true,
@@ -1338,9 +1338,8 @@ pub fn as_deref_mut(&mut self) -> Option<&mut T::Target>
     /// assert_eq!(x.iter().next(), None);
     /// ```
     #[inline]
-    #[rustc_const_unstable(feature = "const_option", issue = "67441")]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub const fn iter(&self) -> Iter<'_, T> {
+    pub fn iter(&self) -> Iter<'_, T> {
         Iter { inner: Item { opt: self.as_ref() } }
     }
 
@@ -1894,7 +1893,7 @@ pub const fn copied(self) -> Option<T>
     where
         T: Copy,
     {
-        // FIXME: this implementation, which sidesteps using `Option::map` since it's not const
+        // FIXME(const-hack): this implementation, which sidesteps using `Option::map` since it's not const
         // ready yet, should be reverted when possible to avoid code repetition
         match self {
             Some(&v) => Some(v),
@@ -1942,7 +1941,7 @@ impl<T> Option<&mut T> {
     /// ```
     #[must_use = "`self` will be dropped if the result is not used"]
     #[stable(feature = "copied", since = "1.35.0")]
-    #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
+    #[rustc_const_unstable(feature = "const_option", issue = "67441")]
     pub const fn copied(self) -> Option<T>
     where
         T: Copy,
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 65f6bfb..9c13662 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1084,7 +1084,7 @@
 #[lang = "pin"]
 #[fundamental]
 #[repr(transparent)]
-#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
+#[rustc_pub_transparent]
 #[derive(Copy, Clone)]
 pub struct Pin<Ptr> {
     // FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to:
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 3b635e2..3b45d46 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -40,15 +40,17 @@ fn runtime_impl(ptr: *const u8) -> bool {
 
         #[inline]
         const fn const_impl(ptr: *const u8) -> bool {
-            // Compare via a cast to a thin pointer, so fat pointers are only
-            // considering their "data" part for null-ness.
             match (ptr).guaranteed_eq(null_mut()) {
-                None => false,
                 Some(res) => res,
+                // To remain maximally convervative, we stop execution when we don't
+                // know whether the pointer is null or not.
+                // We can *not* return `false` here, that would be unsound in `NonNull::new`!
+                None => panic!("null-ness of this pointer cannot be determined in const context"),
             }
         }
 
-        #[allow(unused_unsafe)]
+        // Compare via a cast to a thin pointer, so fat pointers are only
+        // considering their "data" part for null-ness.
         const_eval_select((self as *const u8,), const_impl, runtime_impl)
     }
 
@@ -268,7 +270,7 @@ pub const fn to_raw_parts(self) -> (*const (), <T as super::Pointee>::Metadata)
     /// }
     /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
     #[inline]
     pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> {
         // SAFETY: the caller must guarantee that `self` is valid
@@ -300,7 +302,7 @@ pub const fn to_raw_parts(self) -> (*const (), <T as super::Pointee>::Metadata)
     /// ```
     // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized.
     #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
     #[inline]
     #[must_use]
     pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T {
@@ -334,7 +336,7 @@ pub const fn to_raw_parts(self) -> (*const (), <T as super::Pointee>::Metadata)
     /// ```
     #[inline]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
     where
         T: Sized,
@@ -1662,7 +1664,7 @@ pub unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
     /// [allocated object]: crate::ptr#allocated-object
     #[inline]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
         if self.is_null() {
             None
diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs
index ccc9f87..76a0e2b 100644
--- a/library/core/src/ptr/metadata.rs
+++ b/library/core/src/ptr/metadata.rs
@@ -187,14 +187,14 @@ pub fn size_of(self) -> usize {
         // Consider a reference like `&(i32, dyn Send)`: the vtable will only store the size of the
         // `Send` part!
         // SAFETY: DynMetadata always contains a valid vtable pointer
-        return unsafe { crate::intrinsics::vtable_size(self.vtable_ptr() as *const ()) };
+        unsafe { crate::intrinsics::vtable_size(self.vtable_ptr() as *const ()) }
     }
 
     /// Returns the alignment of the type associated with this vtable.
     #[inline]
     pub fn align_of(self) -> usize {
         // SAFETY: DynMetadata always contains a valid vtable pointer
-        return unsafe { crate::intrinsics::vtable_align(self.vtable_ptr() as *const ()) };
+        unsafe { crate::intrinsics::vtable_align(self.vtable_ptr() as *const ()) }
     }
 
     /// Returns the size and alignment together as a `Layout`
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index d7ed4ed..08d06ca 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -2277,6 +2277,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// `addr_of!(expr)` is equivalent to `&raw const expr`. The macro is *soft-deprecated*;
 /// use `&raw const` instead.
 ///
+/// It is still an open question under which conditions writing through an `addr_of!`-created
+/// pointer is permitted. If the place `expr` evaluates to is based on a raw pointer, then the
+/// result of `addr_of!` inherits all permissions from that raw pointer. However, if the place is
+/// based on a reference, local variable, or `static`, then until all details are decided, the same
+/// rules as for shared references apply: it is UB to write through a pointer created with this
+/// operation, except for bytes located inside an `UnsafeCell`. Use `&raw mut` (or [`addr_of_mut`])
+/// to create a raw pointer that definitely permits mutation.
+///
 /// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned
 /// and points to initialized data. For cases where those requirements do not hold,
 /// raw pointers should be used instead. However, `&expr as *const _` creates a reference
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 42975cc..ddb9195 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -33,22 +33,7 @@ impl<T: ?Sized> *mut T {
     #[rustc_diagnostic_item = "ptr_is_null"]
     #[inline]
     pub const fn is_null(self) -> bool {
-        #[inline]
-        fn runtime_impl(ptr: *mut u8) -> bool {
-            ptr.addr() == 0
-        }
-
-        #[inline]
-        const fn const_impl(ptr: *mut u8) -> bool {
-            // Compare via a cast to a thin pointer, so fat pointers are only
-            // considering their "data" part for null-ness.
-            match (ptr).guaranteed_eq(null_mut()) {
-                None => false,
-                Some(res) => res,
-            }
-        }
-
-        const_eval_select((self as *mut u8,), const_impl, runtime_impl)
+        self.cast_const().is_null()
     }
 
     /// Casts to a pointer of another type.
@@ -276,7 +261,7 @@ pub const fn to_raw_parts(self) -> (*mut (), <T as super::Pointee>::Metadata) {
     /// }
     /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
     #[inline]
     pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> {
         // SAFETY: the caller must guarantee that `self` is valid for a
@@ -310,7 +295,7 @@ pub const fn to_raw_parts(self) -> (*mut (), <T as super::Pointee>::Metadata) {
     /// ```
     // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized.
     #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
     #[inline]
     #[must_use]
     pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T {
@@ -349,7 +334,7 @@ pub const fn to_raw_parts(self) -> (*mut (), <T as super::Pointee>::Metadata) {
     /// ```
     #[inline]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
     where
         T: Sized,
@@ -595,7 +580,7 @@ pub fn mask(self, mask: usize) -> *mut T {
     /// println!("{s:?}"); // It'll print: "[4, 2, 3]".
     /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
     #[inline]
     pub const unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
         // SAFETY: the caller must guarantee that `self` is be valid for
@@ -631,7 +616,7 @@ pub fn mask(self, mask: usize) -> *mut T {
     /// ```
     // FIXME: mention it in the docs for `as_mut` and `as_uninit_mut` once stabilized.
     #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
     #[inline]
     #[must_use]
     pub const unsafe fn as_mut_unchecked<'a>(self) -> &'a mut T {
@@ -654,7 +639,7 @@ pub fn mask(self, mask: usize) -> *mut T {
     /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
     #[inline]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub const unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit<T>>
     where
         T: Sized,
@@ -2031,7 +2016,7 @@ pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
     /// [allocated object]: crate::ptr#allocated-object
     #[inline]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
         if self.is_null() {
             None
@@ -2083,7 +2068,7 @@ pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
     /// [allocated object]: crate::ptr#allocated-object
     #[inline]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub const unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit<T>]> {
         if self.is_null() {
             None
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index b1429ff..673acc2 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -133,7 +133,7 @@ pub const fn dangling() -> Self {
     #[inline]
     #[must_use]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub const unsafe fn as_uninit_ref<'a>(self) -> &'a MaybeUninit<T> {
         // SAFETY: the caller must guarantee that `self` meets all the
         // requirements for a reference.
@@ -157,7 +157,7 @@ pub const fn dangling() -> Self {
     #[inline]
     #[must_use]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub const unsafe fn as_uninit_mut<'a>(self) -> &'a mut MaybeUninit<T> {
         // SAFETY: the caller must guarantee that `self` meets all the
         // requirements for a reference.
@@ -1563,7 +1563,7 @@ pub const fn as_mut_ptr(self) -> *mut T {
     #[inline]
     #[must_use]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub const unsafe fn as_uninit_slice<'a>(self) -> &'a [MaybeUninit<T>] {
         // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
         unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) }
@@ -1628,7 +1628,7 @@ pub const fn as_mut_ptr(self) -> *mut T {
     #[inline]
     #[must_use]
     #[unstable(feature = "ptr_as_uninit", issue = "75402")]
-    #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+    #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
     pub const unsafe fn as_uninit_slice_mut<'a>(self) -> &'a mut [MaybeUninit<T>] {
         // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`.
         unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) }
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 73b11f8..02f6f78 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1535,11 +1535,17 @@ impl<T, E> Result<&T, E> {
     /// ```
     #[inline]
     #[stable(feature = "result_copied", since = "1.59.0")]
-    pub fn copied(self) -> Result<T, E>
+    #[rustc_const_unstable(feature = "const_result", issue = "82814")]
+    pub const fn copied(self) -> Result<T, E>
     where
         T: Copy,
     {
-        self.map(|&t| t)
+        // FIXME(const-hack): this implementation, which sidesteps using `Result::map` since it's not const
+        // ready yet, should be reverted when possible to avoid code repetition
+        match self {
+            Ok(&v) => Ok(v),
+            Err(e) => Err(e),
+        }
     }
 
     /// Maps a `Result<&T, E>` to a `Result<T, E>` by cloning the contents of the
@@ -1579,11 +1585,17 @@ impl<T, E> Result<&mut T, E> {
     /// ```
     #[inline]
     #[stable(feature = "result_copied", since = "1.59.0")]
-    pub fn copied(self) -> Result<T, E>
+    #[rustc_const_unstable(feature = "const_result", issue = "82814")]
+    pub const fn copied(self) -> Result<T, E>
     where
         T: Copy,
     {
-        self.map(|&mut t| t)
+        // FIXME(const-hack): this implementation, which sidesteps using `Result::map` since it's not const
+        // ready yet, should be reverted when possible to avoid code repetition
+        match self {
+            Ok(&mut v) => Ok(v),
+            Err(e) => Err(e),
+        }
     }
 
     /// Maps a `Result<&mut T, E>` to a `Result<T, E>` by cloning the contents of the
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index c791849..166189f 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -4088,7 +4088,7 @@ pub fn as_simd_mut<const LANES: usize>(&mut self) -> (&mut [T], &mut [Simd<T, LA
     /// assert!(![0.0, 1.0, f32::NAN].is_sorted());
     /// ```
     #[inline]
-    #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "is_sorted", since = "1.82.0")]
     #[must_use]
     pub fn is_sorted(&self) -> bool
     where
@@ -4115,7 +4115,7 @@ pub fn is_sorted(&self) -> bool
     /// assert!(empty.is_sorted_by(|a, b| false));
     /// assert!(empty.is_sorted_by(|a, b| true));
     /// ```
-    #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "is_sorted", since = "1.82.0")]
     #[must_use]
     pub fn is_sorted_by<'a, F>(&'a self, mut compare: F) -> bool
     where
@@ -4139,7 +4139,7 @@ pub fn is_sorted_by<'a, F>(&'a self, mut compare: F) -> bool
     /// assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
     /// ```
     #[inline]
-    #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "is_sorted", since = "1.82.0")]
     #[must_use]
     pub fn is_sorted_by_key<'a, F, K>(&'a self, f: F) -> bool
     where
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index 681ec79..d9301a8 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -269,7 +269,7 @@ pub fn as_str(&self) -> &'a str {
     /// ```
     #[inline]
     #[must_use]
-    #[stable(feature = "char_indices_offset", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "char_indices_offset", since = "1.82.0")]
     pub fn offset(&self) -> usize {
         self.front_offset
     }
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index cf9f1bf..e947686 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -338,9 +338,10 @@ pub const fn as_bytes(&self) -> &[u8] {
     /// assert_eq!("🍔∈🌏", s);
     /// ```
     #[stable(feature = "str_mut_extras", since = "1.20.0")]
+    #[rustc_const_unstable(feature = "const_str_as_mut", issue = "130086")]
     #[must_use]
     #[inline(always)]
-    pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
+    pub const unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
         // SAFETY: the cast from `&str` to `&[u8]` is safe since `str`
         // has the same layout as `&[u8]` (only std can make this guarantee).
         // The pointer dereference is safe since it comes from a mutable reference which
@@ -383,10 +384,11 @@ pub const fn as_ptr(&self) -> *const u8 {
     /// It is your responsibility to make sure that the string slice only gets
     /// modified in a way that it remains valid UTF-8.
     #[stable(feature = "str_as_mut_ptr", since = "1.36.0")]
+    #[rustc_const_unstable(feature = "const_str_as_mut", issue = "130086")]
     #[rustc_never_returns_null_ptr]
     #[must_use]
     #[inline(always)]
-    pub fn as_mut_ptr(&mut self) -> *mut u8 {
+    pub const fn as_mut_ptr(&mut self) -> *mut u8 {
         self as *mut str as *mut u8
     }
 
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index 2f1096d..9f1294d 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -1814,7 +1814,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> {
             }
             mask &= !(1 << trailing);
         }
-        return false;
+        false
     };
 
     let test_chunk = |idx| -> u16 {
@@ -1830,7 +1830,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> {
         let both = eq_first.bitand(eq_last);
         let mask = both.to_bitmask() as u16;
 
-        return mask;
+        mask
     };
 
     let mut i = 0;
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 6924b3c..5e559ad 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -234,7 +234,7 @@ pub struct Context<'a> {
 impl<'a> Context<'a> {
     /// Creates a new `Context` from a [`&Waker`](Waker).
     #[stable(feature = "futures_api", since = "1.36.0")]
-    #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_waker", since = "1.82.0")]
     #[must_use]
     #[inline]
     pub const fn from_waker(waker: &'a Waker) -> Self {
@@ -245,7 +245,7 @@ pub const fn from_waker(waker: &'a Waker) -> Self {
     #[inline]
     #[must_use]
     #[stable(feature = "futures_api", since = "1.36.0")]
-    #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_waker", since = "1.82.0")]
     pub const fn waker(&self) -> &'a Waker {
         &self.waker
     }
@@ -321,7 +321,7 @@ impl<'a> ContextBuilder<'a> {
     /// Creates a ContextBuilder from a Waker.
     #[inline]
     #[unstable(feature = "local_waker", issue = "118959")]
-    #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_waker", since = "1.82.0")]
     pub const fn from_waker(waker: &'a Waker) -> Self {
         // SAFETY: LocalWaker is just Waker without thread safety
         let local_waker = unsafe { transmute(waker) };
@@ -379,7 +379,7 @@ pub const fn ext(self, data: &'a mut dyn Any) -> Self {
     /// Builds the `Context`.
     #[inline]
     #[unstable(feature = "local_waker", issue = "118959")]
-    #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_waker", since = "1.82.0")]
     pub const fn build(self) -> Context<'a> {
         let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self;
         Context { waker, local_waker, ext: AssertUnwindSafe(ext), _marker, _marker2 }
@@ -538,7 +538,7 @@ pub fn will_wake(&self, other: &Waker) -> bool {
     #[inline]
     #[must_use]
     #[stable(feature = "futures_api", since = "1.36.0")]
-    #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_waker", since = "1.82.0")]
     pub const unsafe fn from_raw(waker: RawWaker) -> Waker {
         Waker { waker }
     }
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 0390bb5..c19eeed 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -250,7 +250,7 @@ pub const fn from_secs(secs: u64) -> Duration {
     /// ```
     /// use std::time::Duration;
     ///
-    /// let duration = Duration::from_millis(2569);
+    /// let duration = Duration::from_millis(2_569);
     ///
     /// assert_eq!(2, duration.as_secs());
     /// assert_eq!(569_000_000, duration.subsec_nanos());
@@ -279,7 +279,7 @@ pub const fn from_millis(millis: u64) -> Duration {
     /// let duration = Duration::from_micros(1_000_002);
     ///
     /// assert_eq!(1, duration.as_secs());
-    /// assert_eq!(2000, duration.subsec_nanos());
+    /// assert_eq!(2_000, duration.subsec_nanos());
     /// ```
     #[stable(feature = "duration_from_micros", since = "1.27.0")]
     #[must_use]
@@ -472,7 +472,7 @@ pub const fn is_zero(&self) -> bool {
     /// ```
     /// use std::time::Duration;
     ///
-    /// let duration = Duration::new(5, 730023852);
+    /// let duration = Duration::new(5, 730_023_852);
     /// assert_eq!(duration.as_secs(), 5);
     /// ```
     ///
@@ -501,7 +501,7 @@ pub const fn as_secs(&self) -> u64 {
     /// ```
     /// use std::time::Duration;
     ///
-    /// let duration = Duration::from_millis(5432);
+    /// let duration = Duration::from_millis(5_432);
     /// assert_eq!(duration.as_secs(), 5);
     /// assert_eq!(duration.subsec_millis(), 432);
     /// ```
@@ -547,7 +547,7 @@ pub const fn subsec_micros(&self) -> u32 {
     /// ```
     /// use std::time::Duration;
     ///
-    /// let duration = Duration::from_millis(5010);
+    /// let duration = Duration::from_millis(5_010);
     /// assert_eq!(duration.as_secs(), 5);
     /// assert_eq!(duration.subsec_nanos(), 10_000_000);
     /// ```
@@ -566,8 +566,8 @@ pub const fn subsec_nanos(&self) -> u32 {
     /// ```
     /// use std::time::Duration;
     ///
-    /// let duration = Duration::new(5, 730023852);
-    /// assert_eq!(duration.as_millis(), 5730);
+    /// let duration = Duration::new(5, 730_023_852);
+    /// assert_eq!(duration.as_millis(), 5_730);
     /// ```
     #[stable(feature = "duration_as_u128", since = "1.33.0")]
     #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")]
@@ -584,8 +584,8 @@ pub const fn as_millis(&self) -> u128 {
     /// ```
     /// use std::time::Duration;
     ///
-    /// let duration = Duration::new(5, 730023852);
-    /// assert_eq!(duration.as_micros(), 5730023);
+    /// let duration = Duration::new(5, 730_023_852);
+    /// assert_eq!(duration.as_micros(), 5_730_023);
     /// ```
     #[stable(feature = "duration_as_u128", since = "1.33.0")]
     #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")]
@@ -602,8 +602,8 @@ pub const fn as_micros(&self) -> u128 {
     /// ```
     /// use std::time::Duration;
     ///
-    /// let duration = Duration::new(5, 730023852);
-    /// assert_eq!(duration.as_nanos(), 5730023852);
+    /// let duration = Duration::new(5, 730_023_852);
+    /// assert_eq!(duration.as_nanos(), 5_730_023_852);
     /// ```
     #[stable(feature = "duration_as_u128", since = "1.33.0")]
     #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")]
@@ -879,7 +879,7 @@ pub const fn as_secs_f32(&self) -> f32 {
     /// use std::time::Duration;
     ///
     /// let dur = Duration::new(2, 345_678_000);
-    /// assert_eq!(dur.as_millis_f64(), 2345.678);
+    /// assert_eq!(dur.as_millis_f64(), 2_345.678);
     /// ```
     #[unstable(feature = "duration_millis_float", issue = "122451")]
     #[must_use]
@@ -900,7 +900,7 @@ pub const fn as_millis_f64(&self) -> f64 {
     /// use std::time::Duration;
     ///
     /// let dur = Duration::new(2, 345_678_000);
-    /// assert_eq!(dur.as_millis_f32(), 2345.678);
+    /// assert_eq!(dur.as_millis_f32(), 2_345.678);
     /// ```
     #[unstable(feature = "duration_millis_float", issue = "122451")]
     #[must_use]
@@ -1017,7 +1017,7 @@ pub fn mul_f64(self, rhs: f64) -> Duration {
     ///
     /// let dur = Duration::new(2, 700_000_000);
     /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_641));
-    /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847800, 0));
+    /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847_800, 0));
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[must_use = "this returns the result of the operation, \
diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs
index 9ec92e2..206b5b9 100644
--- a/library/core/src/tuple.rs
+++ b/library/core/src/tuple.rs
@@ -154,7 +154,7 @@ fn from(tuple: ($(${ignore($T)} T,)+)) -> Self {
 // Otherwise, it hides the docs entirely.
 macro_rules! maybe_tuple_doc {
     ($a:ident @ #[$meta:meta] $item:item) => {
-        #[cfg_attr(not(bootstrap), doc(fake_variadic))]
+        #[doc(fake_variadic)]
         #[doc = "This trait is implemented for tuples up to twelve items long."]
         #[$meta]
         $item
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 96fc621..dbceb8a 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -1,5 +1,4 @@
 // tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(offset_of_nested))]
 #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
 #![cfg_attr(test, feature(cfg_match))]
 #![feature(alloc_layout_extra)]
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index b7eee10..f3b4387 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -773,15 +773,20 @@ struct Foo {
 #[test]
 fn const_maybe_uninit_zeroed() {
     // Sanity check for `MaybeUninit::zeroed` in a realistic const situation (plugin array term)
+
+    // It is crucial that this type has no padding!
     #[repr(C)]
     struct Foo {
-        a: Option<&'static str>,
+        a: Option<&'static u8>,
         b: Bar,
         c: f32,
+        _pad: u32,
         d: *const u8,
     }
+
     #[repr(C)]
     struct Bar(usize);
+
     struct FooPtr(*const Foo);
     unsafe impl Sync for FooPtr {}
 
diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs
index 82c248c..070c119 100644
--- a/library/panic_unwind/src/seh.rs
+++ b/library/panic_unwind/src/seh.rs
@@ -157,9 +157,6 @@ pub fn new(ptr: *mut u8) -> Self {
             // going to be cross-lang LTOed anyway. However, using expose is shorter and
             // requires less unsafe.
             let addr: usize = ptr.expose_provenance();
-            #[cfg(bootstrap)]
-            let image_base = unsafe { addr_of!(__ImageBase) }.addr();
-            #[cfg(not(bootstrap))]
             let image_base = addr_of!(__ImageBase).addr();
             let offset: usize = addr - image_base;
             Self(offset as u32)
@@ -253,9 +250,6 @@ pub struct _TypeDescriptor {
 // This is fine since the MSVC runtime uses string comparison on the type name
 // to match TypeDescriptors rather than pointer equality.
 static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
-    #[cfg(bootstrap)]
-    pVFTable: unsafe { addr_of!(TYPE_INFO_VTABLE) } as *const _,
-    #[cfg(not(bootstrap))]
     pVFTable: addr_of!(TYPE_INFO_VTABLE) as *const _,
     spare: core::ptr::null_mut(),
     name: TYPE_NAME,
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index e06a851..2891613 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -354,12 +354,8 @@ fn description(&self) -> &str {
 /// }
 /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
 /// ```
-#[cfg_attr(bootstrap, rustc_deprecated_safe_2024)]
-#[cfg_attr(
-    not(bootstrap),
-    rustc_deprecated_safe_2024(
-        audit_that = "the environment access only happens in single-threaded code"
-    )
+#[rustc_deprecated_safe_2024(
+    audit_that = "the environment access only happens in single-threaded code"
 )]
 #[stable(feature = "env", since = "1.0.0")]
 pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
@@ -424,12 +420,8 @@ pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
 /// }
 /// assert!(env::var(key).is_err());
 /// ```
-#[cfg_attr(bootstrap, rustc_deprecated_safe_2024)]
-#[cfg_attr(
-    not(bootstrap),
-    rustc_deprecated_safe_2024(
-        audit_that = "the environment access only happens in single-threaded code"
-    )
+#[rustc_deprecated_safe_2024(
+    audit_that = "the environment access only happens in single-threaded code"
 )]
 #[stable(feature = "env", since = "1.0.0")]
 pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) {
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 918eec2..99bea67 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -852,7 +852,7 @@ pub fn to_str(&self) -> Option<&str> {
 
     /// Converts an `OsStr` to a <code>[Cow]<[str]></code>.
     ///
-    /// Any non-Unicode sequences are replaced with
+    /// Any non-UTF-8 sequences are replaced with
     /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
     ///
     /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index 13028c4..fb8dd2b 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -1,7 +1,5 @@
 use rand::RngCore;
 
-#[cfg(target_os = "macos")]
-use crate::ffi::{c_char, c_int};
 use crate::fs::{self, File, FileTimes, OpenOptions};
 use crate::io::prelude::*;
 use crate::io::{BorrowedBuf, ErrorKind, SeekFrom};
@@ -16,8 +14,6 @@
 use crate::os::windows::fs::{junction_point, symlink_dir, symlink_file, OpenOptionsExt};
 use crate::path::Path;
 use crate::sync::Arc;
-#[cfg(target_os = "macos")]
-use crate::sys::weak::weak;
 use crate::sys_common::io::test::{tmpdir, TempDir};
 use crate::time::{Duration, Instant, SystemTime};
 use crate::{env, str, thread};
@@ -80,17 +76,6 @@ pub fn got_symlink_permission(tmpdir: &TempDir) -> bool {
     }
 }
 
-#[cfg(target_os = "macos")]
-fn able_to_not_follow_symlinks_while_hard_linking() -> bool {
-    weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int);
-    linkat.get().is_some()
-}
-
-#[cfg(not(target_os = "macos"))]
-fn able_to_not_follow_symlinks_while_hard_linking() -> bool {
-    return true;
-}
-
 #[test]
 fn file_test_io_smoke_test() {
     let message = "it's alright. have a good time";
@@ -1456,9 +1441,6 @@ fn symlink_hard_link() {
     if !got_symlink_permission(&tmpdir) {
         return;
     };
-    if !able_to_not_follow_symlinks_while_hard_linking() {
-        return;
-    }
 
     // Create "file", a file.
     check!(fs::File::create(tmpdir.join("file")));
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index e8ae1d9..6ecd946 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -223,10 +223,10 @@ pub enum ErrorKind {
     #[stable(feature = "rust1", since = "1.0.0")]
     ConnectionReset,
     /// The remote host is not reachable.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     HostUnreachable,
     /// The network containing the remote host is not reachable.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     NetworkUnreachable,
     /// The connection was aborted (terminated) by the remote server.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -243,7 +243,7 @@ pub enum ErrorKind {
     #[stable(feature = "rust1", since = "1.0.0")]
     AddrNotAvailable,
     /// The system's networking is down.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     NetworkDown,
     /// The operation failed because a pipe was closed.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -259,18 +259,18 @@ pub enum ErrorKind {
     ///
     /// For example, a filesystem path was specified where one of the intermediate directory
     /// components was, in fact, a plain file.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     NotADirectory,
     /// The filesystem object is, unexpectedly, a directory.
     ///
     /// A directory was specified when a non-directory was expected.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     IsADirectory,
     /// A non-empty directory was specified where an empty directory was expected.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     DirectoryNotEmpty,
     /// The filesystem or storage medium is read-only, but a write operation was attempted.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     ReadOnlyFilesystem,
     /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links.
     ///
@@ -285,7 +285,7 @@ pub enum ErrorKind {
     ///
     /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated
     /// by problems with the network or server.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     StaleNetworkFileHandle,
     /// A parameter was incorrect.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -319,13 +319,13 @@ pub enum ErrorKind {
     /// The underlying storage (typically, a filesystem) is full.
     ///
     /// This does not include out of quota errors.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     StorageFull,
     /// Seek on unseekable file.
     ///
     /// Seeking was attempted on an open file handle which is not suitable for seeking - for
     /// example, on Unix, a named pipe opened with `File::open`.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     NotSeekable,
     /// Filesystem quota was exceeded.
     #[unstable(feature = "io_error_more", issue = "86442")]
@@ -335,22 +335,22 @@ pub enum ErrorKind {
     /// This might arise from a hard limit of the underlying filesystem or file access API, or from
     /// an administratively imposed resource limitation.  Simple disk full, and out of quota, have
     /// their own errors.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     FileTooLarge,
     /// Resource is busy.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     ResourceBusy,
     /// Executable file is busy.
     ///
     /// An attempt was made to write to a file which is also in use as a running program.  (Not all
     /// operating systems detect this situation.)
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     ExecutableFileBusy,
     /// Deadlock (avoided).
     ///
     /// A file locking operation would result in deadlock.  This situation is typically detected, if
     /// at all, on a best-effort basis.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     Deadlock,
     /// Cross-device or cross-filesystem (hard) link or rename.
     #[unstable(feature = "io_error_more", issue = "86442")]
@@ -358,7 +358,7 @@ pub enum ErrorKind {
     /// Too many (hard) links to the same filesystem object.
     ///
     /// The filesystem does not support making so many hardlinks to the same file.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     TooManyLinks,
     /// A filename was invalid.
     ///
@@ -369,7 +369,7 @@ pub enum ErrorKind {
     ///
     /// When trying to run an external program, a system or process limit on the size of the
     /// arguments would have been exceeded.
-    #[unstable(feature = "io_error_more", issue = "86442")]
+    #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
     ArgumentListTooLong,
     /// This operation was interrupted.
     ///
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 606d756..60969af 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -272,7 +272,6 @@
 //
 // Language features:
 // tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))]
 #![feature(alloc_error_handler)]
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index 4620244..9aadd94 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -118,11 +118,7 @@ unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
     /// [`pre_exec`]: CommandExt::pre_exec
     #[stable(feature = "process_exec", since = "1.15.0")]
     #[deprecated(since = "1.37.0", note = "should be unsafe, use `pre_exec` instead")]
-    #[cfg_attr(bootstrap, rustc_deprecated_safe_2024)]
-    #[cfg_attr(
-        not(bootstrap),
-        rustc_deprecated_safe_2024(audit_that = "the closure is async-signal-safe")
-    )]
+    #[rustc_deprecated_safe_2024(audit_that = "the closure is async-signal-safe")]
     unsafe fn before_exec<F>(&mut self, f: F) -> &mut process::Command
     where
         F: FnMut() -> io::Result<()> + Send + Sync + 'static,
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 1c972d3..336e34d 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -23,8 +23,8 @@
 use crate::panic::{BacktraceStyle, PanicHookInfo};
 use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sync::{PoisonError, RwLock};
-use crate::sys::backtrace;
 use crate::sys::stdio::panic_output;
+use crate::sys::{backtrace, dbg};
 use crate::{fmt, intrinsics, process, thread};
 
 // Binary interface to the panic runtime that the standard library depends on.
@@ -859,6 +859,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[cfg_attr(not(test), rustc_std_internal_symbol)]
 #[cfg(not(feature = "panic_immediate_abort"))]
 fn rust_panic(msg: &mut dyn PanicPayload) -> ! {
+    // Break into the debugger if it is attached.
+    // The return value is not currently used.
+    //
+    // This function isn't used anywhere else, and
+    // using inside `#[panic_handler]` doesn't seem
+    // to count, so a warning is issued.
+    let _ = dbg::breakpoint_if_debugging();
+
     let code = unsafe { __rust_start_panic(msg) };
     rtabort!("failed to initiate panic, error {code}")
 }
@@ -866,6 +874,14 @@ fn rust_panic(msg: &mut dyn PanicPayload) -> ! {
 #[cfg_attr(not(test), rustc_std_internal_symbol)]
 #[cfg(feature = "panic_immediate_abort")]
 fn rust_panic(_: &mut dyn PanicPayload) -> ! {
+    // Break into the debugger if it is attached.
+    // The return value is not currently used.
+    //
+    // This function isn't used anywhere else, and
+    // using inside `#[panic_handler]` doesn't seem
+    // to count, so a warning is issued.
+    let _ = dbg::breakpoint_if_debugging();
+
     unsafe {
         crate::intrinsics::abort();
     }
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 9eaa0e0..506ad44 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2200,7 +2200,7 @@ pub fn to_str(&self) -> Option<&str> {
 
     /// Converts a `Path` to a [`Cow<str>`].
     ///
-    /// Any non-Unicode sequences are replaced with
+    /// Any non-UTF-8 sequences are replaced with
     /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
     ///
     /// [U+FFFD]: super::char::REPLACEMENT_CHARACTER
diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs
index 08d46f3..e41cbc1 100644
--- a/library/std/src/sync/condvar.rs
+++ b/library/std/src/sync/condvar.rs
@@ -195,8 +195,11 @@ pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> LockResult<MutexGuard<'a,
         if poisoned { Err(PoisonError::new(guard)) } else { Ok(guard) }
     }
 
-    /// Blocks the current thread until this condition variable receives a
-    /// notification and the provided condition is false.
+    /// Blocks the current thread until the provided condition becomes false.
+    ///
+    /// `condition` is checked immediately; if not met (returns `true`), this
+    /// will [`wait`] for the next notification then check again. This repeats
+    /// until `condition` returns `false`, in which case this function returns.
     ///
     /// This function will atomically unlock the mutex specified (represented by
     /// `guard`) and block the current thread. This means that any calls
@@ -210,6 +213,7 @@ pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> LockResult<MutexGuard<'a,
     /// poisoned when this thread re-acquires the lock. For more information,
     /// see information about [poisoning] on the [`Mutex`] type.
     ///
+    /// [`wait`]: Self::wait
     /// [`notify_one`]: Self::notify_one
     /// [`notify_all`]: Self::notify_all
     /// [poisoning]: super::Mutex#poisoning
diff --git a/library/std/src/sys/dbg.rs b/library/std/src/sys/dbg.rs
new file mode 100644
index 0000000..a6e78db
--- /dev/null
+++ b/library/std/src/sys/dbg.rs
@@ -0,0 +1,229 @@
+//! Debugging aids.
+
+/// Presence of a debugger. The debugger being concerned
+/// is expected to use the OS API to debug this process.
+#[derive(Copy, Clone, Debug)]
+#[allow(unused)]
+pub(crate) enum DebuggerPresence {
+    /// The debugger is attached to this process.
+    Detected,
+    /// The debugger is not attached to this process.
+    NotDetected,
+}
+
+#[cfg(target_os = "windows")]
+mod os {
+    use super::DebuggerPresence;
+
+    #[link(name = "kernel32")]
+    extern "system" {
+        fn IsDebuggerPresent() -> i32;
+    }
+
+    pub(super) fn is_debugger_present() -> Option<DebuggerPresence> {
+        // SAFETY: No state is shared between threads. The call reads
+        // a field from the Thread Environment Block using the OS API
+        // as required by the documentation.
+        if unsafe { IsDebuggerPresent() } != 0 {
+            Some(DebuggerPresence::Detected)
+        } else {
+            Some(DebuggerPresence::NotDetected)
+        }
+    }
+}
+
+#[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
+mod os {
+    use libc::{c_int, sysctl, CTL_KERN, KERN_PROC, KERN_PROC_PID};
+
+    use super::DebuggerPresence;
+    use crate::io::{Cursor, Read, Seek, SeekFrom};
+    use crate::process;
+
+    const P_TRACED: i32 = 0x00000800;
+
+    // The assumption is that the kernel structures available to the
+    // user space may not shrink or repurpose the existing fields over
+    // time. The kernels normally adhere to that for the backward
+    // compatibility of the user space.
+
+    // The macOS 14.5 SDK comes with a header `MacOSX14.5.sdk/usr/include/sys/sysctl.h`
+    // that defines `struct kinfo_proc` be of `648` bytes on the 64-bit system. That has
+    // not changed since macOS 10.13 (released in 2017) at least, validated by building
+    // a C program in XCode while changing the build target. Apple provides this example
+    // for reference: https://developer.apple.com/library/archive/qa/qa1361/_index.html.
+    #[cfg(target_vendor = "apple")]
+    const KINFO_PROC_SIZE: usize = if cfg!(target_pointer_width = "64") { 648 } else { 492 };
+    #[cfg(target_vendor = "apple")]
+    const KINFO_PROC_FLAGS_OFFSET: u64 = if cfg!(target_pointer_width = "64") { 32 } else { 16 };
+
+    // Works for FreeBSD stable (13.3, 13.4) and current (14.0, 14.1).
+    // The size of the structure has stayed the same for a long time,
+    // at least since 2005:
+    // https://lists.freebsd.org/pipermail/freebsd-stable/2005-November/019899.html
+    #[cfg(target_os = "freebsd")]
+    const KINFO_PROC_SIZE: usize = if cfg!(target_pointer_width = "64") { 1088 } else { 768 };
+    #[cfg(target_os = "freebsd")]
+    const KINFO_PROC_FLAGS_OFFSET: u64 = if cfg!(target_pointer_width = "64") { 368 } else { 296 };
+
+    pub(super) fn is_debugger_present() -> Option<DebuggerPresence> {
+        debug_assert_ne!(KINFO_PROC_SIZE, 0);
+
+        let mut flags = [0u8; 4]; // `ki_flag` under FreeBSD and `p_flag` under macOS.
+        let mut mib = [CTL_KERN, KERN_PROC, KERN_PROC_PID, process::id() as c_int];
+        let mut info_size = KINFO_PROC_SIZE;
+        let mut kinfo_proc = [0u8; KINFO_PROC_SIZE];
+
+        // SAFETY: No state is shared with other threads. The sysctl call
+        // is safe according to the documentation.
+        if unsafe {
+            sysctl(
+                mib.as_mut_ptr(),
+                mib.len() as u32,
+                kinfo_proc.as_mut_ptr().cast(),
+                &mut info_size,
+                core::ptr::null_mut(),
+                0,
+            )
+        } != 0
+        {
+            return None;
+        }
+        debug_assert_eq!(info_size, KINFO_PROC_SIZE);
+
+        let mut reader = Cursor::new(kinfo_proc);
+        reader.seek(SeekFrom::Start(KINFO_PROC_FLAGS_OFFSET)).ok()?;
+        reader.read_exact(&mut flags).ok()?;
+        // Just in case, not limiting this to the little-endian systems.
+        let flags = i32::from_ne_bytes(flags);
+
+        if flags & P_TRACED != 0 {
+            Some(DebuggerPresence::Detected)
+        } else {
+            Some(DebuggerPresence::NotDetected)
+        }
+    }
+}
+
+#[cfg(target_os = "linux")]
+mod os {
+    use super::DebuggerPresence;
+    use crate::fs::File;
+    use crate::io::Read;
+
+    pub(super) fn is_debugger_present() -> Option<DebuggerPresence> {
+        // This function is crafted with the following goals:
+        // * Memory efficiency: It avoids crashing the panicking process due to
+        //   out-of-memory (OOM) conditions by not using large heap buffers or
+        //   allocating significant stack space, which could lead to stack overflow.
+        // * Minimal binary size: The function uses a minimal set of facilities
+        //   from the standard library to avoid increasing the resulting binary size.
+        //
+        // To achieve these goals, the function does not use `[std::io::BufReader]`
+        // and instead reads the file byte by byte using a sliding window approach.
+        // It's important to note that the "/proc/self/status" pseudo-file is synthesized
+        // by the Virtual File System (VFS), meaning it is not read from a slow or
+        // non-volatile storage medium so buffering might not be as beneficial because
+        // all data is read from memory, though this approach does incur a syscall for
+        // each byte read.
+        //
+        // We cannot make assumptions about the file size or the position of the
+        // target prefix ("TracerPid:"), so the function does not use
+        // `[std::fs::read_to_string]` thus not employing UTF-8 to ASCII checking,
+        // conversion, or parsing as we're looking for an ASCII prefix.
+        //
+        // These condiderations make the function deviate from the familiar concise pattern
+        // of searching for a string in a text file.
+
+        fn read_byte(file: &mut File) -> Option<u8> {
+            let mut buffer = [0];
+            file.read_exact(&mut buffer).ok()?;
+            Some(buffer[0])
+        }
+
+        // The ASCII prefix of the datum we're interested in.
+        const TRACER_PID: &[u8] = b"TracerPid:\t";
+
+        let mut file = File::open("/proc/self/status").ok()?;
+        let mut matched = 0;
+
+        // Look for the `TRACER_PID` prefix.
+        while let Some(byte) = read_byte(&mut file) {
+            if byte == TRACER_PID[matched] {
+                matched += 1;
+                if matched == TRACER_PID.len() {
+                    break;
+                }
+            } else {
+                matched = 0;
+            }
+        }
+
+        // Was the prefix found?
+        if matched != TRACER_PID.len() {
+            return None;
+        }
+
+        // It was; get the ASCII representation of the first digit
+        // of the PID. That is enough to see if there is a debugger
+        // attached as the kernel does not pad the PID on the left
+        // with the leading zeroes.
+        let byte = read_byte(&mut file)?;
+        if byte.is_ascii_digit() && byte != b'0' {
+            Some(DebuggerPresence::Detected)
+        } else {
+            Some(DebuggerPresence::NotDetected)
+        }
+    }
+}
+
+#[cfg(not(any(
+    target_os = "windows",
+    target_vendor = "apple",
+    target_os = "freebsd",
+    target_os = "linux"
+)))]
+mod os {
+    pub(super) fn is_debugger_present() -> Option<super::DebuggerPresence> {
+        None
+    }
+}
+
+/// Detect the debugger presence.
+///
+/// The code does not try to detect the debugger at all costs (e.g., when anti-debugger
+/// tricks are at play), it relies on the interfaces provided by the OS.
+///
+/// Return value:
+/// * `None`: it's not possible to conclude whether the debugger is attached to this
+///    process or not. When checking for the presence of the debugger, the detection logic
+///    encountered an issue, such as the OS API throwing an error or the feature not being
+///    implemented.
+/// * `Some(DebuggerPresence::Detected)`: yes, the debugger is attached
+///   to this process.
+/// * `Some(DebuggerPresence::NotDetected)`: no, the debugger is not
+///    attached to this process.
+pub(crate) fn is_debugger_present() -> Option<DebuggerPresence> {
+    if cfg!(miri) { None } else { os::is_debugger_present() }
+}
+
+/// Execute the breakpoint instruction if the debugger presence is detected.
+/// Useful for breaking into the debugger without the need to set a breakpoint
+/// in the debugger.
+///
+/// Note that there is a race between attaching or detaching the debugger, and running the
+/// breakpoint instruction. This is nonetheless memory-safe, like [`crate::process::abort`]
+/// is. In case the debugger is attached and the function is about
+/// to run the breakpoint instruction yet right before that the debugger detaches, the
+/// process will crash due to running the breakpoint instruction and the debugger not
+/// handling the trap exception.
+pub(crate) fn breakpoint_if_debugging() -> Option<DebuggerPresence> {
+    let debugger_present = is_debugger_present();
+    if let Some(DebuggerPresence::Detected) = debugger_present {
+        // SAFETY: Executing the breakpoint instruction. No state is shared
+        // or modified by this code.
+        unsafe { core::intrinsics::breakpoint() };
+    }
+
+    debugger_present
+}
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index 1ef17dd..96d6f2c 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -11,6 +11,7 @@
 pub mod anonymous_pipe;
 pub mod backtrace;
 pub mod cmath;
+pub mod dbg;
 pub mod exit_guard;
 pub mod os_str;
 pub mod path;
diff --git a/library/std/src/sys/pal/unix/linux/pidfd.rs b/library/std/src/sys/pal/unix/linux/pidfd.rs
index 7474f80..7874443 100644
--- a/library/std/src/sys/pal/unix/linux/pidfd.rs
+++ b/library/std/src/sys/pal/unix/linux/pidfd.rs
@@ -13,7 +13,7 @@
 
 impl PidFd {
     pub fn kill(&self) -> io::Result<()> {
-        return cvt(unsafe {
+        cvt(unsafe {
             libc::syscall(
                 libc::SYS_pidfd_send_signal,
                 self.0.as_raw_fd(),
@@ -22,7 +22,7 @@ pub fn kill(&self) -> io::Result<()> {
                 0,
             )
         })
-        .map(drop);
+        .map(drop)
     }
 
     pub fn wait(&self) -> io::Result<ExitStatus> {
@@ -30,7 +30,7 @@ pub fn wait(&self) -> io::Result<ExitStatus> {
         cvt(unsafe {
             libc::waitid(libc::P_PIDFD, self.0.as_raw_fd() as u32, &mut siginfo, libc::WEXITED)
         })?;
-        return Ok(ExitStatus::from_waitid_siginfo(siginfo));
+        Ok(ExitStatus::from_waitid_siginfo(siginfo))
     }
 
     pub fn try_wait(&self) -> io::Result<Option<ExitStatus>> {
@@ -45,9 +45,10 @@ pub fn try_wait(&self) -> io::Result<Option<ExitStatus>> {
             )
         })?;
         if unsafe { siginfo.si_pid() } == 0 {
-            return Ok(None);
+            Ok(None)
+        } else {
+            Ok(Some(ExitStatus::from_waitid_siginfo(siginfo)))
         }
-        return Ok(Some(ExitStatus::from_waitid_siginfo(siginfo)));
     }
 }
 
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 9ff44b5..728ce8d 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -32,7 +32,8 @@ fn drop(&mut self) {
     target_os = "macos",
     target_os = "netbsd",
     target_os = "openbsd",
-    target_os = "solaris"
+    target_os = "solaris",
+    target_os = "illumos",
 ))]
 mod imp {
     #[cfg(not(all(target_os = "linux", target_env = "gnu")))]
@@ -280,7 +281,7 @@ fn sigstack_size() -> usize {
         libc::SIGSTKSZ
     }
 
-    #[cfg(target_os = "solaris")]
+    #[cfg(any(target_os = "solaris", target_os = "illumos"))]
     unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
         let mut current_stack: libc::stack_t = crate::mem::zeroed();
         assert_eq!(libc::stack_getbounds(&mut current_stack), 0);
@@ -486,7 +487,12 @@ unsafe fn install_main_guard_default(page_size: usize) -> Option<Range<usize>> {
         Some(guardaddr..guardaddr + page_size)
     }
 
-    #[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))]
+    #[cfg(any(
+        target_os = "macos",
+        target_os = "openbsd",
+        target_os = "solaris",
+        target_os = "illumos",
+    ))]
     // FIXME: I am probably not unsafe.
     unsafe fn current_guard() -> Option<Range<usize>> {
         let stackptr = get_stack_start()?;
@@ -569,7 +575,8 @@ unsafe fn current_guard() -> Option<Range<usize>> {
     target_os = "macos",
     target_os = "netbsd",
     target_os = "openbsd",
-    target_os = "solaris"
+    target_os = "solaris",
+    target_os = "illumos",
 )))]
 mod imp {
     pub unsafe fn init() {}
diff --git a/library/std/src/sys/pal/wasi/fs.rs b/library/std/src/sys/pal/wasi/fs.rs
index 88b1e54..e1c61ca 100644
--- a/library/std/src/sys/pal/wasi/fs.rs
+++ b/library/std/src/sys/pal/wasi/fs.rs
@@ -265,7 +265,7 @@ impl OpenOptions {
     pub fn new() -> OpenOptions {
         let mut base = OpenOptions::default();
         base.dirflags = wasi::LOOKUPFLAGS_SYMLINK_FOLLOW;
-        return base;
+        base
     }
 
     pub fn read(&mut self, read: bool) {
@@ -382,7 +382,7 @@ fn rights_base(&self) -> wasi::Rights {
         base |= wasi::RIGHTS_PATH_UNLINK_FILE;
         base |= wasi::RIGHTS_POLL_FD_READWRITE;
 
-        return base;
+        base
     }
 
     fn rights_inheriting(&self) -> wasi::Rights {
diff --git a/library/std/src/sys/pal/wasi/helpers.rs b/library/std/src/sys/pal/wasi/helpers.rs
index d047bf2..37ef178 100644
--- a/library/std/src/sys/pal/wasi/helpers.rs
+++ b/library/std/src/sys/pal/wasi/helpers.rs
@@ -115,7 +115,7 @@ pub fn hashmap_random_keys() -> (u64, u64) {
         let len = mem::size_of_val(&ret);
         wasi::random_get(base, len).expect("random_get failure");
     }
-    return ret;
+    ret
 }
 
 #[inline]
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index e29c28f..0fc63c5 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -432,7 +432,7 @@ pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>>
     /// ```
     ///
     /// [`io::Result`]: crate::io::Result
-    #[stable(feature = "thread_spawn_unchecked", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")]
     pub unsafe fn spawn_unchecked<F, T>(self, f: F) -> io::Result<JoinHandle<T>>
     where
         F: FnOnce() -> T,
diff --git a/library/windows_targets/src/lib.rs b/library/windows_targets/src/lib.rs
index 1965b6c..395cd6a4 100644
--- a/library/windows_targets/src/lib.rs
+++ b/library/windows_targets/src/lib.rs
@@ -38,4 +38,5 @@
 #[link(name = "ntdll")]
 #[link(name = "userenv")]
 #[link(name = "ws2_32")]
+#[link(name = "dbghelp")] // required for backtrace-rs symbolization
 extern "C" {}
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 71f69e0..666df490 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -106,22 +106,29 @@
 
     try:
         if (probably_big or verbose) and "GITHUB_ACTIONS" not in os.environ:
-            option = "-#"
+            option = "--progress-bar"
         else:
-            option = "-s"
+            option = "--silent"
         # If curl is not present on Win32, we should not sys.exit
         #   but raise `CalledProcessError` or `OSError` instead
         require(["curl", "--version"], exception=platform_is_win32())
         extra_flags = []
         if curl_version() > (7, 70):
             extra_flags = [ "--retry-all-errors" ]
+        # options should be kept in sync with
+        # src/bootstrap/src/core/download.rs
+        # for consistency.
+        # they are also more compreprensivly explained in that file.
         run(["curl", option] + extra_flags + [
-            "-L", # Follow redirect.
-            "-y", "30", "-Y", "10",    # timeout if speed is < 10 bytes/sec for > 30 seconds
-            "--connect-timeout", "30",  # timeout if cannot connect within 30 seconds
-            "-o", path,
+            # Follow redirect.
+            "--location",
+            # timeout if speed is < 10 bytes/sec for > 30 seconds
+            "--speed-time", "30", "--speed-limit", "10",
+            # timeout if cannot connect within 30 seconds
+            "--connect-timeout", "30",
+            "--output", path,
             "--continue-at", "-",
-            "--retry", "3", "-SRf", url],
+            "--retry", "3", "--show-error", "--remote-time", "--fail", url],
             verbose=verbose,
             exception=True, # Will raise RuntimeError on failure
         )
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 768aac9..49d5646 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -71,6 +71,7 @@
 # channel, etc.
 o("optimize-llvm", "llvm.optimize", "build optimized LLVM")
 o("llvm-assertions", "llvm.assertions", "build LLVM with assertions")
+o("llvm-enzyme", "llvm.enzyme", "build LLVM with enzyme")
 o("llvm-plugins", "llvm.plugins", "build LLVM with plugin interface")
 o("debug-assertions", "rust.debug-assertions", "build with debugging assertions")
 o("debug-assertions-std", "rust.debug-assertions-std", "build the standard library with debugging assertions")
diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml
index 789586b..147939d2 100644
--- a/src/bootstrap/defaults/config.compiler.toml
+++ b/src/bootstrap/defaults/config.compiler.toml
@@ -27,4 +27,5 @@
 # Enable warnings during the LLVM compilation (when LLVM is changed, causing a compilation)
 enable-warnings = true
 # Will download LLVM from CI if available on your platform.
-download-ci-llvm = "if-unchanged"
+# If you intend to modify `src/llvm-project`, use `"if-unchanged"` or `false` instead.
+download-ci-llvm = true
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index 9090153..42cecbf 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
 Change this file to make users of the `download-ci-llvm` configuration download
 a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
 
-Last change is for: https://github.com/rust-lang/rust/pull/129116
+Last change is for: https://github.com/rust-lang/rust/pull/129788
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index 7f7faf0..ba12e64 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -228,7 +228,7 @@ fn run(self, builder: &Builder<'_>) {
             self.override_build_kind.unwrap_or(builder.kind),
         );
 
-        rustc_cargo(builder, &mut cargo, target, &compiler);
+        rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
 
         // For ./x.py clippy, don't run with --all-targets because
         // linting tests and benchmarks can produce very noisy results
diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs
index a2bb03c..a099235 100644
--- a/src/bootstrap/src/core/build_steps/clippy.rs
+++ b/src/bootstrap/src/core/build_steps/clippy.rs
@@ -197,7 +197,7 @@ fn run(self, builder: &Builder<'_>) {
             Kind::Clippy,
         );
 
-        rustc_cargo(builder, &mut cargo, target, &compiler);
+        rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
 
         // Explicitly pass -p for all compiler crates -- this will force cargo
         // to also lint the tests/benches/examples for these crates, rather
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index eef5480..102c9fd 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -931,7 +931,12 @@ fn run(self, builder: &Builder<'_>) -> u32 {
         // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler,
         // so its artifacts can't be reused.
         if builder.download_rustc() && compiler.stage != 0 {
-            builder.ensure(Sysroot { compiler, force_recompile: false });
+            let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
+            cp_rustc_component_to_ci_sysroot(
+                builder,
+                &sysroot,
+                builder.config.ci_rustc_dev_contents(),
+            );
             return compiler.stage;
         }
 
@@ -983,7 +988,7 @@ fn run(self, builder: &Builder<'_>) -> u32 {
             Kind::Build,
         );
 
-        rustc_cargo(builder, &mut cargo, target, &compiler);
+        rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
 
         // NB: all RUSTFLAGS should be added to `rustc_cargo()` so they will be
         // consistently applied by check/doc/test modes too.
@@ -1042,10 +1047,11 @@ pub fn rustc_cargo(
     cargo: &mut Cargo,
     target: TargetSelection,
     compiler: &Compiler,
+    crates: &[String],
 ) {
     cargo
         .arg("--features")
-        .arg(builder.rustc_features(builder.kind, target))
+        .arg(builder.rustc_features(builder.kind, target, crates))
         .arg("--manifest-path")
         .arg(builder.src.join("compiler/rustc/Cargo.toml"));
 
@@ -1189,6 +1195,10 @@ pub fn rustc_cargo_env(
         cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
     }
 
+    if builder.config.llvm_enzyme {
+        cargo.rustflag("--cfg=llvm_enzyme");
+    }
+
     // Note that this is disabled if LLVM itself is disabled or we're in a check
     // build. If we are in a check build we still go ahead here presuming we've
     // detected that LLVM is already built and good to go which helps prevent
@@ -1784,6 +1794,24 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
         //        use that to bootstrap this compiler forward.
         let mut build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
 
+        // Build enzyme
+        let enzyme_install = if builder.config.llvm_enzyme {
+            Some(builder.ensure(llvm::Enzyme { target: build_compiler.host }))
+        } else {
+            None
+        };
+
+        if let Some(enzyme_install) = enzyme_install {
+            let lib_ext = std::env::consts::DLL_EXTENSION;
+            let src_lib = enzyme_install.join("build/Enzyme/libEnzyme-19").with_extension(lib_ext);
+            let libdir = builder.sysroot_libdir(build_compiler, build_compiler.host);
+            let target_libdir = builder.sysroot_libdir(target_compiler, target_compiler.host);
+            let dst_lib = libdir.join("libEnzyme-19").with_extension(lib_ext);
+            let target_dst_lib = target_libdir.join("libEnzyme-19").with_extension(lib_ext);
+            builder.copy_link(&src_lib, &dst_lib);
+            builder.copy_link(&src_lib, &target_dst_lib);
+        }
+
         // Build the libraries for this compiler to link to (i.e., the libraries
         // it uses at runtime). NOTE: Crates the target compiler compiles don't
         // link to these. (FIXME: Is that correct? It seems to be correct most
@@ -1884,7 +1912,7 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
         // delegates to the `rust-lld` binary for linking and then runs
         // logic to create the final binary. This is used by the
         // `wasm32-wasip2` target of Rust.
-        if builder.build_wasm_component_ld() {
+        if builder.tool_enabled("wasm-component-ld") {
             let wasm_component_ld_exe =
                 builder.ensure(crate::core::build_steps::tool::WasmComponentLd {
                     compiler: build_compiler,
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 4957de2..b0bd187 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -473,7 +473,7 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
                     );
                 }
             }
-            if builder.build_wasm_component_ld() {
+            if builder.tool_enabled("wasm-component-ld") {
                 let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin");
                 let ld = exe("wasm-component-ld", compiler.host);
                 builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld));
@@ -1348,18 +1348,9 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
             return None;
         }
 
-        if self.backend == "cranelift" {
-            if !target_supports_cranelift_backend(self.compiler.host) {
-                builder.info("target not supported by rustc_codegen_cranelift. skipping");
-                return None;
-            }
-
-            if self.compiler.host.is_windows() {
-                builder.info(
-                    "dist currently disabled for windows by rustc_codegen_cranelift. skipping",
-                );
-                return None;
-            }
+        if self.backend == "cranelift" && !target_supports_cranelift_backend(self.compiler.host) {
+            builder.info("target not supported by rustc_codegen_cranelift. skipping");
+            return None;
         }
 
         let compiler = self.compiler;
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index ffb617c..73d9e3f 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -826,7 +826,7 @@ fn run(self, builder: &Builder<'_>) {
         // see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222
         // cargo.rustdocflag("--generate-link-to-definition");
 
-        compile::rustc_cargo(builder, &mut cargo, target, &compiler);
+        compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
         cargo.arg("-Zskip-rustdoc-fingerprint");
 
         // Only include compiler crates, no dependencies of those, such as `libc`.
@@ -1186,6 +1186,9 @@ fn run(self, builder: &Builder<'_>) {
         cmd.arg("--rustc");
         cmd.arg(&rustc);
         cmd.arg("--rustc-target").arg(self.target.rustc_target_arg());
+        if let Some(target_linker) = builder.linker(self.target) {
+            cmd.arg("--rustc-linker").arg(target_linker);
+        }
         if builder.is_verbose() {
             cmd.arg("--verbose");
         }
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index e1eea31..442638d 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -529,6 +529,7 @@ fn run(self, builder: &Builder<'_>) -> LlvmResult {
             }
         };
 
+        // FIXME(ZuseZ4): Do we need that for Enzyme too?
         // When building LLVM with LLVM_LINK_LLVM_DYLIB for macOS, an unversioned
         // libLLVM.dylib will be built. However, llvm-config will still look
         // for a versioned path like libLLVM-14.dylib. Manually create a symbolic
@@ -849,6 +850,100 @@ fn get_var(var_base: &str, host: &str, target: &str) -> Option<OsString> {
         .or_else(|| env::var_os(var_base))
 }
 
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct Enzyme {
+    pub target: TargetSelection,
+}
+
+impl Step for Enzyme {
+    type Output = PathBuf;
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/tools/enzyme/enzyme")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(Enzyme { target: run.target });
+    }
+
+    /// Compile Enzyme for `target`.
+    fn run(self, builder: &Builder<'_>) -> PathBuf {
+        builder.require_submodule(
+            "src/tools/enzyme",
+            Some("The Enzyme sources are required for autodiff."),
+        );
+        if builder.config.dry_run() {
+            let out_dir = builder.enzyme_out(self.target);
+            return out_dir;
+        }
+        let target = self.target;
+
+        let LlvmResult { llvm_config, .. } = builder.ensure(Llvm { target: self.target });
+
+        static STAMP_HASH_MEMO: OnceLock<String> = OnceLock::new();
+        let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| {
+            generate_smart_stamp_hash(
+                builder,
+                &builder.config.src.join("src/tools/enzyme"),
+                builder.enzyme_info.sha().unwrap_or_default(),
+            )
+        });
+
+        let out_dir = builder.enzyme_out(target);
+        let stamp = out_dir.join("enzyme-finished-building");
+        let stamp = HashStamp::new(stamp, Some(smart_stamp_hash));
+
+        if stamp.is_done() {
+            if stamp.hash.is_none() {
+                builder.info(
+                    "Could not determine the Enzyme submodule commit hash. \
+                     Assuming that an Enzyme rebuild is not necessary.",
+                );
+                builder.info(&format!(
+                    "To force Enzyme to rebuild, remove the file `{}`",
+                    stamp.path.display()
+                ));
+            }
+            return out_dir;
+        }
+
+        builder.info(&format!("Building Enzyme for {}", target));
+        t!(stamp.remove());
+        let _time = helpers::timeit(builder);
+        t!(fs::create_dir_all(&out_dir));
+
+        builder
+            .config
+            .update_submodule(Path::new("src").join("tools").join("enzyme").to_str().unwrap());
+        let mut cfg = cmake::Config::new(builder.src.join("src/tools/enzyme/enzyme/"));
+        // FIXME(ZuseZ4): Find a nicer way to use Enzyme Debug builds
+        //cfg.profile("Debug");
+        //cfg.define("CMAKE_BUILD_TYPE", "Debug");
+        configure_cmake(builder, target, &mut cfg, true, LdFlags::default(), &[]);
+
+        // Re-use the same flags as llvm to control the level of debug information
+        // generated for lld.
+        let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) {
+            (false, _) => "Debug",
+            (true, false) => "Release",
+            (true, true) => "RelWithDebInfo",
+        };
+
+        cfg.out_dir(&out_dir)
+            .profile(profile)
+            .env("LLVM_CONFIG_REAL", &llvm_config)
+            .define("LLVM_ENABLE_ASSERTIONS", "ON")
+            .define("ENZYME_EXTERNAL_SHARED_LIB", "ON")
+            .define("LLVM_DIR", builder.llvm_out(target));
+
+        cfg.build();
+
+        t!(stamp.write());
+        out_dir
+    }
+}
+
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Lld {
     pub target: TargetSelection,
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index a8e1254..83f6561 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -2690,7 +2690,7 @@ fn run(self, builder: &Builder<'_>) {
                 }
             }
             Mode::Rustc => {
-                compile::rustc_cargo(builder, &mut cargo, target, &compiler);
+                compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
             }
             _ => panic!("can only test libraries"),
         };
@@ -3529,11 +3529,13 @@ fn make_run(run: RunConfig<'_>) {
 
     fn run(self, builder: &Builder<'_>) {
         let bootstrap_host = builder.config.build;
-        let compiler = builder.compiler(0, bootstrap_host);
+        let compiler = builder.compiler(builder.top_stage, bootstrap_host);
         let path = self.path.to_str().unwrap();
         let crate_name = self.path.components().last().unwrap().as_os_str().to_str().unwrap();
 
-        builder.ensure(compile::Std::new(compiler, self.host));
+        if !builder.download_rustc() {
+            builder.ensure(compile::Std::new(compiler, self.host));
+        }
 
         // Run any unit tests in the crate
         let cargo_test = tool::prepare_tool_cargo(
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 3a1eb43..3c2d791 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -693,14 +693,7 @@ impl Step for Cargo {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.path("src/tools/cargo").default_condition(
-            builder.config.extended
-                && builder.config.tools.as_ref().map_or(
-                    true,
-                    // If `tools` is set, search list for this tool.
-                    |tools| tools.iter().any(|tool| tool == "cargo"),
-                ),
-        )
+        run.path("src/tools/cargo").default_condition(builder.tool_enabled("cargo"))
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -772,14 +765,7 @@ impl Step for RustAnalyzer {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.path("src/tools/rust-analyzer").default_condition(
-            builder.config.extended
-                && builder
-                    .config
-                    .tools
-                    .as_ref()
-                    .map_or(true, |tools| tools.iter().any(|tool| tool == "rust-analyzer")),
-        )
+        run.path("src/tools/rust-analyzer").default_condition(builder.tool_enabled("rust-analyzer"))
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -821,12 +807,8 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         run.path("src/tools/rust-analyzer")
             .path("src/tools/rust-analyzer/crates/proc-macro-srv-cli")
             .default_condition(
-                builder.config.extended
-                    && builder.config.tools.as_ref().map_or(true, |tools| {
-                        tools.iter().any(|tool| {
-                            tool == "rust-analyzer" || tool == "rust-analyzer-proc-macro-srv"
-                        })
-                    }),
+                builder.tool_enabled("rust-analyzer")
+                    || builder.tool_enabled("rust-analyzer-proc-macro-srv"),
             )
     }
 
@@ -874,16 +856,8 @@ impl Step for LlvmBitcodeLinker {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.path("src/tools/llvm-bitcode-linker").default_condition(
-            builder.config.extended
-                && builder
-                    .config
-                    .tools
-                    .as_ref()
-                    .map_or(builder.build.unstable_features(), |tools| {
-                        tools.iter().any(|tool| tool == "llvm-bitcode-linker")
-                    }),
-        )
+        run.path("src/tools/llvm-bitcode-linker")
+            .default_condition(builder.tool_enabled("llvm-bitcode-linker"))
     }
 
     fn make_run(run: RunConfig<'_>) {
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 304fe8d..1e87798 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -798,6 +798,7 @@ macro_rules! describe {
                 tool::Miri,
                 tool::CargoMiri,
                 llvm::Lld,
+                llvm::Enzyme,
                 llvm::CrtBeginEnd,
                 tool::RustdocGUITest,
                 tool::OptimizedDist,
@@ -1588,6 +1589,12 @@ fn cargo(
             rustflags.arg(sysroot_str);
         }
 
+        // https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/.E2.9C.94.20link.20new.20library.20into.20stage1.2Frustc
+        if self.config.llvm_enzyme {
+            rustflags.arg("-l");
+            rustflags.arg("Enzyme-19");
+        }
+
         let use_new_symbol_mangling = match self.config.rust_new_symbol_mangling {
             Some(setting) => {
                 // If an explicit setting is given, use that
@@ -2456,7 +2463,16 @@ pub fn new(
         cmd_kind: Kind,
     ) -> Cargo {
         let mut cargo = builder.cargo(compiler, mode, source_type, target, cmd_kind);
-        cargo.configure_linker(builder);
+
+        match cmd_kind {
+            // No need to configure the target linker for these command types,
+            // as they don't invoke rustc at all.
+            Kind::Clean | Kind::Suggest | Kind::Format | Kind::Setup => {}
+            _ => {
+                cargo.configure_linker(builder);
+            }
+        }
+
         cargo
     }
 
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index f7cc9ee..f509712 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -221,6 +221,7 @@ pub struct Config {
     // llvm codegen options
     pub llvm_assertions: bool,
     pub llvm_tests: bool,
+    pub llvm_enzyme: bool,
     pub llvm_plugins: bool,
     pub llvm_optimize: bool,
     pub llvm_thin_lto: bool,
@@ -898,6 +899,7 @@ struct Llvm {
         release_debuginfo: Option<bool> = "release-debuginfo",
         assertions: Option<bool> = "assertions",
         tests: Option<bool> = "tests",
+        enzyme: Option<bool> = "enzyme",
         plugins: Option<bool> = "plugins",
         ccache: Option<StringOrBool> = "ccache",
         static_libstdcpp: Option<bool> = "static-libstdcpp",
@@ -1214,13 +1216,23 @@ pub fn default_opts() -> Config {
         }
     }
 
+    pub(crate) fn get_builder_toml(&self, build_name: &str) -> Result<TomlConfig, toml::de::Error> {
+        if self.dry_run() {
+            return Ok(TomlConfig::default());
+        }
+
+        let builder_config_path =
+            self.out.join(self.build.triple).join(build_name).join(BUILDER_CONFIG_FILENAME);
+        Self::get_toml(&builder_config_path)
+    }
+
     #[cfg(test)]
-    fn get_toml(_: &Path) -> Result<TomlConfig, toml::de::Error> {
+    pub(crate) fn get_toml(_: &Path) -> Result<TomlConfig, toml::de::Error> {
         Ok(TomlConfig::default())
     }
 
     #[cfg(not(test))]
-    fn get_toml(file: &Path) -> Result<TomlConfig, toml::de::Error> {
+    pub(crate) fn get_toml(file: &Path) -> Result<TomlConfig, toml::de::Error> {
         let contents =
             t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
         // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
@@ -1588,6 +1600,9 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
 
         config.verbose = cmp::max(config.verbose, flags.verbose as usize);
 
+        // Verbose flag is a good default for `rust.verbose-tests`.
+        config.verbose_tests = config.is_verbose();
+
         if let Some(install) = toml.install {
             let Install { prefix, sysconfdir, docdir, bindir, libdir, mandir, datadir } = install;
             config.prefix = prefix.map(PathBuf::from);
@@ -1603,6 +1618,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
         // we'll infer default values for them later
         let mut llvm_assertions = None;
         let mut llvm_tests = None;
+        let mut llvm_enzyme = None;
         let mut llvm_plugins = None;
         let mut debug = None;
         let mut debug_assertions = None;
@@ -1722,6 +1738,8 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
             config.llvm_tools_enabled = llvm_tools.unwrap_or(true);
             config.rustc_parallel =
                 parallel_compiler.unwrap_or(config.channel == "dev" || config.channel == "nightly");
+            config.llvm_enzyme =
+                llvm_enzyme.unwrap_or(config.channel == "dev" || config.channel == "nightly");
             config.rustc_default_linker = default_linker;
             config.musl_root = musl_root.map(PathBuf::from);
             config.save_toolstates = save_toolstates.map(PathBuf::from);
@@ -1806,6 +1824,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
                 release_debuginfo,
                 assertions,
                 tests,
+                enzyme,
                 plugins,
                 ccache,
                 static_libstdcpp,
@@ -1839,6 +1858,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
             set(&mut config.ninja_in_file, ninja);
             llvm_assertions = assertions;
             llvm_tests = tests;
+            llvm_enzyme = enzyme;
             llvm_plugins = plugins;
             set(&mut config.llvm_optimize, optimize_toml);
             set(&mut config.llvm_thin_lto, thin_lto);
@@ -1901,34 +1921,9 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
                         "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false."
                     );
                 }
-
-                // None of the LLVM options, except assertions, are supported
-                // when using downloaded LLVM. We could just ignore these but
-                // that's potentially confusing, so force them to not be
-                // explicitly set. The defaults and CI defaults don't
-                // necessarily match but forcing people to match (somewhat
-                // arbitrary) CI configuration locally seems bad/hard.
-                check_ci_llvm!(optimize_toml);
-                check_ci_llvm!(thin_lto);
-                check_ci_llvm!(release_debuginfo);
-                check_ci_llvm!(targets);
-                check_ci_llvm!(experimental_targets);
-                check_ci_llvm!(clang_cl);
-                check_ci_llvm!(version_suffix);
-                check_ci_llvm!(cflags);
-                check_ci_llvm!(cxxflags);
-                check_ci_llvm!(ldflags);
-                check_ci_llvm!(use_libcxx);
-                check_ci_llvm!(use_linker);
-                check_ci_llvm!(allow_old_toolchain);
-                check_ci_llvm!(polly);
-                check_ci_llvm!(clang);
-                check_ci_llvm!(build_config);
-                check_ci_llvm!(plugins);
             }
 
-            // NOTE: can never be hit when downloading from CI, since we call `check_ci_llvm!(thin_lto)` above.
-            if config.llvm_thin_lto && link_shared.is_none() {
+            if !config.llvm_from_ci && config.llvm_thin_lto && link_shared.is_none() {
                 // If we're building with ThinLTO on, by default we want to link
                 // to LLVM shared, to avoid re-doing ThinLTO (which happens in
                 // the link step) with each stage.
@@ -2055,6 +2050,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
 
         config.llvm_assertions = llvm_assertions.unwrap_or(false);
         config.llvm_tests = llvm_tests.unwrap_or(false);
+        config.llvm_enzyme = llvm_enzyme.unwrap_or(false);
         config.llvm_plugins = llvm_plugins.unwrap_or(false);
         config.rust_optimize = optimize.unwrap_or(RustOptimize::Bool(true));
 
@@ -2366,10 +2362,7 @@ pub(crate) fn download_rustc_commit(&self) -> Option<&str> {
                     self.download_ci_rustc(commit);
 
                     if let Some(config_path) = &self.config {
-                        let builder_config_path =
-                            self.out.join(self.build.triple).join("ci-rustc").join(BUILDER_CONFIG_FILENAME);
-
-                        let ci_config_toml = match Self::get_toml(&builder_config_path) {
+                        let ci_config_toml = match self.get_builder_toml("ci-rustc") {
                             Ok(ci_config_toml) => ci_config_toml,
                             Err(e) if e.to_string().contains("unknown field") => {
                                 println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
@@ -2377,7 +2370,7 @@ pub(crate) fn download_rustc_commit(&self) -> Option<&str> {
                                 return None;
                             },
                             Err(e) => {
-                                eprintln!("ERROR: Failed to parse CI rustc config at '{}': {e}", builder_config_path.display());
+                                eprintln!("ERROR: Failed to parse CI rustc config.toml: {e}");
                                 exit!(2);
                             },
                         };
@@ -2773,7 +2766,8 @@ fn parse_download_ci_llvm(
                     );
                 }
 
-                b
+                // If download-ci-llvm=true we also want to check that CI llvm is available
+                b && llvm::is_ci_llvm_available(self, asserts)
             }
             Some(StringOrBool::String(s)) if s == "if-unchanged" => if_unchanged(),
             Some(StringOrBool::String(other)) => {
@@ -2838,6 +2832,109 @@ pub fn last_modified_commit(
     }
 }
 
+/// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options.
+/// It does this by destructuring the `Llvm` instance to make sure every `Llvm` field is covered and not missing.
+#[cfg(not(feature = "bootstrap-self-test"))]
+pub(crate) fn check_incompatible_options_for_ci_llvm(
+    current_config_toml: TomlConfig,
+    ci_config_toml: TomlConfig,
+) -> Result<(), String> {
+    macro_rules! err {
+        ($current:expr, $expected:expr) => {
+            if let Some(current) = &$current {
+                if Some(current) != $expected.as_ref() {
+                    return Err(format!(
+                        "ERROR: Setting `llvm.{}` is incompatible with `llvm.download-ci-llvm`. \
+                        Current value: {:?}, Expected value(s): {}{:?}",
+                        stringify!($expected).replace("_", "-"),
+                        $current,
+                        if $expected.is_some() { "None/" } else { "" },
+                        $expected,
+                    ));
+                };
+            };
+        };
+    }
+
+    macro_rules! warn {
+        ($current:expr, $expected:expr) => {
+            if let Some(current) = &$current {
+                if Some(current) != $expected.as_ref() {
+                    println!(
+                        "WARNING: `llvm.{}` has no effect with `llvm.download-ci-llvm`. \
+                        Current value: {:?}, Expected value(s): {}{:?}",
+                        stringify!($expected).replace("_", "-"),
+                        $current,
+                        if $expected.is_some() { "None/" } else { "" },
+                        $expected,
+                    );
+                };
+            };
+        };
+    }
+
+    let (Some(current_llvm_config), Some(ci_llvm_config)) =
+        (current_config_toml.llvm, ci_config_toml.llvm)
+    else {
+        return Ok(());
+    };
+
+    let Llvm {
+        optimize,
+        thin_lto,
+        release_debuginfo,
+        assertions: _,
+        tests: _,
+        plugins,
+        ccache: _,
+        static_libstdcpp: _,
+        libzstd,
+        ninja: _,
+        targets,
+        experimental_targets,
+        link_jobs: _,
+        link_shared: _,
+        version_suffix,
+        clang_cl,
+        cflags,
+        cxxflags,
+        ldflags,
+        use_libcxx,
+        use_linker,
+        allow_old_toolchain,
+        polly,
+        clang,
+        enable_warnings,
+        download_ci_llvm: _,
+        build_config,
+        enzyme,
+    } = ci_llvm_config;
+
+    err!(current_llvm_config.optimize, optimize);
+    err!(current_llvm_config.thin_lto, thin_lto);
+    err!(current_llvm_config.release_debuginfo, release_debuginfo);
+    err!(current_llvm_config.libzstd, libzstd);
+    err!(current_llvm_config.targets, targets);
+    err!(current_llvm_config.experimental_targets, experimental_targets);
+    err!(current_llvm_config.clang_cl, clang_cl);
+    err!(current_llvm_config.version_suffix, version_suffix);
+    err!(current_llvm_config.cflags, cflags);
+    err!(current_llvm_config.cxxflags, cxxflags);
+    err!(current_llvm_config.ldflags, ldflags);
+    err!(current_llvm_config.use_libcxx, use_libcxx);
+    err!(current_llvm_config.use_linker, use_linker);
+    err!(current_llvm_config.allow_old_toolchain, allow_old_toolchain);
+    err!(current_llvm_config.polly, polly);
+    err!(current_llvm_config.clang, clang);
+    err!(current_llvm_config.build_config, build_config);
+    err!(current_llvm_config.plugins, plugins);
+    err!(current_llvm_config.enzyme, enzyme);
+
+    warn!(current_llvm_config.enable_warnings, enable_warnings);
+
+    Ok(())
+}
+
 /// Compares the current Rust options against those in the CI rustc builder and detects any incompatible options.
 /// It does this by destructuring the `Rust` instance to make sure every `Rust` field is covered and not missing.
 fn check_incompatible_options_for_ci_rustc(
diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs
index c3f1740..effc5f5 100644
--- a/src/bootstrap/src/core/config/flags.rs
+++ b/src/bootstrap/src/core/config/flags.rs
@@ -143,9 +143,6 @@ pub struct Flags {
     /// Unless you know exactly what you are doing, you probably don't need this.
     pub bypass_bootstrap_lock: bool,
 
-    /// whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml
-    #[arg(global = true, long, value_name = "VALUE")]
-    pub llvm_skip_rebuild: Option<bool>,
     /// generate PGO profile with rustc build
     #[arg(global = true, value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
     pub rust_profile_generate: Option<String>,
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index 219c5a6..f54a5d3 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -317,3 +317,12 @@ fn order_of_clippy_rules() {
 
     assert_eq!(expected, actual);
 }
+
+#[test]
+fn verbose_tests_default_value() {
+    let config = Config::parse(Flags::parse(&["build".into(), "compiler".into()]));
+    assert_eq!(config.verbose_tests, false);
+
+    let config = Config::parse(Flags::parse(&["build".into(), "compiler".into(), "-v".into()]));
+    assert_eq!(config.verbose_tests, true);
+}
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index 1e3f8da..d8b39ac 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -228,25 +228,42 @@ fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) {
     fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) {
         println!("downloading {url}");
         // Try curl. If that fails and we are on windows, fallback to PowerShell.
+        // options should be kept in sync with
+        // src/bootstrap/src/core/download.rs
+        // for consistency
         let mut curl = command("curl");
         curl.args([
-            "-y",
+            // follow redirect
+            "--location",
+            // timeout if speed is < 10 bytes/sec for > 30 seconds
+            "--speed-time",
             "30",
-            "-Y",
-            "10", // timeout if speed is < 10 bytes/sec for > 30 seconds
+            "--speed-limit",
+            "10",
+            // timeout if cannot connect within 30 seconds
             "--connect-timeout",
-            "30", // timeout if cannot connect within 30 seconds
-            "-o",
+            "30",
+            // output file
+            "--output",
             tempfile.to_str().unwrap(),
+            // if there is an error, don't restart the download,
+            // instead continue where it left off.
             "--continue-at",
             "-",
+            // retry up to 3 times.  note that this means a maximum of 4
+            // attempts will be made, since the first attempt isn't a *re*try.
             "--retry",
             "3",
-            "-SRf",
+            // show errors, even if --silent is specified
+            "--show-error",
+            // set timestamp of downloaded file to that of the server
+            "--remote-time",
+            // fail on non-ok http status
+            "--fail",
         ]);
         // Don't print progress in CI; the \r wrapping looks bad and downloads don't take long enough for progress to be useful.
         if CiEnv::is_ci() {
-            curl.arg("-s");
+            curl.arg("--silent");
         } else {
             curl.arg("--progress-bar");
         }
@@ -299,6 +316,7 @@ fn unpack(&self, tarball: &Path, dst: &Path, pattern: &str) {
         let mut tar = tar::Archive::new(decompressor);
 
         let is_ci_rustc = dst.ends_with("ci-rustc");
+        let is_ci_llvm = dst.ends_with("ci-llvm");
 
         // `compile::Sysroot` needs to know the contents of the `rustc-dev` tarball to avoid adding
         // it to the sysroot unless it was explicitly requested. But parsing the 100 MB tarball is slow.
@@ -315,7 +333,9 @@ fn unpack(&self, tarball: &Path, dst: &Path, pattern: &str) {
             let mut short_path = t!(original_path.strip_prefix(directory_prefix));
             let is_builder_config = short_path.to_str() == Some(BUILDER_CONFIG_FILENAME);
 
-            if !(short_path.starts_with(pattern) || (is_ci_rustc && is_builder_config)) {
+            if !(short_path.starts_with(pattern)
+                || ((is_ci_rustc || is_ci_llvm) && is_builder_config))
+            {
                 continue;
             }
             short_path = short_path.strip_prefix(pattern).unwrap_or(short_path);
@@ -700,17 +720,22 @@ pub(crate) fn maybe_download_ci_llvm(&self) {}
 
     #[cfg(not(feature = "bootstrap-self-test"))]
     pub(crate) fn maybe_download_ci_llvm(&self) {
+        use build_helper::exit;
+
         use crate::core::build_steps::llvm::detect_llvm_sha;
+        use crate::core::config::check_incompatible_options_for_ci_llvm;
 
         if !self.llvm_from_ci {
             return;
         }
+
         let llvm_root = self.ci_llvm_root();
         let llvm_stamp = llvm_root.join(".llvm-stamp");
         let llvm_sha = detect_llvm_sha(self, self.rust_info.is_managed_git_subrepository());
         let key = format!("{}{}", llvm_sha, self.llvm_assertions);
         if program_out_of_date(&llvm_stamp, &key) && !self.dry_run() {
             self.download_ci_llvm(&llvm_sha);
+
             if self.should_fix_bins_and_dylibs() {
                 for entry in t!(fs::read_dir(llvm_root.join("bin"))) {
                     self.fix_bin_or_dylib(&t!(entry).path());
@@ -743,6 +768,26 @@ pub(crate) fn maybe_download_ci_llvm(&self) {
 
             t!(fs::write(llvm_stamp, key));
         }
+
+        if let Some(config_path) = &self.config {
+            let current_config_toml = Self::get_toml(config_path).unwrap();
+
+            match self.get_builder_toml("ci-llvm") {
+                Ok(ci_config_toml) => {
+                    t!(check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml));
+                }
+                Err(e) if e.to_string().contains("unknown field") => {
+                    println!(
+                        "WARNING: CI LLVM has some fields that are no longer supported in bootstrap; download-ci-llvm will be disabled."
+                    );
+                    println!("HELP: Consider rebasing to a newer commit if available.");
+                }
+                Err(e) => {
+                    eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}");
+                    exit!(2);
+                }
+            };
+        };
     }
 
     #[cfg(not(feature = "bootstrap-self-test"))]
diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs
index 1016607..d665544 100644
--- a/src/bootstrap/src/core/metadata.rs
+++ b/src/bootstrap/src/core/metadata.rs
@@ -1,3 +1,4 @@
+use std::collections::BTreeMap;
 use std::path::PathBuf;
 
 use serde_derive::Deserialize;
@@ -21,6 +22,7 @@ struct Package {
     manifest_path: String,
     dependencies: Vec<Dependency>,
     targets: Vec<Target>,
+    features: BTreeMap<String, Vec<String>>,
 }
 
 /// For more information, see the output of
@@ -51,7 +53,13 @@ pub fn build(build: &mut Build) {
                 .map(|dep| dep.name)
                 .collect();
             let has_lib = package.targets.iter().any(|t| t.kind.iter().any(|k| k == "lib"));
-            let krate = Crate { name: name.clone(), deps, path, has_lib };
+            let krate = Crate {
+                name: name.clone(),
+                deps,
+                path,
+                has_lib,
+                features: package.features.keys().cloned().collect(),
+            };
             let relative_path = krate.local_path(build);
             build.crates.insert(name.clone(), krate);
             let existing_path = build.crate_paths.insert(relative_path, name);
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 5751c39..780024e 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -77,6 +77,9 @@
 #[allow(clippy::type_complexity)] // It's fine for hard-coded list and type is explained above.
 const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
     (None, "bootstrap", None),
+    (Some(Mode::Rustc), "llvm_enzyme", None),
+    (Some(Mode::Codegen), "llvm_enzyme", None),
+    (Some(Mode::ToolRustc), "llvm_enzyme", None),
     (Some(Mode::Rustc), "parallel_compiler", None),
     (Some(Mode::ToolRustc), "parallel_compiler", None),
     (Some(Mode::ToolRustc), "rust_analyzer", None),
@@ -140,6 +143,7 @@ pub struct Build {
     clippy_info: GitInfo,
     miri_info: GitInfo,
     rustfmt_info: GitInfo,
+    enzyme_info: GitInfo,
     in_tree_llvm_info: GitInfo,
     local_rebuild: bool,
     fail_fast: bool,
@@ -183,6 +187,7 @@ struct Crate {
     deps: HashSet<String>,
     path: PathBuf,
     has_lib: bool,
+    features: Vec<String>,
 }
 
 impl Crate {
@@ -306,6 +311,7 @@ pub fn new(mut config: Config) -> Build {
         let clippy_info = GitInfo::new(omit_git_hash, &src.join("src/tools/clippy"));
         let miri_info = GitInfo::new(omit_git_hash, &src.join("src/tools/miri"));
         let rustfmt_info = GitInfo::new(omit_git_hash, &src.join("src/tools/rustfmt"));
+        let enzyme_info = GitInfo::new(omit_git_hash, &src.join("src/tools/enzyme"));
 
         // we always try to use git for LLVM builds
         let in_tree_llvm_info = GitInfo::new(false, &src.join("src/llvm-project"));
@@ -332,14 +338,20 @@ pub fn new(mut config: Config) -> Build {
         .trim()
         .to_string();
 
-        let initial_libdir = initial_target_dir
-            .parent()
-            .unwrap()
-            .parent()
-            .unwrap()
-            .strip_prefix(&initial_sysroot)
-            .unwrap()
-            .to_path_buf();
+        // FIXME(Zalathar): Determining this path occasionally fails locally for
+        // unknown reasons, so we print some extra context to help track down why.
+        let find_initial_libdir = || {
+            let initial_libdir =
+                initial_target_dir.parent()?.parent()?.strip_prefix(&initial_sysroot).ok()?;
+            Some(initial_libdir.to_path_buf())
+        };
+        let Some(initial_libdir) = find_initial_libdir() else {
+            panic!(
+                "couldn't determine `initial_libdir` \
+                from target dir {initial_target_dir:?} \
+                and sysroot {initial_sysroot:?}"
+            )
+        };
 
         let version = std::fs::read_to_string(src.join("src").join("version"))
             .expect("failed to read src/version");
@@ -393,6 +405,7 @@ pub fn new(mut config: Config) -> Build {
             clippy_info,
             miri_info,
             rustfmt_info,
+            enzyme_info,
             in_tree_llvm_info,
             cc: RefCell::new(HashMap::new()),
             cxx: RefCell::new(HashMap::new()),
@@ -666,16 +679,24 @@ fn std_features(&self, target: TargetSelection) -> String {
     }
 
     /// Gets the space-separated set of activated features for the compiler.
-    fn rustc_features(&self, kind: Kind, target: TargetSelection) -> String {
+    fn rustc_features(&self, kind: Kind, target: TargetSelection, crates: &[String]) -> String {
+        let possible_features_by_crates: HashSet<_> = crates
+            .iter()
+            .flat_map(|krate| &self.crates[krate].features)
+            .map(std::ops::Deref::deref)
+            .collect();
+        let check = |feature: &str| -> bool {
+            crates.is_empty() || possible_features_by_crates.contains(feature)
+        };
         let mut features = vec![];
-        if self.config.jemalloc {
+        if self.config.jemalloc && check("jemalloc") {
             features.push("jemalloc");
         }
-        if self.config.llvm_enabled(target) || kind == Kind::Check {
+        if (self.config.llvm_enabled(target) || kind == Kind::Check) && check("llvm") {
             features.push("llvm");
         }
         // keep in sync with `bootstrap/compile.rs:rustc_cargo_env`
-        if self.config.rustc_parallel {
+        if self.config.rustc_parallel && check("rustc_use_parallel_compiler") {
             features.push("rustc_use_parallel_compiler");
         }
         if self.config.rust_randomize_layout {
@@ -687,7 +708,7 @@ fn rustc_features(&self, kind: Kind, target: TargetSelection) -> String {
         // which is everything (including debug/trace/etc.)
         // if its unset, if debug_assertions is on, then debug_logging will also be on
         // as well as tracing *ignoring* this feature when debug_assertions is on
-        if !self.config.rust_debug_logging {
+        if !self.config.rust_debug_logging && check("max_level_info") {
             features.push("max_level_info");
         }
 
@@ -740,6 +761,10 @@ fn llvm_out(&self, target: TargetSelection) -> PathBuf {
         }
     }
 
+    fn enzyme_out(&self, target: TargetSelection) -> PathBuf {
+        self.out.join(&*target.triple).join("enzyme")
+    }
+
     fn lld_out(&self, target: TargetSelection) -> PathBuf {
         self.out.join(target).join("lld")
     }
@@ -1382,16 +1407,17 @@ fn default_wasi_runner(&self) -> Option<String> {
         None
     }
 
-    /// Returns whether it's requested that `wasm-component-ld` is built as part
-    /// of the sysroot. This is done either with the `extended` key in
-    /// `config.toml` or with the `tools` set.
-    fn build_wasm_component_ld(&self) -> bool {
-        if self.config.extended {
-            return true;
+    /// Returns whether the specified tool is configured as part of this build.
+    ///
+    /// This requires that both the `extended` key is set and the `tools` key is
+    /// either unset or specifically contains the specified tool.
+    fn tool_enabled(&self, tool: &str) -> bool {
+        if !self.config.extended {
+            return false;
         }
         match &self.config.tools {
-            Some(set) => set.contains("wasm-component-ld"),
-            None => false,
+            Some(set) => set.contains(tool),
+            None => true,
         }
     }
 
diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs
index 29e6b74..c39415e 100644
--- a/src/bootstrap/src/utils/cc_detect.rs
+++ b/src/bootstrap/src/utils/cc_detect.rs
@@ -87,15 +87,28 @@ fn new_cc_build(build: &Build, target: TargetSelection) -> cc::Build {
 }
 
 pub fn find(build: &Build) {
-    // For all targets we're going to need a C compiler for building some shims
-    // and such as well as for being a linker for Rust code.
-    let targets = build
-        .targets
-        .iter()
-        .chain(&build.hosts)
-        .cloned()
-        .chain(iter::once(build.build))
-        .collect::<HashSet<_>>();
+    let targets: HashSet<_> = match build.config.cmd {
+        // We don't need to check cross targets for these commands.
+        crate::Subcommand::Clean { .. }
+        | crate::Subcommand::Suggest { .. }
+        | crate::Subcommand::Format { .. }
+        | crate::Subcommand::Setup { .. } => {
+            build.hosts.iter().cloned().chain(iter::once(build.build)).collect()
+        }
+
+        _ => {
+            // For all targets we're going to need a C compiler for building some shims
+            // and such as well as for being a linker for Rust code.
+            build
+                .targets
+                .iter()
+                .chain(&build.hosts)
+                .cloned()
+                .chain(iter::once(build.build))
+                .collect()
+        }
+    };
+
     for target in targets.into_iter() {
         find_target(build, target);
     }
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 3fec2d9..99bcc6e 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -245,4 +245,14 @@ pub fn human_readable_changes(changes: &[ChangeInfo]) -> String {
         severity: ChangeSeverity::Warning,
         summary: "Removed `rust.split-debuginfo` as it was deprecated long time ago.",
     },
+    ChangeInfo {
+        change_id: 129176,
+        severity: ChangeSeverity::Info,
+        summary: "New option `llvm.enzyme` to control whether the llvm based autodiff tool (Enzyme) is built.",
+    },
+    ChangeInfo {
+        change_id: 129473,
+        severity: ChangeSeverity::Warning,
+        summary: "`download-ci-llvm = true` now checks if CI llvm is available and has become the default for the compiler profile",
+    },
 ];
diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs
index b8aebc2..eb2c825 100644
--- a/src/bootstrap/src/utils/render_tests.rs
+++ b/src/bootstrap/src/utils/render_tests.rs
@@ -88,6 +88,9 @@ struct Renderer<'a> {
     builder: &'a Builder<'a>,
     tests_count: Option<usize>,
     executed_tests: usize,
+    /// Number of tests that were skipped due to already being up-to-date
+    /// (i.e. no relevant changes occurred since they last ran).
+    up_to_date_tests: usize,
     terse_tests_in_line: usize,
 }
 
@@ -100,6 +103,7 @@ fn new(stdout: ChildStdout, builder: &'a Builder<'a>) -> Self {
             builder,
             tests_count: None,
             executed_tests: 0,
+            up_to_date_tests: 0,
             terse_tests_in_line: 0,
         }
     }
@@ -127,6 +131,12 @@ fn render_all(mut self) {
                 }
             }
         }
+
+        if self.up_to_date_tests > 0 {
+            let n = self.up_to_date_tests;
+            let s = if n > 1 { "s" } else { "" };
+            println!("help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n");
+        }
     }
 
     /// Renders the stdout characters one by one
@@ -149,6 +159,11 @@ fn stream_all(mut self) {
     fn render_test_outcome(&mut self, outcome: Outcome<'_>, test: &TestOutcome) {
         self.executed_tests += 1;
 
+        // Keep this in sync with the "up-to-date" ignore message inserted by compiletest.
+        if let Outcome::Ignored { reason: Some("up-to-date") } = outcome {
+            self.up_to_date_tests += 1;
+        }
+
         #[cfg(feature = "build-metrics")]
         self.builder.metrics.record_test(
             &test.name,
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
index a5a5acc..303a2f2 100755
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
@@ -58,8 +58,9 @@
     # Strangely, Linux targets do not work here. cargo always says
     # "error: cannot produce cdylib for ... as the target ... does not support these crate types".
     # Only run "pass" tests, which is quite a bit faster.
-    python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass
-    python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass
+    #FIXME: Re-enable this once CI issues are fixed
+    #python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass
+    #python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass
     ;;
   *)
     echo "FATAL: unexpected host $HOST_TARGET"
@@ -68,6 +69,10 @@
 esac
 # Also smoke-test `x.py miri`. This doesn't run any actual tests (that would take too long),
 # but it ensures that the crates build properly when tested with Miri.
-python3 "$X_PY" miri --stage 2 library/core --test-args notest
-python3 "$X_PY" miri --stage 2 library/alloc --test-args notest
-python3 "$X_PY" miri --stage 2 library/std --test-args notest
+
+#FIXME: Re-enable this for msvc once CI issues are fixed
+if [ "$HOST_TARGET" != "x86_64-pc-windows-msvc" ]; then
+  python3 "$X_PY" miri --stage 2 library/core --test-args notest
+  python3 "$X_PY" miri --stage 2 library/alloc --test-args notest
+  python3 "$X_PY" miri --stage 2 library/std --test-args notest
+fi
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 4de44c6..41d3b31 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -373,6 +373,18 @@
       DEPLOY_TOOLSTATES_JSON: toolstates-windows.json
     <<: *job-windows-8c
 
+  # Temporary builder to workaround CI issues
+  - image: x86_64-msvc-ext2
+    env:
+      SCRIPT: >
+        python x.py test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass &&
+        python x.py test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass &&
+        python x.py miri --stage 2 library/core --test-args notest &&
+        python x.py miri --stage 2 library/alloc --test-args notest &&
+        python x.py miri --stage 2 library/std --test-args notest
+      RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld
+    <<: *job-windows-8c
+
   # 32/64-bit MinGW builds.
   #
   # We are using MinGW with POSIX threads since LLVM requires
@@ -418,6 +430,7 @@
         --set rust.codegen-units=1
       SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths
       DIST_REQUIRE_ALL_TOOLS: 1
+      CODEGEN_BACKENDS: llvm,cranelift
     <<: *job-windows-8c
 
   - image: dist-i686-msvc
@@ -430,6 +443,7 @@
         --enable-profiler
       SCRIPT: python x.py dist bootstrap --include-default-paths
       DIST_REQUIRE_ALL_TOOLS: 1
+      CODEGEN_BACKENDS: llvm,cranelift
     <<: *job-windows-8c
 
   - image: dist-aarch64-msvc
@@ -454,6 +468,7 @@
       NO_DOWNLOAD_CI_LLVM: 1
       SCRIPT: python x.py dist bootstrap --include-default-paths
       DIST_REQUIRE_ALL_TOOLS: 1
+      CODEGEN_BACKENDS: llvm,cranelift
     <<: *job-windows-8c
 
   - image: dist-x86_64-mingw
@@ -466,6 +481,7 @@
       # incompatible with LLVM downloads today).
       NO_DOWNLOAD_CI_LLVM: 1
       DIST_REQUIRE_ALL_TOOLS: 1
+      CODEGEN_BACKENDS: llvm,cranelift
     <<: *job-windows-8c
 
   - image: dist-x86_64-msvc-alt
diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh
index 31aa378..91eab2e 100755
--- a/src/ci/scripts/install-mingw.sh
+++ b/src/ci/scripts/install-mingw.sh
@@ -6,8 +6,8 @@
 
 source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 
-MINGW_ARCHIVE_32="i686-12.2.0-release-posix-dwarf-rt_v10-rev0.7z"
-MINGW_ARCHIVE_64="x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z"
+MINGW_ARCHIVE_32="i686-14.1.0-release-posix-dwarf-msvcrt-rt_v12-rev0.7z"
+MINGW_ARCHIVE_64="x86_64-14.1.0-release-posix-seh-msvcrt-rt_v12-rev0.7z"
 
 if isWindows && isKnownToBeMingwBuild; then
     case "${CI_JOB_NAME}" in
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
index eeba2cb..b3ca7ad 160000
--- a/src/doc/edition-guide
+++ b/src/doc/edition-guide
@@ -1 +1 @@
-Subproject commit eeba2cb9c37ab74118a4fb5e5233f7397e4a91f8
+Subproject commit b3ca7ade0f87d7e3fb538776defc5b2cc4188172
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
index ff5d61d..dbae36b 160000
--- a/src/doc/embedded-book
+++ b/src/doc/embedded-book
@@ -1 +1 @@
-Subproject commit ff5d61d56f11e1986bfa9652c6aff7731576c37d
+Subproject commit dbae36bf3f8410aa4313b3bad42e374735d48a9d
diff --git a/src/doc/reference b/src/doc/reference
index 0668397..687faf9 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit 0668397076da350c404dadcf07b6cbc433ad3743
+Subproject commit 687faf9958c52116d003b41dfd29cc1cf44f5311
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index 859786c..c79ec34 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit 859786c5bc99301bbc22fc631a5c2b341860da08
+Subproject commit c79ec345f08a1e94494cdc8c999709a90203fd88
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
index fa928a6..0ed9229 160000
--- a/src/doc/rustc-dev-guide
+++ b/src/doc/rustc-dev-guide
@@ -1 +1 @@
-Subproject commit fa928a6d19e1666d8d811dfe3fd35cdad3b4e459
+Subproject commit 0ed9229f5b6f7824b333beabd7e3d5ba4b9bd971
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 319dc9a..9a35b35 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -382,6 +382,7 @@
 [`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ |   | 64-bit Unikraft with musl 1.2.3
 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD
 `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
+[`x86_64-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 64-bit GNU/Hurd
 [`x86_64-unknown-hermit`](platform-support/hermit.md) | ✓ |  | x86_64 Hermit
 `x86_64-unknown-l4re-uclibc` | ? |  |
 [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD
diff --git a/src/doc/rustc/src/platform-support/hurd.md b/src/doc/rustc/src/platform-support/hurd.md
index ddf4021..2521f79 100644
--- a/src/doc/rustc/src/platform-support/hurd.md
+++ b/src/doc/rustc/src/platform-support/hurd.md
@@ -1,4 +1,4 @@
-# `i686-unknown-hurd-gnu`
+# `i686-unknown-hurd-gnu` and `x86_64-unknown-hurd-gnu`
 
 **Tier: 3**
 
@@ -16,7 +16,8 @@
 
 ## Building the target
 
-This target can be built by adding `i686-unknown-hurd-gnu` as target in the rustc list.
+This target can be built by adding `i686-unknown-hurd-gnu` and
+`x86_64-unknown-hurd-gnu` as targets in the rustc list.
 
 ## Building Rust programs
 
@@ -32,4 +33,4 @@
 ## Cross-compilation toolchains and C code
 
 The target supports C code, the GNU toolchain calls the target
-`i686-unknown-gnu`.
+`i686-unknown-gnu` and `x86_64-unknown-gnu`.
diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish
index 3a83c89..df31b0d 100644
--- a/src/etc/completions/x.py.fish
+++ b/src/etc/completions/x.py.fish
@@ -1,6 +1,6 @@
 # Print an optspec for argparse to handle cmd's options that are independent of any subcommand.
 function __fish_x.py_global_optspecs
-	string join \n v/verbose i/incremental config= build-dir= build= host= target= exclude= skip= include-default-paths rustc-error-format= on-fail= dry-run dump-bootstrap-shims stage= keep-stage= keep-stage-std= src= j/jobs= warnings= error-format= json-output color= bypass-bootstrap-lock llvm-skip-rebuild= rust-profile-generate= rust-profile-use= llvm-profile-use= llvm-profile-generate enable-bolt-settings skip-stage0-validation reproducible-artifact= set= h/help
+	string join \n v/verbose i/incremental config= build-dir= build= host= target= exclude= skip= include-default-paths rustc-error-format= on-fail= dry-run dump-bootstrap-shims stage= keep-stage= keep-stage-std= src= j/jobs= warnings= error-format= json-output color= bypass-bootstrap-lock rust-profile-generate= rust-profile-use= llvm-profile-use= llvm-profile-generate enable-bolt-settings skip-stage0-validation reproducible-artifact= set= h/help
 end
 
 function __fish_x.py_needs_command
@@ -41,7 +41,6 @@
 complete -c x.py -n "__fish_x.py_needs_command" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_needs_command" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_needs_command" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_needs_command" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_needs_command" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_needs_command" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_needs_command" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -92,7 +91,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand build" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand build" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand build" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand build" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand build" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand build" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand build" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -126,7 +124,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand check" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand check" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand check" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand check" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand check" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand check" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand check" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -165,7 +162,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -202,7 +198,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand fix" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand fix" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand fix" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand fix" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand fix" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand fix" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand fix" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -236,7 +231,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -272,7 +266,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand doc" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand doc" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand doc" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand doc" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand doc" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand doc" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand doc" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -314,7 +307,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand test" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand test" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand test" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand test" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand test" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand test" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand test" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -356,7 +348,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand miri" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand miri" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand miri" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand miri" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand miri" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand miri" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand miri" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -394,7 +385,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand bench" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand bench" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand bench" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand bench" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand bench" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand bench" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand bench" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -428,7 +418,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand clean" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand clean" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand clean" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand clean" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand clean" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand clean" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand clean" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -463,7 +452,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand dist" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand dist" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand dist" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand dist" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand dist" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand dist" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand dist" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -497,7 +485,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand install" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand install" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand install" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand install" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand install" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand install" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand install" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -532,7 +519,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand run" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand run" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand run" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand run" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand run" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand run" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand run" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -566,7 +552,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand setup" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand setup" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand setup" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand setup" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand setup" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand setup" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand setup" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -600,7 +585,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -636,7 +620,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -671,7 +654,6 @@
 complete -c x.py -n "__fish_x.py_using_subcommand perf" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand perf" -l error-format -d 'rustc error format' -r -f
 complete -c x.py -n "__fish_x.py_using_subcommand perf" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand perf" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
 complete -c x.py -n "__fish_x.py_using_subcommand perf" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand perf" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_x.py_using_subcommand perf" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1
index 240de32..afbfb05 100644
--- a/src/etc/completions/x.py.ps1
+++ b/src/etc/completions/x.py.ps1
@@ -39,7 +39,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -97,7 +96,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -138,7 +136,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -184,7 +181,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -228,7 +224,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -269,7 +264,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -312,7 +306,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -361,7 +354,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -410,7 +402,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -455,7 +446,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -496,7 +486,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -538,7 +527,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -579,7 +567,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -621,7 +608,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -662,7 +648,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -703,7 +688,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -746,7 +730,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -788,7 +771,6 @@
             [CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
             [CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
             [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
-            [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
             [CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
             [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh
index b1730e5..2aa0d9f 100644
--- a/src/etc/completions/x.py.sh
+++ b/src/etc/completions/x.py.sh
@@ -70,7 +70,7 @@
 
     case "${cmd}" in
         x.py)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test miri bench clean dist install run setup suggest vendor perf"
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test miri bench clean dist install run setup suggest vendor perf"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -195,10 +195,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -263,7 +259,7 @@
             return 0
             ;;
         x.py__bench)
-            opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -392,10 +388,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -460,7 +452,7 @@
             return 0
             ;;
         x.py__build)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -585,10 +577,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -653,7 +641,7 @@
             return 0
             ;;
         x.py__check)
-            opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -778,10 +766,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -846,7 +830,7 @@
             return 0
             ;;
         x.py__clean)
-            opts="-v -i -j -h --all --stage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --all --stage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -968,10 +952,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -1036,7 +1016,7 @@
             return 0
             ;;
         x.py__clippy)
-            opts="-A -D -W -F -v -i -j -h --fix --allow-dirty --allow-staged --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-A -D -W -F -v -i -j -h --fix --allow-dirty --allow-staged --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1177,10 +1157,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -1245,7 +1221,7 @@
             return 0
             ;;
         x.py__dist)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1370,10 +1346,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -1438,7 +1410,7 @@
             return 0
             ;;
         x.py__doc)
-            opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1563,10 +1535,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -1631,7 +1599,7 @@
             return 0
             ;;
         x.py__fix)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1756,10 +1724,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -1824,7 +1788,7 @@
             return 0
             ;;
         x.py__fmt)
-            opts="-v -i -j -h --check --all --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --check --all --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1949,10 +1913,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -2017,7 +1977,7 @@
             return 0
             ;;
         x.py__install)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -2142,10 +2102,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -2210,7 +2166,7 @@
             return 0
             ;;
         x.py__miri)
-            opts="-v -i -j -h --no-fail-fast --test-args --no-doc --doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --no-fail-fast --test-args --no-doc --doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -2339,10 +2295,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -2407,7 +2359,7 @@
             return 0
             ;;
         x.py__perf)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -2532,10 +2484,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -2600,7 +2548,7 @@
             return 0
             ;;
         x.py__run)
-            opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -2729,10 +2677,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -2797,7 +2741,7 @@
             return 0
             ;;
         x.py__setup)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [<PROFILE>|hook|vscode|link] [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [<PROFILE>|hook|vscode|link] [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -2922,10 +2866,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -2990,7 +2930,7 @@
             return 0
             ;;
         x.py__suggest)
-            opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -3115,10 +3055,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -3183,7 +3119,7 @@
             return 0
             ;;
         x.py__test)
-            opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -3332,10 +3268,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
@@ -3400,7 +3332,7 @@
             return 0
             ;;
         x.py__vendor)
-            opts="-v -i -j -h --sync --versioned-dirs --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --sync --versioned-dirs --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -3529,10 +3461,6 @@
                     COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
                     return 0
                     ;;
-                --llvm-skip-rebuild)
-                    COMPREPLY=($(compgen -W "true false" -- "${cur}"))
-                    return 0
-                    ;;
                 --rust-profile-generate)
                     local oldifs
                     if [ -n "${IFS+x}" ]; then
diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh
index ae076b8..c47937a 100644
--- a/src/etc/completions/x.py.zsh
+++ b/src/etc/completions/x.py.zsh
@@ -33,7 +33,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -84,7 +83,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -127,7 +125,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -175,7 +172,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -221,7 +217,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -264,7 +259,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -309,7 +303,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -360,7 +353,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -411,7 +403,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -458,7 +449,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -501,7 +491,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -545,7 +534,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -588,7 +576,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -632,7 +619,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -675,7 +661,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -719,7 +704,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -764,7 +748,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -808,7 +791,6 @@
 '--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
 '--error-format=[rustc error format]:FORMAT:( )' \
 '--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
 '--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
 '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
 '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 6549010..7e3881c 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -115,17 +115,19 @@ fn synthesize_auto_trait_impl<'tcx>(
 
     Some(clean::Item {
         name: None,
-        attrs: Default::default(),
+        inner: Box::new(clean::ItemInner {
+            attrs: Default::default(),
+            kind: clean::ImplItem(Box::new(clean::Impl {
+                safety: hir::Safety::Safe,
+                generics,
+                trait_: Some(clean_trait_ref_with_constraints(cx, trait_ref, ThinVec::new())),
+                for_: clean_middle_ty(ty::Binder::dummy(ty), cx, None, None),
+                items: Vec::new(),
+                polarity,
+                kind: clean::ImplKind::Auto,
+            })),
+        }),
         item_id: clean::ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
-        kind: Box::new(clean::ImplItem(Box::new(clean::Impl {
-            safety: hir::Safety::Safe,
-            generics,
-            trait_: Some(clean_trait_ref_with_constraints(cx, trait_ref, ThinVec::new())),
-            for_: clean_middle_ty(ty::Binder::dummy(ty), cx, None, None),
-            items: Vec::new(),
-            polarity,
-            kind: clean::ImplKind::Auto,
-        }))),
         cfg: None,
         inline_stmt_id: None,
     })
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 1f5f660..95f6616 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -84,42 +84,44 @@ pub(crate) fn synthesize_blanket_impls(
 
             blanket_impls.push(clean::Item {
                 name: None,
-                attrs: Default::default(),
                 item_id: clean::ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
-                kind: Box::new(clean::ImplItem(Box::new(clean::Impl {
-                    safety: hir::Safety::Safe,
-                    generics: clean_ty_generics(
-                        cx,
-                        tcx.generics_of(impl_def_id),
-                        tcx.explicit_predicates_of(impl_def_id),
-                    ),
-                    // FIXME(eddyb) compute both `trait_` and `for_` from
-                    // the post-inference `trait_ref`, as it's more accurate.
-                    trait_: Some(clean_trait_ref_with_constraints(
-                        cx,
-                        ty::Binder::dummy(trait_ref.instantiate_identity()),
-                        ThinVec::new(),
-                    )),
-                    for_: clean_middle_ty(
-                        ty::Binder::dummy(ty.instantiate_identity()),
-                        cx,
-                        None,
-                        None,
-                    ),
-                    items: tcx
-                        .associated_items(impl_def_id)
-                        .in_definition_order()
-                        .filter(|item| !item.is_impl_trait_in_trait())
-                        .map(|item| clean_middle_assoc_item(item, cx))
-                        .collect(),
-                    polarity: ty::ImplPolarity::Positive,
-                    kind: clean::ImplKind::Blanket(Box::new(clean_middle_ty(
-                        ty::Binder::dummy(trait_ref.instantiate_identity().self_ty()),
-                        cx,
-                        None,
-                        None,
-                    ))),
-                }))),
+                inner: Box::new(clean::ItemInner {
+                    attrs: Default::default(),
+                    kind: clean::ImplItem(Box::new(clean::Impl {
+                        safety: hir::Safety::Safe,
+                        generics: clean_ty_generics(
+                            cx,
+                            tcx.generics_of(impl_def_id),
+                            tcx.explicit_predicates_of(impl_def_id),
+                        ),
+                        // FIXME(eddyb) compute both `trait_` and `for_` from
+                        // the post-inference `trait_ref`, as it's more accurate.
+                        trait_: Some(clean_trait_ref_with_constraints(
+                            cx,
+                            ty::Binder::dummy(trait_ref.instantiate_identity()),
+                            ThinVec::new(),
+                        )),
+                        for_: clean_middle_ty(
+                            ty::Binder::dummy(ty.instantiate_identity()),
+                            cx,
+                            None,
+                            None,
+                        ),
+                        items: tcx
+                            .associated_items(impl_def_id)
+                            .in_definition_order()
+                            .filter(|item| !item.is_impl_trait_in_trait())
+                            .map(|item| clean_middle_assoc_item(item, cx))
+                            .collect(),
+                        polarity: ty::ImplPolarity::Positive,
+                        kind: clean::ImplKind::Blanket(Box::new(clean_middle_ty(
+                            ty::Binder::dummy(trait_ref.instantiate_identity().self_ty()),
+                            cx,
+                            None,
+                            None,
+                        ))),
+                    })),
+                }),
                 cfg: None,
                 inline_stmt_id: None,
             });
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index d22c4cc..8383012 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -5,7 +5,7 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, DefIdSet, LocalModDefId};
+use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModDefId};
 use rustc_hir::Mutability;
 use rustc_metadata::creader::{CStore, LoadedMacro};
 use rustc_middle::ty::fast_reject::SimplifiedType;
@@ -43,7 +43,7 @@ pub(crate) fn try_inline(
     cx: &mut DocContext<'_>,
     res: Res,
     name: Symbol,
-    attrs: Option<(&[ast::Attribute], Option<DefId>)>,
+    attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
     visited: &mut DefIdSet,
 ) -> Option<Vec<clean::Item>> {
     let did = res.opt_def_id()?;
@@ -152,14 +152,8 @@ pub(crate) fn try_inline(
     };
 
     cx.inlined.insert(did.into());
-    let mut item = crate::clean::generate_item_with_correct_attrs(
-        cx,
-        kind,
-        did,
-        name,
-        import_def_id.and_then(|def_id| def_id.as_local()),
-        None,
-    );
+    let mut item =
+        crate::clean::generate_item_with_correct_attrs(cx, kind, did, name, import_def_id, None);
     // The visibility needs to reflect the one from the reexport and not from the "source" DefId.
     item.inline_stmt_id = import_def_id;
     ret.push(item);
@@ -198,7 +192,7 @@ pub(crate) fn try_inline_glob(
                 visited,
                 inlined_names,
                 Some(&reexports),
-                Some((attrs, Some(import.owner_id.def_id.to_def_id()))),
+                Some((attrs, Some(import.owner_id.def_id))),
             );
             items.retain(|item| {
                 if let Some(name) = item.name {
@@ -372,7 +366,7 @@ fn build_type_alias(
 pub(crate) fn build_impls(
     cx: &mut DocContext<'_>,
     did: DefId,
-    attrs: Option<(&[ast::Attribute], Option<DefId>)>,
+    attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
     ret: &mut Vec<clean::Item>,
 ) {
     let _prof_timer = cx.tcx.sess.prof.generic_activity("build_inherent_impls");
@@ -405,7 +399,7 @@ pub(crate) fn build_impls(
 pub(crate) fn merge_attrs(
     cx: &mut DocContext<'_>,
     old_attrs: &[ast::Attribute],
-    new_attrs: Option<(&[ast::Attribute], Option<DefId>)>,
+    new_attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
 ) -> (clean::Attributes, Option<Arc<clean::cfg::Cfg>>) {
     // NOTE: If we have additional attributes (from a re-export),
     // always insert them first. This ensure that re-export
@@ -416,7 +410,7 @@ pub(crate) fn merge_attrs(
         both.extend_from_slice(old_attrs);
         (
             if let Some(item_id) = item_id {
-                Attributes::from_ast_with_additional(old_attrs, (inner, item_id))
+                Attributes::from_ast_with_additional(old_attrs, (inner, item_id.to_def_id()))
             } else {
                 Attributes::from_ast(&both)
             },
@@ -431,7 +425,7 @@ pub(crate) fn merge_attrs(
 pub(crate) fn build_impl(
     cx: &mut DocContext<'_>,
     did: DefId,
-    attrs: Option<(&[ast::Attribute], Option<DefId>)>,
+    attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
     ret: &mut Vec<clean::Item>,
 ) {
     if !cx.inlined.insert(did.into()) {
@@ -623,7 +617,7 @@ pub(crate) fn build_impl(
                 ImplKind::Normal
             },
         })),
-        Box::new(merged_attrs),
+        merged_attrs,
         cfg,
     ));
 }
@@ -641,7 +635,7 @@ fn build_module_items(
     visited: &mut DefIdSet,
     inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
     allowed_def_ids: Option<&DefIdSet>,
-    attrs: Option<(&[ast::Attribute], Option<DefId>)>,
+    attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
 ) -> Vec<clean::Item> {
     let mut items = Vec::new();
 
@@ -673,27 +667,29 @@ fn build_module_items(
                 let prim_ty = clean::PrimitiveType::from(p);
                 items.push(clean::Item {
                     name: None,
-                    attrs: Box::default(),
                     // We can use the item's `DefId` directly since the only information ever used
                     // from it is `DefId.krate`.
                     item_id: ItemId::DefId(did),
-                    kind: Box::new(clean::ImportItem(clean::Import::new_simple(
-                        item.ident.name,
-                        clean::ImportSource {
-                            path: clean::Path {
-                                res,
-                                segments: thin_vec![clean::PathSegment {
-                                    name: prim_ty.as_sym(),
-                                    args: clean::GenericArgs::AngleBracketed {
-                                        args: Default::default(),
-                                        constraints: ThinVec::new(),
-                                    },
-                                }],
+                    inner: Box::new(clean::ItemInner {
+                        attrs: Default::default(),
+                        kind: clean::ImportItem(clean::Import::new_simple(
+                            item.ident.name,
+                            clean::ImportSource {
+                                path: clean::Path {
+                                    res,
+                                    segments: thin_vec![clean::PathSegment {
+                                        name: prim_ty.as_sym(),
+                                        args: clean::GenericArgs::AngleBracketed {
+                                            args: Default::default(),
+                                            constraints: ThinVec::new(),
+                                        },
+                                    }],
+                                },
+                                did: None,
                             },
-                            did: None,
-                        },
-                        true,
-                    ))),
+                            true,
+                        )),
+                    }),
                     cfg: None,
                     inline_stmt_id: None,
                 });
@@ -745,7 +741,7 @@ fn build_macro(
     cx: &mut DocContext<'_>,
     def_id: DefId,
     name: Symbol,
-    import_def_id: Option<DefId>,
+    import_def_id: Option<LocalDefId>,
     macro_kind: MacroKind,
     is_doc_hidden: bool,
 ) -> clean::ItemKind {
@@ -753,7 +749,8 @@ fn build_macro(
         LoadedMacro::MacroDef(item_def, _) => match macro_kind {
             MacroKind::Bang => {
                 if let ast::ItemKind::MacroDef(ref def) = item_def.kind {
-                    let vis = cx.tcx.visibility(import_def_id.unwrap_or(def_id));
+                    let vis =
+                        cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id));
                     clean::MacroItem(clean::Macro {
                         source: utils::display_macro_source(
                             cx,
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 710bd4a..e47ae7d 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -203,8 +203,8 @@ fn generate_item_with_correct_attrs(
     let attrs = Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
 
     let name = renamed.or(Some(name));
-    let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, Box::new(attrs), cfg);
-    item.inline_stmt_id = import_id.map(|local| local.to_def_id());
+    let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, cfg);
+    item.inline_stmt_id = import_id;
     item
 }
 
@@ -2927,7 +2927,7 @@ fn clean_extern_crate<'tcx>(
         })
         && !cx.output_format.is_json();
 
-    let krate_owner_def_id = krate.owner_id.to_def_id();
+    let krate_owner_def_id = krate.owner_id.def_id;
     if please_inline {
         if let Some(items) = inline::try_inline(
             cx,
@@ -2941,7 +2941,7 @@ fn clean_extern_crate<'tcx>(
     }
 
     vec![Item::from_def_id_and_parts(
-        krate_owner_def_id,
+        krate_owner_def_id.to_def_id(),
         Some(name),
         ExternCrateItem { src: orig_name },
         cx,
@@ -2988,7 +2988,7 @@ fn clean_use_statement_inner<'tcx>(
     let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline);
     let pub_underscore = visibility.is_public() && name == kw::Underscore;
     let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id);
-    let import_def_id = import.owner_id.def_id.to_def_id();
+    let import_def_id = import.owner_id.def_id;
 
     // The parent of the module in which this import resides. This
     // is the same as `current_mod` if that's already the top
@@ -3071,7 +3071,7 @@ fn clean_use_statement_inner<'tcx>(
             )
         {
             items.push(Item::from_def_id_and_parts(
-                import_def_id,
+                import_def_id.to_def_id(),
                 None,
                 ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)),
                 cx,
@@ -3081,7 +3081,7 @@ fn clean_use_statement_inner<'tcx>(
         Import::new_simple(name, resolve_use_source(cx, path), true)
     };
 
-    vec![Item::from_def_id_and_parts(import_def_id, None, ImportItem(inner), cx)]
+    vec![Item::from_def_id_and_parts(import_def_id.to_def_id(), None, ImportItem(inner), cx)]
 }
 
 fn clean_maybe_renamed_foreign_item<'tcx>(
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 5666b22..383efe5 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -320,14 +320,28 @@ pub(crate) struct Item {
     /// The name of this item.
     /// Optional because not every item has a name, e.g. impls.
     pub(crate) name: Option<Symbol>,
-    pub(crate) attrs: Box<Attributes>,
+    pub(crate) inner: Box<ItemInner>,
+    pub(crate) item_id: ItemId,
+    /// This is the `LocalDefId` of the `use` statement if the item was inlined.
+    /// The crate metadata doesn't hold this information, so the `use` statement
+    /// always belongs to the current crate.
+    pub(crate) inline_stmt_id: Option<LocalDefId>,
+    pub(crate) cfg: Option<Arc<Cfg>>,
+}
+
+#[derive(Clone)]
+pub(crate) struct ItemInner {
     /// Information about this item that is specific to what kind of item it is.
     /// E.g., struct vs enum vs function.
-    pub(crate) kind: Box<ItemKind>,
-    pub(crate) item_id: ItemId,
-    /// This is the `DefId` of the `use` statement if the item was inlined.
-    pub(crate) inline_stmt_id: Option<DefId>,
-    pub(crate) cfg: Option<Arc<Cfg>>,
+    pub(crate) kind: ItemKind,
+    pub(crate) attrs: Attributes,
+}
+
+impl std::ops::Deref for Item {
+    type Target = ItemInner;
+    fn deref(&self) -> &ItemInner {
+        &*self.inner
+    }
 }
 
 /// NOTE: this does NOT unconditionally print every item, to avoid thousands of lines of logs.
@@ -389,9 +403,9 @@ pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
     }
 
     pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
-        let kind = match &*self.kind {
-            ItemKind::StrippedItem(k) => k,
-            _ => &*self.kind,
+        let kind = match &self.kind {
+            ItemKind::StrippedItem(k) => &*k,
+            _ => &self.kind,
         };
         match kind {
             ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
@@ -436,7 +450,7 @@ pub(crate) fn from_def_id_and_parts(
             def_id,
             name,
             kind,
-            Box::new(Attributes::from_ast(ast_attrs)),
+            Attributes::from_ast(ast_attrs),
             ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
         )
     }
@@ -445,16 +459,15 @@ pub(crate) fn from_def_id_and_attrs_and_parts(
         def_id: DefId,
         name: Option<Symbol>,
         kind: ItemKind,
-        attrs: Box<Attributes>,
+        attrs: Attributes,
         cfg: Option<Arc<Cfg>>,
     ) -> Item {
         trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
 
         Item {
             item_id: def_id.into(),
-            kind: Box::new(kind),
+            inner: Box::new(ItemInner { kind, attrs }),
             name,
-            attrs,
             cfg,
             inline_stmt_id: None,
         }
@@ -522,16 +535,16 @@ pub(crate) fn is_variant(&self) -> bool {
         self.type_() == ItemType::Variant
     }
     pub(crate) fn is_associated_type(&self) -> bool {
-        matches!(&*self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
+        matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
     }
     pub(crate) fn is_ty_associated_type(&self) -> bool {
-        matches!(&*self.kind, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..)))
+        matches!(self.kind, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..)))
     }
     pub(crate) fn is_associated_const(&self) -> bool {
-        matches!(&*self.kind, AssocConstItem(..) | StrippedItem(box AssocConstItem(..)))
+        matches!(self.kind, AssocConstItem(..) | StrippedItem(box AssocConstItem(..)))
     }
     pub(crate) fn is_ty_associated_const(&self) -> bool {
-        matches!(&*self.kind, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..)))
+        matches!(self.kind, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..)))
     }
     pub(crate) fn is_method(&self) -> bool {
         self.type_() == ItemType::Method
@@ -555,14 +568,14 @@ pub(crate) fn is_keyword(&self) -> bool {
         self.type_() == ItemType::Keyword
     }
     pub(crate) fn is_stripped(&self) -> bool {
-        match *self.kind {
+        match self.kind {
             StrippedItem(..) => true,
             ImportItem(ref i) => !i.should_be_displayed,
             _ => false,
         }
     }
     pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
-        match *self.kind {
+        match self.kind {
             StructItem(ref struct_) => Some(struct_.has_stripped_entries()),
             UnionItem(ref union_) => Some(union_.has_stripped_entries()),
             EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
@@ -605,7 +618,7 @@ pub(crate) fn type_(&self) -> ItemType {
     }
 
     pub(crate) fn is_default(&self) -> bool {
-        match *self.kind {
+        match self.kind {
             ItemKind::MethodItem(_, Some(defaultness)) => {
                 defaultness.has_value() && !defaultness.is_final()
             }
@@ -633,7 +646,7 @@ fn build_fn_header(
             };
             hir::FnHeader { safety: sig.safety(), abi: sig.abi(), constness, asyncness }
         }
-        let header = match *self.kind {
+        let header = match self.kind {
             ItemKind::ForeignFunctionItem(_, safety) => {
                 let def_id = self.def_id().unwrap();
                 let abi = tcx.fn_sig(def_id).skip_binder().abi();
@@ -672,7 +685,7 @@ pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
             ItemId::DefId(def_id) => def_id,
         };
 
-        match *self.kind {
+        match self.kind {
             // Primitives and Keywords are written in the source code as private modules.
             // The modules need to be private so that nobody actually uses them, but the
             // keywords and primitives that they are documenting are public.
@@ -702,7 +715,7 @@ pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
             _ => {}
         }
         let def_id = match self.inline_stmt_id {
-            Some(inlined) => inlined,
+            Some(inlined) => inlined.to_def_id(),
             None => def_id,
         };
         Some(tcx.visibility(def_id))
@@ -2559,13 +2572,13 @@ mod size_asserts {
 
     use super::*;
     // tidy-alphabetical-start
-    static_assert_size!(Crate, 64); // frequently moved by-value
+    static_assert_size!(Crate, 56); // frequently moved by-value
     static_assert_size!(DocFragment, 32);
     static_assert_size!(GenericArg, 32);
     static_assert_size!(GenericArgs, 32);
     static_assert_size!(GenericParamDef, 40);
     static_assert_size!(Generics, 16);
-    static_assert_size!(Item, 56);
+    static_assert_size!(Item, 48);
     static_assert_size!(ItemKind, 48);
     static_assert_size!(PathSegment, 40);
     static_assert_size!(Type, 32);
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 5686307..885758c 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -36,7 +36,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
     // understood by rustdoc.
     let mut module = clean_doc_module(&module, cx);
 
-    match *module.kind {
+    match module.kind {
         ItemKind::ModuleItem(ref module) => {
             for it in &module.items {
                 // `compiler_builtins` should be masked too, but we can't apply
@@ -60,7 +60,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
     let primitives = local_crate.primitives(cx.tcx);
     let keywords = local_crate.keywords(cx.tcx);
     {
-        let ItemKind::ModuleItem(ref mut m) = *module.kind else { unreachable!() };
+        let ItemKind::ModuleItem(ref mut m) = &mut module.inner.kind else { unreachable!() };
         m.items.extend(primitives.iter().map(|&(def_id, prim)| {
             Item::from_def_id_and_parts(
                 def_id,
@@ -281,7 +281,7 @@ pub(crate) fn build_deref_target_impls(
     let tcx = cx.tcx;
 
     for item in items {
-        let target = match *item.kind {
+        let target = match item.kind {
             ItemKind::AssocTypeItem(ref t, _) => &t.type_,
             _ => continue,
         };
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 9e7b69e..b3c87a7 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -53,12 +53,18 @@ fn try_from(value: &str) -> Result<Self, Self::Error> {
     }
 }
 
+/// Either an input crate, markdown file, or nothing (--merge=finalize).
+pub(crate) enum InputMode {
+    /// The `--merge=finalize` step does not need an input crate to rustdoc.
+    NoInputMergeFinalize,
+    /// A crate or markdown file.
+    HasFile(Input),
+}
+
 /// Configuration options for rustdoc.
 #[derive(Clone)]
 pub(crate) struct Options {
     // Basic options / Options passed directly to rustc
-    /// The crate root or Markdown file to load.
-    pub(crate) input: Input,
     /// The name of the crate being documented.
     pub(crate) crate_name: Option<String>,
     /// Whether or not this is a bin crate
@@ -179,7 +185,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         }
 
         f.debug_struct("Options")
-            .field("input", &self.input.source_name())
             .field("crate_name", &self.crate_name)
             .field("bin_crate", &self.bin_crate)
             .field("proc_macro_crate", &self.proc_macro_crate)
@@ -289,6 +294,12 @@ pub(crate) struct RenderOptions {
     /// This field is only used for the JSON output. If it's set to true, no file will be created
     /// and content will be displayed in stdout directly.
     pub(crate) output_to_stdout: bool,
+    /// Whether we should read or write rendered cross-crate info in the doc root.
+    pub(crate) should_merge: ShouldMerge,
+    /// Path to crate-info for external crates.
+    pub(crate) include_parts_dir: Vec<PathToParts>,
+    /// Where to write crate-info
+    pub(crate) parts_out_dir: Option<PathToParts>,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -348,7 +359,7 @@ pub(crate) fn from_matches(
         early_dcx: &mut EarlyDiagCtxt,
         matches: &getopts::Matches,
         args: Vec<String>,
-    ) -> Option<(Options, RenderOptions)> {
+    ) -> Option<(InputMode, Options, RenderOptions)> {
         // Check for unstable options.
         nightly_options::check_nightly_options(early_dcx, matches, &opts());
 
@@ -478,15 +489,17 @@ fn println_condition(condition: Condition) {
         let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches);
 
         let input = if describe_lints {
-            "" // dummy, this won't be used
+            InputMode::HasFile(make_input(early_dcx, ""))
         } else {
             match matches.free.as_slice() {
+                [] if matches.opt_str("merge").as_deref() == Some("finalize") => {
+                    InputMode::NoInputMergeFinalize
+                }
                 [] => dcx.fatal("missing file operand"),
-                [input] => input,
+                [input] => InputMode::HasFile(make_input(early_dcx, input)),
                 _ => dcx.fatal("too many file operands"),
             }
         };
-        let input = make_input(early_dcx, input);
 
         let externs = parse_externs(early_dcx, matches, &unstable_opts);
         let extern_html_root_urls = match parse_extern_html_roots(matches) {
@@ -494,6 +507,16 @@ fn println_condition(condition: Condition) {
             Err(err) => dcx.fatal(err),
         };
 
+        let parts_out_dir =
+            match matches.opt_str("parts-out-dir").map(|p| PathToParts::from_flag(p)).transpose() {
+                Ok(parts_out_dir) => parts_out_dir,
+                Err(e) => dcx.fatal(e),
+            };
+        let include_parts_dir = match parse_include_parts_dir(matches) {
+            Ok(include_parts_dir) => include_parts_dir,
+            Err(e) => dcx.fatal(e),
+        };
+
         let default_settings: Vec<Vec<(String, String)>> = vec![
             matches
                 .opt_str("default-theme")
@@ -735,6 +758,10 @@ fn println_condition(condition: Condition) {
         let extern_html_root_takes_precedence =
             matches.opt_present("extern-html-root-takes-precedence");
         let html_no_source = matches.opt_present("html-no-source");
+        let should_merge = match parse_merge(matches) {
+            Ok(result) => result,
+            Err(e) => dcx.fatal(format!("--merge option error: {e}")),
+        };
 
         if generate_link_to_definition && (show_coverage || output_format != OutputFormat::Html) {
             dcx.struct_warn(
@@ -751,7 +778,6 @@ fn println_condition(condition: Condition) {
         let unstable_features =
             rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref());
         let options = Options {
-            input,
             bin_crate,
             proc_macro_crate,
             error_format,
@@ -823,16 +849,17 @@ fn println_condition(condition: Condition) {
             no_emit_shared: false,
             html_no_source,
             output_to_stdout,
+            should_merge,
+            include_parts_dir,
+            parts_out_dir,
         };
-        Some((options, render_options))
+        Some((input, options, render_options))
     }
+}
 
-    /// Returns `true` if the file given as `self.input` is a Markdown file.
-    pub(crate) fn markdown_input(&self) -> Option<&Path> {
-        self.input
-            .opt_path()
-            .filter(|p| matches!(p.extension(), Some(e) if e == "md" || e == "markdown"))
-    }
+/// Returns `true` if the file given as `self.input` is a Markdown file.
+pub(crate) fn markdown_input(input: &Input) -> Option<&Path> {
+    input.opt_path().filter(|p| matches!(p.extension(), Some(e) if e == "md" || e == "markdown"))
 }
 
 fn parse_remap_path_prefix(
@@ -900,3 +927,71 @@ fn parse_extern_html_roots(
     }
     Ok(externs)
 }
+
+/// Path directly to crate-info file.
+///
+/// For example, `/home/user/project/target/doc.parts/<crate>/crate-info`.
+#[derive(Clone, Debug)]
+pub(crate) struct PathToParts(pub(crate) PathBuf);
+
+impl PathToParts {
+    fn from_flag(path: String) -> Result<PathToParts, String> {
+        let mut path = PathBuf::from(path);
+        // check here is for diagnostics
+        if path.exists() && !path.is_dir() {
+            Err(format!(
+                "--parts-out-dir and --include-parts-dir expect directories, found: {}",
+                path.display(),
+            ))
+        } else {
+            // if it doesn't exist, we'll create it. worry about that in write_shared
+            path.push("crate-info");
+            Ok(PathToParts(path))
+        }
+    }
+}
+
+/// Reports error if --include-parts-dir / crate-info is not a file
+fn parse_include_parts_dir(m: &getopts::Matches) -> Result<Vec<PathToParts>, String> {
+    let mut ret = Vec::new();
+    for p in m.opt_strs("include-parts-dir") {
+        let p = PathToParts::from_flag(p)?;
+        // this is just for diagnostic
+        if !p.0.is_file() {
+            return Err(format!("--include-parts-dir expected {} to be a file", p.0.display()));
+        }
+        ret.push(p);
+    }
+    Ok(ret)
+}
+
+/// Controls merging of cross-crate information
+#[derive(Debug, Clone)]
+pub(crate) struct ShouldMerge {
+    /// Should we append to existing cci in the doc root
+    pub(crate) read_rendered_cci: bool,
+    /// Should we write cci to the doc root
+    pub(crate) write_rendered_cci: bool,
+}
+
+/// Extracts read_rendered_cci and write_rendered_cci from command line arguments, or
+/// reports an error if an invalid option was provided
+fn parse_merge(m: &getopts::Matches) -> Result<ShouldMerge, &'static str> {
+    match m.opt_str("merge").as_deref() {
+        // default = read-write
+        None => Ok(ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }),
+        Some("none") if m.opt_present("include-parts-dir") => {
+            Err("--include-parts-dir not allowed if --merge=none")
+        }
+        Some("none") => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: false }),
+        Some("shared") if m.opt_present("parts-out-dir") || m.opt_present("include-parts-dir") => {
+            Err("--parts-out-dir and --include-parts-dir not allowed if --merge=shared")
+        }
+        Some("shared") => Ok(ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }),
+        Some("finalize") if m.opt_present("parts-out-dir") => {
+            Err("--parts-out-dir not allowed if --merge=finalize")
+        }
+        Some("finalize") => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: true }),
+        Some(_) => Err("argument to --merge must be `none`, `shared`, or `finalize`"),
+    }
+}
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 2cde0ac..4fafef6 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -20,7 +20,7 @@
 use rustc_lint::{late_lint_mod, MissingDoc};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
-use rustc_session::config::{self, CrateType, ErrorOutputType, ResolveDocLinks};
+use rustc_session::config::{self, CrateType, ErrorOutputType, Input, ResolveDocLinks};
 pub(crate) use rustc_session::config::{Options, UnstableOptions};
 use rustc_session::{lint, Session};
 use rustc_span::symbol::sym;
@@ -177,8 +177,8 @@ pub(crate) fn new_dcx(
 
 /// Parse, resolve, and typecheck the given crate.
 pub(crate) fn create_config(
+    input: Input,
     RustdocOptions {
-        input,
         crate_name,
         proc_macro_crate,
         error_format,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 8b6588e..05ef728 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -19,7 +19,7 @@
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::CRATE_HIR_ID;
 use rustc_interface::interface;
-use rustc_session::config::{self, CrateType, ErrorOutputType};
+use rustc_session::config::{self, CrateType, ErrorOutputType, Input};
 use rustc_session::lint;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::sym;
@@ -88,7 +88,11 @@ fn get_doctest_dir() -> io::Result<TempDir> {
     TempFileBuilder::new().prefix("rustdoctest").tempdir()
 }
 
-pub(crate) fn run(dcx: DiagCtxtHandle<'_>, options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
+pub(crate) fn run(
+    dcx: DiagCtxtHandle<'_>,
+    input: Input,
+    options: RustdocOptions,
+) -> Result<(), ErrorGuaranteed> {
     let invalid_codeblock_attributes_name = crate::lint::INVALID_CODEBLOCK_ATTRIBUTES.name;
 
     // See core::create_config for what's going on here.
@@ -135,7 +139,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, options: RustdocOptions) -> Result<()
         opts: sessopts,
         crate_cfg: cfgs,
         crate_check_cfg: options.check_cfgs.clone(),
-        input: options.input.clone(),
+        input: input.clone(),
         output_file: None,
         output_dir: None,
         file_loader: None,
diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs
index 9a237f8..4f83bd5 100644
--- a/src/librustdoc/doctest/markdown.rs
+++ b/src/librustdoc/doctest/markdown.rs
@@ -3,6 +3,7 @@
 use std::fs::read_to_string;
 use std::sync::{Arc, Mutex};
 
+use rustc_session::config::Input;
 use rustc_span::FileName;
 use tempfile::tempdir;
 
@@ -69,9 +70,8 @@ fn visit_header(&mut self, name: &str, level: u32) {
 }
 
 /// Runs any tests/code examples in the markdown file `options.input`.
-pub(crate) fn test(options: Options) -> Result<(), String> {
-    use rustc_session::config::Input;
-    let input_str = match &options.input {
+pub(crate) fn test(input: &Input, options: Options) -> Result<(), String> {
+    let input_str = match input {
         Input::File(path) => {
             read_to_string(path).map_err(|err| format!("{}: {err}", path.display()))?
         }
@@ -79,7 +79,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
     };
 
     // Obviously not a real crate name, but close enough for purposes of doctests.
-    let crate_name = options.input.filestem().to_string();
+    let crate_name = input.filestem().to_string();
     let temp_dir =
         tempdir().map_err(|error| format!("failed to create temporary directory: {error:?}"))?;
     let args_file = temp_dir.path().join("rustdoc-cfgs");
@@ -96,8 +96,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
     let mut md_collector = MdCollector {
         tests: vec![],
         cur_path: vec![],
-        filename: options
-            .input
+        filename: input
             .opt_path()
             .map(ToOwned::to_owned)
             .map(FileName::from)
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index bf82c91..c25a4dd 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -1,8 +1,8 @@
 use crate::clean::*;
 
 pub(crate) fn strip_item(mut item: Item) -> Item {
-    if !matches!(*item.kind, StrippedItem(..)) {
-        item.kind = Box::new(StrippedItem(item.kind));
+    if !matches!(item.inner.kind, StrippedItem(..)) {
+        item.inner.kind = StrippedItem(Box::new(item.inner.kind));
     }
     item
 }
@@ -99,10 +99,10 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind {
 
     /// don't override!
     fn fold_item_recur(&mut self, mut item: Item) -> Item {
-        item.kind = Box::new(match *item.kind {
+        item.inner.kind = match item.inner.kind {
             StrippedItem(box i) => StrippedItem(Box::new(self.fold_inner_recur(i))),
-            _ => self.fold_inner_recur(*item.kind),
-        });
+            _ => self.fold_inner_recur(item.inner.kind),
+        };
         item
     }
 
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index c5e2b33..1b3176e 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -216,7 +216,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
 
         // If this is a stripped module,
         // we don't want it or its children in the search index.
-        let orig_stripped_mod = match *item.kind {
+        let orig_stripped_mod = match item.kind {
             clean::StrippedItem(box clean::ModuleItem(..)) => {
                 mem::replace(&mut self.cache.stripped_mod, true)
             }
@@ -232,7 +232,7 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
 
         // If the impl is from a masked crate or references something from a
         // masked crate then remove it completely.
-        if let clean::ImplItem(ref i) = *item.kind
+        if let clean::ImplItem(ref i) = item.kind
             && (self.cache.masked_crates.contains(&item.item_id.krate())
                 || i.trait_
                     .as_ref()
@@ -246,9 +246,9 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
 
         // Propagate a trait method's documentation to all implementors of the
         // trait.
-        if let clean::TraitItem(ref t) = *item.kind {
+        if let clean::TraitItem(ref t) = item.kind {
             self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| (**t).clone());
-        } else if let clean::ImplItem(ref i) = *item.kind
+        } else if let clean::ImplItem(ref i) = item.kind
             && let Some(trait_) = &i.trait_
             && !i.kind.is_blanket()
         {
@@ -263,7 +263,7 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
         // Index this method for searching later on.
         let search_name = if !item.is_stripped() {
             item.name.or_else(|| {
-                if let clean::ImportItem(ref i) = *item.kind
+                if let clean::ImportItem(ref i) = item.kind
                     && let clean::ImportKind::Simple(s) = i.kind
                 {
                     Some(s)
@@ -287,7 +287,7 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
             _ => false,
         };
 
-        match *item.kind {
+        match item.kind {
             clean::StructItem(..)
             | clean::EnumItem(..)
             | clean::TypeAliasItem(..)
@@ -350,7 +350,7 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
         }
 
         // Maintain the parent stack.
-        let (item, parent_pushed) = match *item.kind {
+        let (item, parent_pushed) = match item.kind {
             clean::TraitItem(..)
             | clean::EnumItem(..)
             | clean::ForeignTypeItem
@@ -367,7 +367,11 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
 
         // Once we've recursively found all the generics, hoard off all the
         // implementations elsewhere.
-        let ret = if let clean::Item { kind: box clean::ImplItem(ref i), .. } = item {
+        let ret = if let clean::Item {
+            inner: box clean::ItemInner { kind: clean::ImplItem(ref i), .. },
+            ..
+        } = item
+        {
             // Figure out the id of this impl. This may map to a
             // primitive rather than always to a struct/enum.
             // Note: matching twice to restrict the lifetime of the `i` borrow.
@@ -436,7 +440,7 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
 fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::Item, name: Symbol) {
     // Item has a name, so it must also have a DefId (can't be an impl, let alone a blanket or auto impl).
     let item_def_id = item.item_id.as_def_id().unwrap();
-    let (parent_did, parent_path) = match *item.kind {
+    let (parent_did, parent_path) = match item.kind {
         clean::StrippedItem(..) => return,
         clean::AssocConstItem(..) | clean::AssocTypeItem(..)
             if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) =>
@@ -528,7 +532,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
     // - It's either an inline, or a true re-export
     // - It's got the same name
     // - Both of them have the same exact path
-    let defid = match &*item.kind {
+    let defid = match &item.kind {
         clean::ItemKind::ImportItem(import) => import.source.did.unwrap_or(item_def_id),
         _ => item_def_id,
     };
@@ -605,7 +609,7 @@ enum ParentStackItem {
 
 impl ParentStackItem {
     fn new(item: &clean::Item) -> Self {
-        match &*item.kind {
+        match &item.kind {
             clean::ItemKind::ImplItem(box clean::Impl { for_, trait_, generics, kind, .. }) => {
                 ParentStackItem::Impl {
                     for_: for_.clone(),
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index 9754e1e..383e313 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -70,7 +70,7 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
 
 impl<'a> From<&'a clean::Item> for ItemType {
     fn from(item: &'a clean::Item) -> ItemType {
-        let kind = match *item.kind {
+        let kind = match item.kind {
             clean::StrippedItem(box ref item) => item,
             ref kind => kind,
         };
diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs
index 84adca8..0bdea36 100644
--- a/src/librustdoc/formats/mod.rs
+++ b/src/librustdoc/formats/mod.rs
@@ -16,7 +16,7 @@ pub(crate) struct Impl {
 
 impl Impl {
     pub(crate) fn inner_impl(&self) -> &clean::Impl {
-        match *self.impl_item.kind {
+        match self.impl_item.kind {
             clean::ImplItem(ref impl_) => impl_,
             _ => panic!("non-impl item found in impl"),
         }
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index cc57dca..edd7d56 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -77,7 +77,7 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
 
             cx.mod_item_in(&item)?;
             let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) =
-                *item.kind
+                item.inner.kind
             else {
                 unreachable!()
             };
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 29b4889..e728da6 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -879,7 +879,9 @@ fn advance(
             | TokenKind::UnknownPrefix
             | TokenKind::InvalidPrefix
             | TokenKind::InvalidIdent => Class::Ident(self.new_span(before, text)),
-            TokenKind::Lifetime { .. } => Class::Lifetime,
+            TokenKind::Lifetime { .. }
+            | TokenKind::RawLifetime
+            | TokenKind::UnknownPrefixLifetime => Class::Lifetime,
             TokenKind::Eof => panic!("Eof in advance"),
         };
         // Anything that didn't return above is the simple case where we the
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 9fe43e4..a9b9377 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -16,12 +16,11 @@
 
 use super::print_item::{full_path, item_path, print_item};
 use super::sidebar::{print_sidebar, sidebar_module_like, ModuleLike, Sidebar};
-use super::write_shared::write_shared;
 use super::{collect_spans_and_sources, scrape_examples_help, AllTypes, LinkFromSrc, StylePath};
 use crate::clean::types::ExternalLocation;
 use crate::clean::utils::has_doc_flag;
 use crate::clean::{self, ExternalCrate};
-use crate::config::{ModuleSorting, RenderOptions};
+use crate::config::{ModuleSorting, RenderOptions, ShouldMerge};
 use crate::docfs::{DocFS, PathError};
 use crate::error::Error;
 use crate::formats::cache::Cache;
@@ -30,6 +29,7 @@
 use crate::html::escape::Escape;
 use crate::html::format::{join_with_double_colon, Buffer};
 use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
+use crate::html::render::write_shared::write_shared;
 use crate::html::url_parts_builder::UrlPartsBuilder;
 use crate::html::{layout, sources, static_files};
 use crate::scrape_examples::AllCallLocations;
@@ -128,8 +128,10 @@ pub(crate) struct SharedContext<'tcx> {
     pub(crate) span_correspondence_map: FxHashMap<rustc_span::Span, LinkFromSrc>,
     /// The [`Cache`] used during rendering.
     pub(crate) cache: Cache,
-
     pub(crate) call_locations: AllCallLocations,
+    /// Controls whether we read / write to cci files in the doc root. Defaults read=true,
+    /// write=true
+    should_merge: ShouldMerge,
 }
 
 impl SharedContext<'_> {
@@ -551,6 +553,7 @@ fn init(
             span_correspondence_map: matches,
             cache,
             call_locations,
+            should_merge: options.should_merge,
         };
 
         let dst = output;
@@ -640,92 +643,96 @@ fn after_krate(&mut self) -> Result<(), Error> {
         );
         shared.fs.write(final_file, v)?;
 
-        // Generating settings page.
-        page.title = "Settings";
-        page.description = "Settings of Rustdoc";
-        page.root_path = "./";
-        page.rust_logo = true;
+        // if to avoid writing help, settings files to doc root unless we're on the final invocation
+        if shared.should_merge.write_rendered_cci {
+            // Generating settings page.
+            page.title = "Settings";
+            page.description = "Settings of Rustdoc";
+            page.root_path = "./";
+            page.rust_logo = true;
 
-        let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
-        let v = layout::render(
-            &shared.layout,
-            &page,
-            sidebar,
-            |buf: &mut Buffer| {
-                write!(
-                    buf,
-                    "<div class=\"main-heading\">\
-                     <h1>Rustdoc settings</h1>\
-                     <span class=\"out-of-band\">\
-                         <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
-                            Back\
-                        </a>\
-                     </span>\
-                     </div>\
-                     <noscript>\
-                        <section>\
-                            You need to enable JavaScript be able to update your settings.\
-                        </section>\
-                     </noscript>\
-                     <script defer src=\"{static_root_path}{settings_js}\"></script>",
-                    static_root_path = page.get_static_root_path(),
-                    settings_js = static_files::STATIC_FILES.settings_js,
-                );
-                // Pre-load all theme CSS files, so that switching feels seamless.
-                //
-                // When loading settings.html as a popover, the equivalent HTML is
-                // generated in main.js.
-                for file in &shared.style_files {
-                    if let Ok(theme) = file.basename() {
-                        write!(
-                            buf,
-                            "<link rel=\"preload\" href=\"{root_path}{theme}{suffix}.css\" \
-                                as=\"style\">",
-                            root_path = page.static_root_path.unwrap_or(""),
-                            suffix = page.resource_suffix,
-                        );
+            let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
+            let v = layout::render(
+                &shared.layout,
+                &page,
+                sidebar,
+                |buf: &mut Buffer| {
+                    write!(
+                        buf,
+                        "<div class=\"main-heading\">\
+                         <h1>Rustdoc settings</h1>\
+                         <span class=\"out-of-band\">\
+                             <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
+                                Back\
+                            </a>\
+                         </span>\
+                         </div>\
+                         <noscript>\
+                            <section>\
+                                You need to enable JavaScript be able to update your settings.\
+                            </section>\
+                         </noscript>\
+                         <script defer src=\"{static_root_path}{settings_js}\"></script>",
+                        static_root_path = page.get_static_root_path(),
+                        settings_js = static_files::STATIC_FILES.settings_js,
+                    );
+                    // Pre-load all theme CSS files, so that switching feels seamless.
+                    //
+                    // When loading settings.html as a popover, the equivalent HTML is
+                    // generated in main.js.
+                    for file in &shared.style_files {
+                        if let Ok(theme) = file.basename() {
+                            write!(
+                                buf,
+                                "<link rel=\"preload\" href=\"{root_path}{theme}{suffix}.css\" \
+                                    as=\"style\">",
+                                root_path = page.static_root_path.unwrap_or(""),
+                                suffix = page.resource_suffix,
+                            );
+                        }
                     }
-                }
-            },
-            &shared.style_files,
-        );
-        shared.fs.write(settings_file, v)?;
+                },
+                &shared.style_files,
+            );
+            shared.fs.write(settings_file, v)?;
 
-        // Generating help page.
-        page.title = "Help";
-        page.description = "Documentation for Rustdoc";
-        page.root_path = "./";
-        page.rust_logo = true;
+            // Generating help page.
+            page.title = "Help";
+            page.description = "Documentation for Rustdoc";
+            page.root_path = "./";
+            page.rust_logo = true;
 
-        let sidebar = "<h2 class=\"location\">Help</h2><div class=\"sidebar-elems\"></div>";
-        let v = layout::render(
-            &shared.layout,
-            &page,
-            sidebar,
-            |buf: &mut Buffer| {
-                write!(
-                    buf,
-                    "<div class=\"main-heading\">\
-                     <h1>Rustdoc help</h1>\
-                     <span class=\"out-of-band\">\
-                         <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
-                            Back\
-                        </a>\
-                     </span>\
-                     </div>\
-                     <noscript>\
-                        <section>\
-                            <p>You need to enable JavaScript to use keyboard commands or search.</p>\
-                            <p>For more information, browse the <a href=\"https://doc.rust-lang.org/rustdoc/\">rustdoc handbook</a>.</p>\
-                        </section>\
-                     </noscript>",
-                )
-            },
-            &shared.style_files,
-        );
-        shared.fs.write(help_file, v)?;
+            let sidebar = "<h2 class=\"location\">Help</h2><div class=\"sidebar-elems\"></div>";
+            let v = layout::render(
+                &shared.layout,
+                &page,
+                sidebar,
+                |buf: &mut Buffer| {
+                    write!(
+                        buf,
+                        "<div class=\"main-heading\">\
+                         <h1>Rustdoc help</h1>\
+                         <span class=\"out-of-band\">\
+                             <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
+                                Back\
+                            </a>\
+                         </span>\
+                         </div>\
+                         <noscript>\
+                            <section>\
+                                <p>You need to enable JavaScript to use keyboard commands or search.</p>\
+                                <p>For more information, browse the <a href=\"https://doc.rust-lang.org/rustdoc/\">rustdoc handbook</a>.</p>\
+                            </section>\
+                         </noscript>",
+                    )
+                },
+                &shared.style_files,
+            );
+            shared.fs.write(help_file, v)?;
+        }
 
-        if shared.layout.scrape_examples_extension {
+        // if to avoid writing files to doc root unless we're on the final invocation
+        if shared.layout.scrape_examples_extension && shared.should_merge.write_rendered_cci {
             page.title = "About scraped examples";
             page.description = "How the scraped examples feature works in Rustdoc";
             let v = layout::render(
@@ -800,7 +807,7 @@ fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> {
         // Render sidebar-items.js used throughout this module.
         if !self.render_redirect_pages {
             let (clean::StrippedItem(box clean::ModuleItem(ref module))
-            | clean::ModuleItem(ref module)) = *item.kind
+            | clean::ModuleItem(ref module)) = item.kind
             else {
                 unreachable!()
             };
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index dc34c78..a402d79 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -61,6 +61,7 @@
 
 pub(crate) use self::context::*;
 pub(crate) use self::span_map::{collect_spans_and_sources, LinkFromSrc};
+pub(crate) use self::write_shared::*;
 use crate::clean::{self, ItemId, RenderedLink};
 use crate::error::Error;
 use crate::formats::cache::Cache;
@@ -620,7 +621,7 @@ fn document_full_inner<'a, 'cx: 'a>(
             }
         }
 
-        let kind = match &*item.kind {
+        let kind = match &item.kind {
             clean::ItemKind::StrippedItem(box kind) | kind => kind,
         };
 
@@ -1072,7 +1073,7 @@ fn render_assoc_item(
     cx: &mut Context<'_>,
     render_mode: RenderMode,
 ) {
-    match &*item.kind {
+    match &item.kind {
         clean::StrippedItem(..) => {}
         clean::TyMethodItem(m) => {
             assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode)
@@ -1350,7 +1351,7 @@ fn render_deref_methods(
         .inner_impl()
         .items
         .iter()
-        .find_map(|item| match *item.kind {
+        .find_map(|item| match item.kind {
             clean::AssocTypeItem(box ref t, _) => Some(match *t {
                 clean::TypeAlias { item_type: Some(ref type_), .. } => (type_, &t.type_),
                 _ => (&t.type_, &t.type_),
@@ -1381,7 +1382,7 @@ fn render_deref_methods(
 }
 
 fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool {
-    let self_type_opt = match *item.kind {
+    let self_type_opt = match item.kind {
         clean::MethodItem(ref method, _) => method.decl.receiver_type(),
         clean::TyMethodItem(ref method) => method.decl.receiver_type(),
         _ => None,
@@ -1491,7 +1492,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) {
 
                 write!(&mut out, "<div class=\"where\">{}</div>", impl_.print(false, cx));
                 for it in &impl_.items {
-                    if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind {
+                    if let clean::AssocTypeItem(ref tydef, ref _bounds) = it.kind {
                         out.push_str("<div class=\"where\">    ");
                         let empty_set = FxHashSet::default();
                         let src_link = AssocItemLink::GotoSource(trait_did.into(), &empty_set);
@@ -1659,7 +1660,7 @@ fn doc_impl_item(
             let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
             write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>");
         }
-        match &*item.kind {
+        match &item.kind {
             clean::MethodItem(..) | clean::TyMethodItem(_) => {
                 // Only render when the method is not static or we allow static methods
                 if render_method_item {
@@ -1690,7 +1691,7 @@ fn doc_impl_item(
                     w.write_str("</h4></section>");
                 }
             }
-            clean::TyAssocConstItem(generics, ty) => {
+            clean::TyAssocConstItem(ref generics, ref ty) => {
                 let source_id = format!("{item_type}.{name}");
                 let id = cx.derive_id(&source_id);
                 write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">");
@@ -1734,7 +1735,7 @@ fn doc_impl_item(
                 );
                 w.write_str("</h4></section>");
             }
-            clean::TyAssocTypeItem(generics, bounds) => {
+            clean::TyAssocTypeItem(ref generics, ref bounds) => {
                 let source_id = format!("{item_type}.{name}");
                 let id = cx.derive_id(&source_id);
                 write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">");
@@ -1794,13 +1795,64 @@ fn doc_impl_item(
     let mut default_impl_items = Buffer::empty_from(w);
     let impl_ = i.inner_impl();
 
+    // Impl items are grouped by kinds:
+    //
+    // 1. Constants
+    // 2. Types
+    // 3. Functions
+    //
+    // This order is because you can have associated constants used in associated types (like array
+    // length), and both in associcated functions. So with this order, when reading from top to
+    // bottom, you should see items definitions before they're actually used most of the time.
+    let mut assoc_types = Vec::new();
+    let mut methods = Vec::new();
+
     if !impl_.is_negative_trait_impl() {
         for trait_item in &impl_.items {
+            match trait_item.kind {
+                clean::MethodItem(..) | clean::TyMethodItem(_) => methods.push(trait_item),
+                clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => {
+                    assoc_types.push(trait_item)
+                }
+                clean::TyAssocConstItem(..) | clean::AssocConstItem(_) => {
+                    // We render it directly since they're supposed to come first.
+                    doc_impl_item(
+                        &mut default_impl_items,
+                        &mut impl_items,
+                        cx,
+                        trait_item,
+                        if trait_.is_some() { &i.impl_item } else { parent },
+                        link,
+                        render_mode,
+                        false,
+                        trait_,
+                        rendering_params,
+                    );
+                }
+                _ => {}
+            }
+        }
+
+        for assoc_type in assoc_types {
             doc_impl_item(
                 &mut default_impl_items,
                 &mut impl_items,
                 cx,
-                trait_item,
+                assoc_type,
+                if trait_.is_some() { &i.impl_item } else { parent },
+                link,
+                render_mode,
+                false,
+                trait_,
+                rendering_params,
+            );
+        }
+        for method in methods {
+            doc_impl_item(
+                &mut default_impl_items,
+                &mut impl_items,
+                cx,
+                method,
                 if trait_.is_some() { &i.impl_item } else { parent },
                 link,
                 render_mode,
@@ -2000,7 +2052,7 @@ pub(crate) fn render_impl_summary(
         write!(w, "{}", inner_impl.print(use_absolute, cx));
         if show_def_docs {
             for it in &inner_impl.items {
-                if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind {
+                if let clean::AssocTypeItem(ref tydef, ref _bounds) = it.kind {
                     w.write_str("<div class=\"where\">  ");
                     assoc_type(
                         w,
@@ -2121,7 +2173,7 @@ fn get_id_for_impl<'tcx>(tcx: TyCtxt<'tcx>, impl_id: ItemId) -> String {
 }
 
 fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String, String)> {
-    match *item.kind {
+    match item.kind {
         clean::ItemKind::ImplItem(ref i) if i.trait_.is_some() => {
             // Alternative format produces no URLs,
             // so this parameter does nothing.
@@ -2455,28 +2507,6 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c
         let needs_expansion = line_max - line_min > NUM_VISIBLE_LINES;
         let locations_encoded = serde_json::to_string(&line_ranges).unwrap();
 
-        write!(
-            &mut w,
-            "<div class=\"scraped-example {expanded_cls}\" data-locs=\"{locations}\">\
-                <div class=\"scraped-example-title\">\
-                   {name} (<a href=\"{url}\">{title}</a>)\
-                </div>\
-                <div class=\"code-wrapper\">",
-            expanded_cls = if needs_expansion { "" } else { "expanded" },
-            name = call_data.display_name,
-            url = init_url,
-            title = init_title,
-            // The locations are encoded as a data attribute, so they can be read
-            // later by the JS for interactions.
-            locations = Escape(&locations_encoded)
-        )
-        .unwrap();
-
-        if line_ranges.len() > 1 {
-            w.write_str(r#"<button class="prev">&pr;</button> <button class="next">&sc;</button>"#)
-                .unwrap();
-        }
-
         // Look for the example file in the source map if it exists, otherwise return a dummy span
         let file_span = (|| {
             let source_map = tcx.sess.source_map();
@@ -2507,9 +2537,16 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c
             cx,
             &cx.root_path(),
             highlight::DecorationInfo(decoration_info),
-            sources::SourceContext::Embedded { offset: line_min, needs_expansion },
+            sources::SourceContext::Embedded(sources::ScrapedInfo {
+                needs_prev_next_buttons: line_ranges.len() > 1,
+                needs_expansion,
+                offset: line_min,
+                name: &call_data.display_name,
+                url: init_url,
+                title: init_title,
+                locations: locations_encoded,
+            }),
         );
-        w.write_str("</div></div>").unwrap();
 
         true
     };
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index a0a72d5..52e2515 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -178,7 +178,7 @@ fn print_where_clause_and_check<'a, 'tcx: 'a>(
 
 pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buffer) {
     debug_assert!(!item.is_stripped());
-    let typ = match *item.kind {
+    let typ = match item.kind {
         clean::ModuleItem(_) => {
             if item.is_crate() {
                 "Crate "
@@ -252,7 +252,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf
 
     item_vars.render_into(buf).unwrap();
 
-    match &*item.kind {
+    match &item.kind {
         clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items),
         clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f, _) => {
             item_function(buf, cx, item, f)
@@ -411,7 +411,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
             );
         }
 
-        match *myitem.kind {
+        match myitem.kind {
             clean::ExternCrateItem { ref src } => {
                 use crate::html::format::anchor;
 
@@ -477,7 +477,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
                     continue;
                 }
 
-                let unsafety_flag = match *myitem.kind {
+                let unsafety_flag = match myitem.kind {
                     clean::FunctionItem(_) | clean::ForeignFunctionItem(..)
                         if myitem.fn_header(tcx).unwrap().safety == hir::Safety::Unsafe =>
                     {
@@ -843,33 +843,6 @@ fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::
         }
     }
 
-    if !required_types.is_empty() {
-        write_section_heading(
-            w,
-            "Required Associated Types",
-            "required-associated-types",
-            None,
-            "<div class=\"methods\">",
-        );
-        for t in required_types {
-            trait_item(w, cx, t, it);
-        }
-        w.write_str("</div>");
-    }
-    if !provided_types.is_empty() {
-        write_section_heading(
-            w,
-            "Provided Associated Types",
-            "provided-associated-types",
-            None,
-            "<div class=\"methods\">",
-        );
-        for t in provided_types {
-            trait_item(w, cx, t, it);
-        }
-        w.write_str("</div>");
-    }
-
     if !required_consts.is_empty() {
         write_section_heading(
             w,
@@ -897,6 +870,33 @@ fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::
         w.write_str("</div>");
     }
 
+    if !required_types.is_empty() {
+        write_section_heading(
+            w,
+            "Required Associated Types",
+            "required-associated-types",
+            None,
+            "<div class=\"methods\">",
+        );
+        for t in required_types {
+            trait_item(w, cx, t, it);
+        }
+        w.write_str("</div>");
+    }
+    if !provided_types.is_empty() {
+        write_section_heading(
+            w,
+            "Provided Associated Types",
+            "provided-associated-types",
+            None,
+            "<div class=\"methods\">",
+        );
+        for t in provided_types {
+            trait_item(w, cx, t, it);
+        }
+        w.write_str("</div>");
+    }
+
     // Output the documentation for each function individually
     if !required_methods.is_empty() || must_implement_one_of_functions.is_some() {
         write_section_heading(
@@ -1439,7 +1439,7 @@ fn fields_iter(
             self.s
                 .fields
                 .iter()
-                .filter_map(|f| match *f.kind {
+                .filter_map(|f| match f.kind {
                     clean::StructFieldItem(ref ty) => Some((f, ty)),
                     _ => None,
                 })
@@ -1457,7 +1457,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>(
     display_fn(|f| {
         if !s.is_empty()
             && s.iter().all(|field| {
-                matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))
+                matches!(field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))
             })
         {
             return f.write_str("<span class=\"comment\">/* private fields */</span>");
@@ -1467,7 +1467,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>(
             if i > 0 {
                 f.write_str(", ")?;
             }
-            match *ty.kind {
+            match ty.kind {
                 clean::StrippedItem(box clean::StructFieldItem(_)) => f.write_str("_")?,
                 clean::StructFieldItem(ref ty) => write!(f, "{}", ty.print(cx))?,
                 _ => unreachable!(),
@@ -1521,7 +1521,7 @@ fn should_show_enum_discriminant(
 ) -> bool {
     let mut has_variants_with_value = false;
     for variant in variants {
-        if let clean::VariantItem(ref var) = *variant.kind
+        if let clean::VariantItem(ref var) = variant.kind
             && matches!(var.kind, clean::VariantKind::CLike)
         {
             has_variants_with_value |= var.discriminant.is_some();
@@ -1592,7 +1592,7 @@ fn render_enum_fields(
                 continue;
             }
             w.write_str(TAB);
-            match *v.kind {
+            match v.kind {
                 clean::VariantItem(ref var) => match var.kind {
                     clean::VariantKind::CLike => display_c_like_variant(
                         w,
@@ -1659,7 +1659,7 @@ fn item_variants(
             " rightside",
         );
         w.write_str("<h3 class=\"code-header\">");
-        if let clean::VariantItem(ref var) = *variant.kind
+        if let clean::VariantItem(ref var) = variant.kind
             && let clean::VariantKind::CLike = var.kind
         {
             display_c_like_variant(
@@ -1675,7 +1675,7 @@ fn item_variants(
             w.write_str(variant.name.unwrap().as_str());
         }
 
-        let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() };
+        let clean::VariantItem(variant_data) = &variant.kind else { unreachable!() };
 
         if let clean::VariantKind::Tuple(ref s) = variant_data.kind {
             write!(w, "({})", print_tuple_struct_fields(cx, s));
@@ -1716,7 +1716,7 @@ fn item_variants(
                 document_non_exhaustive(variant)
             );
             for field in fields {
-                match *field.kind {
+                match field.kind {
                     clean::StrippedItem(box clean::StructFieldItem(_)) => {}
                     clean::StructFieldItem(ref ty) => {
                         let id = cx.derive_id(format!(
@@ -1886,7 +1886,7 @@ fn item_fields(
 ) {
     let mut fields = fields
         .iter()
-        .filter_map(|f| match *f.kind {
+        .filter_map(|f| match f.kind {
             clean::StructFieldItem(ref ty) => Some((f, ty)),
             _ => None,
         })
@@ -2196,14 +2196,14 @@ fn render_union<'a, 'cx: 'a>(
 
         write!(f, "{{\n")?;
         let count_fields =
-            fields.iter().filter(|field| matches!(*field.kind, clean::StructFieldItem(..))).count();
+            fields.iter().filter(|field| matches!(field.kind, clean::StructFieldItem(..))).count();
         let toggle = should_hide_fields(count_fields);
         if toggle {
             toggle_open(&mut f, format_args!("{count_fields} fields"));
         }
 
         for field in fields {
-            if let clean::StructFieldItem(ref ty) = *field.kind {
+            if let clean::StructFieldItem(ref ty) = field.kind {
                 write!(
                     f,
                     "    {}{}: {},\n",
@@ -2279,14 +2279,14 @@ fn render_struct_fields(
                 w.write_str("{");
             }
             let count_fields =
-                fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count();
+                fields.iter().filter(|f| matches!(f.kind, clean::StructFieldItem(..))).count();
             let has_visible_fields = count_fields > 0;
             let toggle = should_hide_fields(count_fields);
             if toggle {
                 toggle_open(&mut w, format_args!("{count_fields} fields"));
             }
             for field in fields {
-                if let clean::StructFieldItem(ref ty) = *field.kind {
+                if let clean::StructFieldItem(ref ty) = field.kind {
                     write!(
                         w,
                         "\n{tab}    {vis}{name}: {ty},",
@@ -2314,7 +2314,7 @@ fn render_struct_fields(
             w.write_str("(");
             if !fields.is_empty()
                 && fields.iter().all(|field| {
-                    matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))
+                    matches!(field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))
                 })
             {
                 write!(w, "<span class=\"comment\">/* private fields */</span>");
@@ -2323,7 +2323,7 @@ fn render_struct_fields(
                     if i > 0 {
                         w.write_str(", ");
                     }
-                    match *field.kind {
+                    match field.kind {
                         clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"),
                         clean::StructFieldItem(ref ty) => {
                             write!(w, "{}{}", visibility_print_with_space(field, cx), ty.print(cx),)
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index bfdf457..b84c22a 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -758,7 +758,7 @@ pub(crate) fn get_function_type_for_search<'tcx>(
             None
         }
     });
-    let (mut inputs, mut output, where_clause) = match *item.kind {
+    let (mut inputs, mut output, where_clause) = match item.kind {
         clean::FunctionItem(ref f) | clean::MethodItem(ref f, _) | clean::TyMethodItem(ref f) => {
             get_fn_inputs_and_outputs(f, tcx, impl_or_trait_generics, cache)
         }
@@ -1132,7 +1132,7 @@ fn simplify_fn_type<'tcx, 'a>(
                 && trait_.items.iter().any(|at| at.is_ty_associated_type())
             {
                 for assoc_ty in &trait_.items {
-                    if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &*assoc_ty.kind
+                    if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &assoc_ty.kind
                         && let Some(name) = assoc_ty.name
                     {
                         let idx = -isize::try_from(rgen.len() + 1).unwrap();
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index c75c28e..842ee81 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -119,7 +119,7 @@ pub(crate) fn wrapped<T>(v: T) -> rinja::Result<Safe<impl Display>>
 pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
     let mut ids = IdMap::new();
     let mut blocks: Vec<LinkBlock<'_>> = docblock_toc(cx, it, &mut ids).into_iter().collect();
-    match *it.kind {
+    match it.kind {
         clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks),
         clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks),
         clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks),
@@ -143,7 +143,7 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf
     // crate title is displayed as part of logo lockup
     let (title_prefix, title) = if !blocks.is_empty() && !it.is_crate() {
         (
-            match *it.kind {
+            match it.kind {
                 clean::ModuleItem(..) => "Module ",
                 _ => "",
             },
@@ -181,7 +181,7 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf
 fn get_struct_fields_name<'a>(fields: &'a [clean::Item]) -> Vec<Link<'a>> {
     let mut fields = fields
         .iter()
-        .filter(|f| matches!(*f.kind, clean::StructFieldItem(..)))
+        .filter(|f| matches!(f.kind, clean::StructFieldItem(..)))
         .filter_map(|f| {
             f.name.as_ref().map(|name| Link::new(format!("structfield.{name}"), name.as_str()))
         })
@@ -302,10 +302,10 @@ fn filter_items<'a>(
 
     blocks.extend(
         [
-            ("required-associated-types", "Required Associated Types", req_assoc),
-            ("provided-associated-types", "Provided Associated Types", prov_assoc),
             ("required-associated-consts", "Required Associated Constants", req_assoc_const),
             ("provided-associated-consts", "Provided Associated Constants", prov_assoc_const),
+            ("required-associated-types", "Required Associated Types", req_assoc),
+            ("provided-associated-types", "Provided Associated Types", prov_assoc),
             ("required-methods", "Required Methods", req_method),
             ("provided-methods", "Provided Methods", prov_method),
             ("foreign-impls", "Implementations on Foreign Types", foreign_impls),
@@ -394,6 +394,7 @@ fn sidebar_assoc_items<'a>(
     let cache = cx.cache();
 
     let mut assoc_consts = Vec::new();
+    let mut assoc_types = Vec::new();
     let mut methods = Vec::new();
     if let Some(v) = cache.impls.get(&did) {
         let mut used_links = FxHashSet::default();
@@ -401,22 +402,14 @@ fn sidebar_assoc_items<'a>(
 
         {
             let used_links_bor = &mut used_links;
-            assoc_consts.extend(
-                v.iter()
-                    .filter(|i| i.inner_impl().trait_.is_none())
-                    .flat_map(|i| get_associated_constants(i.inner_impl(), used_links_bor)),
-            );
+            for impl_ in v.iter().map(|i| i.inner_impl()).filter(|i| i.trait_.is_none()) {
+                assoc_consts.extend(get_associated_constants(impl_, used_links_bor));
+                assoc_types.extend(get_associated_types(impl_, used_links_bor));
+                methods.extend(get_methods(impl_, false, used_links_bor, false, cx.tcx()));
+            }
             // We want links' order to be reproducible so we don't use unstable sort.
             assoc_consts.sort();
-
-            #[rustfmt::skip] // rustfmt makes the pipeline less readable
-            methods.extend(
-                v.iter()
-                    .filter(|i| i.inner_impl().trait_.is_none())
-                    .flat_map(|i| get_methods(i.inner_impl(), false, used_links_bor, false, cx.tcx())),
-            );
-
-            // We want links' order to be reproducible so we don't use unstable sort.
+            assoc_types.sort();
             methods.sort();
         }
 
@@ -426,6 +419,11 @@ fn sidebar_assoc_items<'a>(
                 "associatedconstant",
                 assoc_consts,
             ),
+            LinkBlock::new(
+                Link::new("implementations", "Associated Types"),
+                "associatedtype",
+                assoc_types,
+            ),
             LinkBlock::new(Link::new("implementations", "Methods"), "method", methods),
         ];
 
@@ -452,6 +450,7 @@ fn sidebar_assoc_items<'a>(
                 &mut blocks,
             );
         }
+
         links.append(&mut blocks);
     }
 }
@@ -468,7 +467,7 @@ fn sidebar_deref_methods<'a>(
 
     debug!("found Deref: {impl_:?}");
     if let Some((target, real_target)) =
-        impl_.inner_impl().items.iter().find_map(|item| match *item.kind {
+        impl_.inner_impl().items.iter().find_map(|item| match item.kind {
             clean::AssocTypeItem(box ref t, _) => Some(match *t {
                 clean::TypeAlias { item_type: Some(ref type_), .. } => (type_, &t.type_),
                 _ => (&t.type_, &t.type_),
@@ -588,7 +587,7 @@ fn sidebar_module(
                 && it
                     .name
                     .or_else(|| {
-                        if let clean::ImportItem(ref i) = *it.kind
+                        if let clean::ImportItem(ref i) = it.kind
                             && let clean::ImportKind::Simple(s) = i.kind
                         {
                             Some(s)
@@ -715,3 +714,19 @@ fn get_associated_constants<'a>(
         })
         .collect::<Vec<_>>()
 }
+
+fn get_associated_types<'a>(
+    i: &'a clean::Impl,
+    used_links: &mut FxHashSet<String>,
+) -> Vec<Link<'a>> {
+    i.items
+        .iter()
+        .filter_map(|item| match item.name {
+            Some(ref name) if !name.is_empty() && item.is_associated_type() => Some(Link::new(
+                get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocType)),
+                name.as_str(),
+            )),
+            _ => None,
+        })
+        .collect::<Vec<_>>()
+}
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 60dc142..dc1a8cc 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -29,7 +29,7 @@
 use regex::Regex;
 use rustc_data_structures::flock;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::DefId;
 use rustc_span::Symbol;
@@ -39,7 +39,7 @@
 
 use super::{collect_paths_for_type, ensure_trailing_slash, Context, RenderMode};
 use crate::clean::{Crate, Item, ItemId, ItemKind};
-use crate::config::{EmitType, RenderOptions};
+use crate::config::{EmitType, PathToParts, RenderOptions, ShouldMerge};
 use crate::docfs::PathError;
 use crate::error::Error;
 use crate::formats::cache::Cache;
@@ -50,12 +50,11 @@
 use crate::html::render::ordered_json::{EscapedJson, OrderedJson};
 use crate::html::render::search_index::{build_index, SerializedSearchIndex};
 use crate::html::render::sorted_template::{self, FileFormat, SortedTemplate};
-use crate::html::render::{AssocItemLink, ImplRenderingParameters};
+use crate::html::render::{AssocItemLink, ImplRenderingParameters, StylePath};
 use crate::html::static_files::{self, suffix_path};
 use crate::visit::DocVisitor;
 use crate::{try_err, try_none};
 
-/// Write cross-crate information files, static files, invocation-specific files, etc. to disk
 pub(crate) fn write_shared(
     cx: &mut Context<'_>,
     krate: &Crate,
@@ -70,13 +69,14 @@ pub(crate) fn write_shared(
 
     let SerializedSearchIndex { index, desc } =
         build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx);
-    write_search_desc(cx, &krate, &desc)?; // does not need to be merged; written unconditionally
+    write_search_desc(cx, &krate, &desc)?; // does not need to be merged
 
     let crate_name = krate.name(cx.tcx());
     let crate_name = crate_name.as_str(); // rand
     let crate_name_json = OrderedJson::serialize(crate_name).unwrap(); // "rand"
     let external_crates = hack_get_external_crate_names(&cx.dst, &cx.shared.resource_suffix)?;
     let info = CrateInfo {
+        version: CrateInfoVersion::V1,
         src_files_js: SourcesPart::get(cx, &crate_name_json)?,
         search_index_js: SearchIndexPart::get(index, &cx.shared.resource_suffix)?,
         all_crates: AllCratesPart::get(crate_name_json.clone(), &cx.shared.resource_suffix)?,
@@ -85,47 +85,103 @@ pub(crate) fn write_shared(
         type_impl: TypeAliasPart::get(cx, krate, &crate_name_json)?,
     };
 
-    let crates = vec![info]; // we have info from just one crate. rest will found in out dir
-
-    write_static_files(cx, &opt)?;
-    let dst = &cx.dst;
-    if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) {
-        if cx.include_sources {
-            write_rendered_cci::<SourcesPart, _>(SourcesPart::blank, dst, &crates)?;
-        }
-        write_rendered_cci::<SearchIndexPart, _>(SearchIndexPart::blank, dst, &crates)?;
-        write_rendered_cci::<AllCratesPart, _>(AllCratesPart::blank, dst, &crates)?;
+    if let Some(parts_out_dir) = &opt.parts_out_dir {
+        create_parents(&parts_out_dir.0)?;
+        try_err!(
+            fs::write(&parts_out_dir.0, serde_json::to_string(&info).unwrap()),
+            &parts_out_dir.0
+        );
     }
-    write_rendered_cci::<TraitAliasPart, _>(TraitAliasPart::blank, dst, &crates)?;
-    write_rendered_cci::<TypeAliasPart, _>(TypeAliasPart::blank, dst, &crates)?;
-    match &opt.index_page {
-        Some(index_page) if opt.enable_index_page => {
-            let mut md_opts = opt.clone();
-            md_opts.output = cx.dst.clone();
-            md_opts.external_html = cx.shared.layout.external_html.clone();
-            try_err!(
-                crate::markdown::render(&index_page, md_opts, cx.shared.edition()),
-                &index_page
-            );
+
+    let mut crates = CrateInfo::read_many(&opt.include_parts_dir)?;
+    crates.push(info);
+
+    if opt.should_merge.write_rendered_cci {
+        write_not_crate_specific(
+            &crates,
+            &cx.dst,
+            opt,
+            &cx.shared.style_files,
+            cx.shared.layout.css_file_extension.as_deref(),
+            &cx.shared.resource_suffix,
+            cx.include_sources,
+        )?;
+        match &opt.index_page {
+            Some(index_page) if opt.enable_index_page => {
+                let mut md_opts = opt.clone();
+                md_opts.output = cx.dst.clone();
+                md_opts.external_html = cx.shared.layout.external_html.clone();
+                try_err!(
+                    crate::markdown::render(&index_page, md_opts, cx.shared.edition()),
+                    &index_page
+                );
+            }
+            None if opt.enable_index_page => {
+                write_rendered_cci::<CratesIndexPart, _>(
+                    || CratesIndexPart::blank(cx),
+                    &cx.dst,
+                    &crates,
+                    &opt.should_merge,
+                )?;
+            }
+            _ => {} // they don't want an index page
         }
-        None if opt.enable_index_page => {
-            write_rendered_cci::<CratesIndexPart, _>(|| CratesIndexPart::blank(cx), dst, &crates)?;
-        }
-        _ => {} // they don't want an index page
     }
 
     Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false);
     Ok(())
 }
 
-/// Writes the static files, the style files, and the css extensions
-fn write_static_files(cx: &mut Context<'_>, options: &RenderOptions) -> Result<(), Error> {
-    let static_dir = cx.dst.join("static.files");
+/// Writes files that are written directly to the `--out-dir`, without the prefix from the current
+/// crate. These are the rendered cross-crate files that encode info from multiple crates (e.g.
+/// search index), and the static files.
+pub(crate) fn write_not_crate_specific(
+    crates: &[CrateInfo],
+    dst: &Path,
+    opt: &RenderOptions,
+    style_files: &[StylePath],
+    css_file_extension: Option<&Path>,
+    resource_suffix: &str,
+    include_sources: bool,
+) -> Result<(), Error> {
+    write_rendered_cross_crate_info(crates, dst, opt, include_sources)?;
+    write_static_files(dst, opt, style_files, css_file_extension, resource_suffix)?;
+    Ok(())
+}
 
-    cx.shared.fs.create_dir_all(&static_dir).map_err(|e| PathError::new(e, "static.files"))?;
+fn write_rendered_cross_crate_info(
+    crates: &[CrateInfo],
+    dst: &Path,
+    opt: &RenderOptions,
+    include_sources: bool,
+) -> Result<(), Error> {
+    let m = &opt.should_merge;
+    if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) {
+        if include_sources {
+            write_rendered_cci::<SourcesPart, _>(SourcesPart::blank, dst, &crates, m)?;
+        }
+        write_rendered_cci::<SearchIndexPart, _>(SearchIndexPart::blank, dst, &crates, m)?;
+        write_rendered_cci::<AllCratesPart, _>(AllCratesPart::blank, dst, &crates, m)?;
+    }
+    write_rendered_cci::<TraitAliasPart, _>(TraitAliasPart::blank, dst, &crates, m)?;
+    write_rendered_cci::<TypeAliasPart, _>(TypeAliasPart::blank, dst, &crates, m)?;
+    Ok(())
+}
+
+/// Writes the static files, the style files, and the css extensions.
+/// Have to be careful about these, because they write to the root out dir.
+fn write_static_files(
+    dst: &Path,
+    opt: &RenderOptions,
+    style_files: &[StylePath],
+    css_file_extension: Option<&Path>,
+    resource_suffix: &str,
+) -> Result<(), Error> {
+    let static_dir = dst.join("static.files");
+    try_err!(fs::create_dir_all(&static_dir), &static_dir);
 
     // Handle added third-party themes
-    for entry in &cx.shared.style_files {
+    for entry in style_files {
         let theme = entry.basename()?;
         let extension =
             try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path);
@@ -136,22 +192,24 @@ fn write_static_files(cx: &mut Context<'_>, options: &RenderOptions) -> Result<(
         }
 
         let bytes = try_err!(fs::read(&entry.path), &entry.path);
-        let filename = format!("{theme}{suffix}.{extension}", suffix = cx.shared.resource_suffix);
-        cx.shared.fs.write(cx.dst.join(filename), bytes)?;
+        let filename = format!("{theme}{resource_suffix}.{extension}");
+        let dst_filename = dst.join(filename);
+        try_err!(fs::write(&dst_filename, bytes), &dst_filename);
     }
 
     // When the user adds their own CSS files with --extend-css, we write that as an
     // invocation-specific file (that is, with a resource suffix).
-    if let Some(ref css) = cx.shared.layout.css_file_extension {
+    if let Some(css) = css_file_extension {
         let buffer = try_err!(fs::read_to_string(css), css);
-        let path = static_files::suffix_path("theme.css", &cx.shared.resource_suffix);
-        cx.shared.fs.write(cx.dst.join(path), buffer)?;
+        let path = static_files::suffix_path("theme.css", resource_suffix);
+        let dst_path = dst.join(path);
+        try_err!(fs::write(&dst_path, buffer), &dst_path);
     }
 
-    if options.emit.is_empty() || options.emit.contains(&EmitType::Toolchain) {
+    if opt.emit.is_empty() || opt.emit.contains(&EmitType::Toolchain) {
         static_files::for_each(|f: &static_files::StaticFile| {
             let filename = static_dir.join(f.output_filename());
-            cx.shared.fs.write(filename, f.minified())
+            fs::write(&filename, f.minified()).map_err(|e| PathError::new(e, &filename))
         })?;
     }
 
@@ -186,7 +244,8 @@ fn write_search_desc(
 
 /// Contains pre-rendered contents to insert into the CCI template
 #[derive(Serialize, Deserialize, Clone, Debug)]
-struct CrateInfo {
+pub(crate) struct CrateInfo {
+    version: CrateInfoVersion,
     src_files_js: PartsAndLocations<SourcesPart>,
     search_index_js: PartsAndLocations<SearchIndexPart>,
     all_crates: PartsAndLocations<AllCratesPart>,
@@ -195,6 +254,33 @@ struct CrateInfo {
     type_impl: PartsAndLocations<TypeAliasPart>,
 }
 
+impl CrateInfo {
+    /// Read all of the crate info from its location on the filesystem
+    pub(crate) fn read_many(parts_paths: &[PathToParts]) -> Result<Vec<Self>, Error> {
+        parts_paths
+            .iter()
+            .map(|parts_path| {
+                let path = &parts_path.0;
+                let parts = try_err!(fs::read(&path), &path);
+                let parts: CrateInfo = try_err!(serde_json::from_slice(&parts), &path);
+                Ok::<_, Error>(parts)
+            })
+            .collect::<Result<Vec<CrateInfo>, Error>>()
+    }
+}
+
+/// Version for the format of the crate-info file.
+///
+/// This enum should only ever have one variant, representing the current version.
+/// Gives pretty good error message about expecting the current version on deserialize.
+///
+/// Must be incremented (V2, V3, etc.) upon any changes to the search index or CrateInfo,
+/// to provide better diagnostics about including an invalid file.
+#[derive(Serialize, Deserialize, Clone, Debug)]
+enum CrateInfoVersion {
+    V1,
+}
+
 /// Paths (relative to the doc root) and their pre-merge contents
 #[derive(Serialize, Deserialize, Debug, Clone)]
 #[serde(transparent)]
@@ -783,7 +869,7 @@ impl<'cx, 'cache> DocVisitor for TypeImplCollector<'cx, 'cache> {
     fn visit_item(&mut self, it: &Item) {
         self.visit_item_recur(it);
         let cache = self.cache;
-        let ItemKind::TypeAliasItem(ref t) = *it.kind else { return };
+        let ItemKind::TypeAliasItem(ref t) = it.kind else { return };
         let Some(self_did) = it.item_id.as_def_id() else { return };
         if !self.visited_aliases.insert(self_did) {
             return;
@@ -832,7 +918,7 @@ fn visit_item(&mut self, it: &Item) {
             // Be aware of `tests/rustdoc/type-alias/deeply-nested-112515.rs` which might regress.
             let Some(impl_did) = impl_item_id.as_def_id() else { continue };
             let for_ty = self.cx.tcx().type_of(impl_did).skip_binder();
-            let reject_cx = DeepRejectCtxt::new(self.cx.tcx(), TreatParams::AsCandidateKey);
+            let reject_cx = DeepRejectCtxt::relate_infer_infer(self.cx.tcx());
             if !reject_cx.types_may_unify(aliased_ty, for_ty) {
                 continue;
             }
@@ -900,10 +986,14 @@ fn create_parents(path: &Path) -> Result<(), Error> {
 fn read_template_or_blank<F, T: FileFormat>(
     mut make_blank: F,
     path: &Path,
+    should_merge: &ShouldMerge,
 ) -> Result<SortedTemplate<T>, Error>
 where
     F: FnMut() -> SortedTemplate<T>,
 {
+    if !should_merge.read_rendered_cci {
+        return Ok(make_blank());
+    }
     match fs::read_to_string(&path) {
         Ok(template) => Ok(try_err!(SortedTemplate::from_str(&template), &path)),
         Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(make_blank()),
@@ -916,6 +1006,7 @@ fn write_rendered_cci<T: CciPart, F>(
     mut make_blank: F,
     dst: &Path,
     crates_info: &[CrateInfo],
+    should_merge: &ShouldMerge,
 ) -> Result<(), Error>
 where
     F: FnMut() -> SortedTemplate<T::FileFormat>,
@@ -924,7 +1015,8 @@ fn write_rendered_cci<T: CciPart, F>(
     for (path, parts) in get_path_parts::<T>(dst, crates_info) {
         create_parents(&path)?;
         // read previous rendered cci from storage, append to them
-        let mut template = read_template_or_blank::<_, T::FileFormat>(&mut make_blank, &path)?;
+        let mut template =
+            read_template_or_blank::<_, T::FileFormat>(&mut make_blank, &path, should_merge)?;
         for part in parts {
             template.append(part);
         }
diff --git a/src/librustdoc/html/render/write_shared/tests.rs b/src/librustdoc/html/render/write_shared/tests.rs
index e282cd9..a235f1d 100644
--- a/src/librustdoc/html/render/write_shared/tests.rs
+++ b/src/librustdoc/html/render/write_shared/tests.rs
@@ -1,3 +1,4 @@
+use crate::config::ShouldMerge;
 use crate::html::render::ordered_json::{EscapedJson, OrderedJson};
 use crate::html::render::sorted_template::{Html, SortedTemplate};
 use crate::html::render::write_shared::*;
@@ -192,16 +193,17 @@ fn read_template_test() {
     let path = path.path().join("file.html");
     let make_blank = || SortedTemplate::<Html>::from_before_after("<div>", "</div>");
 
-    let template = read_template_or_blank(make_blank, &path).unwrap();
+    let should_merge = ShouldMerge { read_rendered_cci: true, write_rendered_cci: true };
+    let template = read_template_or_blank(make_blank, &path, &should_merge).unwrap();
     assert_eq!(but_last_line(&template.to_string()), "<div></div>");
     fs::write(&path, template.to_string()).unwrap();
-    let mut template = read_template_or_blank(make_blank, &path).unwrap();
+    let mut template = read_template_or_blank(make_blank, &path, &should_merge).unwrap();
     template.append("<img/>".to_string());
     fs::write(&path, template.to_string()).unwrap();
-    let mut template = read_template_or_blank(make_blank, &path).unwrap();
+    let mut template = read_template_or_blank(make_blank, &path, &should_merge).unwrap();
     template.append("<br/>".to_string());
     fs::write(&path, template.to_string()).unwrap();
-    let template = read_template_or_blank(make_blank, &path).unwrap();
+    let template = read_template_or_blank(make_blank, &path, &should_merge).unwrap();
 
     assert_eq!(but_last_line(&template.to_string()), "<div><br/><img/></div>");
 }
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index ae65dd7..551bb56 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -290,9 +290,34 @@ pub(crate) fn clean_path<F, P>(src_root: &Path, p: &Path, mut f: F, mut parent:
     }
 }
 
-pub(crate) enum SourceContext {
+pub(crate) struct ScrapedInfo<'a> {
+    pub(crate) offset: usize,
+    pub(crate) needs_prev_next_buttons: bool,
+    pub(crate) name: &'a str,
+    pub(crate) url: &'a str,
+    pub(crate) title: &'a str,
+    pub(crate) locations: String,
+    pub(crate) needs_expansion: bool,
+}
+
+#[derive(Template)]
+#[template(path = "scraped_source.html")]
+struct ScrapedSource<'a, Code: std::fmt::Display> {
+    info: ScrapedInfo<'a>,
+    lines: RangeInclusive<usize>,
+    code_html: Code,
+}
+
+#[derive(Template)]
+#[template(path = "source.html")]
+struct Source<Code: std::fmt::Display> {
+    lines: RangeInclusive<usize>,
+    code_html: Code,
+}
+
+pub(crate) enum SourceContext<'a> {
     Standalone,
-    Embedded { offset: usize, needs_expansion: bool },
+    Embedded(ScrapedInfo<'a>),
 }
 
 /// Wrapper struct to render the source code of a file. This will do things like
@@ -304,23 +329,8 @@ pub(crate) fn print_src(
     context: &Context<'_>,
     root_path: &str,
     decoration_info: highlight::DecorationInfo,
-    source_context: SourceContext,
+    source_context: SourceContext<'_>,
 ) {
-    #[derive(Template)]
-    #[template(path = "source.html")]
-    struct Source<Code: std::fmt::Display> {
-        embedded: bool,
-        needs_expansion: bool,
-        lines: RangeInclusive<usize>,
-        code_html: Code,
-    }
-    let lines = s.lines().count();
-    let (embedded, needs_expansion, lines) = match source_context {
-        SourceContext::Standalone => (false, false, 1..=lines),
-        SourceContext::Embedded { offset, needs_expansion } => {
-            (true, needs_expansion, (1 + offset)..=(lines + offset))
-        }
-    };
     let current_href = context
         .href_from_span(clean::Span::new(file_span), false)
         .expect("only local crates should have sources emitted");
@@ -333,5 +343,14 @@ struct Source<Code: std::fmt::Display> {
         );
         Ok(())
     });
-    Source { embedded, needs_expansion, lines, code_html: code }.render_into(&mut writer).unwrap();
+    let lines = s.lines().count();
+    match source_context {
+        SourceContext::Standalone => {
+            Source { lines: (1..=lines), code_html: code }.render_into(&mut writer).unwrap()
+        }
+        SourceContext::Embedded(info) => {
+            let lines = (1 + info.offset)..=(lines + info.offset);
+            ScrapedSource { info, lines, code_html: code }.render_into(&mut writer).unwrap();
+        }
+    };
 }
diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css
index 86e8eda..e62b162 100644
--- a/src/librustdoc/html/static/css/noscript.css
+++ b/src/librustdoc/html/static/css/noscript.css
@@ -59,6 +59,8 @@
 	--copy-path-button-color: #999;
 	--copy-path-img-filter: invert(50%);
 	--copy-path-img-hover-filter: invert(35%);
+	--code-example-button-color: #7f7f7f;
+	--code-example-button-hover-color: #595959;
 	--codeblock-error-hover-color: rgb(255, 0, 0);
 	--codeblock-error-color: rgba(255, 0, 0, .5);
 	--codeblock-ignore-hover-color: rgb(255, 142, 0);
@@ -162,6 +164,8 @@
 		--copy-path-button-color: #999;
 		--copy-path-img-filter: invert(50%);
 		--copy-path-img-hover-filter: invert(65%);
+		--code-example-button-color: #7f7f7f;
+		--code-example-button-hover-color: #a5a5a5;
 		--codeblock-error-hover-color: rgb(255, 0, 0);
 		--codeblock-error-color: rgba(255, 0, 0, .5);
 		--codeblock-ignore-hover-color: rgb(255, 142, 0);
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 271de1b..38154de 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -378,7 +378,7 @@
 .src .content pre {
 	padding: 20px;
 }
-.rustdoc.src .example-wrap pre.src-line-numbers  {
+.rustdoc.src .example-wrap .src-line-numbers  {
 	padding: 20px 0 20px 4px;
 }
 
@@ -757,10 +757,32 @@
 	margin-bottom: 10px;
 }
 
-.rustdoc .example-wrap > pre {
+.rustdoc .example-wrap > pre,
+.rustdoc .scraped-example .src-line-numbers,
+.rustdoc .scraped-example .src-line-numbers > pre {
 	border-radius: 6px;
 }
 
+/*
+If the code example line numbers are displayed, there will be a weird radius in the middle from
+both the code example and the line numbers, so we need to remove the radius in this case.
+*/
+.rustdoc .example-wrap > .example-line-numbers,
+.rustdoc .scraped-example .src-line-numbers,
+.rustdoc .scraped-example .src-line-numbers > pre {
+	border-top-right-radius: 0;
+	border-bottom-right-radius: 0;
+}
+.rustdoc .example-wrap > .example-line-numbers + pre,
+.rustdoc .scraped-example .rust {
+	border-top-left-radius: 0;
+	border-bottom-left-radius: 0;
+}
+
+.rustdoc .scraped-example {
+	position: relative;
+}
+
 /* For the last child of a div, the margin will be taken care of
 	by the margin-top of the next item. */
 .rustdoc .example-wrap:last-child {
@@ -772,15 +794,36 @@
 	flex-grow: 1;
 }
 
-.rustdoc:not(.src) .example-wrap pre {
+.scraped-example:not(.expanded) .example-wrap {
+	/* scrape-examples.js has a constant DEFAULT_MAX_LINES (call it N) for the number
+	 * of lines shown in the un-expanded example code viewer. This pre needs to have
+	 * a max-height equal to line-height * N. The line-height is currently 1.5em,
+	 * and we include additional 10px for padding. */
+	max-height: calc(1.5em * 5 + 10px);
+}
+
+.rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers,
+.rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers > pre,
+.rustdoc:not(.src) .scraped-example:not(.expanded) pre.rust {
+	padding-bottom: 0;
+	/* See above comment, should be the same max-height. */
 	overflow: auto hidden;
 }
+.rustdoc:not(.src) .scraped-example .src-line-numbers {
+	padding-top: 0;
+}
+.rustdoc:not(.src) .scraped-example.expanded .src-line-numbers {
+	padding-bottom: 0;
+}
+
+.rustdoc:not(.src) .example-wrap pre {
+	overflow: auto;
+}
 
 .rustdoc .example-wrap pre.example-line-numbers,
-.rustdoc .example-wrap pre.src-line-numbers {
-	flex-grow: 0;
+.rustdoc .example-wrap .src-line-numbers {
 	min-width: fit-content; /* prevent collapsing into nothing in truncated scraped examples */
-	overflow: initial;
+	flex-grow: 0;
 	text-align: right;
 	-webkit-user-select: none;
 	user-select: none;
@@ -788,7 +831,7 @@
 	color: var(--src-line-numbers-span-color);
 }
 
-.rustdoc .example-wrap pre.src-line-numbers {
+.rustdoc .scraped-example .src-line-numbers {
 	padding: 14px 0;
 }
 .src-line-numbers a, .src-line-numbers span {
@@ -1500,17 +1543,23 @@
 .example-wrap .button-holder.keep-visible {
 	visibility: visible;
 }
-.example-wrap .button-holder .copy-button, .example-wrap .test-arrow {
+.example-wrap .button-holder > * {
 	background: var(--main-background-color);
 	cursor: pointer;
 	border-radius: var(--button-border-radius);
 	height: var(--copy-path-height);
 	width: var(--copy-path-width);
+	border: 0;
+	color: var(--code-example-button-color);
+}
+.example-wrap .button-holder > *:hover {
+	color: var(--code-example-button-hover-color);
+}
+.example-wrap .button-holder > *:not(:first-child) {
+	margin-left: var(--button-left-margin);
 }
 .example-wrap .button-holder .copy-button {
-	margin-left: var(--button-left-margin);
 	padding: 2px 0 0 4px;
-	border: 0;
 }
 .example-wrap .button-holder .copy-button::before,
 .example-wrap .test-arrow::before {
@@ -2254,6 +2303,7 @@
 	}
 }
 
+
 /* Should have min-width: (N + 1)px where N is the mobile breakpoint above. */
 @media (min-width: 701px) {
 	/* Places file-link for a scraped example on top of the example to save space.
@@ -2356,99 +2406,41 @@
 	color: var(--scrape-example-help-hover-color);
 }
 
-.scraped-example {
-	/* So .scraped-example-title can be positioned absolutely */
-	position: relative;
-}
-
-.scraped-example .code-wrapper {
-	position: relative;
-	display: flex;
-	flex-direction: row;
-	flex-wrap: wrap;
-	width: 100%;
-}
-
-.scraped-example:not(.expanded) .code-wrapper {
-	/* scrape-examples.js has a constant DEFAULT_MAX_LINES (call it N) for the number
-	 * of lines shown in the un-expanded example code viewer. This pre needs to have
-	 * a max-height equal to line-height * N. The line-height is currently 1.5em,
-	 * and we include additional 10px for padding. */
-	 max-height: calc(1.5em * 5 + 10px);
-}
-
-.scraped-example:not(.expanded) .code-wrapper pre {
-	overflow-y: hidden;
-	padding-bottom: 0;
-	/* See above comment, should be the same max-height. */
-	max-height: calc(1.5em * 5 + 10px);
-}
-
-.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper,
-.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper pre {
-	/* See above comment, except this height is based on HIDDEN_MAX_LINES. */
-	max-height: calc(1.5em * 10 + 10px);
-}
-
-.scraped-example .code-wrapper .next,
-.scraped-example .code-wrapper .prev,
-.scraped-example .code-wrapper .expand {
-	color: var(--main-color);
-	position: absolute;
-	top: 0.25em;
-	z-index: 1;
-	padding: 0;
-	background: none;
-	border: none;
-	/* iOS button gradient: https://stackoverflow.com/q/5438567 */
-	-webkit-appearance: none;
-	opacity: 1;
-}
-.scraped-example .code-wrapper .prev {
-	right: 2.25em;
-}
-.scraped-example .code-wrapper .next {
-	right: 1.25em;
-}
-.scraped-example .code-wrapper .expand {
-	right: 0.25em;
-}
-
-.scraped-example:not(.expanded) .code-wrapper::before,
-.scraped-example:not(.expanded) .code-wrapper::after {
+.scraped-example:not(.expanded) .example-wrap::before,
+.scraped-example:not(.expanded) .example-wrap::after {
 	content: " ";
 	width: 100%;
 	height: 5px;
 	position: absolute;
 	z-index: 1;
 }
-.scraped-example:not(.expanded) .code-wrapper::before {
+.scraped-example:not(.expanded) .example-wrap::before {
 	top: 0;
 	background: linear-gradient(to bottom,
 		var(--scrape-example-code-wrapper-background-start),
 		var(--scrape-example-code-wrapper-background-end));
 }
-.scraped-example:not(.expanded) .code-wrapper::after {
+.scraped-example:not(.expanded) .example-wrap::after {
 	bottom: 0;
 	background: linear-gradient(to top,
 		var(--scrape-example-code-wrapper-background-start),
 		var(--scrape-example-code-wrapper-background-end));
 }
 
-.scraped-example .code-wrapper .example-wrap {
+.scraped-example:not(.expanded) {
 	width: 100%;
 	overflow-y: hidden;
 	margin-bottom: 0;
 }
 
-.scraped-example:not(.expanded) .code-wrapper .example-wrap {
+.scraped-example:not(.expanded) {
 	overflow-x: hidden;
 }
 
-.scraped-example .example-wrap .rust span.highlight {
+.scraped-example .rust span.highlight {
 	background: var(--scrape-example-code-line-highlight);
 }
-.scraped-example .example-wrap .rust span.highlight.focus {
+.scraped-example .rust span.highlight.focus {
 	background: var(--scrape-example-code-line-highlight-focus);
 }
 
@@ -2542,6 +2534,8 @@
 	--copy-path-button-color: #999;
 	--copy-path-img-filter: invert(50%);
 	--copy-path-img-hover-filter: invert(35%);
+	--code-example-button-color: #7f7f7f;
+	--code-example-button-hover-color: #595959;
 	--codeblock-error-hover-color: rgb(255, 0, 0);
 	--codeblock-error-color: rgba(255, 0, 0, .5);
 	--codeblock-ignore-hover-color: rgb(255, 142, 0);
@@ -2644,6 +2638,8 @@
 	--copy-path-button-color: #999;
 	--copy-path-img-filter: invert(50%);
 	--copy-path-img-hover-filter: invert(65%);
+	--code-example-button-color: #7f7f7f;
+	--code-example-button-hover-color: #a5a5a5;
 	--codeblock-error-hover-color: rgb(255, 0, 0);
 	--codeblock-error-color: rgba(255, 0, 0, .5);
 	--codeblock-ignore-hover-color: rgb(255, 142, 0);
@@ -2753,6 +2749,8 @@
 	--copy-path-button-color: #fff;
 	--copy-path-img-filter: invert(70%);
 	--copy-path-img-hover-filter: invert(100%);
+	--code-example-button-color: #b2b2b2;
+	--code-example-button-hover-color: #fff;
 	--codeblock-error-hover-color: rgb(255, 0, 0);
 	--codeblock-error-color: rgba(255, 0, 0, .5);
 	--codeblock-ignore-hover-color: rgb(255, 142, 0);
diff --git a/src/librustdoc/html/static/js/externs.js b/src/librustdoc/html/static/js/externs.js
index 6fd60d6..3d3e0a8 100644
--- a/src/librustdoc/html/static/js/externs.js
+++ b/src/librustdoc/html/static/js/externs.js
@@ -41,6 +41,7 @@
  *     foundElems: number,
  *     totalElems: number,
  *     literalSearch: boolean,
+ *     hasReturnArrow: boolean,
  *     corrections: Array<{from: string, to: integer}> | null,
  *     typeFingerprint: Uint32Array,
  *     error: Array<string> | null,
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 0291b6e..858753a 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -1855,8 +1855,13 @@
         // Since the button will be added, no need to keep this listener around.
         elem.removeEventListener("mouseover", addCopyButton);
 
-        const parent = document.createElement("div");
-        parent.className = "button-holder";
+        // If this is a scrapped example, there will already be a "button-holder" element.
+        let parent = elem.querySelector(".button-holder");
+        if (!parent) {
+            parent = document.createElement("div");
+            parent.className = "button-holder";
+        }
+
         const runButton = elem.querySelector(".test-arrow");
         if (runButton !== null) {
             // If there is a run button, we move it into the same div.
diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js
index 7a3a9c5..06e4281 100644
--- a/src/librustdoc/html/static/js/scrape-examples.js
+++ b/src/librustdoc/html/static/js/scrape-examples.js
@@ -13,7 +13,7 @@
 
     // Scroll code block to the given code location
     function scrollToLoc(elt, loc, isHidden) {
-        const lines = elt.querySelector(".src-line-numbers");
+        const lines = elt.querySelector(".src-line-numbers > pre");
         let scrollOffset;
 
         // If the block is greater than the size of the viewer,
@@ -24,8 +24,7 @@
             const line = Math.max(0, loc[0] - 1);
             scrollOffset = lines.children[line].offsetTop;
         } else {
-            const wrapper = elt.querySelector(".code-wrapper");
-            const halfHeight = wrapper.offsetHeight / 2;
+            const halfHeight = elt.offsetHeight / 2;
             const offsetTop = lines.children[loc[0]].offsetTop;
             const lastLine = lines.children[loc[1]];
             const offsetBot = lastLine.offsetTop + lastLine.offsetHeight;
@@ -33,7 +32,7 @@
             scrollOffset = offsetMid - halfHeight;
         }
 
-        lines.scrollTo(0, scrollOffset);
+        lines.parentElement.scrollTo(0, scrollOffset);
         elt.querySelector(".rust").scrollTo(0, scrollOffset);
     }
 
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 6f575e6..4da0bbc 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -657,7 +657,7 @@
     }
     const typeFilter = parserState.typeFilter;
     parserState.typeFilter = null;
-    if (name === "!") {
+    if (name.trim() === "!") {
         if (typeFilter !== null && typeFilter !== "primitive") {
             throw [
                 "Invalid search type: primitive never type ",
@@ -1795,6 +1795,7 @@
                 // Total number of elements (includes generics).
                 totalElems: 0,
                 literalSearch: false,
+                hasReturnArrow: false,
                 error: null,
                 correction: null,
                 proposeCorrectionFrom: null,
@@ -1823,6 +1824,7 @@
                         continue;
                     } else if (c === "-" || c === ">") {
                         if (isReturnArrow(parserState)) {
+                            query.hasReturnArrow = true;
                             break;
                         }
                         throw ["Unexpected ", c, " (did you mean ", "->", "?)"];
@@ -1889,9 +1891,7 @@
                     // Get returned elements.
                     getItemsBefore(query, parserState, query.returned, "");
                     // Nothing can come afterward!
-                    if (query.returned.length === 0) {
-                        throw ["Expected at least one item after ", "->"];
-                    }
+                    query.hasReturnArrow = true;
                     break;
                 } else {
                     parserState.pos += 1;
@@ -3249,7 +3249,7 @@
                 this.buildFunctionTypeFingerprint(elem, parsedQuery.typeFingerprint, fps);
             }
 
-            if (parsedQuery.foundElems === 1 && parsedQuery.returned.length === 0) {
+            if (parsedQuery.foundElems === 1 && !parsedQuery.hasReturnArrow) {
                 if (parsedQuery.elems.length === 1) {
                     const elem = parsedQuery.elems[0];
                     const length = this.searchIndex.length;
diff --git a/src/librustdoc/html/templates/scraped_source.html b/src/librustdoc/html/templates/scraped_source.html
new file mode 100644
index 0000000..e1fc2e6
--- /dev/null
+++ b/src/librustdoc/html/templates/scraped_source.html
@@ -0,0 +1,33 @@
+<div class="scraped-example{% if !info.needs_expansion +%} expanded{% endif %}" data-locs="{{info.locations}}"> {# #}
+    <div class="scraped-example-title">
+       {{info.name +}} (<a href="{{info.url}}">{{info.title}}</a>) {# #}
+    </div>
+    <div class="example-wrap"> {# #}
+        {# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
+           Do not show "1 2 3 4 5 ..." in web search results. #}
+        <div class="src-line-numbers" data-nosnippet> {# #}
+            <pre>
+                {% for line in lines.clone() %}
+                    {# ~#}
+                    <span>{{line|safe}}</span>
+                {% endfor %}
+            </pre> {# #}
+        </div> {# #}
+        <pre class="rust"> {# #}
+            <code>
+                {{code_html|safe}}
+            </code> {# #}
+        </pre> {# #}
+        {% if info.needs_prev_next_buttons || info.needs_expansion %}
+            <div class="button-holder">
+                {% if info.needs_prev_next_buttons %}
+                    <button class="prev">&pr;</button> {# #}
+                    <button class="next">&sc;</button>
+                {% endif %}
+                {% if info.needs_expansion %}
+                    <button class="expand">&varr;</button>
+                {% endif %}
+            </div>
+        {% endif %}
+    </div> {# #}
+</div> {# #}
diff --git a/src/librustdoc/html/templates/source.html b/src/librustdoc/html/templates/source.html
index 42d0127..60a47f1 100644
--- a/src/librustdoc/html/templates/source.html
+++ b/src/librustdoc/html/templates/source.html
@@ -1,21 +1,15 @@
-<div class="example-wrap"> {# #}
+<div class="example-wrap">
     {# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
        Do not show "1 2 3 4 5 ..." in web search results. #}
     <div data-nosnippet><pre class="src-line-numbers">
         {% for line in lines.clone() %}
-            {% if embedded %}
-                <span>{{line|safe}}</span>
-            {%~ else %}
-                <a href="#{{line|safe}}" id="{{line|safe}}">{{line|safe}}</a>
-            {%~ endif %}
+            {# ~#}
+            <a href="#{{line|safe}}" id="{{line|safe}}">{{line|safe}}</a>
         {% endfor %}
     </pre></div> {# #}
     <pre class="rust"> {# #}
         <code>
-            {% if needs_expansion %}
-                <button class="expand">&varr;</button>
-            {% endif %}
             {{code_html|safe}}
         </code> {# #}
     </pre> {# #}
-</div>
+</div> {# #}
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index b97d710..82ce619 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -49,7 +49,7 @@ pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
         let visibility = item.visibility(self.tcx);
         let clean::Item { name, item_id, .. } = item;
         let id = id_from_item(&item, self.tcx);
-        let inner = match *item.kind {
+        let inner = match item.kind {
             clean::KeywordItem => return None,
             clean::StrippedItem(ref inner) => {
                 match &**inner {
@@ -156,7 +156,7 @@ fn from_tcx(args: clean::GenericArgs, tcx: TyCtxt<'_>) -> Self {
         match args {
             AngleBracketed { args, constraints } => GenericArgs::AngleBracketed {
                 args: args.into_vec().into_tcx(tcx),
-                bindings: constraints.into_tcx(tcx),
+                constraints: constraints.into_tcx(tcx),
             },
             Parenthesized { inputs, output } => GenericArgs::Parenthesized {
                 inputs: inputs.into_vec().into_tcx(tcx),
@@ -198,9 +198,9 @@ fn from_tcx(constant: clean::ConstantKind, tcx: TyCtxt<'_>) -> Self {
     }
 }
 
-impl FromWithTcx<clean::AssocItemConstraint> for TypeBinding {
+impl FromWithTcx<clean::AssocItemConstraint> for AssocItemConstraint {
     fn from_tcx(constraint: clean::AssocItemConstraint, tcx: TyCtxt<'_>) -> Self {
-        TypeBinding {
+        AssocItemConstraint {
             name: constraint.assoc.name.to_string(),
             args: constraint.assoc.args.into_tcx(tcx),
             binding: constraint.kind.into_tcx(tcx),
@@ -208,12 +208,12 @@ fn from_tcx(constraint: clean::AssocItemConstraint, tcx: TyCtxt<'_>) -> Self {
     }
 }
 
-impl FromWithTcx<clean::AssocItemConstraintKind> for TypeBindingKind {
+impl FromWithTcx<clean::AssocItemConstraintKind> for AssocItemConstraintKind {
     fn from_tcx(kind: clean::AssocItemConstraintKind, tcx: TyCtxt<'_>) -> Self {
         use clean::AssocItemConstraintKind::*;
         match kind {
-            Equality { term } => TypeBindingKind::Equality(term.into_tcx(tcx)),
-            Bound { bounds } => TypeBindingKind::Constraint(bounds.into_tcx(tcx)),
+            Equality { term } => AssocItemConstraintKind::Equality(term.into_tcx(tcx)),
+            Bound { bounds } => AssocItemConstraintKind::Constraint(bounds.into_tcx(tcx)),
         }
     }
 }
@@ -294,7 +294,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 pub(crate) fn id_from_item(item: &clean::Item, tcx: TyCtxt<'_>) -> Id {
-    match *item.kind {
+    match item.kind {
         clean::ItemKind::ImportItem(ref import) => {
             let extra =
                 import.source.did.map(ItemId::from).map(|i| id_from_item_inner(i, tcx, None, None));
@@ -310,11 +310,11 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
     let is_crate = item.is_crate();
     let header = item.fn_header(tcx);
 
-    match *item.kind {
+    match item.inner.kind {
         ModuleItem(m) => {
             ItemEnum::Module(Module { is_crate, items: ids(m.items, tcx), is_stripped: false })
         }
-        ImportItem(i) => ItemEnum::Import(i.into_tcx(tcx)),
+        ImportItem(i) => ItemEnum::Use(i.into_tcx(tcx)),
         StructItem(s) => ItemEnum::Struct(s.into_tcx(tcx)),
         UnionItem(u) => ItemEnum::Union(u.into_tcx(tcx)),
         StructFieldItem(f) => ItemEnum::StructField(f.into_tcx(tcx)),
@@ -331,7 +331,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
         ImplItem(i) => ItemEnum::Impl((*i).into_tcx(tcx)),
         StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
         ForeignStaticItem(s, _) => ItemEnum::Static(s.into_tcx(tcx)),
-        ForeignTypeItem => ItemEnum::ForeignType,
+        ForeignTypeItem => ItemEnum::ExternType,
         TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)),
         // FIXME(generic_const_items): Add support for generic free consts
         ConstantItem(ci) => {
@@ -347,21 +347,19 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
         }
         // FIXME(generic_const_items): Add support for generic associated consts.
         TyAssocConstItem(_generics, ty) => {
-            ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), default: None }
+            ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), value: None }
         }
         // FIXME(generic_const_items): Add support for generic associated consts.
         AssocConstItem(ci) => {
-            ItemEnum::AssocConst { type_: ci.type_.into_tcx(tcx), default: Some(ci.kind.expr(tcx)) }
+            ItemEnum::AssocConst { type_: ci.type_.into_tcx(tcx), value: Some(ci.kind.expr(tcx)) }
         }
-        TyAssocTypeItem(g, b) => ItemEnum::AssocType {
-            generics: g.into_tcx(tcx),
-            bounds: b.into_tcx(tcx),
-            default: None,
-        },
+        TyAssocTypeItem(g, b) => {
+            ItemEnum::AssocType { generics: g.into_tcx(tcx), bounds: b.into_tcx(tcx), type_: None }
+        }
         AssocTypeItem(t, b) => ItemEnum::AssocType {
             generics: t.generics.into_tcx(tcx),
             bounds: b.into_tcx(tcx),
-            default: Some(t.item_type.unwrap_or(t.type_).into_tcx(tcx)),
+            type_: Some(t.item_type.unwrap_or(t.type_).into_tcx(tcx)),
         },
         // `convert_item` early returns `None` for stripped items and keywords.
         KeywordItem => unreachable!(),
@@ -385,7 +383,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
 
 impl FromWithTcx<clean::Struct> for Struct {
     fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
-        let fields_stripped = struct_.has_stripped_entries();
+        let has_stripped_fields = struct_.has_stripped_entries();
         let clean::Struct { ctor_kind, generics, fields } = struct_;
 
         let kind = match ctor_kind {
@@ -394,7 +392,7 @@ fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
                 assert!(fields.is_empty());
                 StructKind::Unit
             }
-            None => StructKind::Plain { fields: ids(fields, tcx), fields_stripped },
+            None => StructKind::Plain { fields: ids(fields, tcx), has_stripped_fields },
         };
 
         Struct {
@@ -407,22 +405,22 @@ fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
 
 impl FromWithTcx<clean::Union> for Union {
     fn from_tcx(union_: clean::Union, tcx: TyCtxt<'_>) -> Self {
-        let fields_stripped = union_.has_stripped_entries();
+        let has_stripped_fields = union_.has_stripped_entries();
         let clean::Union { generics, fields } = union_;
         Union {
             generics: generics.into_tcx(tcx),
-            fields_stripped,
+            has_stripped_fields,
             fields: ids(fields, tcx),
             impls: Vec::new(), // Added in JsonRenderer::item
         }
     }
 }
 
-pub(crate) fn from_fn_header(header: &rustc_hir::FnHeader) -> Header {
-    Header {
-        async_: header.is_async(),
-        const_: header.is_const(),
-        unsafe_: header.is_unsafe(),
+pub(crate) fn from_fn_header(header: &rustc_hir::FnHeader) -> FunctionHeader {
+    FunctionHeader {
+        is_async: header.is_async(),
+        is_const: header.is_const(),
+        is_unsafe: header.is_unsafe(),
         abi: convert_abi(header.abi),
     }
 }
@@ -474,7 +472,7 @@ fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self {
             Type { bounds, default, synthetic } => GenericParamDefKind::Type {
                 bounds: bounds.into_tcx(tcx),
                 default: default.map(|x| (*x).into_tcx(tcx)),
-                synthetic,
+                is_synthetic: synthetic,
             },
             Const { ty, default, synthetic: _ } => GenericParamDefKind::Const {
                 type_: (*ty).into_tcx(tcx),
@@ -508,7 +506,7 @@ fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
                                         .map(|bound| bound.into_tcx(tcx))
                                         .collect(),
                                     default: default.map(|ty| (*ty).into_tcx(tcx)),
-                                    synthetic,
+                                    is_synthetic: synthetic,
                                 }
                             }
                             clean::GenericParamDefKind::Const { ty, default, synthetic: _ } => {
@@ -602,12 +600,12 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
             ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)),
             Infer => Type::Infer,
             RawPointer(mutability, type_) => Type::RawPointer {
-                mutable: mutability == ast::Mutability::Mut,
+                is_mutable: mutability == ast::Mutability::Mut,
                 type_: Box::new((*type_).into_tcx(tcx)),
             },
             BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef {
                 lifetime: lifetime.map(convert_lifetime),
-                mutable: mutability == ast::Mutability::Mut,
+                is_mutable: mutability == ast::Mutability::Mut,
                 type_: Box::new((*type_).into_tcx(tcx)),
             },
             QPath(box clean::QPathData { assoc, self_type, trait_, .. }) => Type::QualifiedPath {
@@ -643,29 +641,29 @@ impl FromWithTcx<clean::BareFunctionDecl> for FunctionPointer {
     fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self {
         let clean::BareFunctionDecl { safety, generic_params, decl, abi } = bare_decl;
         FunctionPointer {
-            header: Header {
-                unsafe_: matches!(safety, rustc_hir::Safety::Unsafe),
-                const_: false,
-                async_: false,
+            header: FunctionHeader {
+                is_unsafe: matches!(safety, rustc_hir::Safety::Unsafe),
+                is_const: false,
+                is_async: false,
                 abi: convert_abi(abi),
             },
             generic_params: generic_params.into_tcx(tcx),
-            decl: decl.into_tcx(tcx),
+            sig: decl.into_tcx(tcx),
         }
     }
 }
 
-impl FromWithTcx<clean::FnDecl> for FnDecl {
+impl FromWithTcx<clean::FnDecl> for FunctionSignature {
     fn from_tcx(decl: clean::FnDecl, tcx: TyCtxt<'_>) -> Self {
         let clean::FnDecl { inputs, output, c_variadic } = decl;
-        FnDecl {
+        FunctionSignature {
             inputs: inputs
                 .values
                 .into_iter()
                 .map(|arg| (arg.name.to_string(), arg.type_.into_tcx(tcx)))
                 .collect(),
             output: if output.is_unit() { None } else { Some(output.into_tcx(tcx)) },
-            c_variadic,
+            is_c_variadic: c_variadic,
         }
     }
 }
@@ -702,12 +700,12 @@ fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
         let provided_trait_methods = impl_.provided_trait_methods(tcx);
         let clean::Impl { safety, generics, trait_, for_, items, polarity, kind } = impl_;
         // FIXME: use something like ImplKind in JSON?
-        let (synthetic, blanket_impl) = match kind {
+        let (is_synthetic, blanket_impl) = match kind {
             clean::ImplKind::Normal | clean::ImplKind::FakeVariadic => (false, None),
             clean::ImplKind::Auto => (true, None),
             clean::ImplKind::Blanket(ty) => (false, Some(*ty)),
         };
-        let negative_polarity = match polarity {
+        let is_negative = match polarity {
             ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => false,
             ty::ImplPolarity::Negative => true,
         };
@@ -721,8 +719,8 @@ fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
             trait_: trait_.map(|path| path.into_tcx(tcx)),
             for_: for_.into_tcx(tcx),
             items: ids(items, tcx),
-            negative: negative_polarity,
-            synthetic,
+            is_negative,
+            is_synthetic,
             blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)),
         }
     }
@@ -736,7 +734,7 @@ pub(crate) fn from_function(
 ) -> Function {
     let clean::Function { decl, generics } = *function;
     Function {
-        decl: decl.into_tcx(tcx),
+        sig: decl.into_tcx(tcx),
         generics: generics.into_tcx(tcx),
         header: from_fn_header(&header),
         has_body,
@@ -745,11 +743,11 @@ pub(crate) fn from_function(
 
 impl FromWithTcx<clean::Enum> for Enum {
     fn from_tcx(enum_: clean::Enum, tcx: TyCtxt<'_>) -> Self {
-        let variants_stripped = enum_.has_stripped_entries();
+        let has_stripped_variants = enum_.has_stripped_entries();
         let clean::Enum { variants, generics } = enum_;
         Enum {
             generics: generics.into_tcx(tcx),
-            variants_stripped,
+            has_stripped_variants,
             variants: ids(variants, tcx),
             impls: Vec::new(), // Added in JsonRenderer::item
         }
@@ -766,7 +764,7 @@ fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
             CLike => VariantKind::Plain,
             Tuple(fields) => VariantKind::Tuple(ids_keeping_stripped(fields, tcx)),
             Struct(s) => VariantKind::Struct {
-                fields_stripped: s.has_stripped_entries(),
+                has_stripped_fields: s.has_stripped_entries(),
                 fields: ids(s.fields, tcx),
             },
         };
@@ -787,21 +785,21 @@ fn from_tcx(disr: clean::Discriminant, tcx: TyCtxt<'_>) -> Self {
     }
 }
 
-impl FromWithTcx<clean::Import> for Import {
+impl FromWithTcx<clean::Import> for Use {
     fn from_tcx(import: clean::Import, tcx: TyCtxt<'_>) -> Self {
         use clean::ImportKind::*;
-        let (name, glob) = match import.kind {
+        let (name, is_glob) = match import.kind {
             Simple(s) => (s.to_string(), false),
             Glob => (
                 import.source.path.last_opt().unwrap_or_else(|| Symbol::intern("*")).to_string(),
                 true,
             ),
         };
-        Import {
+        Use {
             source: import.source.path.whole_name(),
             name,
             id: import.source.did.map(ItemId::from).map(|i| id_from_item_default(i, tcx)),
-            glob,
+            is_glob,
         }
     }
 }
@@ -835,7 +833,7 @@ impl FromWithTcx<clean::Static> for Static {
     fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self {
         Static {
             type_: (*stat.type_).into_tcx(tcx),
-            mutable: stat.mutability == ast::Mutability::Mut,
+            is_mutable: stat.mutability == ast::Mutability::Mut,
             expr: stat
                 .expr
                 .map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e)))
@@ -856,7 +854,7 @@ fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self {
         match kind {
             Module => ItemKind::Module,
             ExternCrate => ItemKind::ExternCrate,
-            Import => ItemKind::Import,
+            Import => ItemKind::Use,
             Struct => ItemKind::Struct,
             Union => ItemKind::Union,
             Enum => ItemKind::Enum,
@@ -872,7 +870,7 @@ fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self {
             Primitive => ItemKind::Primitive,
             AssocConst => ItemKind::AssocConst,
             AssocType => ItemKind::AssocType,
-            ForeignType => ItemKind::ForeignType,
+            ForeignType => ItemKind::ExternType,
             Keyword => ItemKind::Keyword,
             TraitAlias => ItemKind::TraitAlias,
             ProcAttribute => ItemKind::ProcAttribute,
diff --git a/src/librustdoc/json/import_finder.rs b/src/librustdoc/json/import_finder.rs
index 976a7fd..e21fe96 100644
--- a/src/librustdoc/json/import_finder.rs
+++ b/src/librustdoc/json/import_finder.rs
@@ -24,7 +24,7 @@ struct ImportFinder {
 
 impl DocFolder for ImportFinder {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
-        match *i.kind {
+        match i.kind {
             clean::ImportItem(Import { source: ImportSource { did: Some(did), .. }, .. }) => {
                 self.imported.insert(did);
                 Some(i)
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 1b2d61a..f30a34c 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -85,7 +85,7 @@ fn get_impls(&mut self, id: DefId) -> Vec<types::Id> {
                         // document primitive items in an arbitrary crate by using
                         // `rustc_doc_primitive`.
                         let mut is_primitive_impl = false;
-                        if let clean::types::ItemKind::ImplItem(ref impl_) = *item.kind
+                        if let clean::types::ItemKind::ImplItem(ref impl_) = item.kind
                             && impl_.trait_.is_none()
                             && let clean::types::Type::Primitive(_) = impl_.for_
                         {
@@ -164,7 +164,7 @@ fn item(&mut self, item: clean::Item) -> Result<(), Error> {
 
         // Flatten items that recursively store other items. We include orphaned items from
         // stripped modules and etc that are otherwise reachable.
-        if let ItemKind::StrippedItem(inner) = &*item.kind {
+        if let ItemKind::StrippedItem(inner) = &item.kind {
             inner.inner_items().for_each(|i| self.item(i.clone()).unwrap());
         }
 
@@ -197,7 +197,7 @@ fn item(&mut self, item: clean::Item) -> Result<(), Error> {
 
                 types::ItemEnum::Function(_)
                 | types::ItemEnum::Module(_)
-                | types::ItemEnum::Import(_)
+                | types::ItemEnum::Use(_)
                 | types::ItemEnum::AssocConst { .. }
                 | types::ItemEnum::AssocType { .. } => true,
                 types::ItemEnum::ExternCrate { .. }
@@ -208,7 +208,7 @@ fn item(&mut self, item: clean::Item) -> Result<(), Error> {
                 | types::ItemEnum::TypeAlias(_)
                 | types::ItemEnum::Constant { .. }
                 | types::ItemEnum::Static(_)
-                | types::ItemEnum::ForeignType
+                | types::ItemEnum::ExternType
                 | types::ItemEnum::Macro(_)
                 | types::ItemEnum::ProcMacro(_) => false,
             };
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index f25acbe..6649e17 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -603,6 +603,33 @@ fn opts() -> Vec<RustcOptGroup> {
                 "path to function call information (for displaying examples in the documentation)",
             )
         }),
+        unstable("merge", |o| {
+            o.optopt(
+                "",
+                "merge",
+                "Controls how rustdoc handles files from previously documented crates in the doc root
+                      none = Do not write cross-crate information to the --out-dir
+                      shared = Append current crate's info to files found in the --out-dir
+                      finalize = Write current crate's info and --include-parts-dir info to the --out-dir, overwriting conflicting files",
+                "none|shared|finalize",
+            )
+        }),
+        unstable("parts-out-dir", |o| {
+            o.optopt(
+                "",
+                "parts-out-dir",
+                "Writes trait implementations and other info for the current crate to provided path. Only use with --merge=none",
+                "path/to/doc.parts/<crate-name>",
+            )
+        }),
+        unstable("include-parts-dir", |o| {
+            o.optmulti(
+                "",
+                "include-parts-dir",
+                "Includes trait implementations and other crate info from provided path. Only use with --merge=finalize",
+                "path/to/doc.parts/<crate-name>",
+            )
+        }),
         // deprecated / removed options
         unstable("disable-minification", |o| o.optflagmulti("", "disable-minification", "removed")),
         stable("plugin-path", |o| {
@@ -697,6 +724,32 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
     }
 }
 
+/// Renders and writes cross-crate info files, like the search index. This function exists so that
+/// we can run rustdoc without a crate root in the `--merge=finalize` mode. Cross-crate info files
+/// discovered via `--include-parts-dir` are combined and written to the doc root.
+fn run_merge_finalize(opt: config::RenderOptions) -> Result<(), error::Error> {
+    assert!(
+        opt.should_merge.write_rendered_cci,
+        "config.rs only allows us to return InputMode::NoInputMergeFinalize if --merge=finalize"
+    );
+    assert!(
+        !opt.should_merge.read_rendered_cci,
+        "config.rs only allows us to return InputMode::NoInputMergeFinalize if --merge=finalize"
+    );
+    let crates = html::render::CrateInfo::read_many(&opt.include_parts_dir)?;
+    let include_sources = !opt.html_no_source;
+    html::render::write_not_crate_specific(
+        &crates,
+        &opt.output,
+        &opt,
+        &opt.themes,
+        opt.extension_css.as_deref(),
+        &opt.resource_suffix,
+        include_sources,
+    )?;
+    Ok(())
+}
+
 fn main_args(
     early_dcx: &mut EarlyDiagCtxt,
     at_args: &[String],
@@ -727,22 +780,35 @@ fn main_args(
 
     // Note that we discard any distinction between different non-zero exit
     // codes from `from_matches` here.
-    let (options, render_options) = match config::Options::from_matches(early_dcx, &matches, args) {
-        Some(opts) => opts,
-        None => return Ok(()),
-    };
+    let (input, options, render_options) =
+        match config::Options::from_matches(early_dcx, &matches, args) {
+            Some(opts) => opts,
+            None => return Ok(()),
+        };
 
     let dcx =
         core::new_dcx(options.error_format, None, options.diagnostic_width, &options.unstable_opts);
     let dcx = dcx.handle();
 
-    match (options.should_test, options.markdown_input()) {
-        (true, Some(_)) => return wrap_return(dcx, doctest::test_markdown(options)),
-        (true, None) => return doctest::run(dcx, options),
-        (false, Some(input)) => {
-            let input = input.to_owned();
+    let input = match input {
+        config::InputMode::HasFile(input) => input,
+        config::InputMode::NoInputMergeFinalize => {
+            return wrap_return(
+                dcx,
+                run_merge_finalize(render_options)
+                    .map_err(|e| format!("could not write merged cross-crate info: {e}")),
+            );
+        }
+    };
+
+    match (options.should_test, config::markdown_input(&input)) {
+        (true, Some(_)) => return wrap_return(dcx, doctest::test_markdown(&input, options)),
+        (true, None) => return doctest::run(dcx, input, options),
+        (false, Some(md_input)) => {
+            let md_input = md_input.to_owned();
             let edition = options.edition;
-            let config = core::create_config(options, &render_options, using_internal_features);
+            let config =
+                core::create_config(input, options, &render_options, using_internal_features);
 
             // `markdown::render` can invoke `doctest::make_test`, which
             // requires session globals and a thread pool, so we use
@@ -750,7 +816,7 @@ fn main_args(
             return wrap_return(
                 dcx,
                 interface::run_compiler(config, |_compiler| {
-                    markdown::render(&input, render_options, edition)
+                    markdown::render(&md_input, render_options, edition)
                 }),
             );
         }
@@ -775,7 +841,7 @@ fn main_args(
     let scrape_examples_options = options.scrape_examples_options.clone();
     let bin_crate = options.bin_crate;
 
-    let config = core::create_config(options, &render_options, using_internal_features);
+    let config = core::create_config(input, options, &render_options, using_internal_features);
 
     interface::run_compiler(config, |compiler| {
         let sess = &compiler.sess;
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 1d0b41f..7391909 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -195,7 +195,7 @@ fn visit_item(&mut self, i: &clean::Item) {
             return;
         }
 
-        match *i.kind {
+        match i.kind {
             clean::StrippedItem(..) => {
                 // don't count items in stripped modules
                 return;
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index d456e8e..733fd91 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -57,7 +57,7 @@ fn visit_test(&mut self, _: String, config: LangString, _: MdRelLine) {
 pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
     if !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item.item_id.expect_def_id())
         || matches!(
-            *item.kind,
+            item.kind,
             clean::StructFieldItem(_)
                 | clean::VariantItem(_)
                 | clean::AssocConstItem(..)
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 394a64d..a9edc48 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -160,13 +160,13 @@ fn add_deref_target(
 
     // scan through included items ahead of time to splice in Deref targets to the "valid" sets
     for it in new_items_external.iter().chain(new_items_local.iter()) {
-        if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = *it.kind
+        if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = it.kind
             && trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait()
             && cleaner.keep_impl(for_, true)
         {
             let target = items
                 .iter()
-                .find_map(|item| match *item.kind {
+                .find_map(|item| match item.kind {
                     AssocTypeItem(ref t, _) => Some(&t.type_),
                     _ => None,
                 })
@@ -200,7 +200,7 @@ fn add_deref_target(
 
     // Filter out external items that are not needed
     new_items_external.retain(|it| {
-        if let ImplItem(box Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind {
+        if let ImplItem(box Impl { ref for_, ref trait_, ref kind, .. }) = it.kind {
             cleaner.keep_impl(
                 for_,
                 trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait(),
@@ -211,7 +211,7 @@ fn add_deref_target(
         }
     });
 
-    if let ModuleItem(Module { items, .. }) = &mut *krate.module.kind {
+    if let ModuleItem(Module { items, .. }) = &mut krate.module.inner.kind {
         items.extend(synth_impls);
         items.extend(new_items_external);
         items.extend(new_items_local);
@@ -258,7 +258,7 @@ impl<'cache> DocVisitor for ItemAndAliasCollector<'cache> {
     fn visit_item(&mut self, i: &Item) {
         self.items.insert(i.item_id);
 
-        if let TypeAliasItem(alias) = &*i.kind
+        if let TypeAliasItem(alias) = &i.inner.kind
             && let Some(did) = alias.type_.def_id(self.cache)
         {
             self.items.insert(ItemId::DefId(did));
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index 5aa6a5e..6be51dd 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -31,7 +31,7 @@ impl<'a, 'tcx> CfgPropagator<'a, 'tcx> {
     // Some items need to merge their attributes with their parents' otherwise a few of them
     // (mostly `cfg` ones) will be missing.
     fn merge_with_parent_attributes(&mut self, item: &mut Item) {
-        let check_parent = match &*item.kind {
+        let check_parent = match &item.kind {
             // impl blocks can be in different modules with different cfg and we need to get them
             // as well.
             ItemKind::ImplItem(_) => false,
diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs
index e1dd2d3..6078ab3 100644
--- a/src/librustdoc/passes/strip_aliased_non_local.rs
+++ b/src/librustdoc/passes/strip_aliased_non_local.rs
@@ -23,7 +23,7 @@ struct AliasedNonLocalStripper<'tcx> {
 
 impl<'tcx> DocFolder for AliasedNonLocalStripper<'tcx> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
-        Some(match *i.kind {
+        Some(match i.kind {
             clean::TypeAliasItem(..) => {
                 let mut stripper = NonLocalStripper { tcx: self.tcx };
                 // don't call `fold_item` as that could strip the type-alias it-self
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index 86f14dd..7c5fbac9 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -89,7 +89,7 @@ fn recurse_in_impl_or_exported_macro(&mut self, i: Item) -> Item {
 impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         let has_doc_hidden = i.is_doc_hidden();
-        let is_impl_or_exported_macro = match *i.kind {
+        let is_impl_or_exported_macro = match i.kind {
             clean::ImplItem(..) => true,
             // If the macro has the `#[macro_export]` attribute, it means it's accessible at the
             // crate level so it should be handled differently.
@@ -138,7 +138,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
         // module it's defined in. Both of these are marked "stripped," and
         // not included in the final docs, but since they still have an effect
         // on the final doc, cannot be completely removed from the Clean IR.
-        match *i.kind {
+        match i.kind {
             clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => {
                 // We need to recurse into stripped modules to
                 // strip things like impl methods but when doing so
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index 3f706ac..a85428f 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -39,7 +39,7 @@ fn is_item_reachable(
 
 impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
-        match *i.kind {
+        match i.kind {
             clean::StrippedItem(..) => {
                 // We need to recurse into stripped modules to strip things
                 // like impl methods but when doing so we must not add any
@@ -130,7 +130,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             clean::KeywordItem => {}
         }
 
-        let fastreturn = match *i.kind {
+        let fastreturn = match i.kind {
             // nothing left to do for traits (don't want to filter their
             // methods out, visibility controlled by the trait)
             clean::TraitItem(..) => true,
@@ -195,7 +195,7 @@ fn should_keep_impl(&self, item: &Item, for_def_id: DefId) -> bool {
 
 impl<'a> DocFolder for ImplStripper<'a, '_> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
-        if let clean::ImplItem(ref imp) = *i.kind {
+        if let clean::ImplItem(ref imp) = i.kind {
             // Impl blocks can be skipped if they are: empty; not a trait impl; and have no
             // documentation.
             //
@@ -272,7 +272,7 @@ fn import_should_be_hidden(&self, i: &Item, imp: &clean::Import) -> bool {
 
 impl<'tcx> DocFolder for ImportStripper<'tcx> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
-        match *i.kind {
+        match &i.kind {
             clean::ImportItem(imp)
                 if !self.document_hidden && self.import_should_be_hidden(&i, &imp) =>
             {
diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs
index 430bbe9..7fb0a32 100644
--- a/src/librustdoc/visit.rs
+++ b/src/librustdoc/visit.rs
@@ -48,8 +48,8 @@ fn visit_inner_recur(&mut self, kind: &ItemKind) {
 
     /// don't override!
     fn visit_item_recur(&mut self, item: &Item) {
-        match &*item.kind {
-            StrippedItem(i) => self.visit_inner_recur(i),
+        match &item.kind {
+            StrippedItem(i) => self.visit_inner_recur(&*i),
             _ => self.visit_inner_recur(&item.kind),
         }
     }
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 40a90c1..ef21779 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -13,7 +13,7 @@
 /// This integer is incremented with every breaking change to the API,
 /// and is returned along with the JSON blob as [`Crate::format_version`].
 /// Consuming code should assert that this value matches the format version(s) that it supports.
-pub const FORMAT_VERSION: u32 = 33;
+pub const FORMAT_VERSION: u32 = 34;
 
 /// The root of the emitted JSON blob.
 ///
@@ -194,7 +194,7 @@ pub enum GenericArgs {
         /// ```
         args: Vec<GenericArg>,
         /// Associated type or constant bindings (e.g. `Item=i32` or `Item: Clone`) for this type.
-        bindings: Vec<TypeBinding>,
+        constraints: Vec<AssocItemConstraint>,
     },
     /// `Fn(A, B) -> C`
     Parenthesized {
@@ -258,19 +258,19 @@ pub struct Constant {
 ///              ^^^^^^^^^^  ^^^^^^^^^^^^^^^
 /// ```
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-pub struct TypeBinding {
+pub struct AssocItemConstraint {
     /// The name of the associated type/constant.
     pub name: String,
     /// Arguments provided to the associated type/constant.
     pub args: GenericArgs,
     /// The kind of bound applied to the associated type/constant.
-    pub binding: TypeBindingKind,
+    pub binding: AssocItemConstraintKind,
 }
 
 /// The way in which an associate type/constant is bound.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 #[serde(rename_all = "snake_case")]
-pub enum TypeBindingKind {
+pub enum AssocItemConstraintKind {
     /// The required value/type is specified exactly. e.g.
     /// ```text
     /// Iterator<Item = u32, IntoIter: DoubleEndedIterator>
@@ -311,7 +311,7 @@ pub enum ItemKind {
     /// A crate imported via the `extern crate` syntax.
     ExternCrate,
     /// An import of 1 or more items into scope, using the `use` keyword.
-    Import,
+    Use,
     /// A `struct` declaration.
     Struct,
     /// A field of a struct.
@@ -341,7 +341,7 @@ pub enum ItemKind {
     /// `type`s from an `extern` block.
     ///
     /// See [the tracking issue](https://github.com/rust-lang/rust/issues/43467)
-    ForeignType,
+    ExternType,
     /// A macro declaration.
     ///
     /// Corresponds to either `ItemEnum::Macro(_)`
@@ -386,7 +386,7 @@ pub enum ItemEnum {
         rename: Option<String>,
     },
     /// An import of 1 or more items into scope, using the `use` keyword.
-    Import(Import),
+    Use(Use),
 
     /// A `union` declaration.
     Union(Union),
@@ -429,7 +429,7 @@ pub enum ItemEnum {
     /// `type`s from an `extern` block.
     ///
     /// See [the tracking issue](https://github.com/rust-lang/rust/issues/43467)
-    ForeignType,
+    ExternType,
 
     /// A macro_rules! declarative macro. Contains a single string with the source
     /// representation of the macro with the patterns stripped.
@@ -447,12 +447,19 @@ pub enum ItemEnum {
         /// The type of the constant.
         #[serde(rename = "type")]
         type_: Type,
-        /// The stringified expression for the default value, if provided, e.g.
+        /// Inside a trait declaration, this is the default value for the associated constant,
+        /// if provided.
+        /// Inside an `impl` block, this is the value assigned to the associated constant,
+        /// and will always be present.
+        ///
+        /// The representation is implementation-defined and not guaranteed to be representative of
+        /// either the resulting value or of the source code.
+        ///
         /// ```rust
         /// const X: usize = 640 * 1024;
         /// //               ^^^^^^^^^^
         /// ```
-        default: Option<String>,
+        value: Option<String>,
     },
     /// An associated type of a trait or a type.
     AssocType {
@@ -467,12 +474,16 @@ pub enum ItemEnum {
         /// }
         /// ```
         bounds: Vec<GenericBound>,
-        /// The default for this type, if provided, e.g.
+        /// Inside a trait declaration, this is the default for the associated type, if provided.
+        /// Inside an impl block, this is the type assigned to the associated type, and will always
+        /// be present.
+        ///
         /// ```rust
         /// type X = usize;
         /// //       ^^^^^
         /// ```
-        default: Option<Type>,
+        #[serde(rename = "type")]
+        type_: Option<Type>,
     },
 }
 
@@ -497,7 +508,7 @@ pub struct Union {
     /// The generic parameters and where clauses on this union.
     pub generics: Generics,
     /// Whether any fields have been removed from the result, due to being private or hidden.
-    pub fields_stripped: bool,
+    pub has_stripped_fields: bool,
     /// The list of fields in the union.
     ///
     /// All of the corresponding [`Item`]s are of kind [`ItemEnum::StructField`].
@@ -554,7 +565,7 @@ pub enum StructKind {
         /// All of the corresponding [`Item`]s are of kind [`ItemEnum::StructField`].
         fields: Vec<Id>,
         /// Whether any fields have been removed from the result, due to being private or hidden.
-        fields_stripped: bool,
+        has_stripped_fields: bool,
     },
 }
 
@@ -564,7 +575,7 @@ pub struct Enum {
     /// Information about the type parameters and `where` clauses of the enum.
     pub generics: Generics,
     /// Whether any variants have been removed from the result, due to being private or hidden.
-    pub variants_stripped: bool,
+    pub has_stripped_variants: bool,
     /// The list of variants in the enum.
     ///
     /// All of the corresponding [`Item`]s are of kind [`ItemEnum::Variant`]
@@ -621,7 +632,7 @@ pub enum VariantKind {
         /// All of the corresponding [`Item`]s are of kind [`ItemEnum::Variant`].
         fields: Vec<Id>,
         /// Whether any variants have been removed from the result, due to being private or hidden.
-        fields_stripped: bool,
+        has_stripped_fields: bool,
     },
 }
 
@@ -645,16 +656,13 @@ pub struct Discriminant {
 
 /// A set of fundamental properties of a function.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-pub struct Header {
+pub struct FunctionHeader {
     /// Is this function marked as `const`?
-    #[serde(rename = "const")]
-    pub const_: bool,
+    pub is_const: bool,
     /// Is this function unsafe?
-    #[serde(rename = "unsafe")]
-    pub unsafe_: bool,
+    pub is_unsafe: bool,
     /// Is this function async?
-    #[serde(rename = "async")]
-    pub async_: bool,
+    pub is_async: bool,
     /// The ABI used by the function.
     pub abi: Abi,
 }
@@ -697,11 +705,11 @@ pub enum Abi {
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 pub struct Function {
     /// Information about the function signature, or declaration.
-    pub decl: FnDecl,
+    pub sig: FunctionSignature,
     /// Information about the function’s type parameters and `where` clauses.
     pub generics: Generics,
     /// Information about core properties of the function, e.g. whether it's `const`, its ABI, etc.
-    pub header: Header,
+    pub header: FunctionHeader,
     /// Whether the function has a body, i.e. an implementation.
     pub has_body: bool,
 }
@@ -784,7 +792,7 @@ pub enum GenericParamDefKind {
         /// In this example, the generic parameter named `impl Trait` (and which
         /// is bound by `Trait`) is synthetic, because it was not originally in
         /// the Rust source text.
-        synthetic: bool,
+        is_synthetic: bool,
     },
 
     /// Denotes a constant parameter.
@@ -894,7 +902,7 @@ pub enum TraitBoundModifier {
 }
 
 /// Either a type or a constant, usually stored as the right-hand side of an equation in places like
-/// [`TypeBinding`]
+/// [`AssocItemConstraint`]
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 #[serde(rename_all = "snake_case")]
 pub enum Term {
@@ -963,7 +971,7 @@ pub enum Type {
     /// A raw pointer type, e.g. `*mut u32`, `*const u8`, etc.
     RawPointer {
         /// This is `true` for `*mut _` and `false` for `*const _`.
-        mutable: bool,
+        is_mutable: bool,
         /// The type of the pointee.
         #[serde(rename = "type")]
         type_: Box<Type>,
@@ -973,7 +981,7 @@ pub enum Type {
         /// The name of the lifetime of the reference, if provided.
         lifetime: Option<String>,
         /// This is `true` for `&mut i32` and `false` for `&i32`
-        mutable: bool,
+        is_mutable: bool,
         /// The type of the pointee, e.g. the `i32` in `&'a mut i32`
         #[serde(rename = "type")]
         type_: Box<Type>,
@@ -1036,7 +1044,7 @@ pub struct Path {
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 pub struct FunctionPointer {
     /// The signature of the function.
-    pub decl: FnDecl,
+    pub sig: FunctionSignature,
     /// Used for Higher-Rank Trait Bounds (HRTBs)
     ///
     /// ```ignore (incomplete expression)
@@ -1045,12 +1053,12 @@ pub struct FunctionPointer {
     /// ```
     pub generic_params: Vec<GenericParamDef>,
     /// The core properties of the function, such as the ABI it conforms to, whether it's unsafe, etc.
-    pub header: Header,
+    pub header: FunctionHeader,
 }
 
 /// The signature of a function.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-pub struct FnDecl {
+pub struct FunctionSignature {
     /// List of argument names and their type.
     ///
     /// Note that not all names will be valid identifiers, as some of
@@ -1063,7 +1071,7 @@ pub struct FnDecl {
     /// ```ignore (incomplete code)
     /// fn printf(fmt: &str, ...);
     /// ```
-    pub c_variadic: bool,
+    pub is_c_variadic: bool,
 }
 
 /// A `trait` declaration.
@@ -1127,10 +1135,10 @@ pub struct Impl {
     /// The list of associated items contained in this impl block.
     pub items: Vec<Id>,
     /// Whether this is a negative impl (e.g. `!Sized` or `!Send`).
-    pub negative: bool,
+    pub is_negative: bool,
     /// Whether this is an impl that’s implied by the compiler
     /// (for autotraits, e.g. `Send` or `Sync`).
-    pub synthetic: bool,
+    pub is_synthetic: bool,
     // FIXME: document this
     pub blanket_impl: Option<Type>,
 }
@@ -1138,7 +1146,7 @@ pub struct Impl {
 /// A `use` statement.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 #[serde(rename_all = "snake_case")]
-pub struct Import {
+pub struct Use {
     /// The full path being imported.
     pub source: String,
     /// May be different from the last segment of `source` when renaming imports:
@@ -1150,7 +1158,7 @@ pub struct Import {
     /// ```
     pub id: Option<Id>,
     /// Whether this statement is a wildcard `use`, e.g. `use source::*;`
-    pub glob: bool,
+    pub is_glob: bool,
 }
 
 /// A procedural macro.
@@ -1205,7 +1213,7 @@ pub struct Static {
     #[serde(rename = "type")]
     pub type_: Type,
     /// This is `true` for mutable statics, declared as `static mut X: T = f();`
-    pub mutable: bool,
+    pub is_mutable: bool,
     /// The stringified expression for the initial value.
     ///
     /// It's not guaranteed that it'll match the actual source code for the initial value.
diff --git a/src/rustdoc-json-types/tests.rs b/src/rustdoc-json-types/tests.rs
index 1126d5f..b9363fc 100644
--- a/src/rustdoc-json-types/tests.rs
+++ b/src/rustdoc-json-types/tests.rs
@@ -4,7 +4,7 @@
 fn test_struct_info_roundtrip() {
     let s = ItemEnum::Struct(Struct {
         generics: Generics { params: vec![], where_predicates: vec![] },
-        kind: StructKind::Plain { fields: vec![], fields_stripped: false },
+        kind: StructKind::Plain { fields: vec![], has_stripped_fields: false },
         impls: vec![],
     });
 
@@ -23,7 +23,7 @@ fn test_struct_info_roundtrip() {
 fn test_union_info_roundtrip() {
     let u = ItemEnum::Union(Union {
         generics: Generics { params: vec![], where_predicates: vec![] },
-        fields_stripped: false,
+        has_stripped_fields: false,
         fields: vec![],
         impls: vec![],
     });
diff --git a/src/stage0 b/src/stage0
index dcc2267..1a60393 100644
--- a/src/stage0
+++ b/src/stage0
@@ -14,448 +14,456 @@
 # All changes below this comment will be overridden the next time the
 # tool is executed.
             
-compiler_date=2024-07-26
+compiler_date=2024-09-04
 compiler_version=beta
-rustfmt_date=2024-07-30
+rustfmt_date=2024-09-04
 rustfmt_version=nightly
 
-dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.gz=a265d7831284938f090ef34cf2fb374f4d2b946c52829de8e53a06b7373c3d7e
-dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.xz=f2420846f82f474892776f0bea176fbb2f1850a1fb9f51a1afe40ae6de8bbc17
-dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.gz=e3e0e2b8d1f8804cc2b5785765cc6807bbf7120fb010d74453097b5931c82e96
-dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.xz=1270aaea2f20a378e68d26518e1d34810ed346a4d4c272138c8aef67e3c386d5
-dist/2024-07-26/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=02bcdc3eed81ba17e485556f1c4d5a00e851afb75a20f860ce7b6d22cb8f9e99
-dist/2024-07-26/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=52b72cc7270fe75e023ca9c40d095a84cb0ce31657357cd7676d6570ca59bc1c
-dist/2024-07-26/rustc-beta-aarch64-unknown-linux-musl.tar.gz=b47ba6f2214f238cf8df3c386765e7816bc86e1166f27ddb6c0ce678ec716939
-dist/2024-07-26/rustc-beta-aarch64-unknown-linux-musl.tar.xz=95537778025708922b4bf27f34f0634a61a1d963a8424f8a06c82564c74e849a
-dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=d79c8b744d00b174be7630a54f9ee23562f8977d7e09e2ee46a9d72a80eef514
-dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=0f7d3d0773a3c1f94e8252d95b134f7f5e727a884ece54aa0f77e5edec5c6e29
-dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=5e0d51532c4bb0c29fd01ef5d931c229f711c9326df0bdcb2b88c75aa72dc210
-dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=5fe623cab0afd5f7bdd664a593ac02791915e30cfc9ca76a02ffd70e1e865ede
-dist/2024-07-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=1df1e1a44170d6c9ab4988e9841ab56ee00248ca5cbf7e38b69677bd5b2de585
-dist/2024-07-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=70791fcd1aef6686e012740017a0e5bb4441eb4018f875e8e50d5597c183291d
-dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.gz=045fe2478c5a5341d7b7a05b9df23ef8f81ddbe0faa78e3f2107341a0e8189f6
-dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.xz=d7f3888692210b6024ed72864015d1c101f28814dec5b60c9e32a772f11f3b47
-dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.gz=5b2988c87d91013cd92ebca43fd6cf5d49250fc0452830ea46622e418984041e
-dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.xz=b9d65cca6691baf2841432d6d2d566face171c460cf161f39a21acf7c0b033c1
-dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.gz=7b037163f1c19a0fbbf4029d12a7b3764e747c9ea7944f1e45a6f91a068df224
-dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.xz=f5044d8f3784e5bc682b03ccbe7389abf5b254a01074fa67eb824d2dfc9fd3ad
-dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=840131ab570c68c0d46244eac743f7d8a1f470d1926068868d288307a488b3c9
-dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=6513a144014807bd258d2a90fa4618aabdb4e265268e408d5cb699a610b78c31
-dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=d703a904da3604e553ba0a74775f8005e9f52615be3266197b71362b20414def
-dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=8ab79d34b3c182a4349fd01a50aa13ca064ecea64c2ab09f7a9ec38046741c7a
-dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=70eb8f65e91068ac20366fca1fc30227f36cb2b2ce1abdaa72504583cc7865c7
-dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=3372e272cf9620191000a95fff23e417586e6b894e211d44e4f658c241c3d014
-dist/2024-07-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=e8f09f56c43ae6e99a42a8c430492157415fa6baee2c3f8f86f94ab4279634cd
-dist/2024-07-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=599fcd5c57687e29eec085f7cc2733965a8e8fe5eac6499abd92ffda64f6e500
-dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=904029f0c81ec9679851d952f0f0f616cc183028882c6686f5b5bb665ca00cef
-dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=31f3f895d665acf082a6dbb40e91fd97f823f84c8e62074dfa82e60f22606f5b
-dist/2024-07-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=4d374e60b8ac2f3fddd5ba9b46ab80555bc5b19f080b86604dde994087b00ed9
-dist/2024-07-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=c905a880b98d1eaabfb306d5b6dda018e5025b42028cbb12bad408f4d469f3ae
-dist/2024-07-26/rustc-beta-s390x-unknown-linux-gnu.tar.gz=69f0228799685960f36f31eb4c139cbd7925f5180468e2d4a435ecbad63e9535
-dist/2024-07-26/rustc-beta-s390x-unknown-linux-gnu.tar.xz=1da1caf5b2ad149ef82af58278dea6c381c372366c48cda8ca7f520cc8752b2c
-dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.gz=81fe4bef33afb3010fdd7af42653fbf5dd9abf0d69268576dfe144c88c7b9944
-dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.xz=c4785475e3f7087cbab405937c0ca3ebc08455dd36df156680cea1ed38fcce5b
-dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.gz=6e58397829f67bf952037c94894409032e52ac8ccdf3858346d131fff6175a50
-dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.xz=8e834602e7cd1fcd585f51ab280266b4ffc57e0c974a1a26b901701b5127135d
-dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.gz=94a8a08495b8093db5d9a32c3258c9f97ea8b0f57947d7ca642664c06cfb438d
-dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.xz=8d057c7167cffeebeddabf25f08a50de8dbad5ed7cfffce625c81a99d757e998
-dist/2024-07-26/rustc-beta-x86_64-unknown-freebsd.tar.gz=dcc93e7b76ca7a469544597885a7b5f4b5f822e05a89b2d7a093e06dede9f52b
-dist/2024-07-26/rustc-beta-x86_64-unknown-freebsd.tar.xz=3efb7d4d97dc9b13a0178464e79bbf96bb71763a588b48c587746acd456ceb8d
-dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.gz=ef5a0d34b78848962e83ed468934d7cbedff778a89e50f2128ba25d0943e25ed
-dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.xz=5cccc7bbb15b63d422dfd2c8ac25e2103906880e843feccd318ba8b8c614d3b4
-dist/2024-07-26/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=a9b352f61f8124c1fba0c76ecc8c1c972e61e97f5299f3b86bc17f035351ced5
-dist/2024-07-26/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=a8fced9a5de02bb660491b440f6596e4baf6eb9114b8dd8d93ac7ada6266d274
-dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.gz=5e6fae2fd75e1780995fa9839593044539fac3f095c8948ba446b7024f632ec9
-dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.xz=9eb16965a7f1f7be7751fb61280f272c2497765e552fc0dd653700d551a04539
-dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.gz=40b7312ce424dcbde5537da50d17854c255c3ed535a124f4f0102cf62bc86b5a
-dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.xz=222a86f97d9bf2db38ebea9f45901790429658154d3448d05e7f0ddd9833ff18
-dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.gz=a9b3cfe03b3053cd533ff02fb54f95db009396802464f32840b3369e9a3e6afc
-dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.xz=9ddb6b8291ade9224cc76f4d946c179bdc6e25f5819a4ba1ebe1f207d4c663ac
-dist/2024-07-26/rust-std-beta-aarch64-apple-ios.tar.gz=8c129310921ed45d3cdfc30e60d93403adf8158a6661de96ee5d4a63119cf3e5
-dist/2024-07-26/rust-std-beta-aarch64-apple-ios.tar.xz=e1fcee4b062f25b0350e5e74064615c354ee8b399adf792d46319ee782857398
-dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.gz=40d6d48dea64407bf31be39f9e0316a1e47648ee75bc0d3361edb961e062aa6b
-dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.xz=3e01648f45e0c7cb040d3c293024477801930d5078d54c6291ba13aa8eb4e1f6
-dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.gz=da310568bee0d4868132589399c9229df5ac575a028f2409f51fd1f8c9e81779
-dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.xz=f3079ebecbe5b9f23495fe0966fc39fee1d38869287695804c3c04d53df07496
-dist/2024-07-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=9dce2956e4b01d867ef6c229dbff9319a779a80e43a29fe1f8b10a333049264d
-dist/2024-07-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=b64e7b87027dceba21283ba71430a8053a918bfaf6c071cc70d5f5da00155944
-dist/2024-07-26/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=0d103e0c4ec8039dd42be09bb9c74f269a9567fe7dfacfc54106912cd2aeb35b
-dist/2024-07-26/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=4b3627e9e363e9b2fd85222c677a7250b12a5d32919f38a31ed7375637a79a81
-dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=061fdac14ee0bd3abba36269f68e9ad25a243ac7062f946155f98680f484a84c
-dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=8acc12f14ac643b822595a6a07c7e5ac65855b83938ac122e3278f64769eeb13
-dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=199498df7d94989d4ff1773fdfe86e97ac99ead487f402d020f78688bc6dfba4
-dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=1337c2f00e9bec2e0a553234d74daea67a9781459d0abe3c8de954981d9354d2
-dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=a7116c13a413989f2ed874d45780aced3299c4ef8ce8e3bc99efe960a73cadb3
-dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=80ef87143ee2339e90842c4893284217ddfa56926524baf94341277c1210dd07
-dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=c47cab4bb196e749f07d03f6f6c8f2fe538c84a055a298f0b505ab98dadf4a1c
-dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=b36aa3f0bab63ac21fb69610d379a87fbd1ee87041153eb1e6886a237d22b171
-dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.gz=92de36c897dbf90f9986396da1f8a954ad7b4fdab3e466d63974c82611e76d47
-dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.xz=fb5d50ce34bd222c1b624e5aa2248776f8926f3ee360b7c4c1e0bd412d01bae2
-dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=fea794a4c8aec3e5357199db7a9b701ceedded1dbb50167b002d368a6ae09cc7
-dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=47fc6e497bd4c8013f708ed052701129c308b657d28ee2dce877cb63ccb1b06b
-dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.gz=17eb45b10a0c9cc702e7fb4f0c7926591d3ad0f052f2bded9cf852ea082cd2bb
-dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.xz=1f6b1a3082fc29546e4d8dcb20675f62ead20fe96112998dcb1260e206e93cbc
-dist/2024-07-26/rust-std-beta-arm-linux-androideabi.tar.gz=baad78bda532ed77dbf3e4265595b9dac82f6fdc27dc6deaf7386a60b981b927
-dist/2024-07-26/rust-std-beta-arm-linux-androideabi.tar.xz=cf4283b1224d4dac3c55da905608c5bba7639b6511977f3de344a999ae39e571
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=0da01efb79d43140515c48561cbe7a2fdb83895fe4351f2fffaaf108fb163268
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=baa52bf16290d71b1b89f12ddcee5adf18c480071f9fd4daf3fcab72f92fad4a
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=2325e8bc225a24a0a8c16da6dded16d4befb671b913051a7cce12ee3e183eac7
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=ab9ad0ec7057deda5c29e5d7de317eb32512fb95b62ba628b91b5246dde9c90d
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=be6d9a01609152eb815cef9462023f0ca2f2950ed03d914629d8e6e3a96af8ab
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=75ec6023cf9a43ec7ed0f52a1633b56154d9505c5d5d769153b48b9991ce99a8
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=cc1d361b775e966c700d122f925a9f2feacecaf7d2891d9c5c5a4a1060336408
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=934c10c58db5d7644bd0b7df6c3a128cc53b88b412128c33de5932fa0194f4bb
-dist/2024-07-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=949a18d9d8b4c7cb3442ec4e387c91feddf0cc26f1fe602ec6c2c484312c9845
-dist/2024-07-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=7adb9a93d35002d0335b3449b8d9af35a80a35524fe98bd86c3896481f020597
-dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.gz=b40dbc6ba0f3f80414bdc11260f291f067acbceb50d84597a9366746cff53348
-dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.xz=1564c3215b173956bae41cda7312ed7912812e0fbb65dd8d75808a1d5084fc8d
-dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.gz=809d7f027aecc4a131921181418e66b956ad0a2a7170a3ec3649e21659c5a524
-dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.xz=1b9589a72d2902cd4491406d93c599d2e850fa2ba19b1bcc6bdc5cc7196f9643
-dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=f2840d36b089fdbcff5f6f9f7a6e576cf21836824957cdf2d1ef2c75a1f5c11f
-dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=5723cf48a1ff47fb764cc5ad921356e490997aa09ecd86404e370ffdacfa4b31
-dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=fb33110ad649aac6f55310e6f03d03d4d75ccdca43ada93fb97a717975ef867f
-dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=cef39c2886fffef2986e9fe8f3be58f0d7f3846466a35443bc0d49464bdef98a
-dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.gz=68fe7b30550cf1ccc44a1669f26620ae418b48cd6283b716aff3dee91acfcbec
-dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.xz=81f24aedc06a25c8dfce729132a77e90adc5fe2aec86a3a9548aec9458127ce1
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=a63c5d40bcf8b0702c1a91e992c042130916edfdcf94fb4615ba10c89dad6642
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=4706424b53063b768223880d87bbec0cf57e524374a6ef053ebef02d096484e4
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=85c3684f175642463777aa69889a20391e39afc0d6356baa3ac0445f7aa25119
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=a8d67436a8ee232d57e2924f8f9e5cb0050c71740d57a4e677674adb75093f31
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=b3226669f49ee8fc89c1f84855c29f8416df3e32d3276547f521f738179164a6
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=9a5711743a0984ab7baed2a50f87e50d7facff2ef05f5b936b7b25f5a5992734
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=fd2db70418d432c7b32bed92f5af0f301baa3a71c171d0ee8b0798bbc8e239e2
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=97922d70b37e1e2ff6dc447625b3482094824910a1d7a483cc707985406560ee
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=710be82238e9ad617b2d5f52ef37976b415e7b6ba3d5f3677080f2ccf78b9d44
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=2cd0956277cf963f95ffa0104bdcd60cb4e6c4bb2a443a683d67f41726408159
-dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.gz=dd38446053d1500f3bdc325ae5cd52d0434c618d79a7c0a0473c76691353bac4
-dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.xz=5b82a2f970be59563cc4f550e4202be802cbe21dcbf14de413ed8f30b0e22020
-dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.gz=9758806233e59d7d40eeda0740559d9838f9a6c608309567af61245ea57dc212
-dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.xz=4266b69d61a46c0c6f6d3aeb2b3378ff88201039df50cd8d3a51c9ff910be181
-dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.gz=6142ea4cdff99902181379fdb9a651fd9d1ab6276ebc104e73b2280a6d9f380f
-dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.xz=bbf4c74f6b6a32f01d03bf101f69dd19b909717036117064fa2c8cdd0b4146da
-dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.gz=2cc32752932477945f248dee4d277754928b982815e2e2e0d27883522fb9b8d2
-dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.xz=e40eae93c31c1fa06517a21cfbdd2dd18e2f740aee1251bcc9bdc680a565241c
-dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.gz=6d7210503568d9fa02231ac2d9a1b400d00a37f38ec8f00bfcfe45c325aeed02
-dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.xz=cdd81201e38226750f2b4292b099b5d78fe0115cedb4c28bf20200144297d8b6
-dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.gz=95244114ed2d6dd2de488f49115b11a25b008134f1fa1c8f2e2a62849b51f213
-dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.xz=fcb3280dabb4aae920a14c7f4fec52dc3f11bc68f5143961fa88347aa020bb9a
-dist/2024-07-26/rust-std-beta-i686-linux-android.tar.gz=d36c3baba2df9d69e197a773f752bc36e107c2411d78037a357039a856e35aa5
-dist/2024-07-26/rust-std-beta-i686-linux-android.tar.xz=14b9bedd1bb95e1bac2bb028670b1d9dbe6998bb6ad0cfab1db0be0cd9e3d4cf
-dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.gz=44463b4a17c87a2de8554e2629eed8172b60b078ccca7e78bb2b0a20324f51ef
-dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.xz=1e4c3a1d8585aac5aa3e66541b4aef03a0b429a6067300c58f6cf588eac19fa6
-dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=b1d9d5967c039721eda402a7227074ba6e6e8f2877be49eed961ecbce00004ed
-dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=2436343b99d81abae0e6bba16850dbc1c005ebba5defb991c3a0e99834410746
-dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.gz=c6147e9c6c39501d133a344972dbb8108bdc45bb2fe8ad624162ad04a9c00c6e
-dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.xz=6207bdfe0796e4bd4e7d25457d67559f15aa2e8bb91b05284ed147f8799de869
-dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.gz=c675df742bd9fbc01f67411a19926e2814412f12e09b53d1492e8c7250f3e685
-dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.xz=d5b9c3783f6d2dbdf25e0495e32a295c4820bbc5b65a44f19f018b1141e85371
-dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.gz=748dfafeb6b953017b9129be9697d02a73d5bc8b1371a6a00bbfa20b7b45033c
-dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.xz=0c9a0717054858fa821e4c418b9e99cb0a0f852ec3c866951c1d1795cc1e8152
-dist/2024-07-26/rust-std-beta-i686-unknown-linux-musl.tar.gz=96afb9b33c86a6007f9c02f1f418d28f13014ec5154b648ceb7f725449dcbddf
-dist/2024-07-26/rust-std-beta-i686-unknown-linux-musl.tar.xz=7ed52c039fdd13a7477ed211ad8432cfd2fab98832174c8a534e5ac280f28572
-dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.gz=676786bd5e7f0739d18d40d99158045fcba746dc306485c0f15ce49ef2b63b0b
-dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.xz=d7fdba095ca515454034891c8a862aaa563ee7451289138ce32b10691dbfe38a
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=ff2eb11f284da7883dbf6ae465af86e50a9cd98c9b7d22b1e710626716e07db5
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=953fedb9dac336cb796290f619919f4ff9b2a6fcce09e23072f93a40b5498bdd
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=ba1b4f772faf2e738d2696eb576f74bdbd1fed1a073053eee341ec6423b6e1c6
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=f3f3eaafd9ecb1ee0ba68259d88d65ced56f20323a4f542fc85993e92a044206
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.gz=f20ecabfab9d8ecbab44d661018b865e449137993726e76b20c7749db4d0986e
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.xz=7da2cf413c0665b07b3083862747c9815a78b3775c2bee6cd1f7551e7f2e4c8a
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=3f7529ea5dcb17c18efa949916dd1ebc29b123a265cc8839cee4fe4e637f19be
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=d2a30f8659cc66d48da0e6c1919707943321d7f3ac0e2d58a9078aec16c86ef7
-dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=f971daa3f8c3d0773fb6667cb7a544f96ebd049e9b5d1b5ac4bd3ea0c342467b
-dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=3cd2f4ad7d9f41e9f903aa49eb86d142bb5ef69c2c39d9ba16a00a39d74046f1
-dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=b319ee87ee034a6a2a67dc2efdc72f8285c73d9bd1bd893586170ac54049151a
-dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=c751e65bbdfd72de07abf138162ab64dcbce51ba50375cef5ca8f35945d9ac7b
-dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=0228f8d7e0913cca5db975e0b9ec4807e817dcbc0cd0bd64b64826c9537f25e5
-dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=d37d5ae3605d745a393fc71c5f0e169cee283aa840edb9543682b339cd040310
-dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=6dd97a7215bdc8145cee5856957bf3f20719f65c73033006243ac2a9e347394b
-dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=d7541a8e83f7b8a9761988c3ac295a665e21e4d5dc9e2284ef48314f6c784166
-dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=34b21aec2cc1b92b2911211fe3c798918ea6c99d51975f6a979c2da3a09b0a05
-dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=50ba48e76e60ffbfb2bb0ba0b8e12418b7f6a9d7cde31b508bb4656536934e82
-dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=e84526736c1a48dbec3b122b8c01458ff549afdbdd0f73e705c76cca1bd1f767
-dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=df8d9909b0afd0e02b9c027f12e28aa2c40716d7c8a8f5e82b7521d2e145fbf8
-dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=7b671c5257a7653481fe6bc090c55398607590292590e0fdf5973f5f9b7b18b1
-dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=7f4d1a8e757fd29f4f58005032608df709003098eb661fe98a0b3116b7237e6a
-dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=9d957edfba201b541bd589ca4085e26bf6f890b3970817fe9af6ccf5f2eb0854
-dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=0f867e1391009d1d0caefb6b9217fc8e9f3e087a7dd9b22a157719bdc44ac074
-dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=a02ccac46574fad8929b419eff7510b8a773211d3ccce9ca96f0485e2dab8eaa
-dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=b70f37cddd519d0d207e28089b469f702bfe72ba5d32a631c85270db75b83d61
-dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=151863cece818be834261e6c148eeabbb1c796c991065c84b813bac64e73fef7
-dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=94cbae695036a4a1fa1faac12a6dd5ebeea18ec2d6e7b01c311d340ce7ddba39
-dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=3c8ca657208a4d96eff193363375a33d966dc319cd329dd7a0d379e052ab43bc
-dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=037f7b599421eca888332dadd797509d81af04743eac06120a9882b27aff5ca2
-dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=d931a3611003cbe61003ca4feeb637449f1d10f7969cd27ca37f11cf5536e465
-dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=3c7a3a9e1e03c2fe097e2e7353d00d02e864d3964db559f6a08a3d33f1fb7927
-dist/2024-07-26/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=f877200e388345c10d3b0f5b8c484dd42905e769dcc1e21692e1cf7f2d59317e
-dist/2024-07-26/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=1052e8e5681c95ed3c004adee2492ff19d109965e9441a3362df876719899486
-dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=e487752db0ecd837fb1ecb57064ef2464f7f85ed5fdc9d47322e7b5c37c32300
-dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=e74a462d598c55822b5841bdc35cb2605b4aa7993e305246b3adf079ae79ea1d
-dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.gz=3ea692ffe99c953d0049c0a16b71eb0bc3da492b9f9308463311dc0143af84dd
-dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.xz=97005f0d686a6481c5a532b6e1ea14befc794ed89394a8f1c94ad39257ebdaa8
-dist/2024-07-26/rust-std-beta-thumbv6m-none-eabi.tar.gz=2aa967414bd03764774338e377c4714b8d169b1bbc651624a20158441b8111c3
-dist/2024-07-26/rust-std-beta-thumbv6m-none-eabi.tar.xz=d1a3b6ccbc55d1d9555674d1596a0c9f489304f9cb211e0c4645c17256ada4d1
-dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.gz=33fe3c61aa2e93c6a925b132fabc11c24e102cc070260d5f89a66e374e9a4d23
-dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.xz=f50bb682fe484f23ae1ae9b2466c450b8fe9ecc3694fb68e162ce43cc8917af7
-dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.gz=53a17d10d498f1b6ebd6852987f304b2e1187544f2c9e91b69d0fdbf88630910
-dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.xz=fb97e6f2b047d6251eb6e34891b64f20d0dbc648beb78bb7364fe563670d7de8
-dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.gz=940eef037faceb2b9bdb1094eac6b175843094d3a3ab3c9850eb28742643e92d
-dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.xz=c892b8a80db788d1f4bf64ec6f740bb1168a8b9dc88d105366892a476ad3c244
-dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=905d378e6fd4387381fc166718ff31f017c99e725a9c8461bbac39d5571e246f
-dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=6c5fc29004bda36ddfb0280636ac2b2c28c538f33cadb07a55174fadb068daa5
-dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=38c8b07558734a9fff1807a823af72faaf8ab5ea47042f1b88a38d6c3648c43b
-dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=e30e0000336449a8aabf60839cba4ecca32cf82b02ed0a7a23935793072679f4
-dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=db784556ebf56a79e6330de3204ce6ce5422eca2543b872ed55c238aedbfedae
-dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=373efe8c55e85aae60dfac234471b76fefbc2ba722d97e0338ec593b7c70cce3
-dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=1bd5a11163f5fb9325e21c425d5d2fb3e1f845d265cbf7736679c3bb9c8d22a7
-dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=d858d0077df0fa7363258994e76a1bc0ff850734de6a0fbe955c3c9b9cd46cb7
-dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=07b356cd0ec3f18617e8f5be04d784847acfca43d6fa2101821dcdee18aada36
-dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=aecacd11945e6e053fe27faab2c0816628b392cb06c41feb8ed693d43043eba4
-dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.gz=7bf6bdb443503d48cb711f8b3e2670fe20e02f71ae940c2f1b273ab1d15452b7
-dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.xz=9ed34d7467722660d625e9a048fcb843bdb80aac407b0395a693a5698f6c1465
-dist/2024-07-26/rust-std-beta-wasm32-unknown-unknown.tar.gz=5144fe563c42205ba777678291950bd1b8c2b010b9aae28e2fe96e14e93e28cb
-dist/2024-07-26/rust-std-beta-wasm32-unknown-unknown.tar.xz=6e55e79f65a02abf37e1533c2590f53dfe56b474b58a3220d88f3d1458b6dcdc
-dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.gz=84d03b1c1fc7338895f82f54fdccb18ea6c4ceb43f47c3d46fadb014aa0c9549
-dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.xz=f28cbf9552e3c680342364087e7305a12417a92ed6b6696d71d476e1c1d8d4e7
-dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.gz=8d56f1aa8661047f854806278b83a514fa79b7a5097635cd095943b3f848ea74
-dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.xz=78609204d01e0d0bcbc1fb5dd3d9cfcac60db23bfbd2428f1e021d1b05793519
-dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.gz=ed1b9141bd68b8c13e295904ac66d18ca92c5b92a263fa5109262d15065aeded
-dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.xz=0c036271c4c4e04357b630146cad296dc6a57363f7dc0cd2f3142ead13bf0602
-dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.gz=c12bc5543c262645f7000cc84247518033f15fcbdfed510eb92393d723906eb1
-dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.xz=a5fc26dd6068cdb28ee2a252af545a34dd2be6e075e7d0aac2d03796c07579f4
-dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.gz=a62be7f900cec101b1b7444c7466e8fe0b823d708fadd92bce8bd531866b4938
-dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.xz=993875efe27c1018bbcb8326665247a33eda6fc0e934f71124b0a08d72685474
-dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=bc6ae4d5e93b47828678f1af55efc1baae2d76975be3259854272a566f5489c9
-dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=51cf1d675e61aaeedf895e52a9a81b188aa066a68d599963e0435bddfd2f6a5b
-dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.gz=6bd4089f30f05d9902d667a2d48028345bd558e7365bd3957bc554a4d0c1f939
-dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.xz=2a7e9250e3bea7f7e502131012139eadb66c71e95e8cec1698e22b21e7c9fbcd
-dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.gz=4169c938b638faff18a5db1bed5e7d2036f45d25ec9799dc2967ad1589d447a9
-dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.xz=8cbda8eeb98be575b78170e9895390e9406c4de41db8363988185dd24e276427
-dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=99a14bf8cffa0c736a25ce117bc5d4ab64963d81c9d9ac377f118a77a6a3c4b6
-dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=9902878b75b3f6cf944909cf6d17efc26dc820708b164b34757d841e89c948bd
-dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=54b83918128c3d19b09a4e1801783500266794395e6a6f138ad647bd890b79f6
-dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=2b0ed80c922e25f3783fbc0ce181b76b7f758d2a1b85b823851b7ac35c6872df
-dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=44ce7faad791029b670a9d815766a647d488dbbb56eb09024a09a595427fd19b
-dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=cd7011512df191100d31caef920d1a5c6d5ec2a771e0b52078d5d60b45e9a497
-dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.gz=dc20c2fc14b2211bf4517464109871f940a227298302d2ec84eaca539a19e9b4
-dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.xz=5a7fa24ca3f7b43526c116a5ebce60f29116640ad51c1ed426f9aee705b10897
-dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=975917e862347f7e1472cdaa2258de16cb9981e3a8256f9b7860104740076187
-dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=bb89062b05f025a964e0110fcfc8fdf57300b23314409924cd4a05e9af9614af
-dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.gz=a1c1e3e15bea1c4e6c70b8a56c4fef1c231b6ab5528c32cb69ded38456b3fa21
-dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.xz=43b31f7dd50621faff96c13a2246c80e84fc4da4076d4aedca4e9a6bf63ca43b
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=3f8df0e35e2e8d5e0f8181f20f0639323aa8e8c21da60697599447c0d77f783a
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=d0e727d9176abdbef02b1276b3b1acf69068b9c0fc0477fb3248fd06c99292b5
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=73ba835c5c4c9fcabbcb4e1460d402cf0c0aa9b2e01342521897abd9769dcc02
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=64e6fc64ccfd0adb2fabc610eba6e877ab83f2de49532363deef4579728baf6f
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=58dcb73ba02fa38742d255bd346a77340cf634247904624c7af9b11e769a364c
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=ea4417de121ab7e869659b26efd144baf2fd839a956da4acb30121d1bc9132aa
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=d1e861a9176a5cb934270592f7b98528283c363d135736477a844499015ac44a
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=c5f548845c6ccbee1980892e630ab06ec1bef498fb7f6fc80b4ced4a84c23f85
-dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.gz=3f6677ecdb1a2f016e9941234c221b06fd0a21cd9bae83a59bdcfde055c4878a
-dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.xz=60eae08756d92a70b740ecd8a1412138a9a14486289d73440bf7ee068586f9c4
-dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.gz=1f11ad1a66d01a09c7237da76327b70ae2e2a9f7647a3ee0de58d563576efacf
-dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.xz=960fb614a927e1b3d1d8e4a9fb7220ae675d0e8219fdde204bc6454fbe69a0a9
-dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.gz=3af955fc52feaee2d89d6d50e0df4d00417897679f0d607a0f146a8d34c20496
-dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.xz=cb607387d0524bc84610cd6cc0a0070e0dadc379a7fb1a736f3f336cf0458b8d
-dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.gz=ae56b334234ba51cf68be42d0fd58cf3487673dbe747bb3efa01e8563b9b8a90
-dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.xz=1468622e9bb6384a6ab7006863d2b7d55307e74239befc8e72dfd39f83c0af1e
-dist/2024-07-26/cargo-beta-aarch64-apple-darwin.tar.gz=62f687da4c02bef3e114b92c75b62fc6f7fdfcd210fb66329f6d4780f7dbcd70
-dist/2024-07-26/cargo-beta-aarch64-apple-darwin.tar.xz=f9346e9ed4e5638f58dc237b22aef9e1b25b23bb588c736dceaa25b7b935f2bb
-dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.gz=f2442eab2908bb90c551f56da8889e39ce44a31936ce63e13a54432105a67cf9
-dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.xz=ffc8c803668d09333fdfee996fa72c8874e91d92567f0b4eff9077d7b9a3070a
-dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=97f6b771f7e559df03f00f8665c6580535499d4afa7bf2a252a145b1aa0e2c0b
-dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=3ee58d5c57ba00e27428392dab1d69655bf7e997a0d3aa6629bb32f4f863396b
-dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.gz=b36871d3c88eca54e4c24d50171fd649d10a92f689d4812ebef7b510f0c3d799
-dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.xz=ee550d60ae217fe7aec12feada1ba1f84222427677de42382d192ec748f73f18
-dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=6599270c877164e76ef30f00a9b47da1a021fdaf1d4f7fdb194500f861ca8d21
-dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=46429528039b5499c6ac4618c4b73fcdfabf7fdd5ed9f9f3d64ccde0428d78c0
-dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=01ba37e80e18e673c275538fc0db63b667ef52a72000dcbe76ac68018bd585e8
-dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=004f5119454fa53c2a7a58f6d176f65903b3c5bfc8eb1f894f6ca4e9bc32b7a1
-dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=2bb2e69563684bf64607d3f584b4216b24fe190dd2eabd6c00c2044290beabde
-dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=454b0dafb3cd62788dc541ddfea5b484ac799253937602f6456e853c2a293707
-dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.gz=779d704f8f64a7290227631d1e396fe00bdada3cfb7f3e6c775a0bb00047cb97
-dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.xz=8cce8e286ff04f4d58235e8716a0ca05aedfeb9db6fb8952c523264ea649e542
-dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.gz=58b31a781da4f5215b0fbb5f355cbc3c5b2212971c68a1e00de19b851698fda3
-dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.xz=008125eca7351844707c9c14637030da45441a68d74f6e2752ee713f6403f03b
-dist/2024-07-26/cargo-beta-i686-unknown-linux-gnu.tar.gz=cbfc580db37b135a20f42f9da02517ec8cf0a286b7274252c23c6a4947ba6755
-dist/2024-07-26/cargo-beta-i686-unknown-linux-gnu.tar.xz=dc2198fabb6fe6f68353c268698dece4ca3d6901b424a7cc2c68850f81f75f20
-dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=46ea726328e1700cf2b7d0ddeb16e25ebb648267c76268ba2f4aecb75ba47661
-dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=520ee25c1f18d80b4e4ce25e8fd961a19c0dd2ee0274e9d9cd3201f7c57c6f77
-dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=fb710b6ae058619042bdf80ef5c2a56457076692a122b4155e0a53f382e8ad83
-dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=ac15e80c28c7a4570bb4a99fa70522a3ae5ba602ce25e96b8e82d097f8b42904
-dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=6907a40c1e7b18146ff2a60c6d44c9716f31cd4aeaae4fe858032aa26c359d27
-dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=4287d73ae2b3272a1893c2ffa32d007edf0b05ff2dbf1da92aa20f2b857e0eab
-dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=edbdd5fc1e9bc5fdea67e7c2fda3fa9f3eb3f599c307a278bc7bf45ff97d1f48
-dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=9c7d487f65a6273b76970b2c057b8120abbd89ba67a2f92dd446ecbacf218576
-dist/2024-07-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=74e57cbc139d548202d94262170ee45e33ae01331358ac2eaa9fa67c968ea1ea
-dist/2024-07-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=6cf99b689e32ff0caa56e9704dd185f6c268b484ccb657eff212e66fe64d1c10
-dist/2024-07-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=ed13a39d74e9d814d585ce7fb1aafd093f94317d6ead76e4b43c03b01e210086
-dist/2024-07-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=b5379d677d6596ffcbd7f3ebef2fd6d968096228101104a45565b170fb050042
-dist/2024-07-26/cargo-beta-s390x-unknown-linux-gnu.tar.gz=1a29502881e6512a8bea566a90781870181f5727359668fa3bed2b3210a21b8d
-dist/2024-07-26/cargo-beta-s390x-unknown-linux-gnu.tar.xz=95970245a7f304c6b83b8dad58b4c877ad2c9b0ca6bfc0090151561ce53a217b
-dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.gz=521f03a968c6e0640de6f09ecbc6328ea57b2815f353a14e1d4dd09925e98366
-dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.xz=14b733585cc768d26a822de630d990f519b6d6b4ae079f09bacd51b7449c18a4
-dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.gz=1bf5d0201ca87a76de8044dd8222517bd130ef3db631dc60a84e2fceced465d7
-dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.xz=2eaeb6863c655047e6c938e208ae952df4da2d8b4326aeda60918414764aa7b6
-dist/2024-07-26/cargo-beta-x86_64-pc-windows-msvc.tar.gz=7b7ef80aa6131ddcb8bfec0f9493417e9a1e617a8f599a27de52ee914d022f95
-dist/2024-07-26/cargo-beta-x86_64-pc-windows-msvc.tar.xz=647a6d0ff8f38dd4404c0006e5ed7b3a981dc89bbc334b1bd53225cc4f5511c8
-dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.gz=bcd0e100d4c66784a2357be74813551c68d4e3b5e6846bfd1bbcb316e5c82c53
-dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.xz=cc31bb9f5a67359f4af4743afbdf9b694e40cd209211d4ea819c94183de6ab60
-dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.gz=12f6a8d3d17b54ea260f6f5b19be9e208111b0ad37518ae6b6eae558d77a1dc5
-dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.xz=221c9cf9d1fce2b5c50bcf8f435f5335f1c5e9533f51d52b941593d6a964b4c8
-dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=53c64845abe4582a90041b2128b3f931ce636d01fc9a8509b35ded5dd7ae0a35
-dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=61805cfca6e7f602eaab0fde2be48cfed244105b2f4b5bff798752ce06d62713
-dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.gz=92ac04de9689176a42e5f0ccf1e44ce78b64bcd15d6e570c171d51c44cf8c6ce
-dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.xz=59a371de4343d330b79e84f629c98b5cb9dc58bd9706d1a7a9ff474b28394851
-dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.gz=f48bb7b7d13862edaa8949be046b5bd2b8c63b0aab8e29bffb1940ec149eb123
-dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.xz=0a6e09604fe291d0a9a0845a8ac7f434c9f4ffbb698c042ba83a070c23f804fb
-dist/2024-07-26/clippy-beta-aarch64-apple-darwin.tar.gz=4c8991c692f200c6a5f25957e6648e07b7271681cbd9c61749bc990216dbbe6f
-dist/2024-07-26/clippy-beta-aarch64-apple-darwin.tar.xz=51b5b85d46af2a3faeb53b81472c285eccc01f0c83575f62f37739cd48397fe2
-dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.gz=3a7755c10b32ee3b4f95875c974f21efad2be7ae27d317bbac056b3e5b9298b7
-dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.xz=718692e6a1e00ca042d9767273e487c941c65440e64729844a46e42ec6a8abb2
-dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=18da4a1fac25597186bdc5c825c71bc6fe020e8e6552ac97dd307a0311acab20
-dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=86a7ec123586e0c953efd23b82aea5eab62ab8c065bf3596d3001a23b01243ce
-dist/2024-07-26/clippy-beta-aarch64-unknown-linux-musl.tar.gz=267b8dd0b5024152e36bcfb15af0b8ae3c68a71f559b8ecea1a3c9a8982e315b
-dist/2024-07-26/clippy-beta-aarch64-unknown-linux-musl.tar.xz=6aaae715599da14ca8cc405e51deed3bc160661ec56e929ae347ef1ead7ccf00
-dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=f794412df97e19240f628037f5d1d7391dd09ee1a6de02f4dbff72e2b03d94b6
-dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=49a78a14b9638cabd19ba4261f5bd04066646e1260146e3be288182b73fa1864
-dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=3dcd9775b46a100a50fbb00188dffdc6f07fca9843994c8406a2d053e41c1672
-dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=e069b852ace430b2f75486a291d3d7849439c67c3381f5eedc0d6a9e6cde56db
-dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=57f7109bef934d0da06f7aea6eaca72b0e66f82d1160fbae05f53c2276da2b82
-dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=5ed50d8d088ae0d86ba51a03bf56040da027376f70b5114f593813daa4ce7a40
-dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.gz=d8712ca2ab26256c0fade4ecc8dd8e4ea6770d91e16e460ff2fe3f070febc59f
-dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.xz=9d0c88881e0535f9cb4a48f59b389b1c2a0b5fa46ad8bfa37fbc540676a8f557
-dist/2024-07-26/clippy-beta-i686-pc-windows-msvc.tar.gz=ffa017562648e98c7229e43a7422602c265441228485f0e14e52ebaf48a13e91
-dist/2024-07-26/clippy-beta-i686-pc-windows-msvc.tar.xz=292ab3d318a34e67463728752dc175f65cf5530f9368344dccaa79bad4df3b85
-dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.gz=89bd927bc9370a405561f6534c5cd88e0f6e06b0b512589e5722349b12a17763
-dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.xz=732120c4fcdde08fadca139216a91af7a6abee15f0a41735dc8860b36039d88d
-dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=101e3118bf23246195b159abab59ee5626e767977d97f00e71fc5e67dfbf7784
-dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=e40c0c15a7b195ed03c5e1167c2cb5e765ef643b0f6621c36643faf87bf46369
-dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=f6ed6391c8997f942d180cd32e81aca654450fb050cd865a8a1b13f77a892245
-dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=16e736f65b0ff029fe9fbafceec938123dff1b5a133f6c48b25edab379a20685
-dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=711fdb406a23ab5c3b1199e7af06608297bd071d7e48734a03bbc1f7a00b66dd
-dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=36d05ba29927b56e0d815dd09b39a3db12b6395e9717e653c20449fa83aa636f
-dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=d53fb59c723a2e76f1716cf1c82aacd2627e1694aebf70511c24529a4fe1ee99
-dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=ffec66667d95cabc893cc87988218552eba8930f031419612f80144dcf2cc881
-dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=a2cd11651304ecf5ce6a1ee5fdd1acbfd36b1dbd2680cd76f2b9d3a86012b837
-dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=c8a8d9fe8badb1e06811412a15ce9cdfef07ecc59bf83cd578b33889751bb560
-dist/2024-07-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=01ba50dae501edf3afa60aab59d8d81ccfd91126ded4cf7d45f7c4b13fb8c4aa
-dist/2024-07-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=a7e749bc581f9c64137a00dd891c4abff0d7f5684d2d501aad20ed1b01d9a312
-dist/2024-07-26/clippy-beta-s390x-unknown-linux-gnu.tar.gz=f19081755c37e3dc43091b06bcdc59c82b28c6fa0a78ff02d800a25d6d9f22f2
-dist/2024-07-26/clippy-beta-s390x-unknown-linux-gnu.tar.xz=d5f222e23f4f0ed4929e11684bc7b861c29fa183fffba0dbbfd5739b921f5234
-dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.gz=edd631b7938dae6bb6c2694df0dab3ff6670e1a5ab3b5f0e6ce5bd7e992b6310
-dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.xz=e4bc44ff13cfdd70f94c5efe86e93de041599e570c19611141c00700a656b40c
-dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.gz=1b1aff83773de4dd972734cb03209eccfc3793f442a1a5dea51f451ca34cd1cc
-dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.xz=71c357ff694cd954314c47e3bd458465453c65e6022799827b8560ecae16fdc8
-dist/2024-07-26/clippy-beta-x86_64-pc-windows-msvc.tar.gz=d4759993b9659ad8354d3fdf858cf99efebdf8202442505e11b55d24a54b31a0
-dist/2024-07-26/clippy-beta-x86_64-pc-windows-msvc.tar.xz=e29eaea7b7f2e54b9285a2216f5b85440313650090c268048ce9e830e007fa92
-dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.gz=4009c19d557156e63ad7123d27264650d046cd20e723ec6cc8ffdb3fc1d3b8b1
-dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.xz=9622117651423c53c35f69cb3087a5294cca098ac93aeb7c18bcab035a1e69ef
-dist/2024-07-26/clippy-beta-x86_64-unknown-illumos.tar.gz=a88fd4b3e30faaecf270936422e254a25ff5dba93b08ca4003a9978ee80d0838
-dist/2024-07-26/clippy-beta-x86_64-unknown-illumos.tar.xz=f391b26009b7089f3d49d2f3409bb4e02e3de0700284727d2d26e7062bb18011
-dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=e467501c65651d519ae9a489e821e7d5dc82fdbeb2da2d4c75f093e1b898abd6
-dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=9dcbd07899af86db3c101275ab0f2fd3b5b0c43d4a92c5b5be05f0e4500d7535
-dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.gz=c2a30c78a6ab64d1655651fdd5c7f970dadcd6dfd1a585d130bd890190fe67f6
-dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.xz=05c2a38fa5bca162e365218670a7c195ebd9b3491d14464282a273dfe93b0ad7
-dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.gz=75ee727a80119a810193519535f962721d547297feb9b5597b397e59277de701
-dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.xz=002b726868a14df5ea31fe8eb75fae24660fb1cfad73591e86f9179dd1bb2dc4
-dist/2024-07-30/rustfmt-nightly-aarch64-apple-darwin.tar.gz=d3bb2f1fa20555373189caa7e58a8e3071c7ea6e7059bab15d6dd52dfef56c4f
-dist/2024-07-30/rustfmt-nightly-aarch64-apple-darwin.tar.xz=ba0019eb0766dd438069988156994270959c875b010afce0f455540a0bb2ee2f
-dist/2024-07-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=24bbbe80a998b78f04c15d82fcef9498315b1b8d0ddabeeb5b6729b14bafbf70
-dist/2024-07-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=cc396d3639c7213ab6442dc79ab6a1a42bb17910aa6d27046cc89ebeb6973231
-dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=e6dc772727a20920607923ff5a99526054e6244c40cc6c97fe68db58896de6fc
-dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=eec95e09ec7bd64ab8a47e7311103f5bc58aa3499edcba052699686315f8441a
-dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=fef3eb7d5dee7458daacfba9b97d579868864267fcdc85334f02384683ce0c17
-dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=44f376f4d9e84645373b4cbfe17678c288a71b92622ab4091ca7b82ed6a21b57
-dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=5c17927f12149fa605e3f671d25ac456d1d2bdac796b5ca466bfa7fb8688d224
-dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=04783b1a2efc10696b0d32fde7c63437e17548d38b2272f928f28915107f4f18
-dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=1365d93efc4391f189726e69c7a968c8debb50411f29404da42d19bc9e053937
-dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=db344c9f6d31ac5a2efc839cbb886c312534e9b1fe4b116629eaca74f79c316d
-dist/2024-07-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=049a2b666956a56365661d944a0fc030673bec5578062ddaad104363f4ff1031
-dist/2024-07-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=32d3bc08316c0cfc3c1ea689ccdc80978f744864c048863b9d51ae59b6e2f0c2
-dist/2024-07-30/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=bc33833cd41bf5ac36730fc9d3ef9c87643d42b8e711de286138962fb5fac4a5
-dist/2024-07-30/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=feffb4527ad627a0239d788272edac9a0fbec704de3a67aabbd8a9cbb95d4fe3
-dist/2024-07-30/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=0ffb98b839f6640ac75e094cbb469a06f2e45f51ced01efbeb51a3fba866a048
-dist/2024-07-30/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=d229ea866bf4d6c2d8d748630146c7bccedb4ba5a17056fbdc4558baf976f067
-dist/2024-07-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=431de55efb797c75d8e440ba3da9ac70a04cccfc56b4e22b80b6488360915f90
-dist/2024-07-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=e9e4eac4205014b6b61c759a8326f7a5e44e8ff05726510a8bbefd656f78e97c
-dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=99381507f8fc42d9bd00c545dd7ef4734e364a4e994d02bae148f78b94f50ab5
-dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=6e2cd283d9370beb9c208bd823ac2433df500adf7e70d8acfe5a261e62be2b4a
-dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=761a9733f53ecba343139bd1c028a66242824ef8f7c54ae63e0aaf0e77cabcf9
-dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=c2973a99220588ea78b7a052861c345f01254073d6bb77e96982b12382907e2b
-dist/2024-07-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=4288ee8fc5f650b3d5c24be2ea114e133d3bad8ddf7e2211cdb72151410c755a
-dist/2024-07-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=2a31e1f211a26f6798acd4c779827bfa4e1ac4d77103a48be74617e5af1661a1
-dist/2024-07-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=9598edeb1ff5eff934f1e4783b3ed263babb53d3513564ccccf453dada872ba1
-dist/2024-07-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=eb5392fce8ee4a016406efba546366ff91d4db8cda94dd131dbda70c553b6c06
-dist/2024-07-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=0e9c55ee790eed653eda7b913e64d344ccbbe1681321377186d1e4882dc93bfc
-dist/2024-07-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=c9a0b3eddac707c4e0c1cdc754d2821845e5f4bdcbd001b71d7287fe851cc44b
-dist/2024-07-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=99c264f806d4a6a1288a9cc7f28e178102520ebe4728fb0da3f8142c1d6720e0
-dist/2024-07-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=3f1835460dbf17a3dbf47f2772e182ebf6337fd6a946a033f9700fb38140eda6
-dist/2024-07-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=385224b95c56de8598dd5b4eeb48d7d7a8eb920825c55bb4d7be54142d7e2857
-dist/2024-07-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=535220608ee858d46746c8de4c1e58f4f675061517b6b06c8af47004d5291f85
-dist/2024-07-30/rustfmt-nightly-x86_64-apple-darwin.tar.gz=aa19f1856befff101bcb433049e923486d7bc1a056638e478651936572e7e3bf
-dist/2024-07-30/rustfmt-nightly-x86_64-apple-darwin.tar.xz=2ed04cf9fddeafbb83d82988e00d3b7f5ae9382468ce1093cbb110bf46b04711
-dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=962dea60de3ac68a573f088f9c1b003816ce93f9088df15fe8cf7771a3abdc73
-dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=72f7b787644bd9008b13018512c0b09a425c15a337821dc9bded9ab7211c61de
-dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=1096ba25a23461eed84804584eb9ffdff780e2c737cc9dce1e8929419dfd645b
-dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=854b9e410e65b953ab71f356bd5b618679aa7c1f5a3de7f81ec388720ed04f60
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=03b4ab410c70fee3daa7a577c311b29344158a7d35ea87627233cb6165191338
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=d755700cc17416c4488db2d582250b5ec329fc0c2b94e9db0e6688ca30a7316c
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=b7448089c61c2f0a427416cd7521130c31a98c52e435bd0d04d6aad72d765ba6
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=cb3f479897032ff9ec5e06913e8e4374ce46af7f8a9030299c7b0cab2dab2005
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=0c7dbff79d04218a7ba3f5992f67d25043bc5f348038f37ab7385cbc4d0df00d
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=4f62cbc75a81d57748111a915ebb20f561f403c1b695141780d50c398b186fa6
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=e5e8b07ae7ba0e1f526828a10f2515a68b0ed6023eed25e3bb10b80e21e8db76
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=424ec90c59fca7e21b302efd7c6c7f7dbc5dcadd1afbb15e90efea38ea8a19cf
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=f22576893113958f6caabcf3ab3e38287fea010c1809a8bb1197220d6660ea4e
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=5e85141abe2a3c537cb4171c60cff5bdb11f075aa79212e0a958081d4648aec6
-dist/2024-07-30/rustc-nightly-aarch64-apple-darwin.tar.gz=f793e4645be9461fae09e82710bcfdfc6d749735be202f2e2cd6c2c643bb8925
-dist/2024-07-30/rustc-nightly-aarch64-apple-darwin.tar.xz=e42f52cc5a865ab92321b97aaeff4d39cbaad1a5b60a9a77de9f42e3b3231d21
-dist/2024-07-30/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=0258ba5bf957d190ef3a384c5451ebbe8406c195a29b3a7ee2a4c48e0514f203
-dist/2024-07-30/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=788b7e9239562f43c0d96cfd66f543604eef1c9b40d22898c456fade608e9c31
-dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=94187df22d7b96a5c39c5c9a078f566b80d392abfd2a5d7059b836cfa0c446e1
-dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=ca1381c6de1a96f32a30736c28aa196f7e653b4f57f01ffe2db52fe238a9f202
-dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=1c72596862a133003f68590a8ae09bf6ab25a5f9667a6d245eafede1ebd8f450
-dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=de0c216f229301bc88690b10b8f063b8e389915503980973b91bfe17b1fb6eda
-dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=e00283a7ee9a702446456feb0156f1d1fc738fd013983f15c456fcafb8294309
-dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=03fab128bc3756676c645f637edc5051f8096b00780d8ef4de7a85b3f248933a
-dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=105e06c0ca69b4a700980f2a588f831c23a9a9253268bd652110328b99918cb1
-dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=0da27ffe5504a03923ae5858b69cdd6eb276e6bd2bfb504bcf13ebdda654316b
-dist/2024-07-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=edb1bec402f3799e05fd3e31f30763e7266d2e062e410af8eab7636440da272c
-dist/2024-07-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=638a09ecfe0b66391ce6802e3e15bf15462aca1c8cfb2a49b948ec69eda0575c
-dist/2024-07-30/rustc-nightly-i686-pc-windows-gnu.tar.gz=456683fa10703ba8249f8b1735293c79edac0c32aec60c1a91315fb41c8e5ecc
-dist/2024-07-30/rustc-nightly-i686-pc-windows-gnu.tar.xz=fd5d9a7bf543d3c61ca85340961d5e17b42b37c35fe45c666c2a0e125548f42e
-dist/2024-07-30/rustc-nightly-i686-pc-windows-msvc.tar.gz=2b75a4e15d1f98f123ef74aecab3570296aeb7e35f18548a2b3d1735e01b06e0
-dist/2024-07-30/rustc-nightly-i686-pc-windows-msvc.tar.xz=1163178e95180725bd31b7dabf1e9a9788a8e7cc576dd53148cfec32443e64a1
-dist/2024-07-30/rustc-nightly-i686-unknown-linux-gnu.tar.gz=0aad8dd79beca26278e1c1847dde17ee22ae64b78f2b02be65e12bc126de699b
-dist/2024-07-30/rustc-nightly-i686-unknown-linux-gnu.tar.xz=a548e90fbce90c26b6700cff7964d72c7e959a6f317e891db4f91ce7cd187c41
-dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=654ec9040afb20d660603adcd31824efeacef0ae2d48d342bb9504bd2f723453
-dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=998407bc1303eecb1ef4c6b14862ffdf31fb0cf991f5d169a822a23627b29352
-dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=5b4febf9a1802c2c756ef8a7693a9cfd83bf95284d79d9f9b9dd265234d6aebc
-dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=dbc2a6417fabcfb37f4fa42d50391c1cb29f18d1771321088c08afdf0a0e4809
-dist/2024-07-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=2befcab4aa3e31064b87e4696aa2f1e76bd9c24067eb1921feb7f6497d58338c
-dist/2024-07-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=508a3c1241507a53a0d6b27df2171eaf0a4df903773b5592f005ee4d39d91287
-dist/2024-07-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=c4e8da248306be350f7a89b2522e976a12ab89d5ae2e19157ed3b148e3948c50
-dist/2024-07-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=5858e1cf6371f25ba3c381e07ba6f4551c2a13516011fc10dbdafc4caf1bff93
-dist/2024-07-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=3639bbb7aac353772171dcfaecd589352de3fd8cc7395e7628d7590830034af4
-dist/2024-07-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=3cad5f0b74fc3f5be70cf496c93054c50e8a3f92cfc894a2febfbecc382dcb55
-dist/2024-07-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=437fc8b815c09a3c5159735d9fec0e5d8dd64416149cb77c13a16863e6636412
-dist/2024-07-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=7bc2917e7816f7df1bc7faeda28010d247c923aba412b5ec1cc9c6757eec37d9
-dist/2024-07-30/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=603e391a14c26a51f4f02020b5abbd307d29476fdc0689e5bf9570f2e6ac69a8
-dist/2024-07-30/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=d04ea4e522cf1ecaa6b2f3edcb32155142378bc648aa159a574838ed2d58b794
-dist/2024-07-30/rustc-nightly-x86_64-apple-darwin.tar.gz=0ed639da01e58645eb33a75e020d57c58c92651d817e89574cb67bae5b298d35
-dist/2024-07-30/rustc-nightly-x86_64-apple-darwin.tar.xz=b4010f38396e7b8acd67cf2234c94ede11cf78a226a134c809d504e594037311
-dist/2024-07-30/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=7ec8aba7a7581d59c7ceaffdd374852d08b17bc7e02674c5bfd4f47f4a0aee39
-dist/2024-07-30/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=41c3ba0543220e11bc53282dd7d2a37acd6450a59683e1c83d2150dc798cfba7
-dist/2024-07-30/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=67e5d75dda47c587a4be517db547354d1da0228110b7d5488d8822a7ef7cda20
-dist/2024-07-30/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=4b5f0c4101a783dd313c0cd1435d7eccfeac97452afaeaf42ba975805541dc74
-dist/2024-07-30/rustc-nightly-x86_64-unknown-freebsd.tar.gz=09e12b5003969b768b5c06b3e3b41a64429e28c32790ff28c12b8c5814f350c0
-dist/2024-07-30/rustc-nightly-x86_64-unknown-freebsd.tar.xz=a4b3b402cf4beb3e7c7b9b6620f34d045ef42261514ae7d8483d3790d1dfd88a
-dist/2024-07-30/rustc-nightly-x86_64-unknown-illumos.tar.gz=c344d0c95aadac0e5e0100743b80768c9d0cd76b123ab07e6387ad1ea3e3efba
-dist/2024-07-30/rustc-nightly-x86_64-unknown-illumos.tar.xz=ac0a79660227fe163c796e6b816596299f6d8b32ba008ce30cde492709efb7c0
-dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=4090ff8086317662d3def1bc92d51e6f2decd2c64f4b6ede38604fd5029d3d02
-dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=e665bd4e3763b456576eaa45bcf188648cc6e6443ecdff8ef91a5c7649cbfd25
-dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=4fa994e08274599ae3bceb9310c584be89d11f231aad3e8fc1e2d6a6ddbb77bf
-dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=bd8d53403bf6337782bffc3050a46887fbe2568c850809c5b32c8d84492d2ee9
-dist/2024-07-30/rustc-nightly-x86_64-unknown-netbsd.tar.gz=606a430036fdda0b92dd4a4cb99830881389693e6ed02a01ddd51eaecdfdf463
-dist/2024-07-30/rustc-nightly-x86_64-unknown-netbsd.tar.xz=fa34273b20336b8b373f686c88ee297033f635895ad225a2ca5271b6da3d7dea
\ No newline at end of file
+dist/2024-09-04/rustc-beta-aarch64-apple-darwin.tar.gz=cb6487c102a7c5822be2236d79a2c4737b0ff284931c61607518a0de8d300abf
+dist/2024-09-04/rustc-beta-aarch64-apple-darwin.tar.xz=2556c7c07811195e94639f6d6556a0f49f3c267e0e3bfc44b1fdc555aac1ffe5
+dist/2024-09-04/rustc-beta-aarch64-pc-windows-msvc.tar.gz=c207a307bf10a50e2884f4d9408528a22703e1010dd921459541ee11aecc2405
+dist/2024-09-04/rustc-beta-aarch64-pc-windows-msvc.tar.xz=d6f99991029db32be7527dbe1a6ae840600db6d7497123156e6672f7a0e83aa2
+dist/2024-09-04/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=b57cb4d25045e23f897078216776f244a73498ea89240077bda7a84c31c2f4fe
+dist/2024-09-04/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=2c2b95c852114d7b18c3db13234ac56f933b70c3cf8b5ac9fce65415434961fe
+dist/2024-09-04/rustc-beta-aarch64-unknown-linux-musl.tar.gz=1f216d67bcd5d1e011bd2c6c69b6791c94e29cf7da3ab7dea82ff71a911e149b
+dist/2024-09-04/rustc-beta-aarch64-unknown-linux-musl.tar.xz=86abb27afb03e347abff65e4e34f1ec2e943af14f04f8cd9dd8666338147562d
+dist/2024-09-04/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=842754febca1a5c6f7ccacf231621ba4578d72718a950ddedbf07a73594fa55f
+dist/2024-09-04/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=3094887ecd5e3432e1ada0bba4a425213215c50680dc30d0c1d15ffda5bc62a0
+dist/2024-09-04/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=27192e3423f2b580d7927ae788cf778ff9c092e2eb7cdd5d16b41aa94d2bf03c
+dist/2024-09-04/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=e57767bd767964d51533e2310f177827842bf49176895280b3de3860caf351ab
+dist/2024-09-04/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=b639bfce72277714769d36efab294ef3578573b93037160be7dff9f4a6e6b5ef
+dist/2024-09-04/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=fce2b931641d51e88eb3e34d60bebe75384c1981654937b16f1333438d8b0696
+dist/2024-09-04/rustc-beta-i686-pc-windows-gnu.tar.gz=b58f7013b41044260ab2f9456940d9ce017dcfea06059fae8a672664f8ba00df
+dist/2024-09-04/rustc-beta-i686-pc-windows-gnu.tar.xz=c91958645f3c4cd562a5eb800ddb843aabfa2f067f5659313fdedeb270935bf8
+dist/2024-09-04/rustc-beta-i686-pc-windows-msvc.tar.gz=9a5075768fe2d42195c639d8c1066a020b573eae24c0c63e9a8876b78c39d673
+dist/2024-09-04/rustc-beta-i686-pc-windows-msvc.tar.xz=e76c27a8892a5b7a74c4d18d10c745af226711dbf62450378a3034a706624ce1
+dist/2024-09-04/rustc-beta-i686-unknown-linux-gnu.tar.gz=c10ffb2db62b113af1feab8625f1d88d31c1d4a4246d00e19a3588c9f69c0164
+dist/2024-09-04/rustc-beta-i686-unknown-linux-gnu.tar.xz=0496fbfa32d6c22929fe94ae5dcaabc47d31d7482f0fe6748ef7b7eb7443b775
+dist/2024-09-04/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=64b55368e8044ea44588c98f1529f46d65f7607ebf2fa2d50785abecfb37c188
+dist/2024-09-04/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=e03528ee7e4e92d666199ebcdde7d10f1d0fbeb2766217fd95f98da93bc361d0
+dist/2024-09-04/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=eeb913008ecfbaaa76b7690b2e68bd1e70efc1afda19f44a1aa551a76e4b536a
+dist/2024-09-04/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=c94c3545fa2a491763b1e593419034294c57a3df2ca8064db0b11d2e82e76c85
+dist/2024-09-04/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=54c97827079aa7646cf206517f603487f4634ab1a17f2a7882b0cd3d6ffae8db
+dist/2024-09-04/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=ee98a0e07989de836ff8ff4e768c6f0f13aa15150d1b59543297f31b2768a5fc
+dist/2024-09-04/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=a0fcd0f7af5b05a22d9be0abb6f3aa44c028c2606195163d2ad4b0352455ed1f
+dist/2024-09-04/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=cf35d480a6c0b439d29baacc4ee4087c4d7b5c1b4050302f3146f0bdbffcd472
+dist/2024-09-04/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=ef19ce4d791b1caad30bc5af9e30494161f343d936a3300eb0d7c5e8f37db441
+dist/2024-09-04/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=12adfd58c851d1f7bb23c5698abf6dffa2c26348df55fbb518c27497f7ebdf17
+dist/2024-09-04/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=818151529f1e445f9202d0092f09f02818a2c52ad6814a89b2bbfcb0227c5202
+dist/2024-09-04/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=e195d07d37699d860ce97422bba7f68166292103cedf4932b3ba8c0d9fa7e186
+dist/2024-09-04/rustc-beta-s390x-unknown-linux-gnu.tar.gz=d4a73ddd7eafdffe7f23720a7202f48676ae0bc49248d3a455c997d718730c5f
+dist/2024-09-04/rustc-beta-s390x-unknown-linux-gnu.tar.xz=475bb6e51f37fc769480345982e14afeee099cdf769773d0d0215d01fc77ce41
+dist/2024-09-04/rustc-beta-x86_64-apple-darwin.tar.gz=c061d06da7d4a283136d8e80f307c1ef4157739898776f5579b8d92980be0775
+dist/2024-09-04/rustc-beta-x86_64-apple-darwin.tar.xz=330b580c90ace563c96db64f639668284d8ede835870acf76b106d4c4913f476
+dist/2024-09-04/rustc-beta-x86_64-pc-windows-gnu.tar.gz=27f9e3c2e9380c689ab0c5e8438f1969261a30445e9b2d38efa9417fba1f4ea2
+dist/2024-09-04/rustc-beta-x86_64-pc-windows-gnu.tar.xz=62fc92dac7be442dcf306ae1baef471447b80a6a221502bf7b14b249dd599db7
+dist/2024-09-04/rustc-beta-x86_64-pc-windows-msvc.tar.gz=c52202bf41aafb517959e01cac2e4bbb53144aa0164f9b31e7b9db0af32be6c6
+dist/2024-09-04/rustc-beta-x86_64-pc-windows-msvc.tar.xz=24db84f0de7573812fe36fed5653fc117c80fc35b02a9340f746ded6a11d3bc0
+dist/2024-09-04/rustc-beta-x86_64-unknown-freebsd.tar.gz=406f8a37572376fec7563664043b4fc3b0e7a48c738b6ef862da3fc41f33b1d3
+dist/2024-09-04/rustc-beta-x86_64-unknown-freebsd.tar.xz=93fa021ca3973a52cbccd51771536e2b9a355eae4f4ab95c7168f4af79e96d4e
+dist/2024-09-04/rustc-beta-x86_64-unknown-illumos.tar.gz=a2a5942342b2f5dc7a196500210075ac695f106a18fd487a3c694847013454f3
+dist/2024-09-04/rustc-beta-x86_64-unknown-illumos.tar.xz=c8b63f35f30bb1d6adb49834b3a42dfc07c27042e8411f1b4777adced6193298
+dist/2024-09-04/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=145c5d6e0edb688dbe59f9c638959e11718e0bdc625db76bac1d2836efd9f116
+dist/2024-09-04/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=82845313e17067dac361eada63fdf2479fc177e8aa97aba5cb40a50861e276bc
+dist/2024-09-04/rustc-beta-x86_64-unknown-linux-musl.tar.gz=8351011105a5a338adbd2433ff5aa24cd038a67c0f0d040e4b92926d4aecd28e
+dist/2024-09-04/rustc-beta-x86_64-unknown-linux-musl.tar.xz=b2a972069142d5fdab775fd7709d4bc85b1c2c4167e9c455d2ef1b72cc207fd1
+dist/2024-09-04/rustc-beta-x86_64-unknown-netbsd.tar.gz=327501931ce36eb5613e5e77fb5356ff24f60078516473cd7f664bc970aee994
+dist/2024-09-04/rustc-beta-x86_64-unknown-netbsd.tar.xz=6d940ec725fa4931c914c291977f63828fe71e9763a3b8195dda668541c9122f
+dist/2024-09-04/rust-std-beta-aarch64-apple-darwin.tar.gz=9bf325e98fa60fcb7d4f09b796f2fe0e7e7c54e83ffba6d5cf30776a0346972d
+dist/2024-09-04/rust-std-beta-aarch64-apple-darwin.tar.xz=45d632045f5e3f8150d82fdc5163aea1d5ad785cd16da2d46293581b09bda895
+dist/2024-09-04/rust-std-beta-aarch64-apple-ios.tar.gz=c42f808164d79e023dc4186e47a6032c0877536a0c9459f3e871c66c129b0f75
+dist/2024-09-04/rust-std-beta-aarch64-apple-ios.tar.xz=9bbe6ae21530fb0555472f9a540b7791d5dce059439608d797507057199e696e
+dist/2024-09-04/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=ae8005ea419f9f19be0c2603529d8801dc77e5344c72c1bd42eed81046fe5113
+dist/2024-09-04/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=0053948699aba18b2bee7473f335940573aaf4bad6aabb00f28f2a335d280dab
+dist/2024-09-04/rust-std-beta-aarch64-apple-ios-sim.tar.gz=5adc7721f8f7fc0537b11a28ee2df6d90b96222a07590c84fab4dbefe33087d1
+dist/2024-09-04/rust-std-beta-aarch64-apple-ios-sim.tar.xz=4f3a9b61500ef3a38961288784c61a520baabfa597e997195007e0e229d1e4bf
+dist/2024-09-04/rust-std-beta-aarch64-linux-android.tar.gz=7192a628d6605b437a7203c18d48ac9a5af4879674117e9aebafb5029a10e069
+dist/2024-09-04/rust-std-beta-aarch64-linux-android.tar.xz=845177bda3220a534b20c66cda3bf27b0681c2977dfbcedeaf41022bc518f832
+dist/2024-09-04/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=1a0ced7e1fbcdd38fcb33f1753f3af8b23f075d4ce38c3d1256ba142ddf80a47
+dist/2024-09-04/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=75272f629adfaacb58c511163ae9b73714fe3f60d5e39b4cd996a42226626518
+dist/2024-09-04/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=3b19e6dca8515f28a2325d7cf2f098e82e194d4418fce7c3caa94c9c08023646
+dist/2024-09-04/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=138e8e1a85efb4f66ec878db18dfa48681f3045589c7b9a749afd0104dafd278
+dist/2024-09-04/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=6da128ca58f46d2608c4d9630c09de263b853f9fe8b6fa41def0749e99a128e0
+dist/2024-09-04/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=67a2c04a9f4947b4c313220150521f494364c5e589ff23a4584fa60b924ae095
+dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=85ccd5a6e81caa63d4d4cfe55eead8a3829a5636d41f7640ea393bf7652eec28
+dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=fb91518e70808c659f6f078c0094ca471e4e4f5d81c29c1bdc8907f6bdffc64f
+dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=410b24f1372f84d60804b4bcf20fa2025adaee3c56ab7dabda1e320809acafdb
+dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=64d7fa38af8a1c38e42bc9b9ab909f476d3388b7d02a21ba92519145cb3a3df8
+dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=f4722b2a656d4f87bd13d4c8da6116e993e916114c55a2fd1a588e51dfde4ab0
+dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=cb9150701f21de444addcdc9a53c83eeed3aaa3bc447e8f6358825a2f889bff2
+dist/2024-09-04/rust-std-beta-aarch64-unknown-none.tar.gz=26cf0407f17db7645fc1a4051d08246f1325b17941dd5139cb69b782498aa043
+dist/2024-09-04/rust-std-beta-aarch64-unknown-none.tar.xz=9dcdfd018e2ca6f21d0689adb152917a8695c2f14c4f6a53a5b52280219c2540
+dist/2024-09-04/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=1d1e555bb8af601d8df16b80dd263391a4c0805e1203c618fb370de1911a5a17
+dist/2024-09-04/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=078d88a6d4882696b3764d10dbd10e0d756752255096690e895903cd83265c70
+dist/2024-09-04/rust-std-beta-aarch64-unknown-uefi.tar.gz=5933f618e5c99e06c8556871a85016eba58f6de1056468a1ad47823105908fba
+dist/2024-09-04/rust-std-beta-aarch64-unknown-uefi.tar.xz=322f61ff7a6f6b261bbb9c592f50a39fa179c1f870d911a57b2afda7d7b2d196
+dist/2024-09-04/rust-std-beta-arm-linux-androideabi.tar.gz=e66bc47a75e12569032c81f6c950513e3fc78cf75e496e9873792b4c83f3dca1
+dist/2024-09-04/rust-std-beta-arm-linux-androideabi.tar.xz=9a84da40c9e5fb55e1ebad0dc9b724fe9d71d86bea0d2227315590f290fdce13
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=3e8b535ec051eaaf63490649b1258ae64f1786abca6967bdc3eb6c6da96a4d81
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=4936561a884b3b725a9b78651ea05a36da5e643be4e574416e12ba1c1e5f37d9
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=00eb51ffccdac33a39da37878104dded2c5efa01da5adf8bd932a0d9fb49d17b
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=3eb187c4a6f416672a8a36997aca5f04bab9ec6aee3a0d1f4ad5a0ed950605c3
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=66752ad65876dad43c19973f8967a098236f2605d2aa82df5b0f040247e049c3
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=f508b8c7956209c87259b38bebe5576ca8a5662a4d4747941082dd39d991610e
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=926f2839c6627c822aa9f494e99030873987b6fca66364cc12ba468928a93b9c
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=e2be0999ea8df01c1029b0976861162c9c60e41a87b4097345f2c5822777ee2b
+dist/2024-09-04/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=ec912c9e372cd0ae1a754305f0645580cf40f9742c4cbcc54952e613d47f595e
+dist/2024-09-04/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=f86091e5d806a9b4efa388e036ee69fa63fca68feca174c6670cd04966e2725f
+dist/2024-09-04/rust-std-beta-armebv7r-none-eabi.tar.gz=d51aa780c5df5b8b2e1fbbe97f79914ed083ea13528c43cca797ab8931a418d2
+dist/2024-09-04/rust-std-beta-armebv7r-none-eabi.tar.xz=19cbb2d1d8a6a3a33669da9fab7eb48f78f0682d777d2c2f188daf6d91895bc7
+dist/2024-09-04/rust-std-beta-armebv7r-none-eabihf.tar.gz=a1ae798b4eaf206510c33d5af1d4c99ed553fce89413449a5f82d5b80a2558aa
+dist/2024-09-04/rust-std-beta-armebv7r-none-eabihf.tar.xz=a0cb421635b927e5b255238658c9f9f5a0b2da60e05c993ecbda35af9318d6bc
+dist/2024-09-04/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=5f9995804004211baefab1d230089a5719bce40b632bd3380044142a89ae5f2d
+dist/2024-09-04/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=66f410541f2f53d44b2a2931b10a229c8143d6e9caabadea2df40704aad71854
+dist/2024-09-04/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=64b62816adc9574f6961832a4c469e1103057ed553a4c42796e3af4962dc694a
+dist/2024-09-04/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=3c0b3741af7f9b50d041dd52fe86fb4144c295632a6eba0197e77ac4ca94ab27
+dist/2024-09-04/rust-std-beta-armv7-linux-androideabi.tar.gz=aa3d37e6fc483c798a9debecf2ae7609609d0560baebb90733582b9bee15c493
+dist/2024-09-04/rust-std-beta-armv7-linux-androideabi.tar.xz=ed88cf7c141efd01eceb81b3b85e4eef38f559d8652d2fc4bf3395f4e3d2ef48
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=f8b34e2dd9bb5b2ea008bf6a69944da389d8d086a1ece57c1572c749717f4df8
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=7ae6076c42fecf7b92305af4220abd3d724d49d96def617a67db1ef298b74bb5
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=4e13553b0288f4cd046372c080f4968a2b69bcb489f6929e98e72682b601d4cc
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=dbaeb0445cfc110d7879a23ea7c4034cebb4158cd9781d8719f51864356a15d4
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=164fa06abffc38aaf81c86aeb50fde51c96d713bb78d759a6f7e668c7967bdfb
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=2ec4d5e339593555d02ea738ae1815e27d108fce5faeffd503308780c80a1a8d
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=36a09d9287c9d89b3946dc6aea2ce846e754ca2b07b667035f62e8d00c81587c
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=573316d483a27930bd1423ae8c1f2624dba141865150a41a5be317cc53fd850a
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=487feddaa3b11ad15b544e3338f4dfeb1f5297ce5d851dec1df36eee7bc016a2
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=866f612bc4fce03e851eb0b370282b35b066018c2b2467d265cbdde4bcc8afbd
+dist/2024-09-04/rust-std-beta-armv7a-none-eabi.tar.gz=3b2f1fefd2d97006264e5ce50839c8c22e9f6553f639e95c8bcc5bd01c54bead
+dist/2024-09-04/rust-std-beta-armv7a-none-eabi.tar.xz=55294ba0b8da663399c427b57157f4a3e43b117c77e011801410a9bfb62584a0
+dist/2024-09-04/rust-std-beta-armv7r-none-eabi.tar.gz=60ef291da36a614ddfd38c8bac0519113dc1203603181ba3a581df074fb62f07
+dist/2024-09-04/rust-std-beta-armv7r-none-eabi.tar.xz=6dde05a2b3a57ae340f699f959e7032bb6e53cf7e1ea24bf1dd88766dba2dcdf
+dist/2024-09-04/rust-std-beta-armv7r-none-eabihf.tar.gz=cc2ae41c8c8ee69f26eb55a033e5c6c23ec1e968aaa4c2e03357b62056176725
+dist/2024-09-04/rust-std-beta-armv7r-none-eabihf.tar.xz=dc7d1e0637369b0a32f8730a771e4b059ce45131b51beb276de8c03e153834b5
+dist/2024-09-04/rust-std-beta-i586-pc-windows-msvc.tar.gz=d6ce6f7d1412c1e0ec60a09c9db3d9bcbd0075617dd1756fa82e93d3df0ef8e4
+dist/2024-09-04/rust-std-beta-i586-pc-windows-msvc.tar.xz=60ff61cf60ac63a6c1ce3c6558351e873968ea1f812afdc7516ae5d19d85e54e
+dist/2024-09-04/rust-std-beta-i586-unknown-linux-gnu.tar.gz=4f5204d8d51ecbf0768419076c94dde6e0c776a9403e3e108866eec3faa68d06
+dist/2024-09-04/rust-std-beta-i586-unknown-linux-gnu.tar.xz=3ba0815668b11d682a54bfc4731aca5f7a821d77ab8ac32f9922bf9d684d72b4
+dist/2024-09-04/rust-std-beta-i586-unknown-linux-musl.tar.gz=ac1094f3e22829c4e3e27a91dae48f84ab2bca4373a6e851bdee807887e145ab
+dist/2024-09-04/rust-std-beta-i586-unknown-linux-musl.tar.xz=6547347750eefb619ac15256a3e1ef09c3ee633d73b23aae239cfcf4261f0d16
+dist/2024-09-04/rust-std-beta-i686-linux-android.tar.gz=af1e7557a1008392a0c2eee4f9e6b26ca56b21be2838ff4a4e3784363b1c3423
+dist/2024-09-04/rust-std-beta-i686-linux-android.tar.xz=b5d395b1c6994447b3358058aaf2219f952cb9fe6d5df0d8a533b9c2ed84134c
+dist/2024-09-04/rust-std-beta-i686-pc-windows-gnu.tar.gz=a0c0535feb405bf313035cdbc690fd80c18e1975ef0da2fcaeaeab66eb8ee461
+dist/2024-09-04/rust-std-beta-i686-pc-windows-gnu.tar.xz=85b08876c40d2bc1b44bf7d64319d1dae3af2dbd75cf3e3f37b3ea20bd21209c
+dist/2024-09-04/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=60c37fb7de68381a3665728eb6a74ea017d81e2dcae11acf683cebcef7267487
+dist/2024-09-04/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=a97edc7de6792da17dbcb6b5a67da4aa79784921c2b160185b2c8a806bd4945b
+dist/2024-09-04/rust-std-beta-i686-pc-windows-msvc.tar.gz=ea25bfabaad2bc02b0d37672bdf9357f317fd27031ef6039460e25c066917b11
+dist/2024-09-04/rust-std-beta-i686-pc-windows-msvc.tar.xz=ef65a47d79945d6375347c9889c3ec3250d4635e1918689cc1f992b7daf4f547
+dist/2024-09-04/rust-std-beta-i686-unknown-freebsd.tar.gz=5c4ca0b3bca99fc468bc7ada8ef1d202e9be8ba9808298485654ceab545538e8
+dist/2024-09-04/rust-std-beta-i686-unknown-freebsd.tar.xz=59ffa74e46e807cacd4ea0a1b16ce0ec7152c4458ad9f86feea82162b1c53da6
+dist/2024-09-04/rust-std-beta-i686-unknown-linux-gnu.tar.gz=dc535c0b1fe81cc6d1bbd8fecbc0625cb85c44a6f10dd8641fb8ae88083febc5
+dist/2024-09-04/rust-std-beta-i686-unknown-linux-gnu.tar.xz=624ce72e0b60a7b0d9a06b6925fd0e9a3bd50d9d7ed59db4a16145ff5381c232
+dist/2024-09-04/rust-std-beta-i686-unknown-linux-musl.tar.gz=6d43cf9f2dc34205616b17eafa8bf28f951de538e6d80ab4993d9b840b72ba49
+dist/2024-09-04/rust-std-beta-i686-unknown-linux-musl.tar.xz=b397f611d609167ddf2b5699d7cfef9da9c6c78988c7ca2c32b2f81f6640eba6
+dist/2024-09-04/rust-std-beta-i686-unknown-uefi.tar.gz=878584e638e92902521231a4b578ae1828d1e06093104b6ceca9a22a6c05939d
+dist/2024-09-04/rust-std-beta-i686-unknown-uefi.tar.xz=2806b9124d6145b65bfefc2e72a8ec3f745d3972904b7a2546bcaf649028a332
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=eb2792e0b57b36ed03762eff460bfbb7d8b28aaa309702e7e6414eba0a7d0e63
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=c36d7526ad190b15a41a1695be4b813d09d649395b1e91bf6dadc336333c690d
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=d891dc7b3c1d05a1c245076a6656f2ad33cba79073e36e8e1eb11ab0c0045cdd
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=6dbbd097bba35b9f0465a6d6b4d19d8b4700dbeecc1b0919aa99c72cad564a0a
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-none.tar.gz=54da489ea59169e39b50d0be0221e20cf03bdad413854e0f35f66c323bf4e88e
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-none.tar.xz=4c360c531107de92b695dd389514dc0af053a04d28c566a06a25e467d5ab548f
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=7ce834710452cb0569cdd234698f647db87e774d3e964493e17017a81a417aba
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=3e554450f5107e02335fa14fc7c7a2a3d4718741001f0f4e43984a3c0841ddf4
+dist/2024-09-04/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=e8c8607e58379162fe0ec072bd544c97d73619df88eb56aeccdf2ebd5357f1b3
+dist/2024-09-04/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=1dd759c92e6c1f67d5b697e1034b4962434a17211383741d0cc71acda9fcf209
+dist/2024-09-04/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=83907d49dd4cf4f73c1295571400c9761bae7a3b2447c140a358a07710e28f93
+dist/2024-09-04/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=f1ec605497fb3d7d364f2dfb7bc5c4898940518c1712b0271372ee608d61fd34
+dist/2024-09-04/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=ac2b94c0f76c1f23be43880c01aab0a45d47e48a6c53b5dcfcf4e9507aa481e9
+dist/2024-09-04/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=129ff2031d8ae69c34e944516bb47e093a2f2b47972bd401337fc1dc8b0f2b93
+dist/2024-09-04/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=2dd17129ca857bfa97d8ae3429984f80a116cc9f967809b7e5bdcc5845398a30
+dist/2024-09-04/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=06426a601db3dfc60f01b03bc201d21cc6bdc9b633a564e7025518decb91fea1
+dist/2024-09-04/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=80bcbeed550e6ac30e9826cb801be5206d7937d2d940fca2d40ddabec62e2111
+dist/2024-09-04/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=2994ee26443be51f11e8cc6e66aa2ee38e7f9440efbe0aa6aa2c513b3fe07f33
+dist/2024-09-04/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=09f2b6dd18ebff39077a252e0d4b63b3557a49fb3a4f218f50f127aa44f653ec
+dist/2024-09-04/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=156c0ef4be19442b8f59269815e570faa464332ccd2a8db91828eff9ab702ea7
+dist/2024-09-04/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=037ceaaf4b1356f72d16f2a6c0dfe50b1df8a82743da79262b020712ffcfb7ff
+dist/2024-09-04/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=a6e6f00d5df339ac19ebe2c661a5a4ec9b648328767db864b3db1bde0b330bfe
+dist/2024-09-04/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=6da55a90ba454e77dd2c90d5d5c5ed833befab415ba65adf27d8e36645b189c0
+dist/2024-09-04/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=9213accb8bc2b3a678c3b3cb4300015b1cc52798157e3898d99699b96bac486d
+dist/2024-09-04/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=5504f5fe7b45570922f7901476b8ac1eb28e9a7643bf5ace75bb368a644a05f8
+dist/2024-09-04/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=50109eb03c075ced8ebcff0909450f173e00491efece5874b8b59ad750bfc9ad
+dist/2024-09-04/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=1ed3d0c1066b52dd2174ed45635386ff22798de8cee92765503fbcf71463094a
+dist/2024-09-04/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=e2b22ed31374775441c6d80da80a52bc7558a1363776363ae341e78d0abf34fb
+dist/2024-09-04/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=eff055a0e773741c4c2101791feea744c57ae95c50ad32ebec616daab1d098c8
+dist/2024-09-04/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=680c9c2de4c7abf391d073709988593eb1daffe19876bd789a0f810f9d8d8458
+dist/2024-09-04/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=ae71d4f0789955cc883948c75aad9e492e37c206a64561705c8b7a9fec243f3e
+dist/2024-09-04/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=f41ecbae85295dda2dde95653a059be1852eacc28c175d36cb82cdacbf97a5e9
+dist/2024-09-04/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=1db39d0674e227b0fcacbc9de7aea52a349f515aaa8ea595cfbd91c6138e0b4c
+dist/2024-09-04/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=971c6dd1c7e3c6ab14d6d5f563edf974c87cbfd2a2028bced6e01175c8abafe6
+dist/2024-09-04/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=029150a3c19afdafaff023ffd80f7aa1c2cfce7d7464339b0873a6e3da10a923
+dist/2024-09-04/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=22a4612a5a7b38adb3e63ec8526444e51fe222c125c2ba51499987a3906b1cf5
+dist/2024-09-04/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=069c8fc749bc2ed94179af8e38849b83912c84cd551c4bf27f95e99def8ed0fc
+dist/2024-09-04/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=5b436df8a26688cc9853f5e12735187e9924a44101e21c4e59fc3dd38778e39a
+dist/2024-09-04/rust-std-beta-sparcv9-sun-solaris.tar.gz=77f6b8e4760ea43aac97ebb177223ad943fbbcc55dc3656afa400d7d1ea35787
+dist/2024-09-04/rust-std-beta-sparcv9-sun-solaris.tar.xz=d2b3e49982ccdb966f420eaba9d582108b227f1acb485f0b176762871d41ef3c
+dist/2024-09-04/rust-std-beta-thumbv6m-none-eabi.tar.gz=5e511b55cc961482998cca16def2424e749cf83a46a52b235e902baf8a653cca
+dist/2024-09-04/rust-std-beta-thumbv6m-none-eabi.tar.xz=8491ec0a3233b04909ad307bf679d6a012fe153eb9ae544956c8fa87a57dd55c
+dist/2024-09-04/rust-std-beta-thumbv7em-none-eabi.tar.gz=9b4d4913146843b01b4b6b7d8e1230c01f764a2ae2433dbb3264bfad14d0b3c6
+dist/2024-09-04/rust-std-beta-thumbv7em-none-eabi.tar.xz=ee700f3dca7d811a230222627ecc6c22d9850151adf47c2a48fb840a079508aa
+dist/2024-09-04/rust-std-beta-thumbv7em-none-eabihf.tar.gz=d54ea14641f79deb2b661e1fe9e9ff56d85189da5ced0f96c16503892c4b367a
+dist/2024-09-04/rust-std-beta-thumbv7em-none-eabihf.tar.xz=cd1529c6f77a079fbf15bcf81d41b4f18a8572729975b2a3ac91e18841e93495
+dist/2024-09-04/rust-std-beta-thumbv7m-none-eabi.tar.gz=fe214540eafddf6dc65ca94f1dad3a12df9e92a157060a9c27a730d99a706b28
+dist/2024-09-04/rust-std-beta-thumbv7m-none-eabi.tar.xz=2b9b1289855f7d9520eab69bc8c4e8505857e44b1e498968e47e3e847ae5a7da
+dist/2024-09-04/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=dc28759dc83a72d5c8505e90abb98ee55fb0ac53736422c95b631e063f566e5f
+dist/2024-09-04/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=b25c463af699783e8df43d7ccc5d1692d97e8a1ade8322dcf0cd74246d1d94b8
+dist/2024-09-04/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=bb8ebf0008749bafb9cee686c7b09db4e4585178b506bc9bec6508577bc98713
+dist/2024-09-04/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=afb9a8ed9a5dccb0c43eb6a920c647735648a1378413ff1fae754a7e5f972b06
+dist/2024-09-04/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=b090d076b04e7894a94c1ed892825a3f6d27aa3908d40d1a66f098b9d53f4309
+dist/2024-09-04/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=3213f7cb7365420b767779edc091a35f9e3a39e9439d0bf542dcc099eff25ce7
+dist/2024-09-04/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=5d977dc47e7c04d1f729a2a153e2c37ceab7d9a049b111505146e82b7b3bc30b
+dist/2024-09-04/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=8e9cef53163ff70ec8868d11d7c237cf40ced06852fcb193b3ef45232c3cd90a
+dist/2024-09-04/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=01f1916e4de4401ef0b7c43bfb0df72169f36ab09eda9ee923ef0d6608b8fafb
+dist/2024-09-04/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=1a9a9fe79884bd8e8e35cc8bcf3d1fb7a82ee4a40c630b78a302aabb047959f1
+dist/2024-09-04/rust-std-beta-wasm32-unknown-emscripten.tar.gz=66da8c5a7e579df020ef012747f9c8ce6a3094bdf43a99dc3763a9234eda3fff
+dist/2024-09-04/rust-std-beta-wasm32-unknown-emscripten.tar.xz=34ba780c992a10428fac49c9149d1f613fac221dd92866a93795543a991c29af
+dist/2024-09-04/rust-std-beta-wasm32-unknown-unknown.tar.gz=485304f0705ea8ef1a3516cd01e9b63e010af514edc03774cd87284367ed5e04
+dist/2024-09-04/rust-std-beta-wasm32-unknown-unknown.tar.xz=414608d21dd7cd268ad57a6be916b0be2c95433e2bc14083ff8c4a7a7cc8952b
+dist/2024-09-04/rust-std-beta-wasm32-wasi.tar.gz=c745c8682a54abe37c2734bf0c7931b6d10269eb56c07765e39dd289dab67e01
+dist/2024-09-04/rust-std-beta-wasm32-wasi.tar.xz=732c12837772531eabc44a7d4a545e130e2ae220d3670748fa2050cd4c65a18b
+dist/2024-09-04/rust-std-beta-wasm32-wasip1.tar.gz=2b54c587ddd908481f5561d6de60c7fdbef234ca2ecec4eb4d4791416038f7db
+dist/2024-09-04/rust-std-beta-wasm32-wasip1.tar.xz=799ee151f0aa3c5ec132f03c42152393d966c9249972967133edef56b30d66ae
+dist/2024-09-04/rust-std-beta-wasm32-wasip1-threads.tar.gz=120b8cad5a2a153bee58ccf81824e6a1c7c16befdd2785f963a9b2dfc350b9f2
+dist/2024-09-04/rust-std-beta-wasm32-wasip1-threads.tar.xz=5d74a8dc4731ab433cf796e7568122c7ca1463c648d2b49876ae1deaeaefa314
+dist/2024-09-04/rust-std-beta-wasm32-wasip2.tar.gz=911e60f2976d3b98dc9f6e82f72c459c5e07713e2dde2c7337569a71db2d1218
+dist/2024-09-04/rust-std-beta-wasm32-wasip2.tar.xz=947d312ec07c6190dcd4abeb493a2b67ac64a9a549ef30372c8eee7164c74883
+dist/2024-09-04/rust-std-beta-x86_64-apple-darwin.tar.gz=7b6e65885f14982f1112a2c0e8dd3266b1c4313276342ed98f2681432720b8c6
+dist/2024-09-04/rust-std-beta-x86_64-apple-darwin.tar.xz=cdbe462e3935c5a34415275afe830a6b5edae2fda84ed35e836ae868c884d19f
+dist/2024-09-04/rust-std-beta-x86_64-apple-ios.tar.gz=f75e7896ed5c9b64f817e9b2d6ed4d637e19ff26a14f72a570b4eff532f5b32b
+dist/2024-09-04/rust-std-beta-x86_64-apple-ios.tar.xz=60db5599bdad826b32637dfd2989daa90597b278ac14b42ede3a7c15aed119e0
+dist/2024-09-04/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=3f57688112d2d80010636724acec5083bce0bc0a901f9ccbd76a09bb21de2b17
+dist/2024-09-04/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=841dcf3eba0ad5b7bc8a4d55fabca80a1a27a3d697431c251b48912131148b6e
+dist/2024-09-04/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=96af596e4bc63519decc0e17005006aee8a2f22258d86b6efa25a94fbbe62f23
+dist/2024-09-04/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=4215a327f11bc7fa02546e69cb52c6c7bfe6a1ca602a6bf7a266e11937204bef
+dist/2024-09-04/rust-std-beta-x86_64-linux-android.tar.gz=80849fc95791de8cf98da9ebd405a4e268445b22b9413c8545870fe83f5891c7
+dist/2024-09-04/rust-std-beta-x86_64-linux-android.tar.xz=f849ad9d7ccc7eda06404e3bd67f150c3d8dfa66609405435fb2ba09c00ca136
+dist/2024-09-04/rust-std-beta-x86_64-pc-solaris.tar.gz=f871244a44131b1e2f56ad7c77ccb4e7433f39d6b248951f449914a65178bea3
+dist/2024-09-04/rust-std-beta-x86_64-pc-solaris.tar.xz=933b3b634b5caf57213be093977b0f56ba3609dc9407ac026079f75f4783642d
+dist/2024-09-04/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=28ef28c4b17b5e8a20ae5f19feeb4643864f64ac8e9c68b84f8cec067317c339
+dist/2024-09-04/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=1e40daa830d390d57c0dd23331849edf45adc0a35d120725bfd9fae43edf13e1
+dist/2024-09-04/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=b9a6e290d7b9c71b4a33164116cc523654c3147168a04fc7608a27397c100944
+dist/2024-09-04/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=a6e1db0945d1a5243caf2d1ad7d24b4dd16f8882d3e88118f203c91ff5e2cd52
+dist/2024-09-04/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=8d70d70a645b36e6de01b08a34a28a995c73f91e8a285607a5516180d3a93350
+dist/2024-09-04/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=d5a6fc72bf9dc0b7083d364358232a5df68b2b9f03a1a553bbeecf2a84936cb8
+dist/2024-09-04/rust-std-beta-x86_64-unknown-freebsd.tar.gz=01e159405178d883deb8eb09e9101826e7591c8d8fd6840133c0e8f77e00e395
+dist/2024-09-04/rust-std-beta-x86_64-unknown-freebsd.tar.xz=7fddda753b5f3e244de9427de6399052c81df87bd2b76d2c1f9a0fa4d1d1cddf
+dist/2024-09-04/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=2c37eaef53b50d812205ed24de580165bfa800658ab9a9ea503667105119a544
+dist/2024-09-04/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=8d1e3d290c5736c4e7a48a6b1a88ba18b9e68876638896b31b61917c6fcd2af4
+dist/2024-09-04/rust-std-beta-x86_64-unknown-illumos.tar.gz=83a57ec9e9696a63dadf9307e0cce117b92be8e9b7d17edfe410d38f75629202
+dist/2024-09-04/rust-std-beta-x86_64-unknown-illumos.tar.xz=3db6747b556581f02e0cf058b93538785d1eca9aaefe36dc8b7667428fa05ef7
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=fe737fb11bd2a16b7636013f37041a35126f0bf8b2c562ac38384d45e49088c4
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=a7a3f5245067b2967bbc4bd010ac3a6e9613cc9b6462c53cdcf0b91eab6cddbb
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=8b3fa007713d4e37de79d5662a3de446d378e00fc631478e465fb170447c49ea
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=c2dd95e94f9a9bc2d31e807a3b7cc5cb43a994cd4400ac1636ade3005344146b
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=a294420b029900027530932ebd29cbd3f17672fffc60128122473088329f8cb8
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=72a1c8052534e1b986ebd1bb5364de9e9e67353cfc6de7341f759d8da370bf2d
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=7227b14f3148302d954756bd4df570289aa8dedd8d889b5399821356ac097f8a
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=61cf15b98ba67fb648ee87901bc33644efc342c2b6401ab8b6a14cae755cbd8d
+dist/2024-09-04/rust-std-beta-x86_64-unknown-netbsd.tar.gz=61b604f112031aadd7ad87e535cbb4966c53099e276fc76d99fecd0e912b2e28
+dist/2024-09-04/rust-std-beta-x86_64-unknown-netbsd.tar.xz=428a0a6955266ac0e74b11bb4c58a461c041f13f241d5a2d698139b4b5839ad5
+dist/2024-09-04/rust-std-beta-x86_64-unknown-none.tar.gz=c8b29984bf2b6d77893cda301e55dd128da76bad7dd87c751aa5585add2262fd
+dist/2024-09-04/rust-std-beta-x86_64-unknown-none.tar.xz=1460566b927586f6afa531aa1cefa9aec0d4e829a08a151638a42c255b6a7ef3
+dist/2024-09-04/rust-std-beta-x86_64-unknown-redox.tar.gz=17503716bb940d50db15bd1b467fe03ff15474f1b0b162eb3f2891699d898768
+dist/2024-09-04/rust-std-beta-x86_64-unknown-redox.tar.xz=66007a1f995597a697747886eacbe38c9d6a588b1ed365e6b4b522c72bc7b8af
+dist/2024-09-04/rust-std-beta-x86_64-unknown-uefi.tar.gz=b612bac841c9f93bc6189971bf82df47e8730cf1696d2d6f3344be67a6c28f0c
+dist/2024-09-04/rust-std-beta-x86_64-unknown-uefi.tar.xz=3dd0f70f8f226160700a52c19aebc2f27801360a8d2882702c5a0be94560da3b
+dist/2024-09-04/cargo-beta-aarch64-apple-darwin.tar.gz=3efe0d5356824c1620e223686c81cf10b629db0a0c385c3177b5fe1866776b5c
+dist/2024-09-04/cargo-beta-aarch64-apple-darwin.tar.xz=07deeec79d74a39b0cf971bd980936eb476005bf0e832adef9e4521bba3c010b
+dist/2024-09-04/cargo-beta-aarch64-pc-windows-msvc.tar.gz=c9da3632a36a2db512015580bd20e0b5207f8a0d98ae093a99755e4c512215f8
+dist/2024-09-04/cargo-beta-aarch64-pc-windows-msvc.tar.xz=b0b9aabd90863c1671ad80955277c2f006654779837cb1358774b8189fba357b
+dist/2024-09-04/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=cb862535909b1f0fea6ee40a6a888f2f860f95b8700b1d5167bd7a41b9e33958
+dist/2024-09-04/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=b1ff8f714cda2c98a7129e861adcf33245bd84bdfbdcec9fb1a89545dcd033f7
+dist/2024-09-04/cargo-beta-aarch64-unknown-linux-musl.tar.gz=5c3659e979393c8c1dbe1a6ccb09eea412671363e228f0c7ab4bd4896cd48470
+dist/2024-09-04/cargo-beta-aarch64-unknown-linux-musl.tar.xz=0435e1332b1bc40a280fc867eab54e925135eba774c3bc0553a8bb100d644f59
+dist/2024-09-04/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=6f7f079ef04c4b1d14864cba67ec650a3e43f3baa81fea1797d00067f22a72a8
+dist/2024-09-04/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=549607bdeacd26fa770ecb00ce54cb3ea72c5568e65966c1fddc3a540b9f6e6a
+dist/2024-09-04/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=e23b18a2a86bca5320b66c54d43a54d90db1b787443cb0e04d66e9d7428fece7
+dist/2024-09-04/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=5968c534ce88a2574a4f59a0ced82df36aef9c7338ed9c718e85aad514a792f4
+dist/2024-09-04/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=3170e39d306e797e5631884c629ecb33a54635056b5a71fbebe5372c1c34da37
+dist/2024-09-04/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=76b729642fdba25c015e49e444e158170d3ed2ac0a533ba7c6095ecdc0862ba5
+dist/2024-09-04/cargo-beta-i686-pc-windows-gnu.tar.gz=c58826189772af945c9d40868e80d64359f4108afa06d150a3d350323b0eb8df
+dist/2024-09-04/cargo-beta-i686-pc-windows-gnu.tar.xz=1b644d661778bfcbec892eab17bee06861940037992821c4ded8321a69c0f6a8
+dist/2024-09-04/cargo-beta-i686-pc-windows-msvc.tar.gz=e026eac2c2e891976e085d26591d85000dccf3c3654f3edd65e99c6c0ba43574
+dist/2024-09-04/cargo-beta-i686-pc-windows-msvc.tar.xz=e7307b2e55302228c5036991ca6141a5202a16f43b0148607f3802fdc90aa0cc
+dist/2024-09-04/cargo-beta-i686-unknown-linux-gnu.tar.gz=0a00604bad2096cd0b0db59a1b41b5737696015a4ddc60f9b1132829a4cd0a5f
+dist/2024-09-04/cargo-beta-i686-unknown-linux-gnu.tar.xz=a623eecb18a21b2dc6a4b62876b8fa4fc467c53fdd0cfdac493f89d619be5aa7
+dist/2024-09-04/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=64955892d99d0e7f0042016d7a5e3ac87f89b6f514b1934611050f89aa5f6a28
+dist/2024-09-04/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=3c7c3061c466fc4a1eb836c97cab95d511778d77d220189a6a77f8e5b46e4888
+dist/2024-09-04/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=be1c255840307bd24c2c8b5c92e2fa0eed6037daf3ed9597e17bc56f313ef506
+dist/2024-09-04/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=d0e456bc8b64a0ee778e69eac75b6a258c37f7b2d06496a8dfcc47d91e1c2dd1
+dist/2024-09-04/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=b9cd94c4ac9a11eece8712b325d08007b641d5da7487fd38b30dbaf0f3d1b5a4
+dist/2024-09-04/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=68dd4a74494fe8f02781a2b338eff5f5cc78d66048eddd3ed7cc3e31dcecd2c8
+dist/2024-09-04/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=b464ad7a1233e3ad5129340e623a60d2ad0882843acbef60a9aed45a453ccac1
+dist/2024-09-04/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=1167f3d38628c01b11dfb9f66eacdf4cd519b46ea1b8c9d182a390e7d552a933
+dist/2024-09-04/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=eb16d3791a79aa384326e2e79aeafd8d3e27adf4733a5bcca441e278e578b60e
+dist/2024-09-04/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=d100dcb6437e87b3b687a7059dd932567855f68d962a109268fcce5a5aa688c6
+dist/2024-09-04/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=ee771d98286302d4a8a93ba5165c342a2fbe770bf7758f8bbc490ad188d2e5cc
+dist/2024-09-04/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=d2e9eb5a1800545eec4186b5252737f3b3a02d232473e6864e4c6fd752a69623
+dist/2024-09-04/cargo-beta-s390x-unknown-linux-gnu.tar.gz=b35ef65a54c9dd068a699f4210c0c88bd2777308fd7ddad3c7d0b9a1c994657e
+dist/2024-09-04/cargo-beta-s390x-unknown-linux-gnu.tar.xz=eaee5c891aab499438427c2c965c2c8f4471a3b051effee139f251f544ac4ac4
+dist/2024-09-04/cargo-beta-x86_64-apple-darwin.tar.gz=917ba277cb3f050fb3e65126b587245bf89891256faec33a57e2b1a064075534
+dist/2024-09-04/cargo-beta-x86_64-apple-darwin.tar.xz=179d6fe24981d477eb806ba714bd639750577cb9de2d152116e994d3955ade38
+dist/2024-09-04/cargo-beta-x86_64-pc-windows-gnu.tar.gz=6aa52989d1ccb25b03433dec436507455256cb1e2ed305ba747c342551d0778f
+dist/2024-09-04/cargo-beta-x86_64-pc-windows-gnu.tar.xz=bc0403c00fa2093f09d95b1ad091850b2450f4e1d7fac225a730d7363074806b
+dist/2024-09-04/cargo-beta-x86_64-pc-windows-msvc.tar.gz=5c1e018191c296ddc443699e48c4f1a3e700983fc45ea230172f35881d09e103
+dist/2024-09-04/cargo-beta-x86_64-pc-windows-msvc.tar.xz=f1b44ff315f5332815263d5b0a1cd06f852431acbf5cc902bb6723c3398e11d6
+dist/2024-09-04/cargo-beta-x86_64-unknown-freebsd.tar.gz=7da980ccdb2d6bc0946749fcceaed7124f311b38bf28cef0797ca85909f5d5fb
+dist/2024-09-04/cargo-beta-x86_64-unknown-freebsd.tar.xz=a935462749686fb68eac699ea67ef1afaa22ed0b147d2e4d0a6712f225341fa2
+dist/2024-09-04/cargo-beta-x86_64-unknown-illumos.tar.gz=ccc3d29e88482885090f6fb954518bcb0b6bd3f54283702df9e0e80b78454c01
+dist/2024-09-04/cargo-beta-x86_64-unknown-illumos.tar.xz=c0cb33e5088f2b9f5fe8bedb3915fec10e7f65563013b914e0738486b5e8ebab
+dist/2024-09-04/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=84fdbbc0912c4020dd1baec1d603c5d5c1986c7b321d3d9c0c42184aa6347f15
+dist/2024-09-04/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=8f8948750141c3ee8a50e575f196bd972876e784cf1793b256a5a9462c9e3d44
+dist/2024-09-04/cargo-beta-x86_64-unknown-linux-musl.tar.gz=9ef6b7450b94ce202f1b603151075bf8f595022f2c52f6bcd1c4a72423db2b80
+dist/2024-09-04/cargo-beta-x86_64-unknown-linux-musl.tar.xz=5b63b98d67e211057fbaeb1db3721b90252a331143ca267bb30eebca4ac01cdd
+dist/2024-09-04/cargo-beta-x86_64-unknown-netbsd.tar.gz=69d500e2fca1c44fea31310b0636a9af009d4ec96b5ed2335864c47350fa7b59
+dist/2024-09-04/cargo-beta-x86_64-unknown-netbsd.tar.xz=7da3c2641f0ecdbd8b770402356416750a52265a6848d3734fce2195c889768a
+dist/2024-09-04/clippy-beta-aarch64-apple-darwin.tar.gz=15395c04235f2475d5e41371e2797f181af71275f82f04fbb885b1cd7a197f45
+dist/2024-09-04/clippy-beta-aarch64-apple-darwin.tar.xz=8be6fb9e0cafcd262594cfc4a36807bede9e158cbf7eb38c0f25144bf3bfdd1e
+dist/2024-09-04/clippy-beta-aarch64-pc-windows-msvc.tar.gz=b043e41facce81a5fc607f2268330b279d7e26975e409158ac2cbbc841d10f85
+dist/2024-09-04/clippy-beta-aarch64-pc-windows-msvc.tar.xz=ba41705b213f863416120c28fa4a7959cf41e261cce8233b12fd91aa0157d601
+dist/2024-09-04/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=b093269be813ea76964de2c03c7380bcefab1e7d6e31c93fd3f374619a99a5f0
+dist/2024-09-04/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=06d71273208fcbfa5958987038eacda066d4518b5cd6bd7405a981bf841868ae
+dist/2024-09-04/clippy-beta-aarch64-unknown-linux-musl.tar.gz=aa159e61c4986def9d27f55504d822d6023c277a546e95079161577ae2991df4
+dist/2024-09-04/clippy-beta-aarch64-unknown-linux-musl.tar.xz=7a3023b98a1c72c993d176c85f4790b234c41f35184636d29deeba40d51587a2
+dist/2024-09-04/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=8e30a0377b780311bf51bdc48dcf233a344cb2fd9ae9aec174bc87d29f94c34b
+dist/2024-09-04/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=488c28d10f45a498b1054fad9feb72a848d0668cd12d29b3a81f5569b1145018
+dist/2024-09-04/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=db25c9aa95b08acdaeaba407367a823e9e2094b0616c80b0c8a84d7c2f6c4292
+dist/2024-09-04/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=7c320cc979ebdde8753093a0e4b1da850b1b680c1ecd10c5d3e33242af12e4dd
+dist/2024-09-04/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=835c0912556cd5b0b180856359db8d75204830984fb1b5f72bf436f137955fa2
+dist/2024-09-04/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=836a54126122c2abfc649982708d97b6451eaf3a31ba556ed73ec1f4269be738
+dist/2024-09-04/clippy-beta-i686-pc-windows-gnu.tar.gz=90b52880cbd51bacb9597ee4fed07fa13fc399f03c5ba840c0c9e6c0a096b772
+dist/2024-09-04/clippy-beta-i686-pc-windows-gnu.tar.xz=c41be130f3276c4c905eab580e866682e4f3bbdd11b348f4d1438c67602fb036
+dist/2024-09-04/clippy-beta-i686-pc-windows-msvc.tar.gz=f023406dc34bb09d020a41fdf6ceb3e60c90dd38380fbbcc26e9f4e144eebca0
+dist/2024-09-04/clippy-beta-i686-pc-windows-msvc.tar.xz=b21746ec1a2c9fc76ce82917b65c8e73482aaefe5f99282f0c5e9682a3af486e
+dist/2024-09-04/clippy-beta-i686-unknown-linux-gnu.tar.gz=cce9cd9d470250c73437e151622b02f804fff3db045c6de25ee949aed435c383
+dist/2024-09-04/clippy-beta-i686-unknown-linux-gnu.tar.xz=9565f70c8d90540d464fb1f3b8bff52b77bf55189ab938b2c18bdeed751e9e4c
+dist/2024-09-04/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=0d1d63a8eca4d0812446f94bc793fbb7660da11babf5d8607d2798749c938a6b
+dist/2024-09-04/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=db178c0eaddcb318653d4b05fe0d97738440713f0cd120657cc2a3e758d52432
+dist/2024-09-04/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=a604be9f091f88e97f702f619d86b91bff0a20fbd267200ac1e66df2bd823766
+dist/2024-09-04/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=93c395e07a8457b8904c470751490326303e2ceaa93b737f8fc521b49dfbd69b
+dist/2024-09-04/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=08aa4a8ccd7569a0513c2443e2b10993cbb92bed531370891452bd3dd8c0eb82
+dist/2024-09-04/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=f6b0222261e1e2b1465549eda331c16d4ea6729d15e6fe208dbc4cce115e75e7
+dist/2024-09-04/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=96e2dca5adb7f5ffe41e5ff30e9419575f3991adde8bdbba023d11f344044dc1
+dist/2024-09-04/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=3ced511aca7268960c616d0105da02a92d83b7983b6accbb37eba722eff64cbf
+dist/2024-09-04/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=421c27b25b79b9c88e4b65ac7cd0a4f06934a63324c56870cd7fff905869a33e
+dist/2024-09-04/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=63254a01ab1a9a21cdb5a0b3a4da9e8ae7921b9ceec2339df4bbfb19ea7c6454
+dist/2024-09-04/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=4ee751b09816886f8edbc431ab8c63df6c664dbedc40a67748fb17a639a070f1
+dist/2024-09-04/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=7e9ffb62ab6c8f1cbb5f9e0b0a3c79cf104dfac09be2ef1d5e6b6c0c34b406c7
+dist/2024-09-04/clippy-beta-s390x-unknown-linux-gnu.tar.gz=0a49c1e844859f27b1283087c476a559c4c3a4c33c8ce2748165cc5c0b0ed039
+dist/2024-09-04/clippy-beta-s390x-unknown-linux-gnu.tar.xz=6daec872df52125b3de854ff0962433ba13b7cbe5519edfb29944fbc4cc817ad
+dist/2024-09-04/clippy-beta-x86_64-apple-darwin.tar.gz=6611771ce0e7cc19fbbb9383875edaf7de975b6cf154fcd5cd18a09f09793a36
+dist/2024-09-04/clippy-beta-x86_64-apple-darwin.tar.xz=1c90c63f87b43797aa04b88e4c1d0fe0f2ad131060fc8495be190d0ebd89a43e
+dist/2024-09-04/clippy-beta-x86_64-pc-windows-gnu.tar.gz=53a04c1426bc151fec4699848e33141df1b04097d4883c07fc07d2bf0bcddf8a
+dist/2024-09-04/clippy-beta-x86_64-pc-windows-gnu.tar.xz=be748b65b238e3e948e2421f82a72d1108ec79651381b1dcdaaa97df15c981df
+dist/2024-09-04/clippy-beta-x86_64-pc-windows-msvc.tar.gz=24ea01230bbf6b4f43094cfcf6c7c72e6d319c493ff3817456c667b89026c608
+dist/2024-09-04/clippy-beta-x86_64-pc-windows-msvc.tar.xz=37130d66eeaed68f0780b1dc19f2f59a2a0419350920521690d4870d7d71d8f1
+dist/2024-09-04/clippy-beta-x86_64-unknown-freebsd.tar.gz=4e427b7ea0f334bd6ea8c2de7fc1d5bf43d5333bc7a435cf65543c564fab6e41
+dist/2024-09-04/clippy-beta-x86_64-unknown-freebsd.tar.xz=b221491159f5352dd392f6ee6419f9d5d693ac347df9863fdac77f2ca1cf6a67
+dist/2024-09-04/clippy-beta-x86_64-unknown-illumos.tar.gz=9d835b4369fb51ab8c1eafb553b9304548e91dd32784ae81cb783b40985d2eee
+dist/2024-09-04/clippy-beta-x86_64-unknown-illumos.tar.xz=a6780c72c71f2e6c6e1bbc8bc4e639389ab9b7aed0ee7e2e0c21819156b5578e
+dist/2024-09-04/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=613bf471668edb8209910dd13086cbefed0da6dea46dce2013a000ecc4315e45
+dist/2024-09-04/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=e3328f37cfc89de1aabd89653a42ff54b8dadcc49e651b22fda325c00644309d
+dist/2024-09-04/clippy-beta-x86_64-unknown-linux-musl.tar.gz=d6a7a5ee37587c0b92aabfc5b9466d175cb8d05d209412a5beee8a61c241396f
+dist/2024-09-04/clippy-beta-x86_64-unknown-linux-musl.tar.xz=dc73b566be162eef2032eccb69b3542ab3c72b760fe7eeaacfcd367ee0b20f12
+dist/2024-09-04/clippy-beta-x86_64-unknown-netbsd.tar.gz=6f1e0be96b59a63a6616b68717c0a393fd99ec1a768affdd5c86249e5eb5d210
+dist/2024-09-04/clippy-beta-x86_64-unknown-netbsd.tar.xz=30fff8aceaedf6d76c6fc0636c2ddecc97fb66f9219b86299550b7312f043e38
+dist/2024-09-04/rustfmt-nightly-aarch64-apple-darwin.tar.gz=37a5383ba608540ed57484e221e87f3cd78fd35f068e98f0da1d3932d86d2eff
+dist/2024-09-04/rustfmt-nightly-aarch64-apple-darwin.tar.xz=a3935c24f5ac1d69756f4598f227e43304ede4e35f9808b3db9f04adfecc5445
+dist/2024-09-04/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=0b21dd8c54055102a41f7ad622565c1fc36ff97642f2e2998e48d1cb1ebae196
+dist/2024-09-04/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=2a543dbf79042924e8c05aaeed97ff37089c8f6994977b932bacb0403f11584c
+dist/2024-09-04/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=8d9b19108587e6d8d12270ff025579dc559173245e08b94113bb91a7ada80670
+dist/2024-09-04/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=d288770b8a85e24b35561129cc2a09c848006c547ce5fa35d33c8ed7e85d5322
+dist/2024-09-04/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=2e69adc7e75efcd889108d185f200db6280494b05de6a06291dbf26ef32e5d42
+dist/2024-09-04/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=fca74af6db1c53a79a4412a020f56ec9c61603d3373eaa936a57dad45f3751d7
+dist/2024-09-04/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=b2be0123cde401aaed259a9387e04f3978fbddce98096b3a8a654b76f92f2e6b
+dist/2024-09-04/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=c44c42a59887f1479383694f43688f9f2a8174ac89fdf657b2e8619372e0bcef
+dist/2024-09-04/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=3d99bab3656d0318173c414dcb8930291ab43285883ca80a04d854023a4201a3
+dist/2024-09-04/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=29e506c1a18449b84a643f0075f1263cd8512662f55e2c5b18305213e4246783
+dist/2024-09-04/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=b486ff8e1e136ba15c9bb14db08dcd14b612adf1617cf1f820a23ee403958049
+dist/2024-09-04/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=b4d593b5a89bb42e7f9eaa17df12778dd816c75e8997e964371286041691cbbf
+dist/2024-09-04/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=dcf94a642166b0664a63c4162a2d303c75fdef6f2a7f9b3e502ba5baae117f69
+dist/2024-09-04/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=4b27ac17748d8cdcd2bc7b9956541333997c6ec56f7a770628dc8e57fc7f442f
+dist/2024-09-04/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=8a3caf2dc2b786ca58f6d37c011dc210e883398a3734f9f13678a9e57c5ccf5d
+dist/2024-09-04/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=e129b88dd69200e305cc5ae16231952d85f9461dad13fd3bae5e889dac89d9c6
+dist/2024-09-04/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=1bc390abb8f754d5b8679b33186b97262dadff9c6db7268cfbcfe605c628a681
+dist/2024-09-04/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=8420198b0a22aaa5951678b954bcce636c78ba6567a06484c830b3eded815228
+dist/2024-09-04/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=05071fe12ed4030464f996fe36dd2e3f60d3701956275499acaeaf03a16e36eb
+dist/2024-09-04/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=2bfdabab0d03e570c073463a8867bbdb54879f501b0822906fa2aa5705603d7c
+dist/2024-09-04/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=0c7e3b10626a9d9a3f8522175085169ea4e34568a7be0093c6682bb9659bf65f
+dist/2024-09-04/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=deb2b51a41dae2e72188fa6c06c4a7bdb08c2723b3ce823602087bd9eb36eb07
+dist/2024-09-04/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=e34590ec2cbd481ffd237101c239f27bd2298517bb7fc9c9f9b6d71abfff69e4
+dist/2024-09-04/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=9cd0d3dd57b764ad054d4295f822a7fd74a1b1ee5babf77ed2dc2c39ee60b7a2
+dist/2024-09-04/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=62566938d97058dd38b1e0c97aa4421d709ce988544956d6a4aaf3e54425dbce
+dist/2024-09-04/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=8f27c6fc5b56092302e49da973ff08f0d3131465bf9a701a9ddc91d373acc435
+dist/2024-09-04/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=7637f3b8060635595a3d2fb83fef68e9990ff1adb1bd3288c7c41767b37ee2c4
+dist/2024-09-04/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=3275f15e3d7e9ccb991f6f9a7059acefd0bee49bfd4cf0724aed11e51e3772db
+dist/2024-09-04/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=29379bab930e7b350cec51be33663ad67a0d30922d658006911f895221dcbffd
+dist/2024-09-04/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=4f71e948ec587836315d7ec98e6f3c6125a298faf1321b4524257d3c9664f9eb
+dist/2024-09-04/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=5b9361317481269e090b4270bcf754caca8a1797f6b2d83a4c570a4024bb0dc3
+dist/2024-09-04/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=db3bf98663017bec6b6beba5848a350d4d34f39e3f98bacb321866112cff7c15
+dist/2024-09-04/rustfmt-nightly-x86_64-apple-darwin.tar.gz=9d5b8c84f82ededb2370c20afdb6b7d06d97161a65348f4ee2b6ab2171236cd0
+dist/2024-09-04/rustfmt-nightly-x86_64-apple-darwin.tar.xz=e880f57ba68bce871fa67230db19aab1f146548254867f09e0d83750bbb50a1c
+dist/2024-09-04/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=8b2c79814b202661c74584d7c4aeb35cc0c8520c4df1c81f2fb2896a22385191
+dist/2024-09-04/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=c193e2f2b859239aa0489c65663fb83c4bd7a87571d5b6ca6572f722c46cef64
+dist/2024-09-04/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=8d6583366248882490371ef5d4532f82ba1779cb993b0078ca6903f9b6a0c5be
+dist/2024-09-04/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=0b69fdd8edb566a75cdff616e09223b10796a91eaf8bd90aa11ddd6af61381b9
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=0a452883a9a494f1613f9b0c796d13745e56eb85597142a677c78daeca95a67c
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=01eb4d938f6e9228cae297688340daf298bf6e5322a4e3cdb4e06554fa131deb
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=4d9220bee07e3576f34c3a3dd327723ed660a774c4391f7a4a7e6a78ea2ca88c
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=2e2cd60bbb356d7b702c511ba56b480ffe0bbceef8f945be0f7b8e338d7998a0
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=4aac5347a6011ff27609b4a6b413454d610a5687253a7e09d1bcc8c0e3aa0e6f
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=ad3a0127c2cc09893fb19e4c58faa6188afeb575996ee4708eae6c5713ff9646
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=869fbf24ca816b0bf931da79920ae8edaef8a749271434c6522f7ff55920a507
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=f4870110759f28ad1cdde912fd3f79bd8eb0073bd42e436a456f0d04e7c2bd26
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=eac75028d080b3d4ab86dbbb4f46c7734c60bd747e0325afbaa3b7a7cf0003be
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=fe13bf3e0ec3088b35608d65b76f77014e0b90886ba81decfa21019ff222c79b
+dist/2024-09-04/rustc-nightly-aarch64-apple-darwin.tar.gz=ecda4ccde26bf6f8405ddbb838239c4f42e9136001e8954b21357d86343ad06d
+dist/2024-09-04/rustc-nightly-aarch64-apple-darwin.tar.xz=cdb1b12e6acf5b2bc5a5328f7cb292760d391b3e269d2b2143c87a344efcc9dd
+dist/2024-09-04/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=46af634f433b9c7182637880f7b910ef13d2da9b1d7d4e255f9cd302691b99fc
+dist/2024-09-04/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=a14935b0b82835388886c826b703057af093dfe16f0367c058dd6d352e585859
+dist/2024-09-04/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=68ced431fa8682f83dd79901ccb986accc5a6d948c837c43eb5fa244c19eab88
+dist/2024-09-04/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=fa078e5edc9f6c7be5a39eac722f142d526b68e30acc8f81bd001035fd657a83
+dist/2024-09-04/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=c88a3c5cbb7a8a55f18d27f2c573192d824e33657a143641d1c8fa1504cbc805
+dist/2024-09-04/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=00170baf596aa6e043598e3c38153f29c1cbfe4a63298d4007979877e9c3e1c2
+dist/2024-09-04/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=19a55b89192897c77240404ff7ed8c64cdba106db13be4a1ae86a9ac44753c30
+dist/2024-09-04/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=42937abfd803faed251cecc7ac74abcc3c40332b8466535cc1727138fe03beeb
+dist/2024-09-04/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=3cc5d6e89cd8b53db0c2900a73e59c188e90d042b2e43502e384f44d229b93e7
+dist/2024-09-04/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=4e1ff68b91e0cc730ca6012aa577aaf73dd5108d0b26575eaade0a2380914fe0
+dist/2024-09-04/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=082a2efdf341bdfd9bbe3e2340ae8dbf71bff71908439696d30fa25d00c5fe1b
+dist/2024-09-04/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=0b480d334a3709ca23dfd4839b518391031b6afde4cea0c30f08f160e39592a0
+dist/2024-09-04/rustc-nightly-i686-pc-windows-gnu.tar.gz=bf06c7a0faebb7dbfa2c09d02f506410f05abc6aa2ba54c515f2a429e904de2a
+dist/2024-09-04/rustc-nightly-i686-pc-windows-gnu.tar.xz=c49f577fa788bb6b40350dd9e9f9088ded647f0a5cf5df69135a83d2e085d9ca
+dist/2024-09-04/rustc-nightly-i686-pc-windows-msvc.tar.gz=e42254e299e367c9414c4b61715125410ddc3ecb30f2457e4eb843725c6b6abd
+dist/2024-09-04/rustc-nightly-i686-pc-windows-msvc.tar.xz=91a752b8a61b81281203297712b1bc775a227d9626b4c84d9e10130f428f843d
+dist/2024-09-04/rustc-nightly-i686-unknown-linux-gnu.tar.gz=6f23df634f3e7028d9a6e9989e1edbc2d00e9b435473807f526fd58c150baf3d
+dist/2024-09-04/rustc-nightly-i686-unknown-linux-gnu.tar.xz=de7cef873379e3d5ef80b402b9d98bdf74366de27e8f928125081628937baf76
+dist/2024-09-04/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=ef0946845c41e096dced01baf6e843c57fcf695c82d5408a1b7c0a5bbd150b39
+dist/2024-09-04/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=d43bb8987a3bb394d7d2cf39d78f54505700525b250cb30741b903bf8712f3bf
+dist/2024-09-04/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=00013767600b1a5153ed4faa9d227fd55a905c375f712a7ca59573a317684c97
+dist/2024-09-04/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=cf1c4351f70e951290583213dade06fe4a61e6dcbc2d0e69be54ea91210051de
+dist/2024-09-04/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=be1957674fdda24a9cd8935789db35a17d3a0d71219bb6f1256af74c64ffc697
+dist/2024-09-04/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=20541daa3925834012ab68f186a1f1ab4d060cced96646e2142a0f14c04b6ad6
+dist/2024-09-04/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=0eb6741b87d430573c9b0d5b9ba9725c0c03caabc01d5ee258867ea19aedafdc
+dist/2024-09-04/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=8ad4670b74093e3c7055149649145a4af2b2a3d24a68bf893ed72202cc934946
+dist/2024-09-04/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=2d7b60aa2d4853eba2bb2644cb14768a5a864386da0854aca7c1f6397374dca2
+dist/2024-09-04/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=17792328178392ad96b1a0c05405c61d0b1e7196bdca9e55baebff12a4949725
+dist/2024-09-04/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=2db9fe19d4e1d7f68a0802868d9344e23932190e2d46407523208a67b5ba053a
+dist/2024-09-04/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=f0d4df5e4cfeff06eb2cb07c6f9ac0596130923133571fd1702d56a0251ebb99
+dist/2024-09-04/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=4d3fea9ec53336195c0daa2b2937507c2216537647829466a19acee2ce9e201a
+dist/2024-09-04/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=84ca3dccf7af68a343fed4d209771bac7439149695f63517bd048287f4539add
+dist/2024-09-04/rustc-nightly-x86_64-apple-darwin.tar.gz=f6f43ebb82851edae301033a2cfbd02724849c7fda42294818f3081f74d3a1a3
+dist/2024-09-04/rustc-nightly-x86_64-apple-darwin.tar.xz=55b0db99f02bd4c5595117663f6b6cc739f63723999062ced0096727e627f072
+dist/2024-09-04/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=6cb63e57f9873e40695b735b8cdb9f0de70306f1692161cd8f7767b4016dcf39
+dist/2024-09-04/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=79bf54beceda0a7f6580d3ef336d8deae3991b3b57e4c6aba635f9d848cc860d
+dist/2024-09-04/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=7757651c78d5000926bd5e91996ea8abdc32db8e67b31271cb70680f551edd5f
+dist/2024-09-04/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=4671e03fc7100bac43cf332e387161c0ccde77d3f893a9dfdd27be63fff39932
+dist/2024-09-04/rustc-nightly-x86_64-unknown-freebsd.tar.gz=675f49fc6a51d5e715789bc9ad92b9db12a94a033254e34efb65358700207bb5
+dist/2024-09-04/rustc-nightly-x86_64-unknown-freebsd.tar.xz=f9efc43f26600caf2ef7c8084fe94ae31ba540ae7e9f104e6a587c6e4272cd6b
+dist/2024-09-04/rustc-nightly-x86_64-unknown-illumos.tar.gz=9bd74b7ee78a02306f47640b99d752ea373ffdd88067376d9f03564f07edfb24
+dist/2024-09-04/rustc-nightly-x86_64-unknown-illumos.tar.xz=67c5d546df9fa451d42804de2d439229e9b21eb9329ff16eeadcc52f5b6393d1
+dist/2024-09-04/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=dfc427db6a14237a12fd077ccc44c07e7bb46a1b2965a3fb1ddd78a2ec334b81
+dist/2024-09-04/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=8d307dce871ae5f7cc1410e85bb7b38f80aed5c1138030b4f112e727fb8c654b
+dist/2024-09-04/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=b7f84d8aab03afcf2bab8ed21fa3ece6ac418d076e0195381110adfac2aa1fbc
+dist/2024-09-04/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=296083c6b50b7dffe8a62884bac7e831e29487a31c8e6fb319f04f0e62157175
+dist/2024-09-04/rustc-nightly-x86_64-unknown-netbsd.tar.gz=96986595ce82c735b87fe75f00722514c49e7118d38c4bced554c9017377ec91
+dist/2024-09-04/rustc-nightly-x86_64-unknown-netbsd.tar.xz=bf8c9411ff7279fd56bb7e3c68ac29c8ce79ba031317b76aac6a74d20f1511f0
\ No newline at end of file
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index a5da52b..8036069 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -50,7 +50,7 @@ pub fn new(conf: &'static Conf) -> Self {
 }
 
 fn is_non_trait_box(ty: Ty<'_>) -> bool {
-    ty.is_box() && !ty.boxed_ty().is_trait()
+    ty.boxed_ty().is_some_and(|boxed| !boxed.is_trait())
 }
 
 struct EscapeDelegate<'a, 'tcx> {
@@ -191,8 +191,8 @@ fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
 impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
     fn is_large_box(&self, ty: Ty<'tcx>) -> bool {
         // Large types need to be boxed to avoid stack overflows.
-        if ty.is_box() {
-            self.cx.layout_of(ty.boxed_ty()).map_or(0, |l| l.size.bytes()) > self.too_large_for_stack
+        if let Some(boxed_ty) = ty.boxed_ty() {
+            self.cx.layout_of(boxed_ty).map_or(0, |l| l.size.bytes()) > self.too_large_for_stack
         } else {
             false
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index d712699..f61bb3a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -5187,8 +5187,8 @@ fn matches<'a>(self, cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> boo
         fn matches_value<'a>(cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
             if ty == parent_ty {
                 true
-            } else if ty.is_box() {
-                ty.boxed_ty() == parent_ty
+            } else if let Some(boxed_ty) = ty.boxed_ty() {
+                boxed_ty == parent_ty
             } else if is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) {
                 if let ty::Adt(_, args) = ty.kind() {
                     args.types().next().map_or(false, |t| t == parent_ty)
diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs
index 0d2b0a3..fe860e5 100644
--- a/src/tools/clippy/clippy_lints/src/methods/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs
@@ -16,7 +16,7 @@ pub(super) fn derefs_to_slice<'tcx>(
     fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool {
         match ty.kind() {
             ty::Slice(_) => true,
-            ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
+            ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => may_slice(cx, boxed),
             ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::Vec),
             ty::Array(_, size) => size.try_eval_target_usize(cx.tcx, cx.param_env).is_some(),
             ty::Ref(_, inner, _) => may_slice(cx, *inner),
@@ -33,7 +33,7 @@ fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool {
     } else {
         match ty.kind() {
             ty::Slice(_) => Some(expr),
-            ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr),
+            _ if ty.boxed_ty().is_some_and(|boxed| may_slice(cx, boxed)) => Some(expr),
             ty::Ref(_, inner, _) => {
                 if may_slice(cx, *inner) {
                     Some(expr)
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index 373bf61..a2ae36c 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -619,10 +619,10 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
                 | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context)
                 | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg, &self.msrv)
                 | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg)
-                | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context)
+                | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg)
                 | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg)
-                | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context)
-                | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context)
+                | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg)
+                | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg)
                 | (unsound_collection_transmute::check(cx, e, from_ty, to_ty)
                     || transmute_undefined_repr::check(cx, e, from_ty, to_ty))
                 | (eager_transmute::check(cx, e, arg, from_ty, to_ty));
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
index ab3bb5e..cb46109 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -15,10 +15,9 @@ pub(super) fn check<'tcx>(
     from_ty: Ty<'tcx>,
     to_ty: Ty<'tcx>,
     mut arg: &'tcx Expr<'_>,
-    const_context: bool,
 ) -> bool {
     match (&from_ty.kind(), &to_ty.kind()) {
-        (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) if !const_context => {
+        (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) => {
             span_lint_and_then(
                 cx,
                 TRANSMUTE_FLOAT_TO_INT,
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
index d51888e..e00fb90 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
@@ -14,10 +14,9 @@ pub(super) fn check<'tcx>(
     from_ty: Ty<'tcx>,
     to_ty: Ty<'tcx>,
     arg: &'tcx Expr<'_>,
-    const_context: bool,
 ) -> bool {
     match (&from_ty.kind(), &to_ty.kind()) {
-        (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context => {
+        (ty::Int(_) | ty::Uint(_), ty::Float(_)) => {
             span_lint_and_then(
                 cx,
                 TRANSMUTE_INT_TO_FLOAT,
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
index 88b0ac5..362f2bb 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
@@ -14,18 +14,12 @@ pub(super) fn check<'tcx>(
     from_ty: Ty<'tcx>,
     to_ty: Ty<'tcx>,
     arg: &'tcx Expr<'_>,
-    const_context: bool,
 ) -> bool {
     match (&from_ty.kind(), &to_ty.kind()) {
         (ty::Int(_) | ty::Uint(_) | ty::Float(_), ty::Array(arr_ty, _)) => {
             if !matches!(arr_ty.kind(), ty::Uint(UintTy::U8)) {
                 return false;
             }
-            if matches!(from_ty.kind(), ty::Float(_)) && const_context {
-                // TODO: Remove when const_float_bits_conv is stabilized
-                // rust#72447
-                return false;
-            }
 
             span_lint_and_then(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
index 3f130bf..14f4aa6 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
@@ -75,11 +75,9 @@ fn check_fn_item(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>, def_id: Loc
             .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(def_id).skip_binder())
             .output();
 
-        if !return_ty.is_box() {
+        let Some(boxed_ty) = return_ty.boxed_ty() else {
             return;
-        }
-
-        let boxed_ty = return_ty.boxed_ty();
+        };
 
         // It's sometimes useful to return Box<T> if T is unsized, so don't lint those.
         // Also, don't lint if we know that T is very large, in which case returning
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index f80981c..5851342 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -704,8 +704,8 @@ pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option<ExprFnS
 
 /// If the type is function like, get the signature for it.
 pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'tcx>> {
-    if ty.is_box() {
-        return ty_sig(cx, ty.boxed_ty());
+    if let Some(boxed_ty) = ty.boxed_ty() {
+        return ty_sig(cx, boxed_ty);
     }
     match *ty.kind() {
         ty::Closure(id, subs) => {
diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs
index 4662952..eeea3f0 100644
--- a/src/tools/clippy/tests/ui/transmute.rs
+++ b/src/tools/clippy/tests/ui/transmute.rs
@@ -140,24 +140,32 @@ fn test() {
 
     mod issue_5747 {
         const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) };
+        //~^ ERROR: transmute from a `u16` to a `f16`
         const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) };
+        //~^ ERROR: transmute from a `u32` to a `f32`
         const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) };
+        //~^ ERROR: transmute from a `i64` to a `f64`
         const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) };
+        //~^ ERROR: transmute from a `i128` to a `f128`
 
         const fn from_bits_16(v: i16) -> f16 {
             unsafe { std::mem::transmute(v) }
+            //~^ ERROR: transmute from a `i16` to a `f16`
         }
 
         const fn from_bits_32(v: i32) -> f32 {
             unsafe { std::mem::transmute(v) }
+            //~^ ERROR: transmute from a `i32` to a `f32`
         }
 
         const fn from_bits_64(v: u64) -> f64 {
             unsafe { std::mem::transmute(v) }
+            //~^ ERROR: transmute from a `u64` to a `f64`
         }
 
         const fn from_bits_128(v: u128) -> f128 {
             unsafe { std::mem::transmute(v) }
+            //~^ ERROR: transmute from a `u128` to a `f128`
         }
     }
 }
@@ -205,9 +213,13 @@ const fn test_const() {
             //~^ ERROR: transmute from a `i128` to a `[u8; 16]`
 
             let _: [u8; 2] = std::mem::transmute(0.0f16);
+            //~^ ERROR: transmute from a `f16` to a `[u8; 2]`
             let _: [u8; 4] = std::mem::transmute(0.0f32);
+            //~^ ERROR: transmute from a `f32` to a `[u8; 4]`
             let _: [u8; 8] = std::mem::transmute(0.0f64);
+            //~^ ERROR: transmute from a `f64` to a `[u8; 8]`
             let _: [u8; 16] = std::mem::transmute(0.0f128);
+            //~^ ERROR: transmute from a `f128` to a `[u8; 16]`
         }
     }
 }
diff --git a/src/tools/clippy/tests/ui/transmute.stderr b/src/tools/clippy/tests/ui/transmute.stderr
index 0072f62..41a10f3 100644
--- a/src/tools/clippy/tests/ui/transmute.stderr
+++ b/src/tools/clippy/tests/ui/transmute.stderr
@@ -148,8 +148,56 @@
 LL |         let _: f128 = unsafe { std::mem::transmute(0_i128) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)`
 
+error: transmute from a `u16` to a `f16`
+  --> tests/ui/transmute.rs:142:39
+   |
+LL |         const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) };
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_u16)`
+
+error: transmute from a `u32` to a `f32`
+  --> tests/ui/transmute.rs:144:39
+   |
+LL |         const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) };
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)`
+
+error: transmute from a `i64` to a `f64`
+  --> tests/ui/transmute.rs:146:39
+   |
+LL |         const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) };
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)`
+
+error: transmute from a `i128` to a `f128`
+  --> tests/ui/transmute.rs:148:41
+   |
+LL |         const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) };
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)`
+
+error: transmute from a `i16` to a `f16`
+  --> tests/ui/transmute.rs:152:22
+   |
+LL |             unsafe { std::mem::transmute(v) }
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(v as u16)`
+
+error: transmute from a `i32` to a `f32`
+  --> tests/ui/transmute.rs:157:22
+   |
+LL |             unsafe { std::mem::transmute(v) }
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(v as u32)`
+
+error: transmute from a `u64` to a `f64`
+  --> tests/ui/transmute.rs:162:22
+   |
+LL |             unsafe { std::mem::transmute(v) }
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(v)`
+
+error: transmute from a `u128` to a `f128`
+  --> tests/ui/transmute.rs:167:22
+   |
+LL |             unsafe { std::mem::transmute(v) }
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(v)`
+
 error: transmute from a `u8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:168:30
+  --> tests/ui/transmute.rs:176:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
@@ -158,97 +206,121 @@
    = help: to override `-D warnings` add `#[allow(clippy::transmute_num_to_bytes)]`
 
 error: transmute from a `u32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:171:30
+  --> tests/ui/transmute.rs:179:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0u32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()`
 
 error: transmute from a `u128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:173:31
+  --> tests/ui/transmute.rs:181:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0u128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()`
 
 error: transmute from a `i8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:175:30
+  --> tests/ui/transmute.rs:183:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0i8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()`
 
 error: transmute from a `i32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:177:30
+  --> tests/ui/transmute.rs:185:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0i32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()`
 
 error: transmute from a `i128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:179:31
+  --> tests/ui/transmute.rs:187:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0i128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
 
 error: transmute from a `f16` to a `[u8; 2]`
-  --> tests/ui/transmute.rs:182:30
+  --> tests/ui/transmute.rs:190:30
    |
 LL |             let _: [u8; 2] = std::mem::transmute(0.0f16);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()`
 
 error: transmute from a `f32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:184:30
+  --> tests/ui/transmute.rs:192:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0.0f32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()`
 
 error: transmute from a `f64` to a `[u8; 8]`
-  --> tests/ui/transmute.rs:186:30
+  --> tests/ui/transmute.rs:194:30
    |
 LL |             let _: [u8; 8] = std::mem::transmute(0.0f64);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()`
 
 error: transmute from a `f128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:188:31
+  --> tests/ui/transmute.rs:196:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0.0f128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()`
 
 error: transmute from a `u8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:194:30
+  --> tests/ui/transmute.rs:202:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
 
 error: transmute from a `u32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:196:30
+  --> tests/ui/transmute.rs:204:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0u32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()`
 
 error: transmute from a `u128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:198:31
+  --> tests/ui/transmute.rs:206:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0u128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()`
 
 error: transmute from a `i8` to a `[u8; 1]`
-  --> tests/ui/transmute.rs:200:30
+  --> tests/ui/transmute.rs:208:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0i8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()`
 
 error: transmute from a `i32` to a `[u8; 4]`
-  --> tests/ui/transmute.rs:202:30
+  --> tests/ui/transmute.rs:210:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0i32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()`
 
 error: transmute from a `i128` to a `[u8; 16]`
-  --> tests/ui/transmute.rs:204:31
+  --> tests/ui/transmute.rs:212:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0i128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
 
+error: transmute from a `f16` to a `[u8; 2]`
+  --> tests/ui/transmute.rs:215:30
+   |
+LL |             let _: [u8; 2] = std::mem::transmute(0.0f16);
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()`
+
+error: transmute from a `f32` to a `[u8; 4]`
+  --> tests/ui/transmute.rs:217:30
+   |
+LL |             let _: [u8; 4] = std::mem::transmute(0.0f32);
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()`
+
+error: transmute from a `f64` to a `[u8; 8]`
+  --> tests/ui/transmute.rs:219:30
+   |
+LL |             let _: [u8; 8] = std::mem::transmute(0.0f64);
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()`
+
+error: transmute from a `f128` to a `[u8; 16]`
+  --> tests/ui/transmute.rs:221:31
+   |
+LL |             let _: [u8; 16] = std::mem::transmute(0.0f128);
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()`
+
 error: transmute from a `&[u8]` to a `&str`
-  --> tests/ui/transmute.rs:218:28
+  --> tests/ui/transmute.rs:230:28
    |
 LL |     let _: &str = unsafe { std::mem::transmute(B) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()`
@@ -257,16 +329,16 @@
    = help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]`
 
 error: transmute from a `&mut [u8]` to a `&mut str`
-  --> tests/ui/transmute.rs:221:32
+  --> tests/ui/transmute.rs:233:32
    |
 LL |     let _: &mut str = unsafe { std::mem::transmute(mb) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()`
 
 error: transmute from a `&[u8]` to a `&str`
-  --> tests/ui/transmute.rs:223:30
+  --> tests/ui/transmute.rs:235:30
    |
 LL |     const _: &str = unsafe { std::mem::transmute(B) };
    |                              ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)`
 
-error: aborting due to 42 previous errors
+error: aborting due to 54 previous errors
 
diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.fixed b/src/tools/clippy/tests/ui/transmute_float_to_int.fixed
index 4361a74..83814ca 100644
--- a/src/tools/clippy/tests/ui/transmute_float_to_int.fixed
+++ b/src/tools/clippy/tests/ui/transmute_float_to_int.fixed
@@ -1,7 +1,7 @@
 #![warn(clippy::transmute_float_to_int)]
 #![allow(clippy::missing_transmute_annotations)]
-#![feature(f128)]
-#![feature(f16)]
+#![feature(f128, f128_const)]
+#![feature(f16, f16_const)]
 
 fn float_to_int() {
     let _: u32 = unsafe { 1f32.to_bits() };
@@ -20,25 +20,33 @@
 }
 
 mod issue_5747 {
-    const VALUE16: i16 = unsafe { std::mem::transmute(1f16) };
-    const VALUE32: i32 = unsafe { std::mem::transmute(1f32) };
-    const VALUE64: u64 = unsafe { std::mem::transmute(1f64) };
-    const VALUE128: u128 = unsafe { std::mem::transmute(1f128) };
+    const VALUE16: i16 = unsafe { 1f16.to_bits() as i16 };
+    //~^ ERROR: transmute from a `f16` to a `i16`
+    const VALUE32: i32 = unsafe { 1f32.to_bits() as i32 };
+    //~^ ERROR: transmute from a `f32` to a `i32`
+    const VALUE64: u64 = unsafe { 1f64.to_bits() };
+    //~^ ERROR: transmute from a `f64` to a `u64`
+    const VALUE128: u128 = unsafe { 1f128.to_bits() };
+    //~^ ERROR: transmute from a `f128` to a `u128`
 
     const fn to_bits_16(v: f16) -> u16 {
-        unsafe { std::mem::transmute(v) }
+        unsafe { v.to_bits() }
+        //~^ ERROR: transmute from a `f16` to a `u16`
     }
 
     const fn to_bits_32(v: f32) -> u32 {
-        unsafe { std::mem::transmute(v) }
+        unsafe { v.to_bits() }
+        //~^ ERROR: transmute from a `f32` to a `u32`
     }
 
     const fn to_bits_64(v: f64) -> i64 {
-        unsafe { std::mem::transmute(v) }
+        unsafe { v.to_bits() as i64 }
+        //~^ ERROR: transmute from a `f64` to a `i64`
     }
 
     const fn to_bits_128(v: f128) -> i128 {
-        unsafe { std::mem::transmute(v) }
+        unsafe { v.to_bits() as i128 }
+        //~^ ERROR: transmute from a `f128` to a `i128`
     }
 }
 
diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.rs b/src/tools/clippy/tests/ui/transmute_float_to_int.rs
index 363ce0b..64d6e91 100644
--- a/src/tools/clippy/tests/ui/transmute_float_to_int.rs
+++ b/src/tools/clippy/tests/ui/transmute_float_to_int.rs
@@ -1,7 +1,7 @@
 #![warn(clippy::transmute_float_to_int)]
 #![allow(clippy::missing_transmute_annotations)]
-#![feature(f128)]
-#![feature(f16)]
+#![feature(f128, f128_const)]
+#![feature(f16, f16_const)]
 
 fn float_to_int() {
     let _: u32 = unsafe { std::mem::transmute(1f32) };
@@ -21,24 +21,32 @@ fn float_to_int() {
 
 mod issue_5747 {
     const VALUE16: i16 = unsafe { std::mem::transmute(1f16) };
+    //~^ ERROR: transmute from a `f16` to a `i16`
     const VALUE32: i32 = unsafe { std::mem::transmute(1f32) };
+    //~^ ERROR: transmute from a `f32` to a `i32`
     const VALUE64: u64 = unsafe { std::mem::transmute(1f64) };
+    //~^ ERROR: transmute from a `f64` to a `u64`
     const VALUE128: u128 = unsafe { std::mem::transmute(1f128) };
+    //~^ ERROR: transmute from a `f128` to a `u128`
 
     const fn to_bits_16(v: f16) -> u16 {
         unsafe { std::mem::transmute(v) }
+        //~^ ERROR: transmute from a `f16` to a `u16`
     }
 
     const fn to_bits_32(v: f32) -> u32 {
         unsafe { std::mem::transmute(v) }
+        //~^ ERROR: transmute from a `f32` to a `u32`
     }
 
     const fn to_bits_64(v: f64) -> i64 {
         unsafe { std::mem::transmute(v) }
+        //~^ ERROR: transmute from a `f64` to a `i64`
     }
 
     const fn to_bits_128(v: f128) -> i128 {
         unsafe { std::mem::transmute(v) }
+        //~^ ERROR: transmute from a `f128` to a `i128`
     }
 }
 
diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.stderr b/src/tools/clippy/tests/ui/transmute_float_to_int.stderr
index 9cac75f..0cabab5 100644
--- a/src/tools/clippy/tests/ui/transmute_float_to_int.stderr
+++ b/src/tools/clippy/tests/ui/transmute_float_to_int.stderr
@@ -37,5 +37,53 @@
 LL |     let _: u64 = unsafe { std::mem::transmute(-1.0) };
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-1.0f64).to_bits()`
 
-error: aborting due to 6 previous errors
+error: transmute from a `f16` to a `i16`
+  --> tests/ui/transmute_float_to_int.rs:23:35
+   |
+LL |     const VALUE16: i16 = unsafe { std::mem::transmute(1f16) };
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f16.to_bits() as i16`
+
+error: transmute from a `f32` to a `i32`
+  --> tests/ui/transmute_float_to_int.rs:25:35
+   |
+LL |     const VALUE32: i32 = unsafe { std::mem::transmute(1f32) };
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits() as i32`
+
+error: transmute from a `f64` to a `u64`
+  --> tests/ui/transmute_float_to_int.rs:27:35
+   |
+LL |     const VALUE64: u64 = unsafe { std::mem::transmute(1f64) };
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits()`
+
+error: transmute from a `f128` to a `u128`
+  --> tests/ui/transmute_float_to_int.rs:29:37
+   |
+LL |     const VALUE128: u128 = unsafe { std::mem::transmute(1f128) };
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f128.to_bits()`
+
+error: transmute from a `f16` to a `u16`
+  --> tests/ui/transmute_float_to_int.rs:33:18
+   |
+LL |         unsafe { std::mem::transmute(v) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits()`
+
+error: transmute from a `f32` to a `u32`
+  --> tests/ui/transmute_float_to_int.rs:38:18
+   |
+LL |         unsafe { std::mem::transmute(v) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits()`
+
+error: transmute from a `f64` to a `i64`
+  --> tests/ui/transmute_float_to_int.rs:43:18
+   |
+LL |         unsafe { std::mem::transmute(v) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits() as i64`
+
+error: transmute from a `f128` to a `i128`
+  --> tests/ui/transmute_float_to_int.rs:48:18
+   |
+LL |         unsafe { std::mem::transmute(v) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits() as i128`
+
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 5402e69..33687a3 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -808,8 +808,12 @@ fn make_test(
                 &config, cache, test_name, &test_path, src_file, revision, poisoned,
             );
             // Ignore tests that already run and are up to date with respect to inputs.
-            if !config.force_rerun {
-                desc.ignore |= is_up_to_date(&config, testpaths, &early_props, revision, inputs);
+            if !config.force_rerun
+                && is_up_to_date(&config, testpaths, &early_props, revision, inputs)
+            {
+                desc.ignore = true;
+                // Keep this in sync with the "up-to-date" message detected by bootstrap.
+                desc.ignore_message = Some("up-to-date");
             }
             test::TestDescAndFn {
                 desc,
diff --git a/src/tools/enzyme b/src/tools/enzyme
new file mode 160000
index 0000000..2fe5164
--- /dev/null
+++ b/src/tools/enzyme
@@ -0,0 +1 @@
+Subproject commit 2fe5164a2423dd67ef25e2c4fb204fd06362494b
diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs
index 7d6ec47..5114683 100644
--- a/src/tools/jsondoclint/src/item_kind.rs
+++ b/src/tools/jsondoclint/src/item_kind.rs
@@ -5,7 +5,7 @@
 pub(crate) enum Kind {
     Module,
     ExternCrate,
-    Import,
+    Use,
     Struct,
     StructField,
     Union,
@@ -18,7 +18,7 @@ pub(crate) enum Kind {
     TraitAlias,
     Impl,
     Static,
-    ForeignType,
+    ExternType,
     Macro,
     ProcAttribute,
     ProcDerive,
@@ -36,7 +36,7 @@ pub fn can_appear_in_mod(self) -> bool {
         match self {
             Module => true,
             ExternCrate => true,
-            Import => true,
+            Use => true,
             Union => true,
             Struct => true,
             Enum => true,
@@ -50,7 +50,7 @@ pub fn can_appear_in_mod(self) -> bool {
             Macro => true,
             ProcMacro => true,
             Primitive => true,
-            ForeignType => true,
+            ExternType => true,
 
             // FIXME(adotinthevoid): I'm not sure if these are correct
             Keyword => false,
@@ -69,7 +69,7 @@ pub fn can_appear_in_mod(self) -> bool {
     pub fn can_appear_in_import(self) -> bool {
         match self {
             Kind::Variant => true,
-            Kind::Import => false,
+            Kind::Use => false,
             other => other.can_appear_in_mod(),
         }
     }
@@ -90,7 +90,7 @@ pub fn can_appear_in_trait(self) -> bool {
 
             Kind::Module => false,
             Kind::ExternCrate => false,
-            Kind::Import => false,
+            Kind::Use => false,
             Kind::Struct => false,
             Kind::StructField => false,
             Kind::Union => false,
@@ -102,7 +102,7 @@ pub fn can_appear_in_trait(self) -> bool {
             Kind::TraitAlias => false,
             Kind::Impl => false,
             Kind::Static => false,
-            Kind::ForeignType => false,
+            Kind::ExternType => false,
             Kind::Macro => false,
             Kind::ProcAttribute => false,
             Kind::ProcDerive => false,
@@ -135,7 +135,7 @@ pub fn from_item(i: &Item) -> Self {
         use Kind::*;
         match i.inner {
             ItemEnum::Module(_) => Module,
-            ItemEnum::Import(_) => Import,
+            ItemEnum::Use(_) => Use,
             ItemEnum::Union(_) => Union,
             ItemEnum::Struct(_) => Struct,
             ItemEnum::StructField(_) => StructField,
@@ -151,7 +151,7 @@ pub fn from_item(i: &Item) -> Self {
             ItemEnum::Macro(_) => Macro,
             ItemEnum::ProcMacro(_) => ProcMacro,
             ItemEnum::Primitive(_) => Primitive,
-            ItemEnum::ForeignType => ForeignType,
+            ItemEnum::ExternType => ExternType,
             ItemEnum::ExternCrate { .. } => ExternCrate,
             ItemEnum::AssocConst { .. } => AssocConst,
             ItemEnum::AssocType { .. } => AssocType,
@@ -166,10 +166,10 @@ pub fn from_summary(s: &ItemSummary) -> Self {
             ItemKind::Constant => Constant,
             ItemKind::Enum => Enum,
             ItemKind::ExternCrate => ExternCrate,
-            ItemKind::ForeignType => ForeignType,
+            ItemKind::ExternType => ExternType,
             ItemKind::Function => Function,
             ItemKind::Impl => Impl,
-            ItemKind::Import => Import,
+            ItemKind::Use => Use,
             ItemKind::Keyword => Keyword,
             ItemKind::Macro => Macro,
             ItemKind::Module => Module,
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index 0ffb96b..10ab62c 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -2,10 +2,11 @@
 use std::hash::Hash;
 
 use rustdoc_json_types::{
-    Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs,
-    GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module, Path,
-    Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeAlias,
-    TypeBinding, TypeBindingKind, Union, Variant, VariantKind, WherePredicate,
+    AssocItemConstraint, AssocItemConstraintKind, Constant, Crate, DynTrait, Enum, Function,
+    FunctionPointer, FunctionSignature, GenericArg, GenericArgs, GenericBound, GenericParamDef,
+    Generics, Id, Impl, ItemEnum, ItemSummary, Module, Path, Primitive, ProcMacro, Static, Struct,
+    StructKind, Term, Trait, TraitAlias, Type, TypeAlias, Union, Use, Variant, VariantKind,
+    WherePredicate,
 };
 use serde_json::Value;
 
@@ -90,7 +91,7 @@ fn check_item(&mut self, id: &'a Id) {
             item.links.values().for_each(|id| self.add_any_id(id));
 
             match &item.inner {
-                ItemEnum::Import(x) => self.check_import(x),
+                ItemEnum::Use(x) => self.check_use(x),
                 ItemEnum::Union(x) => self.check_union(x),
                 ItemEnum::Struct(x) => self.check_struct(x),
                 ItemEnum::StructField(x) => self.check_struct_field(x),
@@ -106,18 +107,18 @@ fn check_item(&mut self, id: &'a Id) {
                     self.check_constant(const_);
                 }
                 ItemEnum::Static(x) => self.check_static(x),
-                ItemEnum::ForeignType => {} // nop
+                ItemEnum::ExternType => {} // nop
                 ItemEnum::Macro(x) => self.check_macro(x),
                 ItemEnum::ProcMacro(x) => self.check_proc_macro(x),
                 ItemEnum::Primitive(x) => self.check_primitive_type(x),
                 ItemEnum::Module(x) => self.check_module(x, id),
                 // FIXME: Why don't these have their own structs?
                 ItemEnum::ExternCrate { .. } => {}
-                ItemEnum::AssocConst { type_, default: _ } => self.check_type(type_),
-                ItemEnum::AssocType { generics, bounds, default } => {
+                ItemEnum::AssocConst { type_, value: _ } => self.check_type(type_),
+                ItemEnum::AssocType { generics, bounds, type_ } => {
                     self.check_generics(generics);
                     bounds.iter().for_each(|b| self.check_generic_bound(b));
-                    if let Some(ty) = default {
+                    if let Some(ty) = type_ {
                         self.check_type(ty);
                     }
                 }
@@ -133,8 +134,8 @@ fn check_module(&mut self, module: &'a Module, id: &Id) {
         module.items.iter().for_each(|i| self.add_mod_item_id(i));
     }
 
-    fn check_import(&mut self, x: &'a Import) {
-        if x.glob {
+    fn check_use(&mut self, x: &'a Use) {
+        if x.is_glob {
             self.add_glob_import_item_id(x.id.as_ref().unwrap());
         } else if let Some(id) = &x.id {
             self.add_import_item_id(id);
@@ -152,7 +153,7 @@ fn check_struct(&mut self, x: &'a Struct) {
         match &x.kind {
             StructKind::Unit => {}
             StructKind::Tuple(fields) => fields.iter().flatten().for_each(|f| self.add_field_id(f)),
-            StructKind::Plain { fields, fields_stripped: _ } => {
+            StructKind::Plain { fields, has_stripped_fields: _ } => {
                 fields.iter().for_each(|f| self.add_field_id(f))
             }
         }
@@ -187,7 +188,7 @@ fn check_variant(&mut self, x: &'a Variant, id: &'a Id) {
         match kind {
             VariantKind::Plain => {}
             VariantKind::Tuple(tys) => tys.iter().flatten().for_each(|t| self.add_field_id(t)),
-            VariantKind::Struct { fields, fields_stripped: _ } => {
+            VariantKind::Struct { fields, has_stripped_fields: _ } => {
                 fields.iter().for_each(|f| self.add_field_id(f))
             }
         }
@@ -195,7 +196,7 @@ fn check_variant(&mut self, x: &'a Variant, id: &'a Id) {
 
     fn check_function(&mut self, x: &'a Function) {
         self.check_generics(&x.generics);
-        self.check_fn_decl(&x.decl);
+        self.check_function_signature(&x.sig);
     }
 
     fn check_trait(&mut self, x: &'a Trait, id: &Id) {
@@ -267,8 +268,8 @@ fn check_type(&mut self, x: &'a Type) {
             Type::Array { type_, len: _ } => self.check_type(&**type_),
             Type::ImplTrait(bounds) => bounds.iter().for_each(|b| self.check_generic_bound(b)),
             Type::Infer => {}
-            Type::RawPointer { mutable: _, type_ } => self.check_type(&**type_),
-            Type::BorrowedRef { lifetime: _, mutable: _, type_ } => self.check_type(&**type_),
+            Type::RawPointer { is_mutable: _, type_ } => self.check_type(&**type_),
+            Type::BorrowedRef { lifetime: _, is_mutable: _, type_ } => self.check_type(&**type_),
             Type::QualifiedPath { name: _, args, self_type, trait_ } => {
                 self.check_generic_args(&**args);
                 self.check_type(&**self_type);
@@ -279,7 +280,7 @@ fn check_type(&mut self, x: &'a Type) {
         }
     }
 
-    fn check_fn_decl(&mut self, x: &'a FnDecl) {
+    fn check_function_signature(&mut self, x: &'a FunctionSignature) {
         x.inputs.iter().for_each(|(_name, ty)| self.check_type(ty));
         if let Some(output) = &x.output {
             self.check_type(output);
@@ -309,9 +310,9 @@ fn check_path(&mut self, x: &'a Path, kind: PathKind) {
 
     fn check_generic_args(&mut self, x: &'a GenericArgs) {
         match x {
-            GenericArgs::AngleBracketed { args, bindings } => {
+            GenericArgs::AngleBracketed { args, constraints } => {
                 args.iter().for_each(|arg| self.check_generic_arg(arg));
-                bindings.iter().for_each(|bind| self.check_type_binding(bind));
+                constraints.iter().for_each(|bind| self.check_assoc_item_constraint(bind));
             }
             GenericArgs::Parenthesized { inputs, output } => {
                 inputs.iter().for_each(|ty| self.check_type(ty));
@@ -325,7 +326,7 @@ fn check_generic_args(&mut self, x: &'a GenericArgs) {
     fn check_generic_param_def(&mut self, gpd: &'a GenericParamDef) {
         match &gpd.kind {
             rustdoc_json_types::GenericParamDefKind::Lifetime { outlives: _ } => {}
-            rustdoc_json_types::GenericParamDefKind::Type { bounds, default, synthetic: _ } => {
+            rustdoc_json_types::GenericParamDefKind::Type { bounds, default, is_synthetic: _ } => {
                 bounds.iter().for_each(|b| self.check_generic_bound(b));
                 if let Some(ty) = default {
                     self.check_type(ty);
@@ -346,11 +347,11 @@ fn check_generic_arg(&mut self, arg: &'a GenericArg) {
         }
     }
 
-    fn check_type_binding(&mut self, bind: &'a TypeBinding) {
+    fn check_assoc_item_constraint(&mut self, bind: &'a AssocItemConstraint) {
         self.check_generic_args(&bind.args);
         match &bind.binding {
-            TypeBindingKind::Equality(term) => self.check_term(term),
-            TypeBindingKind::Constraint(bounds) => {
+            AssocItemConstraintKind::Equality(term) => self.check_term(term),
+            AssocItemConstraintKind::Constraint(bounds) => {
                 bounds.iter().for_each(|b| self.check_generic_bound(b))
             }
         }
@@ -388,7 +389,7 @@ fn check_dyn_trait(&mut self, dyn_trait: &'a DynTrait) {
     }
 
     fn check_function_pointer(&mut self, fp: &'a FunctionPointer) {
-        self.check_fn_decl(&fp.decl);
+        self.check_function_signature(&fp.sig);
         fp.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
     }
 
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index 72bb9db..532a27b 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -56,6 +56,8 @@ pub struct LintExtractor<'a> {
     pub rustc_path: &'a Path,
     /// The target arch to build the docs for.
     pub rustc_target: &'a str,
+    /// The target linker overriding `rustc`'s default
+    pub rustc_linker: Option<&'a str>,
     /// Verbose output.
     pub verbose: bool,
     /// Validate the style and the code example.
@@ -459,6 +461,9 @@ fn generate_lint_output(
         }
         cmd.arg("--error-format=json");
         cmd.arg("--target").arg(self.rustc_target);
+        if let Some(target_linker) = self.rustc_linker {
+            cmd.arg(format!("-Clinker={target_linker}"));
+        }
         if options.contains(&"test") {
             cmd.arg("--test");
         }
diff --git a/src/tools/lint-docs/src/main.rs b/src/tools/lint-docs/src/main.rs
index 2055fed..e377283 100644
--- a/src/tools/lint-docs/src/main.rs
+++ b/src/tools/lint-docs/src/main.rs
@@ -27,6 +27,7 @@ fn doit() -> Result<(), Box<dyn Error>> {
     let mut out_path = None;
     let mut rustc_path = None;
     let mut rustc_target = None;
+    let mut rustc_linker = None;
     let mut verbose = false;
     let mut validate = false;
     while let Some(arg) = args.next() {
@@ -55,6 +56,12 @@ fn doit() -> Result<(), Box<dyn Error>> {
                     None => return Err("--rustc-target requires a value".into()),
                 };
             }
+            "--rustc-linker" => {
+                rustc_linker = match args.next() {
+                    Some(s) => Some(s),
+                    None => return Err("--rustc-linker requires a value".into()),
+                };
+            }
             "-v" | "--verbose" => verbose = true,
             "--validate" => validate = true,
             s => return Err(format!("unexpected argument `{}`", s).into()),
@@ -77,6 +84,7 @@ fn doit() -> Result<(), Box<dyn Error>> {
         out_path: &out_path.unwrap(),
         rustc_path: &rustc_path.unwrap(),
         rustc_target: &rustc_target.unwrap(),
+        rustc_linker: rustc_linker.as_deref(),
         verbose,
         validate,
     };
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index 4b7f348..d8cfa5b 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -37,8 +37,6 @@
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
-
-[target.'cfg(target_os = "linux")'.dependencies]
 libffi = "3.2.0"
 libloading = "0.8"
 
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 5821adb..dbb0e8a 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -383,7 +383,7 @@
   file descriptors will be mixed up.
   This is **work in progress**; currently, only integer arguments and return values are
   supported (and no, pointer/integer casts to work around this limitation will not work;
-  they will fail horribly). It also only works on Linux hosts for now.
+  they will fail horribly). It also only works on Unix hosts for now.
 * `-Zmiri-measureme=<name>` enables `measureme` profiling for the interpreted program.
    This can be used to find which parts of your program are executing slowly under Miri.
    The profile is written out to a file inside a directory called `<name>`, and can be processed
diff --git a/src/tools/miri/miri.bat b/src/tools/miri/miri.bat
index 6f9a8f3..b046b63 100644
--- a/src/tools/miri/miri.bat
+++ b/src/tools/miri/miri.bat
@@ -5,8 +5,8 @@
 
 :: If any other steps are added, the "|| exit /b" must be appended to early
 :: return from the script. If not, it will continue execution.
-cargo +stable build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml ^
-  || (echo Failed to build miri-script. Is the 'stable' toolchain installed? & exit /b)
+cargo +nightly build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml ^
+  || (echo Failed to build miri-script. Is the 'nightly' toolchain installed? & exit /b)
 
 :: Forwards all arguments to this file to the executable.
 :: We invoke the binary directly to avoid going through rustup, which would set some extra
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index c33d9ad..3fdad2a 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-0d634185dfddefe09047881175f35c65d68dcff1
+54fdef7799d9ff9470bb5cabd29fde9471a99eaa
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index 76c68ad..c19a962 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -5,7 +5,6 @@
 
 use std::cell::RefCell;
 use std::cmp::max;
-use std::collections::hash_map::Entry;
 
 use rand::Rng;
 
@@ -151,6 +150,95 @@ fn alloc_id_from_addr(&self, addr: u64, size: i64) -> Option<AllocId> {
         }
     }
 
+    fn addr_from_alloc_id_uncached(
+        &self,
+        global_state: &mut GlobalStateInner,
+        alloc_id: AllocId,
+        memory_kind: MemoryKind,
+    ) -> InterpResult<'tcx, u64> {
+        let ecx = self.eval_context_ref();
+        let mut rng = ecx.machine.rng.borrow_mut();
+        let (size, align, kind) = ecx.get_alloc_info(alloc_id);
+        // This is either called immediately after allocation (and then cached), or when
+        // adjusting `tcx` pointers (which never get freed). So assert that we are looking
+        // at a live allocation. This also ensures that we never re-assign an address to an
+        // allocation that previously had an address, but then was freed and the address
+        // information was removed.
+        assert!(!matches!(kind, AllocKind::Dead));
+
+        // This allocation does not have a base address yet, pick or reuse one.
+        if ecx.machine.native_lib.is_some() {
+            // In native lib mode, we use the "real" address of the bytes for this allocation.
+            // This ensures the interpreted program and native code have the same view of memory.
+            let base_ptr = match kind {
+                AllocKind::LiveData => {
+                    if ecx.tcx.try_get_global_alloc(alloc_id).is_some() {
+                        // For new global allocations, we always pre-allocate the memory to be able use the machine address directly.
+                        let prepared_bytes = MiriAllocBytes::zeroed(size, align)
+                            .unwrap_or_else(|| {
+                                panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes")
+                            });
+                        let ptr = prepared_bytes.as_ptr();
+                        // Store prepared allocation space to be picked up for use later.
+                        global_state
+                            .prepared_alloc_bytes
+                            .try_insert(alloc_id, prepared_bytes)
+                            .unwrap();
+                        ptr
+                    } else {
+                        ecx.get_alloc_bytes_unchecked_raw(alloc_id)?
+                    }
+                }
+                AllocKind::Function | AllocKind::VTable => {
+                    // Allocate some dummy memory to get a unique address for this function/vtable.
+                    let alloc_bytes =
+                        MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap());
+                    let ptr = alloc_bytes.as_ptr();
+                    // Leak the underlying memory to ensure it remains unique.
+                    std::mem::forget(alloc_bytes);
+                    ptr
+                }
+                AllocKind::Dead => unreachable!(),
+            };
+            // Ensure this pointer's provenance is exposed, so that it can be used by FFI code.
+            return Ok(base_ptr.expose_provenance().try_into().unwrap());
+        }
+        // We are not in native lib mode, so we control the addresses ourselves.
+        if let Some((reuse_addr, clock)) =
+            global_state.reuse.take_addr(&mut *rng, size, align, memory_kind, ecx.active_thread())
+        {
+            if let Some(clock) = clock {
+                ecx.acquire_clock(&clock);
+            }
+            Ok(reuse_addr)
+        } else {
+            // We have to pick a fresh address.
+            // Leave some space to the previous allocation, to give it some chance to be less aligned.
+            // We ensure that `(global_state.next_base_addr + slack) % 16` is uniformly distributed.
+            let slack = rng.gen_range(0..16);
+            // From next_base_addr + slack, round up to adjust for alignment.
+            let base_addr = global_state
+                .next_base_addr
+                .checked_add(slack)
+                .ok_or_else(|| err_exhaust!(AddressSpaceFull))?;
+            let base_addr = align_addr(base_addr, align.bytes());
+
+            // Remember next base address.  If this allocation is zero-sized, leave a gap of at
+            // least 1 to avoid two allocations having the same base address. (The logic in
+            // `alloc_id_from_addr` assumes unique addresses, and different function/vtable pointers
+            // need to be distinguishable!)
+            global_state.next_base_addr = base_addr
+                .checked_add(max(size.bytes(), 1))
+                .ok_or_else(|| err_exhaust!(AddressSpaceFull))?;
+            // Even if `Size` didn't overflow, we might still have filled up the address space.
+            if global_state.next_base_addr > ecx.target_usize_max() {
+                throw_exhaust!(AddressSpaceFull);
+            }
+
+            Ok(base_addr)
+        }
+    }
+
     fn addr_from_alloc_id(
         &self,
         alloc_id: AllocId,
@@ -160,98 +248,16 @@ fn addr_from_alloc_id(
         let mut global_state = ecx.machine.alloc_addresses.borrow_mut();
         let global_state = &mut *global_state;
 
-        Ok(match global_state.base_addr.entry(alloc_id) {
-            Entry::Occupied(entry) => *entry.get(),
-            Entry::Vacant(entry) => {
-                let mut rng = ecx.machine.rng.borrow_mut();
-                let (size, align, kind) = ecx.get_alloc_info(alloc_id);
-                // This is either called immediately after allocation (and then cached), or when
-                // adjusting `tcx` pointers (which never get freed). So assert that we are looking
-                // at a live allocation. This also ensures that we never re-assign an address to an
-                // allocation that previously had an address, but then was freed and the address
-                // information was removed.
-                assert!(!matches!(kind, AllocKind::Dead));
-
-                // This allocation does not have a base address yet, pick or reuse one.
-                let base_addr = if ecx.machine.native_lib.is_some() {
-                    // In native lib mode, we use the "real" address of the bytes for this allocation.
-                    // This ensures the interpreted program and native code have the same view of memory.
-                    match kind {
-                        AllocKind::LiveData => {
-                            let ptr = if ecx.tcx.try_get_global_alloc(alloc_id).is_some() {
-                                // For new global allocations, we always pre-allocate the memory to be able use the machine address directly.
-                                let prepared_bytes = MiriAllocBytes::zeroed(size, align)
-                                    .unwrap_or_else(|| {
-                                        panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes")
-                                    });
-                                let ptr = prepared_bytes.as_ptr();
-                                    // Store prepared allocation space to be picked up for use later.
-                                    global_state.prepared_alloc_bytes.try_insert(alloc_id, prepared_bytes).unwrap();
-                                ptr
-                            } else {
-                                ecx.get_alloc_bytes_unchecked_raw(alloc_id)?
-                            };
-                            // Ensure this pointer's provenance is exposed, so that it can be used by FFI code.
-                            ptr.expose_provenance().try_into().unwrap()
-                        }
-                        AllocKind::Function | AllocKind::VTable => {
-                            // Allocate some dummy memory to get a unique address for this function/vtable.
-                            let alloc_bytes = MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap());
-                            // We don't need to expose these bytes as nobody is allowed to access them.
-                            let addr = alloc_bytes.as_ptr().addr().try_into().unwrap();
-                            // Leak the underlying memory to ensure it remains unique.
-                            std::mem::forget(alloc_bytes);
-                            addr
-                        }
-                        AllocKind::Dead => unreachable!()
-                    }
-                } else if let Some((reuse_addr, clock)) = global_state.reuse.take_addr(                    
-                    &mut *rng,
-                    size,
-                    align,
-                    memory_kind,
-                    ecx.active_thread(),
-                ) {
-                    if let Some(clock) = clock {
-                        ecx.acquire_clock(&clock);
-                    }
-                    reuse_addr
-                } else {
-                    // We have to pick a fresh address.
-                    // Leave some space to the previous allocation, to give it some chance to be less aligned.
-                    // We ensure that `(global_state.next_base_addr + slack) % 16` is uniformly distributed.
-                    let slack = rng.gen_range(0..16);
-                    // From next_base_addr + slack, round up to adjust for alignment.
-                    let base_addr = global_state
-                        .next_base_addr
-                        .checked_add(slack)
-                        .ok_or_else(|| err_exhaust!(AddressSpaceFull))?;
-                    let base_addr = align_addr(base_addr, align.bytes());
-
-                    // Remember next base address.  If this allocation is zero-sized, leave a gap
-                    // of at least 1 to avoid two allocations having the same base address.
-                    // (The logic in `alloc_id_from_addr` assumes unique addresses, and different
-                    // function/vtable pointers need to be distinguishable!)
-                    global_state.next_base_addr = base_addr
-                        .checked_add(max(size.bytes(), 1))
-                        .ok_or_else(|| err_exhaust!(AddressSpaceFull))?;
-                    // Even if `Size` didn't overflow, we might still have filled up the address space.
-                    if global_state.next_base_addr > ecx.target_usize_max() {
-                        throw_exhaust!(AddressSpaceFull);
-                    }
-
-                    base_addr
-                };
-                trace!(
-                    "Assigning base address {:#x} to allocation {:?} (size: {}, align: {})",
-                    base_addr,
-                    alloc_id,
-                    size.bytes(),
-                    align.bytes(),
-                );
+        match global_state.base_addr.get(&alloc_id) {
+            Some(&addr) => Ok(addr),
+            None => {
+                // First time we're looking for the absolute address of this allocation.
+                let base_addr =
+                    self.addr_from_alloc_id_uncached(global_state, alloc_id, memory_kind)?;
+                trace!("Assigning base address {:#x} to allocation {:?}", base_addr, alloc_id);
 
                 // Store address in cache.
-                entry.insert(base_addr);
+                global_state.base_addr.try_insert(alloc_id, base_addr).unwrap();
 
                 // Also maintain the opposite mapping in `int_to_ptr_map`, ensuring we keep it sorted.
                 // We have a fast-path for the common case that this address is bigger than all previous ones.
@@ -269,9 +275,9 @@ fn addr_from_alloc_id(
                 };
                 global_state.int_to_ptr_map.insert(pos, (base_addr, alloc_id));
 
-                base_addr
+                Ok(base_addr)
             }
-        })
+        }
     }
 }
 
@@ -359,16 +365,23 @@ fn adjust_alloc_root_pointer(
 
     // This returns some prepared `MiriAllocBytes`, either because `addr_from_alloc_id` reserved
     // memory space in the past, or by doing the pre-allocation right upon being called.
-    fn get_global_alloc_bytes(&self, id: AllocId, kind: MemoryKind, bytes: &[u8], align: Align) -> InterpResult<'tcx, MiriAllocBytes> {
+    fn get_global_alloc_bytes(
+        &self,
+        id: AllocId,
+        kind: MemoryKind,
+        bytes: &[u8],
+        align: Align,
+    ) -> InterpResult<'tcx, MiriAllocBytes> {
         let ecx = self.eval_context_ref();
-        Ok(if ecx.machine.native_lib.is_some() {
+        if ecx.machine.native_lib.is_some() {
             // In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`.
-            // This additional call ensures that some `MiriAllocBytes` are always prepared.
+            // This additional call ensures that some `MiriAllocBytes` are always prepared, just in case
+            // this function gets called before the first time `addr_from_alloc_id` gets called.
             ecx.addr_from_alloc_id(id, kind)?;
-            let mut global_state = ecx.machine.alloc_addresses.borrow_mut();
             // The memory we need here will have already been allocated during an earlier call to
             // `addr_from_alloc_id` for this allocation. So don't create a new `MiriAllocBytes` here, instead
             // fetch the previously prepared bytes from `prepared_alloc_bytes`.
+            let mut global_state = ecx.machine.alloc_addresses.borrow_mut();
             let mut prepared_alloc_bytes = global_state
                 .prepared_alloc_bytes
                 .remove(&id)
@@ -378,10 +391,10 @@ fn get_global_alloc_bytes(&self, id: AllocId, kind: MemoryKind, bytes: &[u8], al
             assert_eq!(prepared_alloc_bytes.len(), bytes.len());
             // Copy allocation contents into prepared memory.
             prepared_alloc_bytes.copy_from_slice(bytes);
-            prepared_alloc_bytes
+            Ok(prepared_alloc_bytes)
         } else {
-            MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(&*bytes), align)
-        })
+            Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align))
+        }
     }
 
     /// When a pointer is used for a memory access, this computes where in which allocation the
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index 6fd207c..b604fd8 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -637,7 +637,7 @@ fn write_scalar_atomic(
         // The program didn't actually do a read, so suppress the memory access hooks.
         // This is also a very special exception where we just ignore an error -- if this read
         // was UB e.g. because the memory is uninitialized, we don't want to know!
-        let old_val = this.run_for_validation(|| this.read_scalar(dest)).ok();
+        let old_val = this.run_for_validation(|this| this.read_scalar(dest)).ok();
         this.allow_data_races_mut(move |this| this.write_scalar(val, dest))?;
         this.validate_atomic_store(dest, atomic)?;
         this.buffered_atomic_write(val, dest, atomic, old_val)
diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs
index c23e573..d709e4e 100644
--- a/src/tools/miri/src/concurrency/init_once.rs
+++ b/src/tools/miri/src/concurrency/init_once.rs
@@ -35,8 +35,14 @@ fn init_once_get_or_create_id(
         offset: u64,
     ) -> InterpResult<'tcx, InitOnceId> {
         let this = self.eval_context_mut();
-        this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.init_onces)?
-            .ok_or_else(|| err_ub_format!("init_once has invalid ID").into())
+        this.get_or_create_id(
+            lock_op,
+            lock_layout,
+            offset,
+            |ecx| &mut ecx.machine.sync.init_onces,
+            |_| Ok(Default::default()),
+        )?
+        .ok_or_else(|| err_ub_format!("init_once has invalid ID").into())
     }
 
     #[inline]
diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs
index d972831..97e910d 100644
--- a/src/tools/miri/src/concurrency/sync.rs
+++ b/src/tools/miri/src/concurrency/sync.rs
@@ -66,6 +66,27 @@ pub fn to_u32_scalar(&self) -> Scalar {
 
 declare_id!(MutexId);
 
+/// The mutex kind.
+#[derive(Debug, Clone, Copy)]
+#[non_exhaustive]
+pub enum MutexKind {
+    Invalid,
+    Normal,
+    Default,
+    Recursive,
+    ErrorCheck,
+}
+
+#[derive(Debug)]
+/// Additional data that may be used by shim implementations.
+pub struct AdditionalMutexData {
+    /// The mutex kind, used by some mutex implementations like pthreads mutexes.
+    pub kind: MutexKind,
+
+    /// The address of the mutex.
+    pub address: u64,
+}
+
 /// The mutex state.
 #[derive(Default, Debug)]
 struct Mutex {
@@ -77,6 +98,9 @@ struct Mutex {
     queue: VecDeque<ThreadId>,
     /// Mutex clock. This tracks the moment of the last unlock.
     clock: VClock,
+
+    /// Additional data that can be set by shim implementations.
+    data: Option<AdditionalMutexData>,
 }
 
 declare_id!(RwLockId);
@@ -168,13 +192,15 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Returns `None` if memory stores a non-zero invalid ID.
     ///
     /// `get_objs` must return the `IndexVec` that stores all the objects of this type.
+    /// `create_obj` must create the new object if initialization is needed.
     #[inline]
-    fn get_or_create_id<Id: SyncId + Idx, T: Default>(
+    fn get_or_create_id<Id: SyncId + Idx, T>(
         &mut self,
         lock_op: &OpTy<'tcx>,
         lock_layout: TyAndLayout<'tcx>,
         offset: u64,
         get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec<Id, T>,
+        create_obj: impl for<'a> FnOnce(&'a mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>,
     ) -> InterpResult<'tcx, Option<Id>> {
         let this = self.eval_context_mut();
         let value_place =
@@ -196,7 +222,8 @@ fn get_or_create_id<Id: SyncId + Idx, T: Default>(
         Ok(if success.to_bool().expect("compare_exchange's second return value is a bool") {
             // We set the in-memory ID to `next_index`, now also create this object in the machine
             // state.
-            let new_index = get_objs(this).push(T::default());
+            let obj = create_obj(this)?;
+            let new_index = get_objs(this).push(obj);
             assert_eq!(next_index, new_index);
             Some(new_index)
         } else {
@@ -210,6 +237,32 @@ fn get_or_create_id<Id: SyncId + Idx, T: Default>(
         })
     }
 
+    /// Eagerly creates a Miri sync structure.
+    ///
+    /// `create_id` will store the index of the sync_structure in the memory pointed to by
+    /// `lock_op`, so that future calls to `get_or_create_id` will see it as initialized.
+    /// - `lock_op` must hold a pointer to the sync structure.
+    /// - `lock_layout` must be the memory layout of the sync structure.
+    /// - `offset` must be the offset inside the sync structure where its miri id will be stored.
+    /// - `get_objs` is described in `get_or_create_id`.
+    /// - `obj` must be the new sync object.
+    fn create_id<Id: SyncId + Idx, T>(
+        &mut self,
+        lock_op: &OpTy<'tcx>,
+        lock_layout: TyAndLayout<'tcx>,
+        offset: u64,
+        get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec<Id, T>,
+        obj: T,
+    ) -> InterpResult<'tcx, Id> {
+        let this = self.eval_context_mut();
+        let value_place =
+            this.deref_pointer_and_offset(lock_op, offset, lock_layout, this.machine.layouts.u32)?;
+
+        let new_index = get_objs(this).push(obj);
+        this.write_scalar(Scalar::from_u32(new_index.to_u32()), &value_place)?;
+        Ok(new_index)
+    }
+
     fn condvar_reacquire_mutex(
         &mut self,
         mutex: MutexId,
@@ -236,15 +289,53 @@ fn condvar_reacquire_mutex(
 // situations.
 impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
+    /// Eagerly create and initialize a new mutex.
+    fn mutex_create(
+        &mut self,
+        lock_op: &OpTy<'tcx>,
+        lock_layout: TyAndLayout<'tcx>,
+        offset: u64,
+        data: Option<AdditionalMutexData>,
+    ) -> InterpResult<'tcx, MutexId> {
+        let this = self.eval_context_mut();
+        this.create_id(
+            lock_op,
+            lock_layout,
+            offset,
+            |ecx| &mut ecx.machine.sync.mutexes,
+            Mutex { data, ..Default::default() },
+        )
+    }
+
+    /// Lazily create a new mutex.
+    /// `initialize_data` must return any additional data that a user wants to associate with the mutex.
     fn mutex_get_or_create_id(
         &mut self,
         lock_op: &OpTy<'tcx>,
         lock_layout: TyAndLayout<'tcx>,
         offset: u64,
+        initialize_data: impl for<'a> FnOnce(
+            &'a mut MiriInterpCx<'tcx>,
+        ) -> InterpResult<'tcx, Option<AdditionalMutexData>>,
     ) -> InterpResult<'tcx, MutexId> {
         let this = self.eval_context_mut();
-        this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.mutexes)?
-            .ok_or_else(|| err_ub_format!("mutex has invalid ID").into())
+        this.get_or_create_id(
+            lock_op,
+            lock_layout,
+            offset,
+            |ecx| &mut ecx.machine.sync.mutexes,
+            |ecx| initialize_data(ecx).map(|data| Mutex { data, ..Default::default() }),
+        )?
+        .ok_or_else(|| err_ub_format!("mutex has invalid ID").into())
+    }
+
+    /// Retrieve the additional data stored for a mutex.
+    fn mutex_get_data<'a>(&'a mut self, id: MutexId) -> Option<&'a AdditionalMutexData>
+    where
+        'tcx: 'a,
+    {
+        let this = self.eval_context_ref();
+        this.machine.sync.mutexes[id].data.as_ref()
     }
 
     fn rwlock_get_or_create_id(
@@ -254,8 +345,14 @@ fn rwlock_get_or_create_id(
         offset: u64,
     ) -> InterpResult<'tcx, RwLockId> {
         let this = self.eval_context_mut();
-        this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.rwlocks)?
-            .ok_or_else(|| err_ub_format!("rwlock has invalid ID").into())
+        this.get_or_create_id(
+            lock_op,
+            lock_layout,
+            offset,
+            |ecx| &mut ecx.machine.sync.rwlocks,
+            |_| Ok(Default::default()),
+        )?
+        .ok_or_else(|| err_ub_format!("rwlock has invalid ID").into())
     }
 
     fn condvar_get_or_create_id(
@@ -265,8 +362,14 @@ fn condvar_get_or_create_id(
         offset: u64,
     ) -> InterpResult<'tcx, CondvarId> {
         let this = self.eval_context_mut();
-        this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.condvars)?
-            .ok_or_else(|| err_ub_format!("condvar has invalid ID").into())
+        this.get_or_create_id(
+            lock_op,
+            lock_layout,
+            offset,
+            |ecx| &mut ecx.machine.sync.condvars,
+            |_| Ok(Default::default()),
+        )?
+        .ok_or_else(|| err_ub_format!("condvar has invalid ID").into())
     }
 
     #[inline]
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index 79f292f..306245a 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -888,8 +888,13 @@ fn get_or_create_thread_local_alloc(
             }
             let alloc = this.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?;
             // We make a full copy of this allocation.
-            let mut alloc =
-                alloc.inner().adjust_from_tcx(&this.tcx, |bytes, align| Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align)), |ptr| this.global_root_pointer(ptr))?;
+            let mut alloc = alloc.inner().adjust_from_tcx(
+                &this.tcx,
+                |bytes, align| {
+                    Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align))
+                },
+                |ptr| this.global_root_pointer(ptr),
+            )?;
             // This allocation will be deallocated when the thread dies, so it is not in read-only memory.
             alloc.mutability = Mutability::Mut;
             // Create a fresh allocation with this content.
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index bb623c6..0850a8f 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -458,14 +458,7 @@ pub fn eval_entry<'tcx>(
         panic::resume_unwind(panic_payload)
     });
     // `Ok` can never happen.
-    #[cfg(not(bootstrap))]
     let Err(res) = res;
-    #[cfg(bootstrap)]
-    let res = match res {
-        Err(res) => res,
-        // `Ok` can never happen
-        Ok(never) => match never {},
-    };
 
     // Machine cleanup. Only do this if all threads have terminated; threads that are still running
     // might cause Stacked Borrows errors (https://github.com/rust-lang/miri/issues/2396).
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index a546ad2..cba99c0 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -869,7 +869,7 @@ fn try_unwrap_io_result<T: From<i32>>(
     /// Dereference a pointer operand to a place using `layout` instead of the pointer's declared type
     fn deref_pointer_as(
         &self,
-        op: &impl Readable<'tcx, Provenance>,
+        op: &impl Projectable<'tcx, Provenance>,
         layout: TyAndLayout<'tcx>,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
         let this = self.eval_context_ref();
@@ -880,7 +880,7 @@ fn deref_pointer_as(
     /// Calculates the MPlaceTy given the offset and layout of an access on an operand
     fn deref_pointer_and_offset(
         &self,
-        op: &impl Readable<'tcx, Provenance>,
+        op: &impl Projectable<'tcx, Provenance>,
         offset: u64,
         base_layout: TyAndLayout<'tcx>,
         value_layout: TyAndLayout<'tcx>,
@@ -897,7 +897,7 @@ fn deref_pointer_and_offset(
 
     fn deref_pointer_and_read(
         &self,
-        op: &impl Readable<'tcx, Provenance>,
+        op: &impl Projectable<'tcx, Provenance>,
         offset: u64,
         base_layout: TyAndLayout<'tcx>,
         value_layout: TyAndLayout<'tcx>,
@@ -909,7 +909,7 @@ fn deref_pointer_and_read(
 
     fn deref_pointer_and_write(
         &mut self,
-        op: &impl Readable<'tcx, Provenance>,
+        op: &impl Projectable<'tcx, Provenance>,
         offset: u64,
         value: impl Into<Scalar>,
         base_layout: TyAndLayout<'tcx>,
diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index 18b2282..0ab1b9d 100644
--- a/src/tools/miri/src/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -152,8 +152,10 @@ fn emulate_intrinsic_by_name(
             // ```
             // Would not be considered UB, or the other way around (`is_val_statically_known(0)`).
             "is_val_statically_known" => {
-                let [arg] = check_arg_count(args)?;
-                this.validate_operand(arg, /*recursive*/ false)?;
+                let [_arg] = check_arg_count(args)?;
+                // FIXME: should we check for validity here? It's tricky because we do not have a
+                // place. Codegen does not seem to set any attributes like `noundef` for intrinsic
+                // calls, so we don't *have* to do anything.
                 let branch: bool = this.machine.rng.get_mut().gen();
                 this.write_scalar(Scalar::from_bool(branch), dest)?;
             }
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 8a59206..85b4b02 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -133,7 +133,10 @@
     cpu_affinity::MAX_CPUS,
     data_race::{AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, EvalContextExt as _},
     init_once::{EvalContextExt as _, InitOnceId},
-    sync::{CondvarId, EvalContextExt as _, MutexId, RwLockId, SynchronizationObjects},
+    sync::{
+        AdditionalMutexData, CondvarId, EvalContextExt as _, MutexId, MutexKind, RwLockId,
+        SynchronizationObjects,
+    },
     thread::{
         BlockReason, EvalContextExt as _, StackEmptyCallback, ThreadId, ThreadManager,
         TimeoutAnchor, TimeoutClock, UnblockCallback,
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 66c6966..76b4366 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -535,9 +535,9 @@ pub struct MiriMachine<'tcx> {
     pub(crate) basic_block_count: u64,
 
     /// Handle of the optional shared object file for native functions.
-    #[cfg(target_os = "linux")]
+    #[cfg(unix)]
     pub native_lib: Option<(libloading::Library, std::path::PathBuf)>,
-    #[cfg(not(target_os = "linux"))]
+    #[cfg(not(unix))]
     pub native_lib: Option<!>,
 
     /// Run a garbage collector for BorTags every N basic blocks.
@@ -572,6 +572,9 @@ pub struct MiriMachine<'tcx> {
     /// Invariant: the promised alignment will never be less than the native alignment of the
     /// allocation.
     pub(crate) symbolic_alignment: RefCell<FxHashMap<AllocId, (Size, Align)>>,
+
+    /// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes).
+    union_data_ranges: FxHashMap<Ty<'tcx>, RangeSet>,
 }
 
 impl<'tcx> MiriMachine<'tcx> {
@@ -678,7 +681,7 @@ pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>)
             report_progress: config.report_progress,
             basic_block_count: 0,
             clock: Clock::new(config.isolated_op == IsolatedOp::Allow),
-            #[cfg(target_os = "linux")]
+            #[cfg(unix)]
             native_lib: config.native_lib.as_ref().map(|lib_file_path| {
                 let target_triple = layout_cx.tcx.sess.opts.target_triple.triple();
                 // Check if host target == the session target.
@@ -700,9 +703,9 @@ pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>)
                     lib_file_path.clone(),
                 )
             }),
-            #[cfg(not(target_os = "linux"))]
+            #[cfg(not(unix))]
             native_lib: config.native_lib.as_ref().map(|_| {
-                panic!("loading external .so files is only supported on Linux")
+                panic!("calling functions from native libraries via FFI is only supported on Unix")
             }),
             gc_interval: config.gc_interval,
             since_gc: 0,
@@ -714,6 +717,7 @@ pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>)
             allocation_spans: RefCell::new(FxHashMap::default()),
             const_cache: RefCell::new(FxHashMap::default()),
             symbolic_alignment: RefCell::new(FxHashMap::default()),
+            union_data_ranges: FxHashMap::default(),
         }
     }
 
@@ -826,6 +830,7 @@ fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
             allocation_spans: _,
             const_cache: _,
             symbolic_alignment: _,
+            union_data_ranges: _,
         } = self;
 
         threads.visit_provenance(visit);
@@ -1277,12 +1282,12 @@ fn adjust_global_allocation<'b>(
     ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>
     {
         let kind = Self::GLOBAL_KIND.unwrap().into();
-        let alloc = alloc.adjust_from_tcx(&ecx.tcx,
+        let alloc = alloc.adjust_from_tcx(
+            &ecx.tcx,
             |bytes, align| ecx.get_global_alloc_bytes(id, kind, bytes, align),
             |ptr| ecx.global_root_pointer(ptr),
         )?;
-        let extra =
-            Self::init_alloc_extra(ecx, id, kind, alloc.size(), alloc.align)?;
+        let extra = Self::init_alloc_extra(ecx, id, kind, alloc.size(), alloc.align)?;
         Ok(Cow::Owned(alloc.with_extra(extra)))
     }
 
@@ -1627,4 +1632,12 @@ fn get_global_alloc_salt(
             ecx.machine.rng.borrow_mut().gen::<usize>() % ADDRS_PER_ANON_GLOBAL
         }
     }
+
+    fn cached_union_data_range<'e>(
+        ecx: &'e mut InterpCx<'tcx, Self>,
+        ty: Ty<'tcx>,
+        compute_range: impl FnOnce() -> RangeSet,
+    ) -> Cow<'e, RangeSet> {
+        Cow::Borrowed(ecx.machine.union_data_ranges.entry(ty).or_insert_with(compute_range))
+    }
 }
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index d40dbdb..1b45bc2 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -226,7 +226,7 @@ fn emulate_foreign_item_inner(
         let this = self.eval_context_mut();
 
         // First deal with any external C functions in linked .so file.
-        #[cfg(target_os = "linux")]
+        #[cfg(unix)]
         if this.machine.native_lib.as_ref().is_some() {
             use crate::shims::native_lib::EvalContextExt as _;
             // An Ok(false) here means that the function being called was not exported
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index 7d5349f..618cf8c 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -2,7 +2,7 @@
 
 mod alloc;
 mod backtrace;
-#[cfg(target_os = "linux")]
+#[cfg(unix)]
 mod native_lib;
 mod unix;
 mod wasi;
diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs
index 25d96fb..e4998c3 100644
--- a/src/tools/miri/src/shims/native_lib.rs
+++ b/src/tools/miri/src/shims/native_lib.rs
@@ -240,13 +240,16 @@ fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'t
         ty::RawPtr(_, mutability) => {
             // Arbitrary mutable pointer accesses are not currently supported in Miri.
             if mutability.is_mut() {
-                throw_unsup_format!("unsupported mutable pointer type for native call: {}", v.layout.ty);
+                throw_unsup_format!(
+                    "unsupported mutable pointer type for native call: {}",
+                    v.layout.ty
+                );
             } else {
                 let s = v.to_scalar().to_pointer(cx)?.addr();
                 // This relies on the `expose_provenance` in `addr_from_alloc_id`.
                 CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize()))
             }
-        },
+        }
         _ => throw_unsup_format!("unsupported argument type for native call: {}", v.layout.ty),
     })
 }
diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs
index 5e5fccb..882c08c 100644
--- a/src/tools/miri/src/shims/unix/macos/sync.rs
+++ b/src/tools/miri/src/shims/unix/macos/sync.rs
@@ -19,7 +19,7 @@ fn os_unfair_lock_getid(&mut self, lock_op: &OpTy<'tcx>) -> InterpResult<'tcx, M
         // os_unfair_lock holds a 32-bit value, is initialized with zero and
         // must be assumed to be opaque. Therefore, we can just store our
         // internal mutex ID in the structure without anyone noticing.
-        this.mutex_get_or_create_id(lock_op, this.libc_ty_layout("os_unfair_lock"), 0)
+        this.mutex_get_or_create_id(lock_op, this.libc_ty_layout("os_unfair_lock"), 0, |_| Ok(None))
     }
 }
 
diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs
index 0b889b1..57cc9cf4 100644
--- a/src/tools/miri/src/shims/unix/sync.rs
+++ b/src/tools/miri/src/shims/unix/sync.rs
@@ -62,7 +62,6 @@ fn is_mutex_kind_normal<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResu
 // pthread_mutex_t is between 24 and 48 bytes, depending on the platform.
 // We ignore the platform layout and store our own fields:
 // - id: u32
-// - kind: i32
 
 fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
     let offset = match &*ecx.tcx.sess.target.os {
@@ -74,6 +73,8 @@ fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
 
     // Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once):
     // the id must start out as 0.
+    // FIXME on some platforms (e.g linux) there are more static initializers for
+    // recursive or error checking mutexes. We should also add thme in this sanity check.
     static SANITY: AtomicBool = AtomicBool::new(false);
     if !SANITY.swap(true, Ordering::Relaxed) {
         let static_initializer = ecx.eval_path(&["libc", "PTHREAD_MUTEX_INITIALIZER"]);
@@ -90,79 +91,92 @@ fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
     Ok(offset)
 }
 
-fn mutex_kind_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> u64 {
-    // These offsets are picked for compatibility with Linux's static initializer
-    // macros, e.g. PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP.)
-    let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
-
-    // Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once):
-    // the kind must start out as PTHREAD_MUTEX_DEFAULT.
-    static SANITY: AtomicBool = AtomicBool::new(false);
-    if !SANITY.swap(true, Ordering::Relaxed) {
-        let static_initializer = ecx.eval_path(&["libc", "PTHREAD_MUTEX_INITIALIZER"]);
-        let kind_field = static_initializer
-            .offset(Size::from_bytes(mutex_kind_offset(ecx)), ecx.machine.layouts.i32, ecx)
-            .unwrap();
-        let kind = ecx.read_scalar(&kind_field).unwrap().to_i32().unwrap();
-        assert_eq!(
-            kind,
-            ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"),
-            "PTHREAD_MUTEX_INITIALIZER is incompatible with our pthread_mutex layout: kind is not PTHREAD_MUTEX_DEFAULT"
-        );
-    }
-
-    offset
+/// Eagerly create and initialize a new mutex.
+fn mutex_create<'tcx>(
+    ecx: &mut MiriInterpCx<'tcx>,
+    mutex_op: &OpTy<'tcx>,
+    kind: i32,
+) -> InterpResult<'tcx> {
+    // FIXME: might be worth changing mutex_create to take the mplace
+    // rather than the `OpTy`.
+    let address = ecx.read_pointer(mutex_op)?.addr().bytes();
+    let kind = translate_kind(ecx, kind)?;
+    let data = Some(AdditionalMutexData { address, kind });
+    ecx.mutex_create(mutex_op, ecx.libc_ty_layout("pthread_mutex_t"), mutex_id_offset(ecx)?, data)?;
+    Ok(())
 }
 
+/// Returns the `MutexId` of the mutex stored at `mutex_op`.
+///
+/// `mutex_get_id` will also check if the mutex has been moved since its first use and
+/// return an error if it has.
 fn mutex_get_id<'tcx>(
     ecx: &mut MiriInterpCx<'tcx>,
     mutex_op: &OpTy<'tcx>,
 ) -> InterpResult<'tcx, MutexId> {
-    ecx.mutex_get_or_create_id(
+    let address = ecx.read_pointer(mutex_op)?.addr().bytes();
+
+    // FIXME: might be worth changing mutex_get_or_create_id to take the mplace
+    // rather than the `OpTy`.
+    let id = ecx.mutex_get_or_create_id(
         mutex_op,
         ecx.libc_ty_layout("pthread_mutex_t"),
         mutex_id_offset(ecx)?,
-    )
+        |ecx| {
+            // This is called if a static initializer was used and the lock has not been assigned
+            // an ID yet. We have to determine the mutex kind from the static initializer.
+            let kind = kind_from_static_initializer(ecx, mutex_op)?;
+
+            Ok(Some(AdditionalMutexData { kind, address }))
+        },
+    )?;
+
+    // Check that the mutex has not been moved since last use.
+    let data = ecx.mutex_get_data(id).expect("data should be always exist for pthreads");
+    if data.address != address {
+        throw_ub_format!("pthread_mutex_t can't be moved after first use")
+    }
+
+    Ok(id)
 }
 
-fn mutex_reset_id<'tcx>(
-    ecx: &mut MiriInterpCx<'tcx>,
-    mutex_op: &OpTy<'tcx>,
-) -> InterpResult<'tcx, ()> {
-    ecx.deref_pointer_and_write(
-        mutex_op,
-        mutex_id_offset(ecx)?,
-        Scalar::from_u32(0),
-        ecx.libc_ty_layout("pthread_mutex_t"),
-        ecx.machine.layouts.u32,
-    )
-}
-
-fn mutex_get_kind<'tcx>(
+/// Returns the kind of a static initializer.
+fn kind_from_static_initializer<'tcx>(
     ecx: &MiriInterpCx<'tcx>,
     mutex_op: &OpTy<'tcx>,
-) -> InterpResult<'tcx, i32> {
-    ecx.deref_pointer_and_read(
-        mutex_op,
-        mutex_kind_offset(ecx),
-        ecx.libc_ty_layout("pthread_mutex_t"),
-        ecx.machine.layouts.i32,
-    )?
-    .to_i32()
+) -> InterpResult<'tcx, MutexKind> {
+    // Only linux has static initializers other than PTHREAD_MUTEX_DEFAULT.
+    let kind = match &*ecx.tcx.sess.target.os {
+        "linux" => {
+            let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
+
+            ecx.deref_pointer_and_read(
+                mutex_op,
+                offset,
+                ecx.libc_ty_layout("pthread_mutex_t"),
+                ecx.machine.layouts.i32,
+            )?
+            .to_i32()?
+        }
+        | "illumos" | "solaris" | "macos" => ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"),
+        os => throw_unsup_format!("`pthread_mutex` is not supported on {os}"),
+    };
+
+    translate_kind(ecx, kind)
 }
 
-fn mutex_set_kind<'tcx>(
-    ecx: &mut MiriInterpCx<'tcx>,
-    mutex_op: &OpTy<'tcx>,
-    kind: i32,
-) -> InterpResult<'tcx, ()> {
-    ecx.deref_pointer_and_write(
-        mutex_op,
-        mutex_kind_offset(ecx),
-        Scalar::from_i32(kind),
-        ecx.libc_ty_layout("pthread_mutex_t"),
-        ecx.machine.layouts.i32,
-    )
+fn translate_kind<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResult<'tcx, MutexKind> {
+    Ok(if is_mutex_kind_default(ecx, kind)? {
+        MutexKind::Default
+    } else if is_mutex_kind_normal(ecx, kind)? {
+        MutexKind::Normal
+    } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") {
+        MutexKind::ErrorCheck
+    } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
+        MutexKind::Recursive
+    } else {
+        throw_unsup_format!("unsupported type of mutex: {kind}");
+    })
 }
 
 // pthread_rwlock_t is between 32 and 56 bytes, depending on the platform.
@@ -452,10 +466,7 @@ fn pthread_mutex_init(
             mutexattr_get_kind(this, attr_op)?
         };
 
-        // Write 0 to use the same code path as the static initializers.
-        mutex_reset_id(this, mutex_op)?;
-
-        mutex_set_kind(this, mutex_op, kind)?;
+        mutex_create(this, mutex_op, kind)?;
 
         Ok(())
     }
@@ -467,8 +478,9 @@ fn pthread_mutex_lock(
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
-        let kind = mutex_get_kind(this, mutex_op)?;
         let id = mutex_get_id(this, mutex_op)?;
+        let kind =
+            this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind;
 
         let ret = if this.mutex_is_locked(id) {
             let owner_thread = this.mutex_get_owner(id);
@@ -477,19 +489,19 @@ fn pthread_mutex_lock(
                 return Ok(());
             } else {
                 // Trying to acquire the same mutex again.
-                if is_mutex_kind_default(this, kind)? {
-                    throw_ub_format!("trying to acquire already locked default mutex");
-                } else if is_mutex_kind_normal(this, kind)? {
-                    throw_machine_stop!(TerminationInfo::Deadlock);
-                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") {
-                    this.eval_libc_i32("EDEADLK")
-                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
-                    this.mutex_lock(id);
-                    0
-                } else {
-                    throw_unsup_format!(
-                        "called pthread_mutex_lock on an unsupported type of mutex"
-                    );
+                match kind {
+                    MutexKind::Default =>
+                        throw_ub_format!("trying to acquire already locked default mutex"),
+                    MutexKind::Normal => throw_machine_stop!(TerminationInfo::Deadlock),
+                    MutexKind::ErrorCheck => this.eval_libc_i32("EDEADLK"),
+                    MutexKind::Recursive => {
+                        this.mutex_lock(id);
+                        0
+                    }
+                    _ =>
+                        throw_unsup_format!(
+                            "called pthread_mutex_lock on an unsupported type of mutex"
+                        ),
                 }
             }
         } else {
@@ -504,26 +516,26 @@ fn pthread_mutex_lock(
     fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
-        let kind = mutex_get_kind(this, mutex_op)?;
         let id = mutex_get_id(this, mutex_op)?;
+        let kind =
+            this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind;
 
         Ok(Scalar::from_i32(if this.mutex_is_locked(id) {
             let owner_thread = this.mutex_get_owner(id);
             if owner_thread != this.active_thread() {
                 this.eval_libc_i32("EBUSY")
             } else {
-                if is_mutex_kind_default(this, kind)?
-                    || is_mutex_kind_normal(this, kind)?
-                    || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
-                {
-                    this.eval_libc_i32("EBUSY")
-                } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
-                    this.mutex_lock(id);
-                    0
-                } else {
-                    throw_unsup_format!(
-                        "called pthread_mutex_trylock on an unsupported type of mutex"
-                    );
+                match kind {
+                    MutexKind::Default | MutexKind::Normal | MutexKind::ErrorCheck =>
+                        this.eval_libc_i32("EBUSY"),
+                    MutexKind::Recursive => {
+                        this.mutex_lock(id);
+                        0
+                    }
+                    _ =>
+                        throw_unsup_format!(
+                            "called pthread_mutex_trylock on an unsupported type of mutex"
+                        ),
                 }
             }
         } else {
@@ -536,8 +548,9 @@ fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx,
     fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
         let this = self.eval_context_mut();
 
-        let kind = mutex_get_kind(this, mutex_op)?;
         let id = mutex_get_id(this, mutex_op)?;
+        let kind =
+            this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind;
 
         if let Some(_old_locked_count) = this.mutex_unlock(id)? {
             // The mutex was locked by the current thread.
@@ -546,20 +559,21 @@ fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx,
             // The mutex was locked by another thread or not locked at all. See
             // the “Unlock When Not Owner” column in
             // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_unlock.html.
-            if is_mutex_kind_default(this, kind)? {
-                throw_ub_format!(
-                    "unlocked a default mutex that was not locked by the current thread"
-                );
-            } else if is_mutex_kind_normal(this, kind)? {
-                throw_ub_format!(
-                    "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread"
-                );
-            } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
-                || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")
-            {
-                Ok(Scalar::from_i32(this.eval_libc_i32("EPERM")))
-            } else {
-                throw_unsup_format!("called pthread_mutex_unlock on an unsupported type of mutex");
+            match kind {
+                MutexKind::Default =>
+                    throw_ub_format!(
+                        "unlocked a default mutex that was not locked by the current thread"
+                    ),
+                MutexKind::Normal =>
+                    throw_ub_format!(
+                        "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread"
+                    ),
+                MutexKind::ErrorCheck | MutexKind::Recursive =>
+                    Ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))),
+                _ =>
+                    throw_unsup_format!(
+                        "called pthread_mutex_unlock on an unsupported type of mutex"
+                    ),
             }
         }
     }
@@ -574,7 +588,6 @@ fn pthread_mutex_destroy(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx,
         }
 
         // Destroying an uninit pthread_mutex is UB, so check to make sure it's not uninit.
-        mutex_get_kind(this, mutex_op)?;
         mutex_get_id(this, mutex_op)?;
 
         // This might lead to false positives, see comment in pthread_mutexattr_destroy
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr
new file mode 100644
index 0000000..5ca6acc
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr
@@ -0,0 +1,20 @@
+error: Undefined Behavior: pthread_mutex_t can't be moved after first use
+  --> $DIR/libc_pthread_mutex_move.rs:LL:CC
+   |
+LL |         libc::pthread_mutex_lock(&mut m2 as *mut _);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_mutex_t can't be moved after first use
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `check` at $DIR/libc_pthread_mutex_move.rs:LL:CC
+note: inside `main`
+  --> $DIR/libc_pthread_mutex_move.rs:LL:CC
+   |
+LL |     check();
+   |     ^^^^^^^
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs
new file mode 100644
index 0000000..229335c
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs
@@ -0,0 +1,28 @@
+//@ignore-target-windows: No pthreads on Windows
+//@revisions: static_initializer init
+
+fn main() {
+    check();
+}
+
+#[cfg(init)]
+fn check() {
+    unsafe {
+        let mut m: libc::pthread_mutex_t = std::mem::zeroed();
+        assert_eq!(libc::pthread_mutex_init(&mut m as *mut _, std::ptr::null()), 0);
+
+        let mut m2 = m; // move the mutex
+        libc::pthread_mutex_lock(&mut m2 as *mut _); //~[init] ERROR: pthread_mutex_t can't be moved after first use
+    }
+}
+
+#[cfg(static_initializer)]
+fn check() {
+    unsafe {
+        let mut m: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER;
+        libc::pthread_mutex_lock(&mut m as *mut _);
+
+        let mut m2 = m; // move the mutex
+        libc::pthread_mutex_unlock(&mut m2 as *mut _); //~[static_initializer] ERROR: pthread_mutex_t can't be moved after first use
+    }
+}
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr
new file mode 100644
index 0000000..c3632ec
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr
@@ -0,0 +1,20 @@
+error: Undefined Behavior: pthread_mutex_t can't be moved after first use
+  --> $DIR/libc_pthread_mutex_move.rs:LL:CC
+   |
+LL |         libc::pthread_mutex_unlock(&mut m2 as *mut _);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_mutex_t can't be moved after first use
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `check` at $DIR/libc_pthread_mutex_move.rs:LL:CC
+note: inside `main`
+  --> $DIR/libc_pthread_mutex_move.rs:LL:CC
+   |
+LL |     check();
+   |     ^^^^^^^
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs
new file mode 100644
index 0000000..fd0773e
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs
@@ -0,0 +1,10 @@
+use std::mem;
+
+// Doing a copy at integer type should lose provenance.
+// This tests the unoptimized base case.
+fn main() {
+    let ptrs = [(&42, true)];
+    let ints: [(usize, bool); 1] = unsafe { mem::transmute(ptrs) };
+    let ptr = (&raw const ints[0].0).cast::<&i32>();
+    let _val = unsafe { *ptr.read() }; //~ERROR: dangling
+}
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr
new file mode 100644
index 0000000..fc012af
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+  --> $DIR/int_copy_looses_provenance0.rs:LL:CC
+   |
+LL |     let _val = unsafe { *ptr.read() };
+   |                          ^^^^^^^^^^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/int_copy_looses_provenance0.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs
new file mode 100644
index 0000000..ce64dcc
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs
@@ -0,0 +1,10 @@
+use std::mem;
+
+// Doing a copy at integer type should lose provenance.
+// This tests the optimized-array case of integer copies.
+fn main() {
+    let ptrs = [&42];
+    let ints: [usize; 1] = unsafe { mem::transmute(ptrs) };
+    let ptr = (&raw const ints[0]).cast::<&i32>();
+    let _val = unsafe { *ptr.read() }; //~ERROR: dangling
+}
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr
new file mode 100644
index 0000000..3752626
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+  --> $DIR/int_copy_looses_provenance1.rs:LL:CC
+   |
+LL |     let _val = unsafe { *ptr.read() };
+   |                          ^^^^^^^^^^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/int_copy_looses_provenance1.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs
new file mode 100644
index 0000000..e8966c5
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs
@@ -0,0 +1,12 @@
+use std::mem;
+
+// Doing a copy at integer type should lose provenance.
+// This tests the case where provenacne is hiding in the metadata of a pointer.
+fn main() {
+    let ptrs = [(&42, &42)];
+    // Typed copy at wide pointer type (with integer-typed metadata).
+    let ints: [*const [usize]; 1] = unsafe { mem::transmute(ptrs) };
+    // Get a pointer to the metadata field.
+    let ptr = (&raw const ints[0]).wrapping_byte_add(mem::size_of::<*const ()>()).cast::<&i32>();
+    let _val = unsafe { *ptr.read() }; //~ERROR: dangling
+}
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr
new file mode 100644
index 0000000..8402c7b
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+  --> $DIR/int_copy_looses_provenance2.rs:LL:CC
+   |
+LL |     let _val = unsafe { *ptr.read() };
+   |                          ^^^^^^^^^^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/int_copy_looses_provenance2.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs
new file mode 100644
index 0000000..48a48ce
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs
@@ -0,0 +1,29 @@
+#![feature(strict_provenance)]
+use std::mem;
+
+#[repr(C, usize)]
+#[allow(unused)]
+enum E {
+    Var1(usize),
+    Var2(usize),
+}
+
+// Doing a copy at integer type should lose provenance.
+// This tests the case where provenacne is hiding in the discriminant of an enum.
+fn main() {
+    assert_eq!(mem::size_of::<E>(), 2*mem::size_of::<usize>());
+
+    // We want to store provenance in the enum discriminant, but the value still needs to
+    // be valid atfor the type. So we split provenance and data.
+    let ptr = &42;
+    let ptr = ptr as *const i32;
+    let ptrs = [(ptr.with_addr(0), ptr)];
+    // Typed copy at the enum type.
+    let ints: [E; 1] = unsafe { mem::transmute(ptrs) };
+    // Read the discriminant.
+    let discr = unsafe { (&raw const ints[0]).cast::<*const i32>().read() };
+    // Take the provenance from there, together with the original address.
+    let ptr = discr.with_addr(ptr.addr());
+    // There should be no provenance is `discr`, so this should be UB.
+    let _val = unsafe { *ptr }; //~ERROR: dangling
+}
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr
new file mode 100644
index 0000000..b50e23d
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
+  --> $DIR/int_copy_looses_provenance3.rs:LL:CC
+   |
+LL |     let _val = unsafe { *ptr };
+   |                         ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/int_copy_looses_provenance3.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs
new file mode 100644
index 0000000..ff94f22
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs
@@ -0,0 +1,18 @@
+fn main() {
+    let half_ptr = std::mem::size_of::<*const ()>() / 2;
+    let mut bytes = [1u8; 16];
+    let bytes = bytes.as_mut_ptr();
+
+    unsafe {
+        // Put a pointer in the middle.
+        bytes.add(half_ptr).cast::<&i32>().write_unaligned(&42);
+        // Typed copy of the entire thing as two pointers, but not perfectly
+        // overlapping with the pointer we have in there.
+        let copy = bytes.cast::<[*const (); 2]>().read_unaligned();
+        let copy_bytes = copy.as_ptr().cast::<u8>();
+        // Now go to the middle of the copy and get the pointer back out.
+        let ptr = copy_bytes.add(half_ptr).cast::<*const i32>().read_unaligned();
+        // Dereferencing this should fail as the copy has removed the provenance.
+        let _val = *ptr; //~ERROR: dangling
+    }
+}
diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr
new file mode 100644
index 0000000..ed38572
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
+  --> $DIR/ptr_copy_loses_partial_provenance0.rs:LL:CC
+   |
+LL |         let _val = *ptr;
+   |                    ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/ptr_copy_loses_partial_provenance0.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs
new file mode 100644
index 0000000..d0e3dac
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs
@@ -0,0 +1,18 @@
+fn main() {
+    let half_ptr = std::mem::size_of::<*const ()>() / 2;
+    let mut bytes = [1u8; 16];
+    let bytes = bytes.as_mut_ptr();
+
+    unsafe {
+        // Put a pointer in the middle.
+        bytes.add(half_ptr).cast::<&i32>().write_unaligned(&42);
+        // Typed copy of the entire thing as two *function* pointers, but not perfectly
+        // overlapping with the pointer we have in there.
+        let copy = bytes.cast::<[fn(); 2]>().read_unaligned();
+        let copy_bytes = copy.as_ptr().cast::<u8>();
+        // Now go to the middle of the copy and get the pointer back out.
+        let ptr = copy_bytes.add(half_ptr).cast::<*const i32>().read_unaligned();
+        // Dereferencing this should fail as the copy has removed the provenance.
+        let _val = *ptr; //~ERROR: dangling
+    }
+}
diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr
new file mode 100644
index 0000000..2e11687
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
+  --> $DIR/ptr_copy_loses_partial_provenance1.rs:LL:CC
+   |
+LL |         let _val = *ptr;
+   |                    ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/ptr_copy_loses_partial_provenance1.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.rs b/src/tools/miri/tests/fail/uninit/padding-enum.rs
new file mode 100644
index 0000000..3852ac5
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-enum.rs
@@ -0,0 +1,23 @@
+use std::mem;
+
+// We have three fields to avoid the ScalarPair optimization.
+#[allow(unused)]
+enum E {
+    None,
+    Some(&'static (), &'static (), usize),
+}
+
+fn main() { unsafe {
+    let mut p: mem::MaybeUninit<E> = mem::MaybeUninit::zeroed();
+    // The copy when `E` is returned from `transmute` should destroy padding
+    // (even when we use `write_unaligned`, which under the hood uses an untyped copy).
+    p.as_mut_ptr().write_unaligned(mem::transmute((0usize, 0usize, 0usize)));
+    // This is a `None`, so everything but the discriminant is padding.
+    assert!(matches!(*p.as_ptr(), E::None));
+
+    // Turns out the discriminant is (currently) stored
+    // in the 2nd pointer, so the first half is padding.
+    let c = &p as *const _ as *const u8;
+    let _val = *c.add(0); // Get a padding byte.
+    //~^ERROR: uninitialized
+} }
diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.stderr b/src/tools/miri/tests/fail/uninit/padding-enum.stderr
new file mode 100644
index 0000000..c571f188
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-enum.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+  --> $DIR/padding-enum.rs:LL:CC
+   |
+LL |     let _val = *c.add(0); // Get a padding byte.
+   |                ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/padding-enum.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/uninit/padding-pair.rs b/src/tools/miri/tests/fail/uninit/padding-pair.rs
new file mode 100644
index 0000000..c8c00b3
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-pair.rs
@@ -0,0 +1,25 @@
+#![feature(core_intrinsics)]
+
+use std::mem::{self, MaybeUninit};
+
+fn main() {
+    // This constructs a `(usize, bool)` pair: 9 bytes initialized, the rest not.
+    // Ensure that these 9 bytes are indeed initialized, and the rest is indeed not.
+    // This should be the case even if we write into previously initialized storage.
+    let mut x: MaybeUninit<Box<[u8]>> = MaybeUninit::zeroed();
+    let z = std::intrinsics::add_with_overflow(0usize, 0usize);
+    unsafe { x.as_mut_ptr().cast::<(usize, bool)>().write(z) };
+    // Now read this bytewise. There should be (`ptr_size + 1`) def bytes followed by
+    // (`ptr_size - 1`) undef bytes (the padding after the bool) in there.
+    let z: *const u8 = &x as *const _ as *const _;
+    let first_undef = mem::size_of::<usize>() as isize + 1;
+    for i in 0..first_undef {
+        let byte = unsafe { *z.offset(i) };
+        assert_eq!(byte, 0);
+    }
+    let v = unsafe { *z.offset(first_undef) };
+    //~^ ERROR: uninitialized
+    if v == 0 {
+        println!("it is zero");
+    }
+}
diff --git a/src/tools/miri/tests/fail/uninit/padding-pair.stderr b/src/tools/miri/tests/fail/uninit/padding-pair.stderr
new file mode 100644
index 0000000..d35934d
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-pair.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+  --> $DIR/padding-pair.rs:LL:CC
+   |
+LL |     let v = unsafe { *z.offset(first_undef) };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/padding-pair.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs
new file mode 100644
index 0000000..132b858
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs
@@ -0,0 +1,32 @@
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+struct Foo {
+    val16: u16,
+    // Padding bytes go here!
+    val32: u32,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+struct Bar {
+    bytes: [u8; 8],
+}
+
+#[repr(C)]
+union FooBar {
+    foo: Foo,
+    bar: Bar,
+}
+
+pub fn main() {
+    // Initialize as u8 to ensure padding bytes are zeroed.
+    let mut foobar = FooBar { bar: Bar { bytes: [0u8; 8] } };
+    // Reading either field is ok.
+    let _val = unsafe { (foobar.foo, foobar.bar) };
+    // Does this assignment copy the uninitialized padding bytes
+    // over the initialized padding bytes? miri doesn't seem to think so.
+    foobar.foo = Foo { val16: 1, val32: 2 };
+    // This resets the padding to uninit.
+    let _val = unsafe { (foobar.foo, foobar.bar) };
+    //~^ ERROR: uninitialized
+}
diff --git a/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr
new file mode 100644
index 0000000..e122249
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value at .bytes[2]: encountered uninitialized memory, but expected an integer
+  --> $DIR/padding-struct-in-union.rs:LL:CC
+   |
+LL |     let _val = unsafe { (foobar.foo, foobar.bar) };
+   |                                      ^^^^^^^^^^ constructing invalid value at .bytes[2]: encountered uninitialized memory, but expected an integer
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/padding-struct-in-union.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/uninit/padding-struct.rs b/src/tools/miri/tests/fail/uninit/padding-struct.rs
new file mode 100644
index 0000000..dd3be50
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-struct.rs
@@ -0,0 +1,11 @@
+use std::mem;
+
+#[repr(C)]
+struct Pair(u8, u16);
+
+fn main() { unsafe {
+    let p: Pair = mem::transmute(0u32); // The copy when `Pair` is returned from `transmute` should destroy padding.
+    let c = &p as *const _ as *const u8;
+    let _val = *c.add(1); // Get the padding byte.
+    //~^ERROR: uninitialized
+} }
diff --git a/src/tools/miri/tests/fail/uninit/padding-struct.stderr b/src/tools/miri/tests/fail/uninit/padding-struct.stderr
new file mode 100644
index 0000000..8dc40a4
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-struct.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+  --> $DIR/padding-struct.rs:LL:CC
+   |
+LL |     let _val = *c.add(1); // Get the padding byte.
+   |                ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/padding-struct.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/uninit/padding-union.rs b/src/tools/miri/tests/fail/uninit/padding-union.rs
new file mode 100644
index 0000000..2e9e0a4
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-union.rs
@@ -0,0 +1,14 @@
+use std::mem;
+
+#[allow(unused)]
+#[repr(C)]
+union U {
+    field: (u8, u16),
+}
+
+fn main() { unsafe {
+    let p: U = mem::transmute(0u32); // The copy when `U` is returned from `transmute` should destroy padding.
+    let c = &p as *const _ as *const [u8; 4];
+    let _val = *c; // Read the entire thing, definitely contains the padding byte.
+    //~^ERROR: uninitialized
+} }
diff --git a/src/tools/miri/tests/fail/uninit/padding-union.stderr b/src/tools/miri/tests/fail/uninit/padding-union.stderr
new file mode 100644
index 0000000..04002da
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-union.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value at [1]: encountered uninitialized memory, but expected an integer
+  --> $DIR/padding-union.rs:LL:CC
+   |
+LL |     let _val = *c; // Read the entire thing, definitely contains the padding byte.
+   |                ^^ constructing invalid value at [1]: encountered uninitialized memory, but expected an integer
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/padding-union.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs
new file mode 100644
index 0000000..0403a9c
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs
@@ -0,0 +1,18 @@
+use std::mem;
+
+// If this is `None`, the metadata becomes padding.
+type T = Option<&'static str>;
+
+fn main() { unsafe {
+    let mut p: mem::MaybeUninit<T> = mem::MaybeUninit::zeroed();
+    // The copy when `T` is returned from `transmute` should destroy padding
+    // (even when we use `write_unaligned`, which under the hood uses an untyped copy).
+    p.as_mut_ptr().write_unaligned(mem::transmute((0usize, 0usize)));
+    // Null epresents `None`.
+    assert!(matches!(*p.as_ptr(), None));
+
+    // The second part, with the length, becomes padding.
+    let c = &p as *const _ as *const u8;
+    let _val = *c.add(mem::size_of::<*const u8>()); // Get a padding byte.
+    //~^ERROR: uninitialized
+} }
diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr
new file mode 100644
index 0000000..0da7255
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+  --> $DIR/padding-wide-ptr.rs:LL:CC
+   |
+LL |     let _val = *c.add(mem::size_of::<*const u8>()); // Get a padding byte.
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/padding-wide-ptr.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/transmute-pair-uninit.rs b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs
similarity index 61%
rename from src/tools/miri/tests/fail/transmute-pair-uninit.rs
rename to src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs
index bc95f3c..0ba5520 100644
--- a/src/tools/miri/tests/fail/transmute-pair-uninit.rs
+++ b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs
@@ -1,16 +1,17 @@
 #![feature(core_intrinsics)]
 
-use std::mem;
+use std::mem::{self, MaybeUninit};
 
 fn main() {
-    let x: Option<Box<[u8]>> = unsafe {
+    // This constructs a `(usize, bool)` pair: 9 bytes initialized, the rest not.
+    // Ensure that these 9 bytes are indeed initialized, and the rest is indeed not.
+    let x: MaybeUninit<Box<[u8]>> = unsafe {
         let z = std::intrinsics::add_with_overflow(0usize, 0usize);
-        std::mem::transmute::<(usize, bool), Option<Box<[u8]>>>(z)
+        std::mem::transmute::<(usize, bool), MaybeUninit<Box<[u8]>>>(z)
     };
-    let y = &x;
     // Now read this bytewise. There should be (`ptr_size + 1`) def bytes followed by
     // (`ptr_size - 1`) undef bytes (the padding after the bool) in there.
-    let z: *const u8 = y as *const _ as *const _;
+    let z: *const u8 = &x as *const _ as *const _;
     let first_undef = mem::size_of::<usize>() as isize + 1;
     for i in 0..first_undef {
         let byte = unsafe { *z.offset(i) };
diff --git a/src/tools/miri/tests/fail/transmute-pair-uninit.stderr b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr
similarity index 100%
rename from src/tools/miri/tests/fail/transmute-pair-uninit.stderr
rename to src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr
diff --git a/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs b/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs
index 3540c75..c532d05 100644
--- a/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs
+++ b/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs
@@ -1,4 +1,6 @@
-//@only-target-linux
+// Only works on Unix targets
+//@ignore-target-windows
+//@ignore-target-wasm
 //@only-on-host
 //@normalize-stderr-test: "OS `.*`" -> "$$OS"
 
diff --git a/src/tools/miri/tests/native-lib/fail/private_function.rs b/src/tools/miri/tests/native-lib/fail/private_function.rs
new file mode 100644
index 0000000..3c6fda7
--- /dev/null
+++ b/src/tools/miri/tests/native-lib/fail/private_function.rs
@@ -0,0 +1,15 @@
+// Only works on Unix targets
+//@ignore-target-windows
+//@ignore-target-wasm
+//@only-on-host
+//@normalize-stderr-test: "OS `.*`" -> "$$OS"
+
+extern "C" {
+    fn not_exported();
+}
+
+fn main() {
+    unsafe {
+        not_exported(); //~ ERROR: unsupported operation: can't call foreign function `not_exported`
+    }
+}
diff --git a/src/tools/miri/tests/native-lib/fail/private_function.stderr b/src/tools/miri/tests/native-lib/fail/private_function.stderr
new file mode 100644
index 0000000..e27a501
--- /dev/null
+++ b/src/tools/miri/tests/native-lib/fail/private_function.stderr
@@ -0,0 +1,15 @@
+error: unsupported operation: can't call foreign function `not_exported` on $OS
+  --> $DIR/private_function.rs:LL:CC
+   |
+LL |         not_exported();
+   |         ^^^^^^^^^^^^^^ can't call foreign function `not_exported` on $OS
+   |
+   = help: if this is a basic API commonly used on this target, please report an issue with Miri
+   = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/private_function.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/native-lib/native-lib.map b/src/tools/miri/tests/native-lib/native-lib.map
deleted file mode 100644
index 7e3bd19..0000000
--- a/src/tools/miri/tests/native-lib/native-lib.map
+++ /dev/null
@@ -1,20 +0,0 @@
-CODEABI_1.0 {
-    # Define which symbols to export.
-    global:
-        # scalar_arguments.c
-        add_one_int;
-        printer;
-        test_stack_spill;
-        get_unsigned_int;
-        add_int16;
-        add_short_to_long;
-
-        # ptr_read_access.c
-        print_pointer;
-        access_simple;
-        access_nested;
-        access_static;
-
-    # The rest remains private.
-    local: *;
-};
diff --git a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs
index d8e6209..2990dfa 100644
--- a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs
+++ b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs
@@ -1,4 +1,6 @@
-//@only-target-linux
+// Only works on Unix targets
+//@ignore-target-windows
+//@ignore-target-wasm
 //@only-on-host
 
 fn main() {
@@ -26,7 +28,7 @@ fn test_pointer() {
 fn test_simple() {
     #[repr(C)]
     struct Simple {
-        field: i32
+        field: i32,
     }
 
     extern "C" {
@@ -41,7 +43,7 @@ struct Simple {
 // Test function that dereferences nested struct pointers and accesses fields.
 fn test_nested() {
     use std::ptr::NonNull;
-    
+
     #[derive(Debug, PartialEq, Eq)]
     #[repr(C)]
     struct Nested {
@@ -62,7 +64,6 @@ struct Nested {
 
 // Test function that dereferences static struct pointers and accesses fields.
 fn test_static() {
-
     #[repr(C)]
     struct Static {
         value: i32,
@@ -72,11 +73,8 @@ struct Static {
     extern "C" {
         fn access_static(n_ptr: *const Static) -> i32;
     }
-    
-    static STATIC: Static = Static {
-        value: 9001,
-        recurse: &STATIC,
-    };
+
+    static STATIC: Static = Static { value: 9001, recurse: &STATIC };
 
     assert_eq!(unsafe { access_static(&STATIC) }, 9001);
 }
diff --git a/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs b/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs
index 1e1d0b1..378baa7 100644
--- a/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs
+++ b/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs
@@ -1,4 +1,6 @@
-//@only-target-linux
+// Only works on Unix targets
+//@ignore-target-windows
+//@ignore-target-wasm
 //@only-on-host
 
 extern "C" {
diff --git a/src/tools/miri/tests/native-lib/ptr_read_access.c b/src/tools/miri/tests/native-lib/ptr_read_access.c
index 03b9189..540845d 100644
--- a/src/tools/miri/tests/native-lib/ptr_read_access.c
+++ b/src/tools/miri/tests/native-lib/ptr_read_access.c
@@ -1,8 +1,11 @@
 #include <stdio.h>
 
+// See comments in build_native_lib()
+#define EXPORT __attribute__((visibility("default")))
+
 /* Test: test_pointer */
 
-void print_pointer(const int *ptr) {
+EXPORT void print_pointer(const int *ptr) {
   printf("printing pointer dereference from C: %d\n", *ptr);
 }
 
@@ -12,7 +15,7 @@
   int field;
 } Simple;
 
-int access_simple(const Simple *s_ptr) {
+EXPORT int access_simple(const Simple *s_ptr) {
   return s_ptr->field;
 }
 
@@ -24,7 +27,7 @@
 } Nested;
 
 // Returns the innermost/last value of a Nested pointer chain.
-int access_nested(const Nested *n_ptr) {
+EXPORT int access_nested(const Nested *n_ptr) {
   // Edge case: `n_ptr == NULL` (i.e. first Nested is None).
   if (!n_ptr) { return 0; }
 
@@ -42,6 +45,6 @@
     struct Static *recurse;
 } Static;
 
-int access_static(const Static *s_ptr) {
+EXPORT int access_static(const Static *s_ptr) {
   return s_ptr->recurse->recurse->value;
 }
diff --git a/src/tools/miri/tests/native-lib/scalar_arguments.c b/src/tools/miri/tests/native-lib/scalar_arguments.c
index 68714f1..6da730a 100644
--- a/src/tools/miri/tests/native-lib/scalar_arguments.c
+++ b/src/tools/miri/tests/native-lib/scalar_arguments.c
@@ -1,27 +1,35 @@
 #include <stdio.h>
 
-int add_one_int(int x) {
+// See comments in build_native_lib()
+#define EXPORT __attribute__((visibility("default")))
+
+EXPORT int add_one_int(int x) {
   return 2 + x;
 }
 
-void printer() {
+EXPORT void printer(void) {
   printf("printing from C\n");
 }
 
 // function with many arguments, to test functionality when some args are stored
 // on the stack
-int test_stack_spill(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) {
+EXPORT int test_stack_spill(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) {
   return a+b+c+d+e+f+g+h+i+j+k+l;
 }
 
-unsigned int get_unsigned_int() {
+EXPORT unsigned int get_unsigned_int(void) {
   return -10;
 }
 
-short add_int16(short x) {
+EXPORT short add_int16(short x) {
   return x + 3;
 }
 
-long add_short_to_long(short x, long y) {
+EXPORT long add_short_to_long(short x, long y) {
   return x + y;
 }
+
+// To test that functions not marked with EXPORT cannot be called by Miri.
+int not_exported(void) {
+  return 0;
+}
diff --git a/src/tools/miri/tests/pass/arrays.rs b/src/tools/miri/tests/pass/arrays.rs
index 61b4445..b0c6f54 100644
--- a/src/tools/miri/tests/pass/arrays.rs
+++ b/src/tools/miri/tests/pass/arrays.rs
@@ -61,6 +61,20 @@ fn debug() {
     println!("{:?}", array);
 }
 
+fn huge_zst() {
+    fn id<T>(x: T) -> T { x }
+
+    // A "huge" zero-sized array. Make sure we don't loop over it in any part of Miri.
+    let val = [(); usize::MAX];
+    id(val); // make a copy
+
+    let val = [val; 2];
+    id(val);
+
+    // Also wrap it in a union (which, in particular, hits the logic for computing union padding).
+    let _copy = std::mem::MaybeUninit::new(val);
+}
+
 fn main() {
     assert_eq!(empty_array(), []);
     assert_eq!(index_unsafe(), 20);
@@ -73,4 +87,5 @@ fn main() {
     from();
     eq();
     debug();
+    huge_zst();
 }
diff --git a/src/tools/miri/tests/pass/async-niche-aliasing.rs b/src/tools/miri/tests/pass/async-niche-aliasing.rs
new file mode 100644
index 0000000..7f19afb
--- /dev/null
+++ b/src/tools/miri/tests/pass/async-niche-aliasing.rs
@@ -0,0 +1,66 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
+
+use std::{
+    future::Future,
+    pin::Pin,
+    sync::Arc,
+    task::{Context, Poll, Wake},
+    mem::MaybeUninit,
+};
+
+struct ThingAdder<'a> {
+    // Using `MaybeUninit` to ensure there are no niches here.
+    thing: MaybeUninit<&'a mut String>,
+}
+
+impl Future for ThingAdder<'_> {
+    type Output = ();
+
+    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
+        unsafe {
+            **self.get_unchecked_mut().thing.assume_init_mut() += ", world";
+        }
+        Poll::Pending
+    }
+}
+
+fn main() {
+    let mut thing = "hello".to_owned();
+    // This future has (at least) two fields, a String (`thing`) and a ThingAdder pointing to that string.
+    let fut = async move { ThingAdder { thing: MaybeUninit::new(&mut thing) }.await };
+
+    let mut fut = MaybeDone::Future(fut);
+    let mut fut = unsafe { Pin::new_unchecked(&mut fut) };
+
+    let waker = Arc::new(DummyWaker).into();
+    let mut ctx = Context::from_waker(&waker);
+    // This ends up reading the discriminant of the `MaybeDone`. If that is stored inside the
+    // `thing: String` as a niche optimization, that causes aliasing conflicts with the reference
+    // stored in `ThingAdder`.
+    assert_eq!(fut.as_mut().poll(&mut ctx), Poll::Pending);
+    assert_eq!(fut.as_mut().poll(&mut ctx), Poll::Pending);
+}
+
+struct DummyWaker;
+
+impl Wake for DummyWaker {
+    fn wake(self: Arc<Self>) {}
+}
+
+pub enum MaybeDone<F: Future> {
+    Future(F),
+    Done,
+}
+impl<F: Future<Output = ()>> Future for MaybeDone<F> {
+    type Output = ();
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        unsafe {
+            match *self.as_mut().get_unchecked_mut() {
+                MaybeDone::Future(ref mut f) => Pin::new_unchecked(f).poll(cx),
+                MaybeDone::Done => unreachable!(),
+            }
+        }
+    }
+}
diff --git a/src/tools/miri/tests/pass/enums.rs b/src/tools/miri/tests/pass/enums.rs
index 1dafef0..9fc61f0 100644
--- a/src/tools/miri/tests/pass/enums.rs
+++ b/src/tools/miri/tests/pass/enums.rs
@@ -132,6 +132,43 @@ enum Aligned {
     assert_eq!(aligned as u8, 0);
 }
 
+// This hits a corner case in the logic for clearing padding on typed copies.
+fn padding_clear_corner_case() {
+    #[allow(unused)]
+    #[derive(Copy, Clone)]
+    #[repr(C)]
+    pub struct Decoded {
+        /// The scaled mantissa.
+        pub mant: u64,
+        /// The lower error range.
+        pub minus: u64,
+        /// The upper error range.
+        pub plus: u64,
+        /// The shared exponent in base 2.
+        pub exp: i16,
+        /// True when the error range is inclusive.
+        ///
+        /// In IEEE 754, this is true when the original mantissa was even.
+        pub inclusive: bool,
+    }
+
+    #[allow(unused)]
+    #[derive(Copy, Clone)]
+    pub enum FullDecoded {
+        /// Not-a-number.
+        Nan,
+        /// Infinities, either positive or negative.
+        Infinite,
+        /// Zero, either positive or negative.
+        Zero,
+        /// Finite numbers with further decoded fields.
+        Finite(Decoded),
+    }
+
+    let val = FullDecoded::Finite(Decoded { mant: 0, minus: 0, plus: 0, exp: 0, inclusive: false });
+    let _val2 = val; // trigger typed copy
+}
+
 fn main() {
     test(MyEnum::MyEmptyVariant);
     test(MyEnum::MyNewtypeVariant(42));
@@ -141,4 +178,5 @@ fn main() {
     discriminant_overflow();
     more_discriminant_overflow();
     overaligned_casts();
+    padding_clear_corner_case();
 }
diff --git a/src/tools/miri/tests/pass/provenance.rs b/src/tools/miri/tests/pass/provenance.rs
index 9e8a965..2e4d240 100644
--- a/src/tools/miri/tests/pass/provenance.rs
+++ b/src/tools/miri/tests/pass/provenance.rs
@@ -12,6 +12,7 @@ fn main() {
     bytewise_custom_memcpy();
     bytewise_custom_memcpy_chunked();
     int_load_strip_provenance();
+    maybe_uninit_preserves_partial_provenance();
 }
 
 /// Some basic smoke tests for provenance.
@@ -145,3 +146,24 @@ fn int_load_strip_provenance() {
     let ints: [usize; 1] = unsafe { mem::transmute(ptrs) };
     assert_eq!(ptrs[0] as *const _ as usize, ints[0]);
 }
+
+fn maybe_uninit_preserves_partial_provenance() {
+    // This is the same test as ptr_copy_loses_partial_provenance.rs, but using MaybeUninit and thus
+    // properly preserving partial provenance.
+    unsafe {
+        let mut bytes = [1u8; 16];
+        let bytes = bytes.as_mut_ptr();
+
+        // Put a pointer in the middle.
+        bytes.add(4).cast::<&i32>().write_unaligned(&42);
+        // Copy the entire thing as two pointers but not perfectly
+        // overlapping with the pointer we have in there.
+        let copy = bytes.cast::<[mem::MaybeUninit<*const ()>; 2]>().read_unaligned();
+        let copy_bytes = copy.as_ptr().cast::<u8>();
+        // Now go to the middle of the copy and get the pointer back out.
+        let ptr = copy_bytes.add(4).cast::<*const i32>().read_unaligned();
+        // And deref this to ensure we get the right value.
+        let val = *ptr;
+        assert_eq!(val, 42);
+    }
+}
diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs
index c510ef9..e62394b 100644
--- a/src/tools/miri/tests/ui.rs
+++ b/src/tools/miri/tests/ui.rs
@@ -36,20 +36,21 @@ fn build_native_lib() -> PathBuf {
     // Create the directory if it does not already exist.
     std::fs::create_dir_all(&so_target_dir)
         .expect("Failed to create directory for shared object file");
-    let so_file_path = so_target_dir.join("native-lib.so");
+    // We use a platform-neutral file extension to avoid having to hard-code alternatives.
+    let native_lib_path = so_target_dir.join("native-lib.module");
     let cc_output = Command::new(cc)
         .args([
             "-shared",
+            "-fPIC",
+            // We hide all symbols by default and export just the ones we need
+            // This is to future-proof against a more complex shared object which eg defines its own malloc
+            // (but we wouldn't want miri to call that, as it would if it was exported).
+            "-fvisibility=hidden",
             "-o",
-            so_file_path.to_str().unwrap(),
+            native_lib_path.to_str().unwrap(),
             // FIXME: Automate gathering of all relevant C source files in the directory.
             "tests/native-lib/scalar_arguments.c",
             "tests/native-lib/ptr_read_access.c",
-            // Only add the functions specified in libcode.version to the shared object file.
-            // This is to avoid automatically adding `malloc`, etc.
-            // Source: https://anadoxin.org/blog/control-over-symbol-exports-in-gcc.html/
-            "-fPIC",
-            "-Wl,--version-script=tests/native-lib/native-lib.map",
             // Ensure we notice serious problems in the C code.
             "-Wall",
             "-Wextra",
@@ -64,7 +65,7 @@ fn build_native_lib() -> PathBuf {
             String::from_utf8_lossy(&cc_output.stderr),
         );
     }
-    so_file_path
+    native_lib_path
 }
 
 /// Does *not* set any args or env vars, since it is shared between the test runner and
@@ -300,7 +301,7 @@ fn main() -> Result<()> {
         WithDependencies,
         tmpdir.path(),
     )?;
-    if cfg!(target_os = "linux") {
+    if cfg!(unix) {
         ui(Mode::Pass, "tests/native-lib/pass", &target, WithoutDependencies, tmpdir.path())?;
         ui(
             Mode::Fail { require_patterns: true, rustfix: RustfixMode::Disabled },
diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs
index a0b96e2..6b58173 100644
--- a/src/tools/run-make-support/src/command.rs
+++ b/src/tools/run-make-support/src/command.rs
@@ -15,7 +15,7 @@
 /// This is a custom command wrapper that simplifies working with commands and makes it easier to
 /// ensure that we check the exit status of executed processes.
 ///
-/// # A [`Command`] must be executed
+/// # A [`Command`] must be executed exactly once
 ///
 /// A [`Command`] is armed by a [`DropBomb`] on construction to enforce that it will be executed. If
 /// a [`Command`] is constructed but never executed, the drop bomb will explode and cause the test
@@ -23,26 +23,73 @@
 /// containing constructed but never executed commands is dangerous because it can give a false
 /// sense of confidence.
 ///
+/// Each [`Command`] invocation can also only be executed once, because we want to enforce
+/// `std{in,out,err}` config via [`std::process::Stdio`] but [`std::process::Stdio`] is not
+/// cloneable.
+///
+/// In this sense, [`Command`] exhibits linear type semantics but enforced at run-time.
+///
 /// [`run`]: Self::run
 /// [`run_fail`]: Self::run_fail
 /// [`run_unchecked`]: Self::run_unchecked
 #[derive(Debug)]
 pub struct Command {
     cmd: StdCommand,
-    stdin: Option<Box<[u8]>>,
+    // Convience for providing a quick stdin buffer.
+    stdin_buf: Option<Box<[u8]>>,
+
+    // Configurations for child process's std{in,out,err} handles.
+    stdin: Option<Stdio>,
+    stdout: Option<Stdio>,
+    stderr: Option<Stdio>,
+
+    // Emulate linear type semantics.
     drop_bomb: DropBomb,
+    already_executed: bool,
 }
 
 impl Command {
     #[track_caller]
     pub fn new<P: AsRef<OsStr>>(program: P) -> Self {
         let program = program.as_ref();
-        Self { cmd: StdCommand::new(program), stdin: None, drop_bomb: DropBomb::arm(program) }
+        Self {
+            cmd: StdCommand::new(program),
+            stdin_buf: None,
+            drop_bomb: DropBomb::arm(program),
+            stdin: None,
+            stdout: None,
+            stderr: None,
+            already_executed: false,
+        }
     }
 
-    /// Specify a stdin input
-    pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
-        self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
+    /// Specify a stdin input buffer. This is a convenience helper,
+    pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
+        self.stdin_buf = Some(input.as_ref().to_vec().into_boxed_slice());
+        self
+    }
+
+    /// Configuration for the child process’s standard input (stdin) handle.
+    ///
+    /// See [`std::process::Command::stdin`].
+    pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
+        self.stdin = Some(cfg.into());
+        self
+    }
+
+    /// Configuration for the child process’s standard output (stdout) handle.
+    ///
+    /// See [`std::process::Command::stdout`].
+    pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
+        self.stdout = Some(cfg.into());
+        self
+    }
+
+    /// Configuration for the child process’s standard error (stderr) handle.
+    ///
+    /// See [`std::process::Command::stderr`].
+    pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
+        self.stderr = Some(cfg.into());
         self
     }
 
@@ -105,6 +152,8 @@ pub fn current_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
     }
 
     /// Run the constructed command and assert that it is successfully run.
+    ///
+    /// By default, std{in,out,err} are [`Stdio::piped()`].
     #[track_caller]
     pub fn run(&mut self) -> CompletedProcess {
         let output = self.command_output();
@@ -115,6 +164,8 @@ pub fn run(&mut self) -> CompletedProcess {
     }
 
     /// Run the constructed command and assert that it does not successfully run.
+    ///
+    /// By default, std{in,out,err} are [`Stdio::piped()`].
     #[track_caller]
     pub fn run_fail(&mut self) -> CompletedProcess {
         let output = self.command_output();
@@ -124,10 +175,10 @@ pub fn run_fail(&mut self) -> CompletedProcess {
         output
     }
 
-    /// Run the command but do not check its exit status.
-    /// Only use if you explicitly don't care about the exit status.
-    /// Prefer to use [`Self::run`] and [`Self::run_fail`]
-    /// whenever possible.
+    /// Run the command but do not check its exit status. Only use if you explicitly don't care
+    /// about the exit status.
+    ///
+    /// Prefer to use [`Self::run`] and [`Self::run_fail`] whenever possible.
     #[track_caller]
     pub fn run_unchecked(&mut self) -> CompletedProcess {
         self.command_output()
@@ -135,13 +186,19 @@ pub fn run_unchecked(&mut self) -> CompletedProcess {
 
     #[track_caller]
     fn command_output(&mut self) -> CompletedProcess {
+        if self.already_executed {
+            panic!("command was already executed");
+        } else {
+            self.already_executed = true;
+        }
+
         self.drop_bomb.defuse();
         // let's make sure we piped all the input and outputs
-        self.cmd.stdin(Stdio::piped());
-        self.cmd.stdout(Stdio::piped());
-        self.cmd.stderr(Stdio::piped());
+        self.cmd.stdin(self.stdin.take().unwrap_or(Stdio::piped()));
+        self.cmd.stdout(self.stdout.take().unwrap_or(Stdio::piped()));
+        self.cmd.stderr(self.stderr.take().unwrap_or(Stdio::piped()));
 
-        let output = if let Some(input) = &self.stdin {
+        let output = if let Some(input) = &self.stdin_buf {
             let mut child = self.cmd.spawn().unwrap();
 
             {
diff --git a/src/tools/run-make-support/src/external_deps/cargo.rs b/src/tools/run-make-support/src/external_deps/cargo.rs
new file mode 100644
index 0000000..b0e045d
--- /dev/null
+++ b/src/tools/run-make-support/src/external_deps/cargo.rs
@@ -0,0 +1,7 @@
+use crate::command::Command;
+use crate::env_var;
+
+/// Returns a command that can be used to invoke Cargo.
+pub fn cargo() -> Command {
+    Command::new(env_var("BOOTSTRAP_CARGO"))
+}
diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs
index e931585..16c4251 100644
--- a/src/tools/run-make-support/src/external_deps/llvm.rs
+++ b/src/tools/run-make-support/src/external_deps/llvm.rs
@@ -110,6 +110,13 @@ pub struct LlvmDwarfdump {
     cmd: Command,
 }
 
+/// A `llvm-pdbutil` invocation builder.
+#[derive(Debug)]
+#[must_use]
+pub struct LlvmPdbutil {
+    cmd: Command,
+}
+
 crate::macros::impl_common_helpers!(LlvmReadobj);
 crate::macros::impl_common_helpers!(LlvmProfdata);
 crate::macros::impl_common_helpers!(LlvmFilecheck);
@@ -118,6 +125,7 @@ pub struct LlvmDwarfdump {
 crate::macros::impl_common_helpers!(LlvmNm);
 crate::macros::impl_common_helpers!(LlvmBcanalyzer);
 crate::macros::impl_common_helpers!(LlvmDwarfdump);
+crate::macros::impl_common_helpers!(LlvmPdbutil);
 
 /// Generate the path to the bin directory of LLVM.
 #[must_use]
@@ -227,9 +235,10 @@ pub fn new() -> Self {
         Self { cmd }
     }
 
-    /// Pipe a read file into standard input containing patterns that will be matched against the .patterns(path) call.
-    pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
-        self.cmd.stdin(input);
+    /// Provide a buffer representing standard input containing patterns that will be matched
+    /// against the `.patterns(path)` call.
+    pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
+        self.cmd.stdin_buf(input);
         self
     }
 
@@ -359,3 +368,19 @@ pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         self
     }
 }
+
+impl LlvmPdbutil {
+    /// Construct a new `llvm-pdbutil` invocation. This assumes that `llvm-pdbutil` is available
+    /// at `$LLVM_BIN_DIR/llvm-pdbutil`.
+    pub fn new() -> Self {
+        let llvm_pdbutil = llvm_bin_dir().join("llvm-pdbutil");
+        let cmd = Command::new(llvm_pdbutil);
+        Self { cmd }
+    }
+
+    /// Provide an input file.
+    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg(path.as_ref());
+        self
+    }
+}
diff --git a/src/tools/run-make-support/src/external_deps/mod.rs b/src/tools/run-make-support/src/external_deps/mod.rs
index f7c8472..80c34a9 100644
--- a/src/tools/run-make-support/src/external_deps/mod.rs
+++ b/src/tools/run-make-support/src/external_deps/mod.rs
@@ -2,6 +2,7 @@
 //! such as `cc` or `python`.
 
 pub mod c_build;
+pub mod cargo;
 pub mod cc;
 pub mod clang;
 pub mod htmldocck;
diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs
index cece58d..35d983d 100644
--- a/src/tools/run-make-support/src/external_deps/rustc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustc.rs
@@ -36,10 +36,13 @@ pub struct Rustc {
 
 crate::macros::impl_common_helpers!(Rustc);
 
+pub fn rustc_path() -> String {
+    env_var("RUSTC")
+}
+
 #[track_caller]
 fn setup_common() -> Command {
-    let rustc = env_var("RUSTC");
-    let mut cmd = Command::new(rustc);
+    let mut cmd = Command::new(rustc_path());
     set_host_rpath(&mut cmd);
     cmd
 }
@@ -291,9 +294,9 @@ pub fn link_args(&mut self, link_args: &str) -> &mut Self {
         self
     }
 
-    /// Specify a stdin input
-    pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
-        self.cmd.stdin(input);
+    /// Specify a stdin input buffer.
+    pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
+        self.cmd.stdin_buf(input);
         self
     }
 
diff --git a/src/tools/run-make-support/src/external_deps/rustdoc.rs b/src/tools/run-make-support/src/external_deps/rustdoc.rs
index 96b1c71..df5e5d8 100644
--- a/src/tools/run-make-support/src/external_deps/rustdoc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs
@@ -85,9 +85,9 @@ pub fn arg_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
         self
     }
 
-    /// Specify a stdin input
-    pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
-        self.cmd.stdin(input);
+    /// Specify a stdin input buffer.
+    pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
+        self.cmd.stdin_buf(input);
         self
     }
 
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 989d00d..15d813c 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -34,6 +34,7 @@ pub mod rfs {
 }
 
 // Re-exports of third-party library crates.
+// tidy-alphabetical-start
 pub use bstr;
 pub use gimli;
 pub use libc;
@@ -41,6 +42,7 @@ pub mod rfs {
 pub use regex;
 pub use serde_json;
 pub use wasmparser;
+// tidy-alphabetical-end
 
 // Re-exports of external dependencies.
 pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rustdoc};
@@ -48,6 +50,7 @@ pub mod rfs {
 // These rely on external dependencies.
 pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc};
 pub use c_build::{build_native_dynamic_lib, build_native_static_lib, build_native_static_lib_optimized, build_native_static_lib_cxx};
+pub use cargo::cargo;
 pub use clang::{clang, Clang};
 pub use htmldocck::htmldocck;
 pub use llvm::{
@@ -56,7 +59,7 @@ pub mod rfs {
     LlvmProfdata, LlvmReadobj,
 };
 pub use python::python_command;
-pub use rustc::{aux_build, bare_rustc, rustc, Rustc};
+pub use rustc::{aux_build, bare_rustc, rustc, rustc_path, Rustc};
 pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
 
 /// [`diff`][mod@diff] is implemented in terms of the [similar] library.
@@ -71,7 +74,7 @@ pub mod rfs {
 pub use run::{cmd, run, run_fail, run_with_args};
 
 /// Helpers for checking target information.
-pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname};
+pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname, apple_os};
 
 /// Helpers for building names of output artifacts that are potentially target-specific.
 pub use artifact_names::{
@@ -96,3 +99,4 @@ pub mod rfs {
 pub use string::{
     count_regex_matches_in_files_with_extension, invalid_utf8_contains, invalid_utf8_not_contains,
 };
+use crate::external_deps::cargo;
diff --git a/src/tools/run-make-support/src/targets.rs b/src/tools/run-make-support/src/targets.rs
index 5dcb0b8..896abb7 100644
--- a/src/tools/run-make-support/src/targets.rs
+++ b/src/tools/run-make-support/src/targets.rs
@@ -28,6 +28,24 @@ pub fn is_darwin() -> bool {
     target().contains("darwin")
 }
 
+/// Get the target OS on Apple operating systems.
+#[must_use]
+pub fn apple_os() -> &'static str {
+    if target().contains("darwin") {
+        "macos"
+    } else if target().contains("ios") {
+        "ios"
+    } else if target().contains("tvos") {
+        "tvos"
+    } else if target().contains("watchos") {
+        "watchos"
+    } else if target().contains("visionos") {
+        "visionos"
+    } else {
+        panic!("not an Apple OS")
+    }
+}
+
 /// Check if `component` is within `LLVM_COMPONENTS`
 #[must_use]
 pub fn llvm_components_contain(component: &str) -> bool {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
index ee15b1b..5c25a55 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
@@ -464,6 +464,9 @@ macro_rules! experimental {
     // Used by the `rustc::potential_query_instability` lint to warn methods which
     // might not be stable during incremental compilation.
     rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
+    // Used by the `rustc::untracked_query_information` lint to warn methods which
+    // might break incremental compilation.
+    rustc_attr!(rustc_lint_untracked_query_information, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
     // Used by the `rustc::untranslatable_diagnostic` and `rustc::diagnostic_outside_of_impl` lints
     // to assist in changes to diagnostic APIs.
     rustc_attr!(rustc_lint_diagnostics, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
index ff92483..3590486 100644
--- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
@@ -198,6 +198,13 @@ fn extend_token(&mut self, kind: &rustc_lexer::TokenKind, token_text: &str) {
                     }
                     LIFETIME_IDENT
                 }
+                rustc_lexer::TokenKind::UnknownPrefixLifetime => {
+                    err = "Unknown lifetime prefix";
+                    LIFETIME_IDENT
+                }
+                rustc_lexer::TokenKind::RawLifetime => {
+                    LIFETIME_IDENT
+                }
 
                 rustc_lexer::TokenKind::Semi => T![;],
                 rustc_lexer::TokenKind::Comma => T![,],
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index 6ba5217..75c75c5 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -462,7 +462,7 @@ fn rewrite_empty_block(
         return None;
     }
 
-    let label_str = rewrite_label(label);
+    let label_str = rewrite_label(context, label);
     if attrs.map_or(false, |a| !inner_attributes(a).is_empty()) {
         return None;
     }
@@ -527,7 +527,7 @@ fn rewrite_single_line_block(
     if let Some(block_expr) = stmt::Stmt::from_simple_block(context, block, attrs) {
         let expr_shape = shape.offset_left(last_line_width(prefix))?;
         let expr_str = block_expr.rewrite(context, expr_shape)?;
-        let label_str = rewrite_label(label);
+        let label_str = rewrite_label(context, label);
         let result = format!("{prefix}{label_str}{{ {expr_str} }}");
         if result.len() <= shape.width && !result.contains('\n') {
             return Some(result);
@@ -562,7 +562,7 @@ pub(crate) fn rewrite_block_with_visitor(
     }
 
     let inner_attrs = attrs.map(inner_attributes);
-    let label_str = rewrite_label(label);
+    let label_str = rewrite_label(context, label);
     visitor.visit_block(block, inner_attrs.as_deref(), has_braces);
     let visitor_context = visitor.get_context();
     context
@@ -939,7 +939,7 @@ fn rewrite_cond(
             fresh_shape
         };
 
-        let label_string = rewrite_label(self.label);
+        let label_string = rewrite_label(context, self.label);
         // 1 = space after keyword.
         let offset = self.keyword.len() + label_string.len() + 1;
 
@@ -1168,9 +1168,9 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
     }
 }
 
-fn rewrite_label(opt_label: Option<ast::Label>) -> Cow<'static, str> {
+fn rewrite_label(context: &RewriteContext<'_>, opt_label: Option<ast::Label>) -> Cow<'static, str> {
     match opt_label {
-        Some(label) => Cow::from(format!("{}: ", label.ident)),
+        Some(label) => Cow::from(format!("{}: ", context.snippet(label.ident.span))),
         None => Cow::from(""),
     }
 }
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index b14b74a..524fc66 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -1074,7 +1074,7 @@ fn force_space_before(tok: &TokenKind) -> bool {
 fn ident_like(tok: &Token) -> bool {
     matches!(
         tok.kind,
-        TokenKind::Ident(..) | TokenKind::Literal(..) | TokenKind::Lifetime(_)
+        TokenKind::Ident(..) | TokenKind::Literal(..) | TokenKind::Lifetime(..)
     )
 }
 
@@ -1099,7 +1099,9 @@ fn next_space(tok: &TokenKind) -> SpaceState {
         | TokenKind::OpenDelim(_)
         | TokenKind::CloseDelim(_) => SpaceState::Never,
 
-        TokenKind::Literal(..) | TokenKind::Ident(..) | TokenKind::Lifetime(_) => SpaceState::Ident,
+        TokenKind::Literal(..) | TokenKind::Ident(..) | TokenKind::Lifetime(..) => {
+            SpaceState::Ident
+        }
 
         _ => SpaceState::Always,
     }
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 875c611..7730aa4 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -548,7 +548,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
 
 impl Rewrite for ast::Lifetime {
     fn rewrite(&self, context: &RewriteContext<'_>, _: Shape) -> Option<String> {
-        Some(rewrite_ident(context, self.ident).to_owned())
+        Some(context.snippet(self.ident.span).to_owned())
     }
 }
 
diff --git a/src/tools/rustfmt/tests/target/raw-lifetimes.rs b/src/tools/rustfmt/tests/target/raw-lifetimes.rs
new file mode 100644
index 0000000..62fb9be
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/raw-lifetimes.rs
@@ -0,0 +1,15 @@
+// rustfmt-edition: 2021
+
+// Simple idempotence test for raw lifetimes.
+
+fn test<'r#gen>() -> &'r#gen () {
+    // Test raw lifetimes...
+}
+
+fn label() {
+    'r#label: {
+        // Test raw labels.
+    }
+}
+
+fn main() {}
diff --git a/src/tools/tidy/config/black.toml b/src/tools/tidy/config/black.toml
index e73847a..a1e1eef 100644
--- a/src/tools/tidy/config/black.toml
+++ b/src/tools/tidy/config/black.toml
@@ -12,5 +12,6 @@
     src/llvm-project/|\
     src/doc/embedded-book/|\
     src/tools/rustc-perf/|\
+    src/tools/enzyme/|\
     library/backtrace/
     )"""
diff --git a/src/tools/tidy/config/ruff.toml b/src/tools/tidy/config/ruff.toml
index c87c17f..2be1090 100644
--- a/src/tools/tidy/config/ruff.toml
+++ b/src/tools/tidy/config/ruff.toml
@@ -16,6 +16,7 @@
     "src/llvm-project/",
     "src/doc/embedded-book/",
     "library/backtrace/",
+    "src/tools/enzyme/",
     "src/tools/rustc-perf/",
     # Hack: CI runs from a subdirectory under the main checkout
     "../src/doc/nomicon/",
@@ -29,6 +30,7 @@
     "../src/llvm-project/",
     "../src/doc/embedded-book/",
     "../library/backtrace/",
+    "../src/tools/enzyme/",
     "../src/tools/rustc-perf/",
 ]
 
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 22d1e93..50d21c7 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -6,7 +6,6 @@
 run-make/issue-84395-lto-embed-bitcode/Makefile
 run-make/jobserver-error/Makefile
 run-make/libs-through-symlinks/Makefile
-run-make/macos-deployment-target/Makefile
 run-make/split-debuginfo/Makefile
 run-make/symbol-mangling-hashed/Makefile
 run-make/translation/Makefile
diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs
index d4721b5..4a69022 100644
--- a/src/tools/tidy/src/walk.rs
+++ b/src/tools/tidy/src/walk.rs
@@ -24,6 +24,7 @@ pub fn filter_dirs(path: &Path) -> bool {
         "src/tools/rust-analyzer",
         "src/tools/rustc-perf",
         "src/tools/rustfmt",
+        "src/tools/enzyme",
         "src/doc/book",
         "src/doc/edition-guide",
         "src/doc/embedded-book",
diff --git a/src/tools/wasm-component-ld/README.md b/src/tools/wasm-component-ld/README.md
index 54608a2..b51de9a 100644
--- a/src/tools/wasm-component-ld/README.md
+++ b/src/tools/wasm-component-ld/README.md
@@ -1,7 +1,7 @@
 # `wasm-component-ld`
 
-This wrapper is a wrapper around the [`wasm-component-ld`] crates.io crate. That
-crate. That crate is itself a thin wrapper around two pieces:
+This wrapper is a wrapper around the [`wasm-component-ld`] crates.io crate.
+That crate is itself a thin wrapper around two pieces:
 
 * `wasm-ld` - the LLVM-based linker distributed as part of LLD and packaged in
   Rust as `rust-lld`.
diff --git a/tests/assembly/asm/aarch64-modifiers.rs b/tests/assembly/asm/aarch64-modifiers.rs
index b7ef1d7..a4a41dd 100644
--- a/tests/assembly/asm/aarch64-modifiers.rs
+++ b/tests/assembly/asm/aarch64-modifiers.rs
@@ -1,6 +1,7 @@
 //@ assembly-output: emit-asm
 //@ compile-flags: -O -C panic=abort
 //@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ compile-flags: -Zmerge-functions=disabled
 //@ needs-llvm-components: aarch64
 
 #![feature(no_core, lang_items, rustc_attrs)]
@@ -29,12 +30,6 @@ macro_rules! check {
         // -O and extern "C" guarantee that the selected register is always r0/s0/d0/q0
         #[no_mangle]
         pub unsafe extern "C" fn $func() -> i32 {
-            // Hack to avoid function merging
-            extern "Rust" {
-                fn dont_merge(s: &str);
-            }
-            dont_merge(stringify!($func));
-
             let y;
             asm!($code, out($reg) y);
             y
diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs
index f363456..cf1882b 100644
--- a/tests/assembly/asm/aarch64-types.rs
+++ b/tests/assembly/asm/aarch64-types.rs
@@ -4,6 +4,7 @@
 //@ [aarch64] needs-llvm-components: aarch64
 //@ [arm64ec] compile-flags: --target arm64ec-pc-windows-msvc
 //@ [arm64ec] needs-llvm-components: aarch64
+//@ compile-flags: -Zmerge-functions=disabled
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch, f16, f128)]
 #![crate_type = "rlib"]
@@ -132,12 +133,6 @@ macro_rules! check {
         // LLVM issue: <https://github.com/llvm/llvm-project/issues/94434>
         #[no_mangle]
         pub unsafe fn $func(inp: &$ty, out: &mut $ty) {
-            // Hack to avoid function merging
-            extern "Rust" {
-                fn dont_merge(s: &str);
-            }
-            dont_merge(stringify!($func));
-
             let x = *inp;
             let y;
             asm!(
@@ -155,12 +150,6 @@ macro_rules! check_reg {
         // FIXME(f16_f128): See FIXME in `check!`
         #[no_mangle]
         pub unsafe fn $func(inp: &$ty, out: &mut $ty) {
-            // Hack to avoid function merging
-            extern "Rust" {
-                fn dont_merge(s: &str);
-            }
-            dont_merge(stringify!($func));
-
             let x = *inp;
             let y;
             asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
diff --git a/tests/assembly/asm/arm-modifiers.rs b/tests/assembly/asm/arm-modifiers.rs
index 0674e16..d421e0e 100644
--- a/tests/assembly/asm/arm-modifiers.rs
+++ b/tests/assembly/asm/arm-modifiers.rs
@@ -2,6 +2,7 @@
 //@ compile-flags: -O -C panic=abort
 //@ compile-flags: --target armv7-unknown-linux-gnueabihf
 //@ compile-flags: -C target-feature=+neon
+//@ compile-flags: -Zmerge-functions=disabled
 //@ needs-llvm-components: arm
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd)]
@@ -40,12 +41,6 @@ macro_rules! check {
         // -O and extern "C" guarantee that the selected register is always r0/s0/d0/q0
         #[no_mangle]
         pub unsafe extern "C" fn $func() -> $ty {
-            // Hack to avoid function merging
-            extern "Rust" {
-                fn dont_merge(s: &str);
-            }
-            dont_merge(stringify!($func));
-
             let y;
             asm!(concat!($mov, " {0:", $modifier, "}, {0:", $modifier, "}"), out($reg) y);
             y
diff --git a/tests/assembly/asm/arm-types.rs b/tests/assembly/asm/arm-types.rs
index eeff1a0..448b92a 100644
--- a/tests/assembly/asm/arm-types.rs
+++ b/tests/assembly/asm/arm-types.rs
@@ -2,6 +2,7 @@
 //@ assembly-output: emit-asm
 //@ compile-flags: --target armv7-unknown-linux-gnueabihf
 //@ compile-flags: -C opt-level=0
+//@ compile-flags: -Zmerge-functions=disabled
 //@[d32] compile-flags: -C target-feature=+d32
 //@[neon] compile-flags: -C target-feature=+neon --cfg d32
 //@[neon] filecheck-flags: --check-prefix d32
@@ -114,12 +115,6 @@ macro_rules! check {
     ($func:ident $ty:ident $class:ident $mov:literal) => {
         #[no_mangle]
         pub unsafe fn $func(x: $ty) -> $ty {
-            // Hack to avoid function merging
-            extern "Rust" {
-                fn dont_merge(s: &str);
-            }
-            dont_merge(stringify!($func));
-
             let y;
             asm!(concat!($mov, " {}, {}"), out($class) y, in($class) x);
             y
@@ -131,12 +126,6 @@ macro_rules! check_reg {
     ($func:ident $ty:ident $reg:tt $mov:literal) => {
         #[no_mangle]
         pub unsafe fn $func(x: $ty) -> $ty {
-            // Hack to avoid function merging
-            extern "Rust" {
-                fn dont_merge(s: &str);
-            }
-            dont_merge(stringify!($func));
-
             let y;
             asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
             y
diff --git a/tests/assembly/asm/hexagon-types.rs b/tests/assembly/asm/hexagon-types.rs
index 269c758..9389fcf 100644
--- a/tests/assembly/asm/hexagon-types.rs
+++ b/tests/assembly/asm/hexagon-types.rs
@@ -1,5 +1,6 @@
 //@ assembly-output: emit-asm
 //@ compile-flags: --target hexagon-unknown-linux-musl
+//@ compile-flags: -Zmerge-functions=disabled
 //@ needs-llvm-components: hexagon
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
@@ -41,12 +42,6 @@ macro_rules! check {
     ($func:ident $ty:ident $class:ident) => {
         #[no_mangle]
         pub unsafe fn $func(x: $ty) -> $ty {
-            // Hack to avoid function merging
-            extern "Rust" {
-                fn dont_merge(s: &str);
-            }
-            dont_merge(stringify!($func));
-
             let y;
             asm!("{} = {}", out($class) y, in($class) x);
             y
@@ -58,12 +53,6 @@ macro_rules! check_reg {
     ($func:ident $ty:ident $reg:tt) => {
         #[no_mangle]
         pub unsafe fn $func(x: $ty) -> $ty {
-            // Hack to avoid function merging
-            extern "Rust" {
-                fn dont_merge(s: &str);
-            }
-            dont_merge(stringify!($func));
-
             let y;
             asm!(concat!($reg, " = ", $reg), lateout($reg) y, in($reg) x);
             y
@@ -77,12 +66,6 @@ pub unsafe fn $func(x: $ty) -> $ty {
 // CHECK: InlineAsm End
 #[no_mangle]
 pub unsafe fn sym_static() {
-    // Hack to avoid function merging
-    extern "Rust" {
-        fn dont_merge(s: &str);
-    }
-    dont_merge(stringify!($func));
-
     asm!("r0 = #{}", sym extern_static);
 }
 
@@ -92,12 +75,6 @@ pub unsafe fn sym_static() {
 // CHECK: InlineAsm End
 #[no_mangle]
 pub unsafe fn sym_fn() {
-    // Hack to avoid function merging
-    extern "Rust" {
-        fn dont_merge(s: &str);
-    }
-    dont_merge(stringify!($func));
-
     asm!("r0 = #{}", sym extern_func);
 }
 
diff --git a/tests/assembly/asm/loongarch-type.rs b/tests/assembly/asm/loongarch-type.rs
index e4c46cf..1b097f4 100644
--- a/tests/assembly/asm/loongarch-type.rs
+++ b/tests/assembly/asm/loongarch-type.rs
@@ -1,5 +1,6 @@
 //@ assembly-output: emit-asm
 //@ compile-flags: --target loongarch64-unknown-linux-gnu
+//@ compile-flags: -Zmerge-functions=disabled
 //@ needs-llvm-components: loongarch
 
 #![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)]
@@ -39,11 +40,6 @@ impl Copy for ptr {}
     static extern_static: u8;
 }
 
-// Hack to avoid function merging
-extern "Rust" {
-    fn dont_merge(s: &str);
-}
-
 // CHECK-LABEL: sym_fn:
 // CHECK: #APP
 // CHECK: pcalau12i $t0, %got_pc_hi20(extern_func)
@@ -67,8 +63,6 @@ pub unsafe fn sym_static() {
 macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
     #[no_mangle]
     pub unsafe fn $func(x: $ty) -> $ty {
-        dont_merge(stringify!($func));
-
         let y;
         asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
         y
@@ -78,8 +72,6 @@ pub unsafe fn $func(x: $ty) -> $ty {
 macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
     #[no_mangle]
     pub unsafe fn $func(x: $ty) -> $ty {
-        dont_merge(stringify!($func));
-
         let y;
         asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
         y
diff --git a/tests/assembly/asm/mips-types.rs b/tests/assembly/asm/mips-types.rs
index bd62f4a..f40a28b 100644
--- a/tests/assembly/asm/mips-types.rs
+++ b/tests/assembly/asm/mips-types.rs
@@ -4,6 +4,7 @@
 //@[mips32] needs-llvm-components: mips
 //@[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64
 //@[mips64] needs-llvm-components: mips
+//@ compile-flags: -Zmerge-functions=disabled
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
 #![crate_type = "rlib"]
@@ -43,16 +44,9 @@ impl Copy for ptr {}
     static extern_static: u8;
 }
 
-// Hack to avoid function merging
-extern "Rust" {
-    fn dont_merge(s: &str);
-}
-
 macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
     #[no_mangle]
     pub unsafe fn $func(x: $ty) -> $ty {
-        dont_merge(stringify!($func));
-
         let y;
         asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
         y
@@ -62,8 +56,6 @@ pub unsafe fn $func(x: $ty) -> $ty {
 macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
     #[no_mangle]
     pub unsafe fn $func(x: $ty) -> $ty {
-        dont_merge(stringify!($func));
-
         let y;
         asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
         y
diff --git a/tests/assembly/asm/powerpc-types.rs b/tests/assembly/asm/powerpc-types.rs
index bc8af08..85321e5 100644
--- a/tests/assembly/asm/powerpc-types.rs
+++ b/tests/assembly/asm/powerpc-types.rs
@@ -4,6 +4,7 @@
 //@[powerpc] needs-llvm-components: powerpc
 //@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
 //@[powerpc64] needs-llvm-components: powerpc
+//@ compile-flags: -Zmerge-functions=disabled
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
 #![crate_type = "rlib"]
@@ -43,16 +44,9 @@ impl Copy for ptr {}
     static extern_static: u8;
 }
 
-// Hack to avoid function merging
-extern "Rust" {
-    fn dont_merge(s: &str);
-}
-
 macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
     #[no_mangle]
     pub unsafe fn $func(x: $ty) -> $ty {
-        dont_merge(stringify!($func));
-
         let y;
         asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
         y
@@ -62,8 +56,6 @@ pub unsafe fn $func(x: $ty) -> $ty {
 macro_rules! check_reg { ($func:ident, $ty:ty, $rego:tt, $regc:tt, $mov:literal) => {
     #[no_mangle]
     pub unsafe fn $func(x: $ty) -> $ty {
-        dont_merge(stringify!($func));
-
         let y;
         asm!(concat!($mov, " ", $rego, ", ", $rego), lateout($regc) y, in($regc) x);
         y
diff --git a/tests/assembly/asm/riscv-types.rs b/tests/assembly/asm/riscv-types.rs
index 51b3aaf..1f5d7d8 100644
--- a/tests/assembly/asm/riscv-types.rs
+++ b/tests/assembly/asm/riscv-types.rs
@@ -27,6 +27,7 @@
 //@[riscv32-zfh] filecheck-flags: --check-prefix zfhmin
 
 //@ compile-flags: -C target-feature=+d
+//@ compile-flags: -Zmerge-functions=disabled
 
 #![feature(no_core, lang_items, rustc_attrs, f16)]
 #![crate_type = "rlib"]
@@ -90,12 +91,6 @@ macro_rules! check {
     ($func:ident $ty:ident $class:ident $mov:literal) => {
         #[no_mangle]
         pub unsafe fn $func(x: $ty) -> $ty {
-            // Hack to avoid function merging
-            extern "Rust" {
-                fn dont_merge(s: &str);
-            }
-            dont_merge(stringify!($func));
-
             let y;
             asm!(concat!($mov, " {}, {}"), out($class) y, in($class) x);
             y
@@ -107,12 +102,6 @@ macro_rules! check_reg {
     ($func:ident $ty:ident $reg:tt $mov:literal) => {
         #[no_mangle]
         pub unsafe fn $func(x: $ty) -> $ty {
-            // Hack to avoid function merging
-            extern "Rust" {
-                fn dont_merge(s: &str);
-            }
-            dont_merge(stringify!($func));
-
             let y;
             asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
             y
diff --git a/tests/assembly/asm/s390x-types.rs b/tests/assembly/asm/s390x-types.rs
index 6619073..e68b18d 100644
--- a/tests/assembly/asm/s390x-types.rs
+++ b/tests/assembly/asm/s390x-types.rs
@@ -2,6 +2,7 @@
 //@ assembly-output: emit-asm
 //@[s390x] compile-flags: --target s390x-unknown-linux-gnu
 //@[s390x] needs-llvm-components: systemz
+//@ compile-flags: -Zmerge-functions=disabled
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
 #![crate_type = "rlib"]
@@ -42,16 +43,9 @@ impl Copy for ptr {}
     static extern_static: u8;
 }
 
-// Hack to avoid function merging
-extern "Rust" {
-    fn dont_merge(s: &str);
-}
-
 macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
     #[no_mangle]
     pub unsafe fn $func(x: $ty) -> $ty {
-        dont_merge(stringify!($func));
-
         let y;
         asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
         y
@@ -61,8 +55,6 @@ pub unsafe fn $func(x: $ty) -> $ty {
 macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
     #[no_mangle]
     pub unsafe fn $func(x: $ty) -> $ty {
-        dont_merge(stringify!($func));
-
         let y;
         asm!(concat!($mov, " %", $reg, ", %", $reg), lateout($reg) y, in($reg) x);
         y
diff --git a/tests/assembly/asm/x86-modifiers.rs b/tests/assembly/asm/x86-modifiers.rs
index c5e393b..5a48af9 100644
--- a/tests/assembly/asm/x86-modifiers.rs
+++ b/tests/assembly/asm/x86-modifiers.rs
@@ -7,6 +7,7 @@
 //@[i686] needs-llvm-components: x86
 //@ compile-flags: -C llvm-args=--x86-asm-syntax=intel
 //@ compile-flags: -C target-feature=+avx512bw
+//@ compile-flags: -Zmerge-functions=disabled
 
 #![feature(no_core, lang_items, rustc_attrs)]
 #![crate_type = "rlib"]
@@ -38,12 +39,6 @@ macro_rules! check {
         // -O and extern "C" guarantee that the selected register is always ax/xmm0
         #[no_mangle]
         pub unsafe extern "C" fn $func() -> i32 {
-            // Hack to avoid function merging
-            extern "Rust" {
-                fn dont_merge(s: &str);
-            }
-            dont_merge(stringify!($func));
-
             let y;
             asm!(concat!($mov, " {0:", $modifier, "}, {0:", $modifier, "}"), out($reg) y);
             y
diff --git a/tests/assembly/asm/x86-types.rs b/tests/assembly/asm/x86-types.rs
index 8e22961..a40bc10 100644
--- a/tests/assembly/asm/x86-types.rs
+++ b/tests/assembly/asm/x86-types.rs
@@ -6,6 +6,7 @@
 //@[i686] needs-llvm-components: x86
 //@ compile-flags: -C llvm-args=--x86-asm-syntax=intel
 //@ compile-flags: -C target-feature=+avx512bw
+//@ compile-flags: -Zmerge-functions=disabled
 
 #![feature(no_core, lang_items, rustc_attrs, repr_simd, f16, f128)]
 #![crate_type = "rlib"]
@@ -283,12 +284,6 @@ macro_rules! check {
     ($func:ident $ty:ident $class:ident $mov:literal) => {
         #[no_mangle]
         pub unsafe fn $func(x: $ty) -> $ty {
-            // Hack to avoid function merging
-            extern "Rust" {
-                fn dont_merge(s: &str);
-            }
-            dont_merge(stringify!($func));
-
             let y;
             asm!(concat!($mov, " {}, {}"), lateout($class) y, in($class) x);
             y
@@ -300,12 +295,6 @@ macro_rules! check_reg {
     ($func:ident $ty:ident $reg:tt $mov:literal) => {
         #[no_mangle]
         pub unsafe fn $func(x: $ty) -> $ty {
-            // Hack to avoid function merging
-            extern "Rust" {
-                fn dont_merge(s: &str);
-            }
-            dont_merge(stringify!($func));
-
             let y;
             asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
             y
diff --git a/tests/assembly/s390x-backchain-toggle.rs b/tests/assembly/s390x-backchain-toggle.rs
new file mode 100644
index 0000000..8b6d0cf
--- /dev/null
+++ b/tests/assembly/s390x-backchain-toggle.rs
@@ -0,0 +1,46 @@
+//@ revisions: enable-backchain disable-backchain
+//@ assembly-output: emit-asm
+//@ compile-flags: -O --crate-type=lib --target=s390x-unknown-linux-gnu
+//@ needs-llvm-components: systemz
+//@[enable-backchain] compile-flags: -Ctarget-feature=+backchain
+//@[disable-backchain] compile-flags: -Ctarget-feature=-backchain
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+extern "C" {
+    fn extern_func();
+}
+
+// CHECK-LABEL: test_backchain
+#[no_mangle]
+extern "C" fn test_backchain() -> i32 {
+    // Here we try to match if backchain register is saved to the parameter area (stored in r15/sp)
+    // And also if a new parameter area (160 bytes) is allocated for the upcoming function call
+    // enable-backchain: lgr [[REG1:.*]], %r15
+    // enable-backchain-NEXT: aghi %r15, -160
+    // enable-backchain: stg [[REG1]], 0(%r15)
+    // disable-backchain: aghi %r15, -160
+    // disable-backchain-NOT: stg %r{{.*}}, 0(%r15)
+    unsafe {
+        extern_func();
+    }
+    // enable-backchain-NEXT: brasl %r{{.*}}, extern_func@PLT
+    // disable-backchain: brasl %r{{.*}}, extern_func@PLT
+
+    // Make sure that the expected return value is written into %r2 (return register):
+    // enable-backchain-NEXT: lghi %r2, 1
+    // disable-backchain: lghi %r2, 0
+    #[cfg(target_feature = "backchain")]
+    {
+        1
+    }
+    #[cfg(not(target_feature = "backchain"))]
+    {
+        0
+    }
+    // CHECK: br %r{{.*}}
+}
diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs
index c8610e0..4e1c5e6 100644
--- a/tests/assembly/targets/targets-elf.rs
+++ b/tests/assembly/targets/targets-elf.rs
@@ -552,6 +552,9 @@
 //@ revisions: x86_64_unknown_haiku
 //@ [x86_64_unknown_haiku] compile-flags: --target x86_64-unknown-haiku
 //@ [x86_64_unknown_haiku] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_hurd_gnu
+//@ [x86_64_unknown_hurd_gnu] compile-flags: --target x86_64-unknown-hurd-gnu
+//@ [x86_64_unknown_hurd_gnu] needs-llvm-components: x86
 //@ revisions: x86_64_unknown_hermit
 //@ [x86_64_unknown_hermit] compile-flags: --target x86_64-unknown-hermit
 //@ [x86_64_unknown_hermit] needs-llvm-components: x86
diff --git a/tests/codegen/intrinsics/likely.rs b/tests/codegen/intrinsics/likely.rs
index 098fd99..9dc31d2 100644
--- a/tests/codegen/intrinsics/likely.rs
+++ b/tests/codegen/intrinsics/likely.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -C no-prepopulate-passes
+//@ compile-flags: -C no-prepopulate-passes -Copt-level=1
 
 #![crate_type = "lib"]
 #![feature(core_intrinsics)]
diff --git a/tests/codegen/naked-asan.rs b/tests/codegen/naked-asan.rs
new file mode 100644
index 0000000..ac36018
--- /dev/null
+++ b/tests/codegen/naked-asan.rs
@@ -0,0 +1,23 @@
+// Make sure we do not request sanitizers for naked functions.
+
+//@ only-x86_64
+//@ needs-sanitizer-address
+//@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static
+
+#![crate_type = "lib"]
+#![no_std]
+#![feature(abi_x86_interrupt, naked_functions)]
+
+// CHECK: define x86_intrcc void @page_fault_handler(ptr {{.*}}%0, i64 {{.*}}%1){{.*}}#[[ATTRS:[0-9]+]] {
+// CHECK-NOT: memcpy
+#[naked]
+#[no_mangle]
+pub extern "x86-interrupt" fn page_fault_handler(_: u64, _: u64) {
+    unsafe {
+        core::arch::asm!("ud2", options(noreturn));
+    }
+}
+
+// CHECK: #[[ATTRS]] =
+// CHECK-NOT: sanitize_address
+// CHECK: !llvm.module.flags
diff --git a/tests/coverage/async.cov-map b/tests/coverage/async.cov-map
index 9e5a4bd..1ba165f 100644
--- a/tests/coverage/async.cov-map
+++ b/tests/coverage/async.cov-map
@@ -92,20 +92,18 @@
 - Code(Counter(0)) at (prev + 25, 1) to (start + 0, 23)
 
 Function name: async::g::{closure#0} (unused)
-Raw bytes (69): 0x[01, 01, 00, 0d, 00, 19, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
+Raw bytes (59): 0x[01, 01, 00, 0b, 00, 19, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
-Number of file 0 mappings: 13
+Number of file 0 mappings: 11
 - Code(Zero) at (prev + 25, 23) to (start + 1, 12)
 - Code(Zero) at (prev + 2, 9) to (start + 0, 10)
-- Code(Zero) at (prev + 0, 14) to (start + 0, 17)
-- Code(Zero) at (prev + 0, 18) to (start + 0, 23)
+- Code(Zero) at (prev + 0, 14) to (start + 0, 23)
 - Code(Zero) at (prev + 0, 27) to (start + 0, 28)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 34)
 - Code(Zero) at (prev + 1, 9) to (start + 0, 10)
-- Code(Zero) at (prev + 0, 14) to (start + 0, 17)
-- Code(Zero) at (prev + 0, 18) to (start + 0, 23)
+- Code(Zero) at (prev + 0, 14) to (start + 0, 23)
 - Code(Zero) at (prev + 0, 27) to (start + 0, 28)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 34)
 - Code(Zero) at (prev + 1, 14) to (start + 0, 16)
@@ -120,15 +118,14 @@
 - Code(Counter(0)) at (prev + 33, 1) to (start + 0, 22)
 
 Function name: async::h::{closure#0} (unused)
-Raw bytes (44): 0x[01, 01, 00, 08, 00, 21, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 13, 00, 00, 14, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
+Raw bytes (39): 0x[01, 01, 00, 07, 00, 21, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
-Number of file 0 mappings: 8
+Number of file 0 mappings: 7
 - Code(Zero) at (prev + 33, 22) to (start + 3, 12)
 - Code(Zero) at (prev + 4, 9) to (start + 0, 10)
-- Code(Zero) at (prev + 0, 14) to (start + 0, 19)
-- Code(Zero) at (prev + 0, 20) to (start + 0, 25)
+- Code(Zero) at (prev + 0, 14) to (start + 0, 25)
 - Code(Zero) at (prev + 0, 26) to (start + 0, 27)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 34)
 - Code(Zero) at (prev + 1, 14) to (start + 0, 16)
@@ -143,28 +140,25 @@
 - Code(Counter(0)) at (prev + 42, 1) to (start + 0, 19)
 
 Function name: async::i::{closure#0}
-Raw bytes (78): 0x[01, 01, 02, 07, 21, 19, 1d, 0e, 01, 2a, 13, 04, 0c, 0d, 05, 09, 00, 0a, 01, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 0d, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 1d, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
+Raw bytes (63): 0x[01, 01, 02, 07, 19, 11, 15, 0b, 01, 2a, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 15, 01, 09, 00, 0a, 0d, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 15, 00, 24, 00, 26, 19, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 2
-- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(8)
-- expression 1 operands: lhs = Counter(6), rhs = Counter(7)
-Number of file 0 mappings: 14
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(6)
+- expression 1 operands: lhs = Counter(4), rhs = Counter(5)
+Number of file 0 mappings: 11
 - Code(Counter(0)) at (prev + 42, 19) to (start + 4, 12)
-- Code(Counter(3)) at (prev + 5, 9) to (start + 0, 10)
-- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 18)
-- Code(Counter(1)) at (prev + 0, 19) to (start + 0, 24)
-- Code(Counter(2)) at (prev + 0, 28) to (start + 0, 33)
-- Code(Counter(3)) at (prev + 0, 39) to (start + 0, 42)
-- Code(Counter(5)) at (prev + 0, 43) to (start + 0, 48)
-- Code(Counter(7)) at (prev + 1, 9) to (start + 0, 10)
-- Code(Counter(4)) at (prev + 0, 14) to (start + 0, 17)
-- Code(Counter(9)) at (prev + 0, 18) to (start + 0, 23)
-- Code(Counter(10)) at (prev + 0, 27) to (start + 0, 32)
-- Code(Counter(7)) at (prev + 0, 36) to (start + 0, 38)
-- Code(Counter(8)) at (prev + 1, 14) to (start + 0, 16)
+- Code(Counter(2)) at (prev + 5, 9) to (start + 0, 10)
+- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 24)
+- Code(Counter(1)) at (prev + 0, 28) to (start + 0, 33)
+- Code(Counter(2)) at (prev + 0, 39) to (start + 0, 48)
+- Code(Counter(5)) at (prev + 1, 9) to (start + 0, 10)
+- Code(Counter(3)) at (prev + 0, 14) to (start + 0, 23)
+- Code(Counter(7)) at (prev + 0, 27) to (start + 0, 32)
+- Code(Counter(5)) at (prev + 0, 36) to (start + 0, 38)
+- Code(Counter(6)) at (prev + 1, 14) to (start + 0, 16)
 - Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2)
-    = ((c6 + c7) + c8)
+    = ((c4 + c5) + c6)
 
 Function name: async::j
 Raw bytes (58): 0x[01, 01, 02, 07, 0d, 05, 09, 0a, 01, 35, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
diff --git a/tests/coverage/async.coverage b/tests/coverage/async.coverage
index f547382..9956742 100644
--- a/tests/coverage/async.coverage
+++ b/tests/coverage/async.coverage
@@ -45,9 +45,9 @@
    LL|      1|                    // executed asynchronously.
    LL|      1|    match x {
    LL|      1|        y if c(x).await == y + 1 => { d().await; }
-                      ^0        ^0                  ^0  ^0
+                      ^0                            ^0
    LL|      1|        y if f().await == y + 1 => (),
-                      ^0       ^0                ^0
+                      ^0                         ^0
    LL|      1|        _ => (),
    LL|       |    }
    LL|      1|}
diff --git a/tests/coverage/await_ready.cov-map b/tests/coverage/await_ready.cov-map
new file mode 100644
index 0000000..0c9f2ae
--- /dev/null
+++ b/tests/coverage/await_ready.cov-map
@@ -0,0 +1,25 @@
+Function name: await_ready::await_ready
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 00, 1e]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 10, 1) to (start + 0, 30)
+
+Function name: await_ready::await_ready::{closure#0}
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0a, 1e, 03, 0f, 05, 04, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 10, 30) to (start + 3, 15)
+- Code(Counter(1)) at (prev + 4, 1) to (start + 0, 2)
+
+Function name: await_ready::main
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 10, 01, 03, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 16, 1) to (start + 3, 2)
+
diff --git a/tests/coverage/await_ready.coverage b/tests/coverage/await_ready.coverage
new file mode 100644
index 0000000..0075f09
--- /dev/null
+++ b/tests/coverage/await_ready.coverage
@@ -0,0 +1,38 @@
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |#![feature(custom_inner_attributes)] // for #![rustfmt::skip]
+   LL|       |#![feature(noop_waker)]
+   LL|       |#![rustfmt::skip]
+   LL|       |//@ edition: 2021
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |async fn ready() -> u8 { 1 }
+   LL|       |
+   LL|      1|async fn await_ready() -> u8 {
+   LL|      1|    // await should be covered even if the function never yields
+   LL|      1|    ready()
+   LL|      1|        .await
+   LL|      1|}
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    let mut future = Box::pin(await_ready());
+   LL|      1|    executor::block_on(future.as_mut());
+   LL|      1|}
+   LL|       |
+   LL|       |mod executor {
+   LL|       |    use core::future::Future;
+   LL|       |    use core::pin::pin;
+   LL|       |    use core::task::{Context, Poll, Waker};
+   LL|       |
+   LL|       |    #[coverage(off)]
+   LL|       |    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+   LL|       |        let mut future = pin!(future);
+   LL|       |        let mut context = Context::from_waker(Waker::noop());
+   LL|       |
+   LL|       |        loop {
+   LL|       |            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+   LL|       |                break val;
+   LL|       |            }
+   LL|       |        }
+   LL|       |    }
+   LL|       |}
+
diff --git a/tests/coverage/await_ready.rs b/tests/coverage/await_ready.rs
new file mode 100644
index 0000000..9212a4b
--- /dev/null
+++ b/tests/coverage/await_ready.rs
@@ -0,0 +1,37 @@
+#![feature(coverage_attribute)]
+#![feature(custom_inner_attributes)] // for #![rustfmt::skip]
+#![feature(noop_waker)]
+#![rustfmt::skip]
+//@ edition: 2021
+
+#[coverage(off)]
+async fn ready() -> u8 { 1 }
+
+async fn await_ready() -> u8 {
+    // await should be covered even if the function never yields
+    ready()
+        .await
+}
+
+fn main() {
+    let mut future = Box::pin(await_ready());
+    executor::block_on(future.as_mut());
+}
+
+mod executor {
+    use core::future::Future;
+    use core::pin::pin;
+    use core::task::{Context, Poll, Waker};
+
+    #[coverage(off)]
+    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+        let mut future = pin!(future);
+        let mut context = Context::from_waker(Waker::noop());
+
+        loop {
+            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+                break val;
+            }
+        }
+    }
+}
diff --git a/tests/crashes/118987.rs b/tests/crashes/118987.rs
deleted file mode 100644
index 4382a7b..0000000
--- a/tests/crashes/118987.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//@ known-bug: #118987
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
-
-trait Assoc {
-    type Output;
-}
-
-default impl<T: Clone> Assoc for T {
-    type Output = bool;
-}
-
-impl Assoc for u8 {}
-
-trait Foo {}
-
-impl Foo for <u8 as Assoc>::Output {}
-impl Foo for <u16 as Assoc>::Output {}
diff --git a/tests/crashes/123629.rs b/tests/crashes/123629.rs
new file mode 100644
index 0000000..6153232
--- /dev/null
+++ b/tests/crashes/123629.rs
@@ -0,0 +1,10 @@
+//@ known-bug: #123629
+#![feature(generic_assert)]
+
+fn foo()
+where
+    for<const N: usize = { assert!(u) }> ():,
+{
+}
+
+fn main() {}
diff --git a/tests/crashes/124164.rs b/tests/crashes/124164.rs
deleted file mode 100644
index 8c9b4bd..0000000
--- a/tests/crashes/124164.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ known-bug: #124164
-static S_COUNT: = std::sync::atomic::AtomicUsize::new(0);
-
-fn main() {}
diff --git a/tests/crashes/126896.rs b/tests/crashes/126896.rs
deleted file mode 100644
index 49c539d..0000000
--- a/tests/crashes/126896.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//@ known-bug: rust-lang/rust#126896
-//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes
-
-#![feature(type_alias_impl_trait)]
-type Two<'a, 'b> = impl std::fmt::Debug;
-
-fn set(x: &mut isize) -> isize {
-    *x
-}
-
-fn d(x: Two) {
-    let c1 = || set(x);
-    c1;
-}
-
-fn main() {
-}
diff --git a/tests/crashes/127033.rs b/tests/crashes/127033.rs
new file mode 100644
index 0000000..919c9df
--- /dev/null
+++ b/tests/crashes/127033.rs
@@ -0,0 +1,18 @@
+//@ known-bug: #127033
+//@ compile-flags: --edition=2021
+
+pub trait RaftLogStorage {
+    fn save_vote(vote: ()) -> impl std::future::Future + Send;
+}
+
+struct X;
+impl RaftLogStorage for X {
+    fn save_vote(vote: ()) -> impl std::future::Future {
+        loop {}
+        async {
+            vote
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/crashes/129166.rs b/tests/crashes/129166.rs
deleted file mode 100644
index d3635d4..0000000
--- a/tests/crashes/129166.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ known-bug: rust-lang/rust#129166
-
-fn main() {
-    #[cfg_eval]
-    #[cfg]
-    0
-}
diff --git a/tests/crashes/129372.rs b/tests/crashes/129372.rs
new file mode 100644
index 0000000..43be01b
--- /dev/null
+++ b/tests/crashes/129372.rs
@@ -0,0 +1,52 @@
+//@ known-bug: #129372
+//@ compile-flags: -Cdebuginfo=2 -Copt-level=0
+
+pub struct Wrapper<T>(T);
+struct Struct;
+
+pub trait TraitA {
+    type AssocA<'t>;
+}
+pub trait TraitB {
+    type AssocB;
+}
+
+pub fn helper(v: impl MethodTrait) {
+    let _local_that_causes_ice = v.method();
+}
+
+pub fn main() {
+    helper(Wrapper(Struct));
+}
+
+pub trait MethodTrait {
+    type Assoc<'a>;
+
+    fn method(self) -> impl for<'a> FnMut(&'a ()) -> Self::Assoc<'a>;
+}
+
+impl<T: TraitB> MethodTrait for T
+where
+    <T as TraitB>::AssocB: TraitA,
+{
+    type Assoc<'a> = <T::AssocB as TraitA>::AssocA<'a>;
+
+    fn method(self) -> impl for<'a> FnMut(&'a ()) -> Self::Assoc<'a> {
+        move |_| loop {}
+    }
+}
+
+impl<T, B> TraitB for Wrapper<B>
+where
+    B: TraitB<AssocB = T>,
+{
+    type AssocB = T;
+}
+
+impl TraitB for Struct {
+    type AssocB = Struct;
+}
+
+impl TraitA for Struct {
+    type AssocA<'t> = Self;
+}
diff --git a/tests/crashes/74299.rs b/tests/crashes/74299.rs
deleted file mode 100644
index 0e2ddce..0000000
--- a/tests/crashes/74299.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-//@ known-bug: #74299
-#![feature(specialization)]
-
-trait X {
-    type U;
-    fn f(&self) -> Self::U {
-        loop {}
-    }
-}
-
-impl<T> X for T {
-    default type U = ();
-}
-
-trait Y {
-    fn g(&self) {}
-}
-
-impl Y for <() as X>::U {}
-impl Y for <i32 as X>::U {}
-
-fn main() {
-    ().f().g();
-}
diff --git a/tests/debuginfo/by-value-non-immediate-argument.rs b/tests/debuginfo/by-value-non-immediate-argument.rs
index f0a39a4..192f6ef 100644
--- a/tests/debuginfo/by-value-non-immediate-argument.rs
+++ b/tests/debuginfo/by-value-non-immediate-argument.rs
@@ -1,6 +1,7 @@
 //@ min-lldb-version: 1800
 //@ min-gdb-version: 13.0
 //@ compile-flags:-g
+//@ ignore-windows-gnu: #128973
 
 // === GDB TESTS ===================================================================================
 
diff --git a/tests/debuginfo/method-on-enum.rs b/tests/debuginfo/method-on-enum.rs
index a570144..754b4a2 100644
--- a/tests/debuginfo/method-on-enum.rs
+++ b/tests/debuginfo/method-on-enum.rs
@@ -3,6 +3,8 @@
 
 //@ compile-flags:-g
 
+//@ ignore-windows-gnu: #128973
+
 // === GDB TESTS ===================================================================================
 
 // gdb-command:run
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.built.after.mir"
similarity index 81%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
rename to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.built.after.mir"
index 1f5bb55..7da33b8 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.built.after.mir"
@@ -1,11 +1,11 @@
-// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_move
+// MIR for `main::{closure#0}::{closure#0}::{closure#0}` after built
 
-fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10}, _2: ResumeTy) -> ()
 yields ()
  {
     debug _task_context => _2;
     debug a => (_1.0: i32);
-    debug b => (_1.1: i32);
+    debug b => (*(_1.1: &i32));
     let mut _0: ();
     let _3: i32;
     scope 1 {
@@ -28,7 +28,7 @@
         _4 = &_3;
         FakeRead(ForLet(None), _4);
         StorageLive(_5);
-        _5 = &(_1.1: i32);
+        _5 = &(*(_1.1: &i32));
         FakeRead(ForLet(None), _5);
         _0 = const ();
         StorageDead(_5);
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-unwind.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-unwind.mir"
deleted file mode 100644
index 1f5bb55..0000000
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-unwind.mir"
+++ /dev/null
@@ -1,47 +0,0 @@
-// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_move
-
-fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
-yields ()
- {
-    debug _task_context => _2;
-    debug a => (_1.0: i32);
-    debug b => (_1.1: i32);
-    let mut _0: ();
-    let _3: i32;
-    scope 1 {
-        debug a => _3;
-        let _4: &i32;
-        scope 2 {
-            debug a => _4;
-            let _5: &i32;
-            scope 3 {
-                debug b => _5;
-            }
-        }
-    }
-
-    bb0: {
-        StorageLive(_3);
-        _3 = copy (_1.0: i32);
-        FakeRead(ForLet(None), _3);
-        StorageLive(_4);
-        _4 = &_3;
-        FakeRead(ForLet(None), _4);
-        StorageLive(_5);
-        _5 = &(_1.1: i32);
-        FakeRead(ForLet(None), _5);
-        _0 = const ();
-        StorageDead(_5);
-        StorageDead(_4);
-        StorageDead(_3);
-        drop(_1) -> [return: bb1, unwind: bb2];
-    }
-
-    bb1: {
-        return;
-    }
-
-    bb2 (cleanup): {
-        resume;
-    }
-}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0431\175.built.after.mir"
similarity index 80%
copy from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
copy to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0431\175.built.after.mir"
index 1f5bb55..a21e82e 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0431\175.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_move
+// MIR for `main::{closure#0}::{closure#0}::{closure#1}` after built
 
-fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10}, _2: ResumeTy) -> ()
 yields ()
  {
     debug _task_context => _2;
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.mir"
new file mode 100644
index 0000000..c156636
--- /dev/null
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.mir"
@@ -0,0 +1,10 @@
+// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move
+
+fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:54:33: 54:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10} {
+    let mut _0: {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10};
+
+    bb0: {
+        _0 = {coroutine@$DIR/async_closure_shims.rs:54:53: 57:10 (#0)} { a: move _2, b: move (_1.0: i32) };
+        return;
+    }
+}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.panic-abort.mir"
deleted file mode 100644
index a984845..0000000
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.panic-abort.mir"
+++ /dev/null
@@ -1,10 +0,0 @@
-// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move
-
-fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:53:33: 53:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10} {
-    let mut _0: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10};
-
-    bb0: {
-        _0 = {coroutine@$DIR/async_closure_shims.rs:53:53: 56:10 (#0)} { a: move _2, b: move (_1.0: i32) };
-        return;
-    }
-}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.panic-unwind.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.panic-unwind.mir"
deleted file mode 100644
index a984845..0000000
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.panic-unwind.mir"
+++ /dev/null
@@ -1,10 +0,0 @@
-// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move
-
-fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:53:33: 53:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10} {
-    let mut _0: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10};
-
-    bb0: {
-        _0 = {coroutine@$DIR/async_closure_shims.rs:53:53: 56:10 (#0)} { a: move _2, b: move (_1.0: i32) };
-        return;
-    }
-}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.built.after.mir"
similarity index 86%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
rename to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.built.after.mir"
index 17fa931..a4a6a53 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `main::{closure#0}::{closure#1}::{closure#0}` 0 coroutine_by_move
+// MIR for `main::{closure#0}::{closure#1}::{closure#0}` after built
 
-fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10}, _2: ResumeTy) -> ()
 yields ()
  {
     debug _task_context => _2;
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-unwind.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-unwind.mir"
deleted file mode 100644
index 17fa931..0000000
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-unwind.mir"
+++ /dev/null
@@ -1,47 +0,0 @@
-// MIR for `main::{closure#0}::{closure#1}::{closure#0}` 0 coroutine_by_move
-
-fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
-yields ()
- {
-    debug _task_context => _2;
-    debug a => (_1.0: i32);
-    debug b => (*(_1.1: &i32));
-    let mut _0: ();
-    let _3: i32;
-    scope 1 {
-        debug a => _3;
-        let _4: &i32;
-        scope 2 {
-            debug a => _4;
-            let _5: &i32;
-            scope 3 {
-                debug b => _5;
-            }
-        }
-    }
-
-    bb0: {
-        StorageLive(_3);
-        _3 = copy (_1.0: i32);
-        FakeRead(ForLet(None), _3);
-        StorageLive(_4);
-        _4 = &_3;
-        FakeRead(ForLet(None), _4);
-        StorageLive(_5);
-        _5 = &(*(_1.1: &i32));
-        FakeRead(ForLet(None), _5);
-        _0 = const ();
-        StorageDead(_5);
-        StorageDead(_4);
-        StorageDead(_3);
-        drop(_1) -> [return: bb1, unwind: bb2];
-    }
-
-    bb1: {
-        return;
-    }
-
-    bb2 (cleanup): {
-        resume;
-    }
-}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0431\175.built.after.mir"
similarity index 80%
copy from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
copy to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0431\175.built.after.mir"
index 17fa931..69bba6f 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0431\175.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `main::{closure#0}::{closure#1}::{closure#0}` 0 coroutine_by_move
+// MIR for `main::{closure#0}::{closure#1}::{closure#1}` after built
 
-fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#1}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10}, _2: ResumeTy) -> ()
 yields ()
  {
     debug _task_context => _2;
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.mir"
similarity index 60%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.panic-abort.mir"
rename to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.mir"
index aab9f7b..134fe14 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.panic-abort.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.mir"
@@ -1,10 +1,10 @@
 // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_move
 
-fn main::{closure#0}::{closure#1}(_1: {async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} {
-    let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10};
+fn main::{closure#0}::{closure#1}(_1: {async closure@$DIR/async_closure_shims.rs:63:33: 63:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10} {
+    let mut _0: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10};
 
     bb0: {
-        _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: move (_1.0: &i32) };
+        _0 = {coroutine@$DIR/async_closure_shims.rs:63:48: 66:10 (#0)} { a: move _2, b: move (_1.0: &i32) };
         return;
     }
 }
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.panic-unwind.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.panic-unwind.mir"
deleted file mode 100644
index aab9f7b..0000000
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.panic-unwind.mir"
+++ /dev/null
@@ -1,10 +0,0 @@
-// MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_move
-
-fn main::{closure#0}::{closure#1}(_1: {async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} {
-    let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10};
-
-    bb0: {
-        _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: move (_1.0: &i32) };
-        return;
-    }
-}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.mir"
similarity index 60%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.panic-abort.mir"
rename to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.mir"
index 3fdc817..f267d93 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.panic-abort.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.mir"
@@ -1,10 +1,10 @@
 // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref
 
-fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} {
-    let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10};
+fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.rs:63:33: 63:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10} {
+    let mut _0: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10};
 
     bb0: {
-        _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) };
+        _0 = {coroutine@$DIR/async_closure_shims.rs:63:48: 66:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) };
         return;
     }
 }
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.panic-unwind.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.panic-unwind.mir"
deleted file mode 100644
index 3fdc817..0000000
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.panic-unwind.mir"
+++ /dev/null
@@ -1,10 +0,0 @@
-// MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref
-
-fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} {
-    let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10};
-
-    bb0: {
-        _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) };
-        return;
-    }
-}
diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs
index 57c55ef..b2168ba 100644
--- a/tests/mir-opt/async_closure_shims.rs
+++ b/tests/mir-opt/async_closure_shims.rs
@@ -1,6 +1,5 @@
 //@ edition:2021
 // skip-filecheck
-// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
 #![feature(async_closure, noop_waker, async_fn_traits)]
 #![allow(unused)]
@@ -22,7 +21,7 @@ pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
     }
 }
 
-async fn call(f: &mut impl AsyncFn(i32)) {
+async fn call(f: &impl AsyncFn(i32)) {
     f(0).await;
 }
 
@@ -43,10 +42,12 @@ async fn call_normal_mut<F: Future<Output = ()>>(f: &mut impl FnMut(i32) -> F) {
 }
 
 // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir
-// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir
 // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir
 // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir
-// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir
 pub fn main() {
     block_on(async {
         let b = 2i32;
@@ -54,7 +55,7 @@ pub fn main() {
             let a = &a;
             let b = &b;
         };
-        call(&mut async_closure).await;
+        call(&async_closure).await;
         call_mut(&mut async_closure).await;
         call_once(async_closure).await;
 
diff --git a/tests/run-make/apple-deployment-target/foo.rs b/tests/run-make/apple-deployment-target/foo.rs
new file mode 100644
index 0000000..f328e4d
--- /dev/null
+++ b/tests/run-make/apple-deployment-target/foo.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make/apple-deployment-target/rmake.rs b/tests/run-make/apple-deployment-target/rmake.rs
new file mode 100644
index 0000000..b2d1af6
--- /dev/null
+++ b/tests/run-make/apple-deployment-target/rmake.rs
@@ -0,0 +1,157 @@
+//! Test codegen when setting deployment targets on Apple platforms.
+//!
+//! This is important since its a compatibility hazard. The linker will
+//! generate load commands differently based on what minimum OS it can assume.
+//!
+//! See https://github.com/rust-lang/rust/pull/105123.
+
+//@ only-apple
+
+use run_make_support::{apple_os, cmd, run_in_tmpdir, rustc, target};
+
+/// Run vtool to check the `minos` field in LC_BUILD_VERSION.
+///
+/// On lower deployment targets, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS and similar
+/// are used instead of LC_BUILD_VERSION - these have a `version` field, so also check that.
+#[track_caller]
+fn minos(file: &str, version: &str) {
+    cmd("vtool")
+        .arg("-show-build")
+        .arg(file)
+        .run()
+        .assert_stdout_contains_regex(format!("(minos|version) {version}"));
+}
+
+fn main() {
+    // These versions should generally be higher than the default versions
+    let (env_var, example_version, higher_example_version) = match apple_os() {
+        "macos" => ("MACOSX_DEPLOYMENT_TARGET", "12.0", "13.0"),
+        // armv7s-apple-ios and i386-apple-ios only supports iOS 10.0
+        "ios" if target() == "armv7s-apple-ios" || target() == "i386-apple-ios" => {
+            ("IPHONEOS_DEPLOYMENT_TARGET", "10.0", "10.0")
+        }
+        "ios" => ("IPHONEOS_DEPLOYMENT_TARGET", "15.0", "16.0"),
+        "watchos" => ("WATCHOS_DEPLOYMENT_TARGET", "7.0", "9.0"),
+        "tvos" => ("TVOS_DEPLOYMENT_TARGET", "14.0", "15.0"),
+        "visionos" => ("XROS_DEPLOYMENT_TARGET", "1.1", "1.2"),
+        _ => unreachable!(),
+    };
+    let default_version =
+        rustc().target(target()).env_remove(env_var).print("deployment-target").run().stdout_utf8();
+    let default_version = default_version.strip_prefix("deployment_target=").unwrap().trim();
+
+    // Test that version makes it to the object file.
+    run_in_tmpdir(|| {
+        let rustc = || {
+            let mut rustc = rustc();
+            rustc.target(target());
+            rustc.crate_type("lib");
+            rustc.emit("obj");
+            rustc.input("foo.rs");
+            rustc.output("foo.o");
+            rustc
+        };
+
+        rustc().env(env_var, example_version).run();
+        minos("foo.o", example_version);
+
+        // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator.
+        if !target().contains("macabi") && !target().contains("sim") {
+            rustc().env_remove(env_var).run();
+            minos("foo.o", default_version);
+        }
+    });
+
+    // Test that version makes it to the linker when linking dylibs.
+    run_in_tmpdir(|| {
+        // Certain watchOS targets don't support dynamic linking, so we disable the test on those.
+        if apple_os() == "watchos" {
+            return;
+        }
+
+        let rustc = || {
+            let mut rustc = rustc();
+            rustc.target(target());
+            rustc.crate_type("dylib");
+            rustc.input("foo.rs");
+            rustc.output("libfoo.dylib");
+            rustc
+        };
+
+        rustc().env(env_var, example_version).run();
+        minos("libfoo.dylib", example_version);
+
+        // FIXME(madsmtm): Deployment target is not currently passed properly to linker
+        // rustc().env_remove(env_var).run();
+        // minos("libfoo.dylib", default_version);
+
+        // Test with ld64 instead
+
+        rustc().arg("-Clinker-flavor=ld").env(env_var, example_version).run();
+        minos("libfoo.dylib", example_version);
+
+        rustc().arg("-Clinker-flavor=ld").env_remove(env_var).run();
+        minos("libfoo.dylib", default_version);
+    });
+
+    // Test that version makes it to the linker when linking executables.
+    run_in_tmpdir(|| {
+        let rustc = || {
+            let mut rustc = rustc();
+            rustc.target(target());
+            rustc.crate_type("bin");
+            rustc.input("foo.rs");
+            rustc.output("foo");
+            rustc
+        };
+
+        // FIXME(madsmtm): Doesn't work on watchOS for some reason?
+        if !target().contains("watchos") {
+            rustc().env(env_var, example_version).run();
+            minos("foo", example_version);
+
+            // FIXME(madsmtm): Deployment target is not currently passed properly to linker
+            // rustc().env_remove(env_var).run();
+            // minos("foo", default_version);
+        }
+
+        // Test with ld64 instead
+
+        rustc().arg("-Clinker-flavor=ld").env(env_var, example_version).run();
+        minos("foo", example_version);
+
+        rustc().arg("-Clinker-flavor=ld").env_remove(env_var).run();
+        minos("foo", default_version);
+    });
+
+    // Test that changing the deployment target busts the incremental cache.
+    run_in_tmpdir(|| {
+        let rustc = || {
+            let mut rustc = rustc();
+            rustc.target(target());
+            rustc.incremental("incremental");
+            rustc.crate_type("lib");
+            rustc.emit("obj");
+            rustc.input("foo.rs");
+            rustc.output("foo.o");
+            rustc
+        };
+
+        // FIXME(madsmtm): Incremental cache is not yet busted
+        // https://github.com/rust-lang/rust/issues/118204
+        let higher_example_version = example_version;
+        let default_version = example_version;
+
+        rustc().env(env_var, example_version).run();
+        minos("foo.o", example_version);
+
+        rustc().env(env_var, higher_example_version).run();
+        minos("foo.o", higher_example_version);
+
+        // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator.
+        if !target().contains("macabi") && !target().contains("sim") {
+            rustc().env_remove(env_var).run();
+            minos("foo.o", default_version);
+        }
+    });
+}
diff --git a/tests/run-make/clear-error-blank-output/rmake.rs b/tests/run-make/clear-error-blank-output/rmake.rs
index e0f042c..22e0306 100644
--- a/tests/run-make/clear-error-blank-output/rmake.rs
+++ b/tests/run-make/clear-error-blank-output/rmake.rs
@@ -8,6 +8,6 @@
 use run_make_support::rustc;
 
 fn main() {
-    let output = rustc().output("").stdin(b"fn main() {}").run_fail();
+    let output = rustc().output("").stdin_buf(b"fn main() {}").run_fail();
     output.assert_stderr_not_contains("panic");
 }
diff --git a/tests/run-make/comment-section/rmake.rs b/tests/run-make/comment-section/rmake.rs
index 1557f50..ccfc38e 100644
--- a/tests/run-make/comment-section/rmake.rs
+++ b/tests/run-make/comment-section/rmake.rs
@@ -14,7 +14,7 @@ fn main() {
 
     rustc()
         .arg("-")
-        .stdin("fn main() {}")
+        .stdin_buf("fn main() {}")
         .emit("link,obj")
         .arg("-Csave-temps")
         .target(target)
diff --git a/tests/run-make/compile-stdin/rmake.rs b/tests/run-make/compile-stdin/rmake.rs
index f93080d..b824433 100644
--- a/tests/run-make/compile-stdin/rmake.rs
+++ b/tests/run-make/compile-stdin/rmake.rs
@@ -8,6 +8,6 @@
 use run_make_support::{run, rustc};
 
 fn main() {
-    rustc().arg("-").stdin("fn main() {}").run();
+    rustc().arg("-").stdin_buf("fn main() {}").run();
     run("rust_out");
 }
diff --git a/tests/run-make/libtest-junit/rmake.rs b/tests/run-make/libtest-junit/rmake.rs
index d631313..5917660 100644
--- a/tests/run-make/libtest-junit/rmake.rs
+++ b/tests/run-make/libtest-junit/rmake.rs
@@ -21,7 +21,7 @@ fn run_tests(extra_args: &[&str], expected_file: &str) {
         .run_fail();
     let test_stdout = &cmd_out.stdout_utf8();
 
-    python_command().arg("validate_junit.py").stdin(test_stdout).run();
+    python_command().arg("validate_junit.py").stdin_buf(test_stdout).run();
 
     diff()
         .expected_file(expected_file)
diff --git a/tests/run-make/llvm-ident/rmake.rs b/tests/run-make/llvm-ident/rmake.rs
index 9699d05..47e6fc4 100644
--- a/tests/run-make/llvm-ident/rmake.rs
+++ b/tests/run-make/llvm-ident/rmake.rs
@@ -17,7 +17,7 @@ fn main() {
         .codegen_units(16)
         .opt_level("2")
         .target(&env_var("TARGET"))
-        .stdin("fn main(){}")
+        .stdin_buf("fn main(){}")
         .run();
 
     // `llvm-dis` is used here since `--emit=llvm-ir` does not emit LLVM IR
diff --git a/tests/run-make/llvm-outputs/rmake.rs b/tests/run-make/llvm-outputs/rmake.rs
index b8ac21c..632e9a0 100644
--- a/tests/run-make/llvm-outputs/rmake.rs
+++ b/tests/run-make/llvm-outputs/rmake.rs
@@ -11,8 +11,8 @@ fn main() {
         let p = cwd();
         path_bc = p.join("nonexistant_dir_bc");
         path_ir = p.join("nonexistant_dir_ir");
-        rustc().input("-").stdin("fn main() {}").out_dir(&path_bc).emit("llvm-bc").run();
-        rustc().input("-").stdin("fn main() {}").out_dir(&path_ir).emit("llvm-ir").run();
+        rustc().input("-").stdin_buf("fn main() {}").out_dir(&path_bc).emit("llvm-bc").run();
+        rustc().input("-").stdin_buf("fn main() {}").out_dir(&path_ir).emit("llvm-ir").run();
         assert!(path_bc.exists());
         assert!(path_ir.exists());
     });
diff --git a/tests/run-make/macos-deployment-target/Makefile b/tests/run-make/macos-deployment-target/Makefile
deleted file mode 100644
index 757ca69..0000000
--- a/tests/run-make/macos-deployment-target/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-# only-macos
-#
-# Check that a set deployment target actually makes it to the linker.
-# This is important since its a compatibility hazard. The linker will
-# generate load commands differently based on what minimum OS it can assume.
-
-include ../tools.mk
-
-ifeq ($(strip $(shell uname -m)),arm64)
-	GREP_PATTERN = "minos 11.0"
-else
- 	GREP_PATTERN = "version 10.13"
-endif
-
-OUT_FILE=$(TMPDIR)/with_deployment_target.dylib
-all:
-	env MACOSX_DEPLOYMENT_TARGET=10.13 $(RUSTC) with_deployment_target.rs -o $(OUT_FILE)
-# XXX: The check is for either the x86_64 minimum OR the aarch64 minimum (M1 starts at macOS 11).
-# They also use different load commands, so we let that change with each too. The aarch64 check
-# isn't as robust as the x86 one, but testing both seems unneeded.
-	vtool -show-build $(OUT_FILE) | $(CGREP) -e $(GREP_PATTERN)
diff --git a/tests/run-make/macos-deployment-target/with_deployment_target.rs b/tests/run-make/macos-deployment-target/with_deployment_target.rs
deleted file mode 100644
index 342fe0e..0000000
--- a/tests/run-make/macos-deployment-target/with_deployment_target.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#![crate_type = "cdylib"]
-
-#[allow(dead_code)]
-fn something_and_nothing() {}
diff --git a/tests/run-make/no-builtins-attribute/rmake.rs b/tests/run-make/no-builtins-attribute/rmake.rs
index 1e15b0c..7182c65 100644
--- a/tests/run-make/no-builtins-attribute/rmake.rs
+++ b/tests/run-make/no-builtins-attribute/rmake.rs
@@ -9,5 +9,5 @@
 fn main() {
     rustc().input("no_builtins.rs").emit("link").run();
     rustc().input("main.rs").emit("llvm-ir").run();
-    llvm_filecheck().patterns("filecheck.main.txt").stdin(rfs::read("main.ll")).run();
+    llvm_filecheck().patterns("filecheck.main.txt").stdin_buf(rfs::read("main.ll")).run();
 }
diff --git a/tests/run-make/pgo-branch-weights/rmake.rs b/tests/run-make/pgo-branch-weights/rmake.rs
index ef33d00..105c2fa 100644
--- a/tests/run-make/pgo-branch-weights/rmake.rs
+++ b/tests/run-make/pgo-branch-weights/rmake.rs
@@ -35,5 +35,8 @@ fn main() {
         .codegen_units(1)
         .emit("llvm-ir")
         .run();
-    llvm_filecheck().patterns("filecheck-patterns.txt").stdin(rfs::read("interesting.ll")).run();
+    llvm_filecheck()
+        .patterns("filecheck-patterns.txt")
+        .stdin_buf(rfs::read("interesting.ll"))
+        .run();
 }
diff --git a/tests/run-make/pgo-indirect-call-promotion/rmake.rs b/tests/run-make/pgo-indirect-call-promotion/rmake.rs
index d0ccfd8..28232eb 100644
--- a/tests/run-make/pgo-indirect-call-promotion/rmake.rs
+++ b/tests/run-make/pgo-indirect-call-promotion/rmake.rs
@@ -29,5 +29,8 @@ fn main() {
         .codegen_units(1)
         .emit("llvm-ir")
         .run();
-    llvm_filecheck().patterns("filecheck-patterns.txt").stdin(rfs::read("interesting.ll")).run();
+    llvm_filecheck()
+        .patterns("filecheck-patterns.txt")
+        .stdin_buf(rfs::read("interesting.ll"))
+        .run();
 }
diff --git a/tests/run-make/pgo-use/rmake.rs b/tests/run-make/pgo-use/rmake.rs
index cad4937..276af9e 100644
--- a/tests/run-make/pgo-use/rmake.rs
+++ b/tests/run-make/pgo-use/rmake.rs
@@ -51,5 +51,5 @@ fn main() {
     let lines: Vec<_> = ir.lines().rev().collect();
     let mut reversed_ir = lines.join("\n");
     reversed_ir.push('\n');
-    llvm_filecheck().patterns("filecheck-patterns.txt").stdin(reversed_ir.as_bytes()).run();
+    llvm_filecheck().patterns("filecheck-patterns.txt").stdin_buf(reversed_ir.as_bytes()).run();
 }
diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs
new file mode 100644
index 0000000..81cc775
--- /dev/null
+++ b/tests/run-make/rustc-crates-on-stable/rmake.rs
@@ -0,0 +1,36 @@
+//! Checks if selected rustc crates can be compiled on the stable channel (or a "simulation" of it).
+//! These crates are designed to be used by downstream users.
+
+use run_make_support::{cargo, rustc_path, source_root};
+
+fn main() {
+    // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we use)
+    cargo()
+        // Ensure `proc-macro2`'s nightly detection is disabled
+        .env("RUSTC_STAGE", "0")
+        .env("RUSTC", rustc_path())
+        // We want to disallow all nightly features to simulate a stable build
+        .env("RUSTFLAGS", "-Zallow-features=")
+        .arg("build")
+        .arg("--manifest-path")
+        .arg(source_root().join("Cargo.toml"))
+        .args(&[
+            // Avoid depending on transitive rustc crates
+            "--no-default-features",
+            // Emit artifacts in this temporary directory, not in the source_root's `target` folder
+            "--target-dir",
+            "target",
+        ])
+        // Check that these crates can be compiled on "stable"
+        .args(&[
+            "-p",
+            "rustc_type_ir",
+            "-p",
+            "rustc_next_trait_solver",
+            "-p",
+            "rustc_pattern_analysis",
+            "-p",
+            "rustc_lexer",
+        ])
+        .run();
+}
diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout
index bc38d9e..125443c 100644
--- a/tests/run-make/rustdoc-default-output/output-default.stdout
+++ b/tests/run-make/rustdoc-default-output/output-default.stdout
@@ -172,6 +172,23 @@
         --scrape-tests  Include test code when scraping examples
         --with-examples path to function call information (for displaying examples in the documentation)
                         
+        --merge none|shared|finalize
+                        Controls how rustdoc handles files from previously
+                        documented crates in the doc root
+                        none = Do not write cross-crate information to the
+                        --out-dir
+                        shared = Append current crate's info to files found in
+                        the --out-dir
+                        finalize = Write current crate's info and
+                        --include-parts-dir info to the --out-dir, overwriting
+                        conflicting files
+        --parts-out-dir path/to/doc.parts/<crate-name>
+                        Writes trait implementations and other info for the
+                        current crate to provided path. Only use with
+                        --merge=none
+        --include-parts-dir path/to/doc.parts/<crate-name>
+                        Includes trait implementations and other crate info
+                        from provided path. Only use with --merge=finalize
         --disable-minification 
                         removed
         --plugin-path DIR
diff --git a/tests/run-make/separate-link/rmake.rs b/tests/run-make/separate-link/rmake.rs
index e91b254..0ec7334 100644
--- a/tests/run-make/separate-link/rmake.rs
+++ b/tests/run-make/separate-link/rmake.rs
@@ -8,7 +8,7 @@
 use run_make_support::{run, rustc};
 
 fn main() {
-    rustc().stdin(b"fn main(){}").arg("-Zno-link").arg("-").run();
+    rustc().stdin_buf(b"fn main(){}").arg("-Zno-link").arg("-").run();
     rustc().arg("-Zlink-only").input("rust_out.rlink").run();
     run("rust_out");
 }
diff --git a/tests/run-make/static-pie/rmake.rs b/tests/run-make/static-pie/rmake.rs
index 74f86bb..1557c17 100644
--- a/tests/run-make/static-pie/rmake.rs
+++ b/tests/run-make/static-pie/rmake.rs
@@ -28,7 +28,7 @@ fn ok_compiler_version(compiler: &str) -> bool {
     }
 
     let compiler_output =
-        cmd(compiler).stdin(trigger).arg("-").arg("-E").arg("-x").arg("c").run().stdout_utf8();
+        cmd(compiler).stdin_buf(trigger).arg("-").arg("-E").arg("-x").arg("c").run().stdout_utf8();
     let re = Regex::new(r"(?m)^(\d+)").unwrap();
     let version: u32 =
         re.captures(&compiler_output).unwrap().get(1).unwrap().as_str().parse().unwrap();
diff --git a/tests/run-make/stdin-rustc/rmake.rs b/tests/run-make/stdin-rustc/rmake.rs
index 68e9cf2..2d634dd 100644
--- a/tests/run-make/stdin-rustc/rmake.rs
+++ b/tests/run-make/stdin-rustc/rmake.rs
@@ -14,7 +14,7 @@ fn main() {
 
 fn main() {
     // echo $HELLO_WORLD | rustc -
-    rustc().arg("-").stdin(HELLO_WORLD).run();
+    rustc().arg("-").stdin_buf(HELLO_WORLD).run();
     assert!(
         PathBuf::from(if !is_windows() { "rust_out" } else { "rust_out.exe" })
             .try_exists()
@@ -22,7 +22,7 @@ fn main() {
     );
 
     // echo $NOT_UTF8 | rustc -
-    rustc().arg("-").stdin(NOT_UTF8).run_fail().assert_stderr_contains(
+    rustc().arg("-").stdin_buf(NOT_UTF8).run_fail().assert_stderr_contains(
         "error: couldn't read from stdin, as it did not contain valid UTF-8",
     );
 }
diff --git a/tests/run-make/stdin-rustdoc/rmake.rs b/tests/run-make/stdin-rustdoc/rmake.rs
index de47a24..30f97b8 100644
--- a/tests/run-make/stdin-rustdoc/rmake.rs
+++ b/tests/run-make/stdin-rustdoc/rmake.rs
@@ -15,11 +15,11 @@ fn main() {
     let out_dir = PathBuf::from("doc");
 
     // rustdoc -
-    rustdoc().arg("-").out_dir(&out_dir).stdin(INPUT).run();
+    rustdoc().arg("-").out_dir(&out_dir).stdin_buf(INPUT).run();
     assert!(out_dir.join("rust_out/struct.F.html").try_exists().unwrap());
 
     // rustdoc --test -
-    rustdoc().arg("--test").arg("-").stdin(INPUT).run();
+    rustdoc().arg("--test").arg("-").stdin_buf(INPUT).run();
 
     // rustdoc file.rs -
     rustdoc().arg("file.rs").arg("-").run_fail();
diff --git a/tests/run-make/sysroot-crates-are-unstable/rmake.rs b/tests/run-make/sysroot-crates-are-unstable/rmake.rs
index 2240d87..c81c7fa 100644
--- a/tests/run-make/sysroot-crates-are-unstable/rmake.rs
+++ b/tests/run-make/sysroot-crates-are-unstable/rmake.rs
@@ -34,7 +34,7 @@ fn check_crate_is_unstable(cr: &Crate) {
         .target(target())
         .extern_(name, path)
         .input("-")
-        .stdin(format!("extern crate {name};"))
+        .stdin_buf(format!("extern crate {name};"))
         .run_fail();
 
     // Make sure it failed for the intended reason, not some other reason.
diff --git a/tests/run-make/unknown-mod-stdin/rmake.rs b/tests/run-make/unknown-mod-stdin/rmake.rs
index 0fe5c78..6be3119 100644
--- a/tests/run-make/unknown-mod-stdin/rmake.rs
+++ b/tests/run-make/unknown-mod-stdin/rmake.rs
@@ -12,7 +12,7 @@
 use run_make_support::{diff, rustc};
 
 fn main() {
-    let out = rustc().crate_type("rlib").stdin(b"mod unknown;").arg("-").run_fail();
+    let out = rustc().crate_type("rlib").stdin_buf(b"mod unknown;").arg("-").run_fail();
     diff()
         .actual_text("actual-stdout", out.stdout_utf8())
         .expected_file("unknown-mod.stdout")
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs
index 130781a..e58762a 100644
--- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs
@@ -78,19 +78,23 @@ fn check(func_re: &str, mut checks: &str) {
     // This is because frame pointers are optional, and them being enabled requires
     // an additional `popq` in the pattern checking file.
     if func_re == "std::io::stdio::_print::[[:alnum:]]+" {
-        let output = llvm_filecheck().stdin(&dump).patterns(checks).run_unchecked();
+        let output = llvm_filecheck().stdin_buf(&dump).patterns(checks).run_unchecked();
         if !output.status().success() {
             checks = "print.without_frame_pointers.checks";
-            llvm_filecheck().stdin(&dump).patterns(checks).run();
+            llvm_filecheck().stdin_buf(&dump).patterns(checks).run();
         }
     } else {
-        llvm_filecheck().stdin(&dump).patterns(checks).run();
+        llvm_filecheck().stdin_buf(&dump).patterns(checks).run();
     }
     if !["rust_plus_one_global_asm", "cmake_plus_one_c_global_asm", "cmake_plus_one_cxx_global_asm"]
         .contains(&func_re)
     {
         // The assembler cannot avoid explicit `ret` instructions. Sequences
         // of `shlq $0x0, (%rsp); lfence; retq` are used instead.
-        llvm_filecheck().args(&["--implicit-check-not", "ret"]).stdin(dump).patterns(checks).run();
+        llvm_filecheck()
+            .args(&["--implicit-check-not", "ret"])
+            .stdin_buf(dump)
+            .patterns(checks)
+            .run();
     }
 }
diff --git a/tests/rustdoc-gui/code-example-buttons.goml b/tests/rustdoc-gui/code-example-buttons.goml
index 4f037ec..c62683b 100644
--- a/tests/rustdoc-gui/code-example-buttons.goml
+++ b/tests/rustdoc-gui/code-example-buttons.goml
@@ -94,3 +94,24 @@
     "filter": "invert(0.5)",
     "filter_hover": "invert(0.35)",
 })
+
+define-function: (
+    "check-buttons-position",
+    [pre_selector],
+    block {
+        move-cursor-to: |pre_selector| + " .rust:not(.item-decl)"
+        store-position: (|pre_selector| + " .rust:not(.item-decl)", {"x": x, "y": y})
+        assert-position: (|pre_selector| + " .rust:not(.item-decl) + .button-holder", {
+            "y": |y| + 4,
+        })
+    }
+)
+
+call-function: ("check-buttons-position", {"pre_selector": ".example-wrap"})
+
+go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
+// We should work as well for scraped examples.
+call-function: ("check-buttons-position", {"pre_selector": ".scraped-example .example-wrap"})
+// And also when the scraped example "title" goes above.
+set-window-size: (600, 600)
+call-function: ("check-buttons-position", {"pre_selector": ".scraped-example .example-wrap"})
diff --git a/tests/rustdoc-gui/docblock-code-block-line-number.goml b/tests/rustdoc-gui/docblock-code-block-line-number.goml
index 348ce0c..03f8f80 100644
--- a/tests/rustdoc-gui/docblock-code-block-line-number.goml
+++ b/tests/rustdoc-gui/docblock-code-block-line-number.goml
@@ -5,6 +5,18 @@
 // We check that without this setting, there is no line number displayed.
 assert-false: "pre.example-line-numbers"
 
+// All corners should be rounded.
+assert-css: (
+    ".example-wrap .rust",
+    {
+        "border-top-left-radius": "6px",
+        "border-bottom-left-radius": "6px",
+        "border-top-right-radius": "6px",
+        "border-bottom-right-radius": "6px",
+    },
+    ALL,
+)
+
 // We set the setting to show the line numbers on code examples.
 set-local-storage: {"rustdoc-line-numbers": "true"}
 reload:
@@ -29,9 +41,21 @@
                 "margin": "0px",
                 "padding": "14px 8px",
                 "text-align": "right",
+                // There should not be a radius on the right of the line numbers.
+                "border-top-left-radius": "6px",
+                "border-bottom-left-radius": "6px",
+                "border-top-right-radius": "0px",
+                "border-bottom-right-radius": "0px",
             },
             ALL,
         )
+        // There should not be a radius on the left of the line numbers.
+        assert-css: ("pre.example-line-numbers + .rust", {
+            "border-top-left-radius": "0px",
+            "border-bottom-left-radius": "0px",
+            "border-top-right-radius": "6px",
+            "border-bottom-right-radius": "6px",
+        })
     },
 )
 call-function: ("check-colors", {
@@ -64,7 +88,56 @@
 assert-false: "pre.example-line-numbers"
 assert-local-storage: {"rustdoc-line-numbers": "false" }
 
+// Check that the rounded corners are back.
+assert-css: (
+    ".example-wrap .rust",
+    {
+        "border-top-left-radius": "6px",
+        "border-bottom-left-radius": "6px",
+        "border-top-right-radius": "6px",
+        "border-bottom-right-radius": "6px",
+    },
+    ALL,
+)
+
 // Finally, turn it on again.
 click: "input#line-numbers"
 wait-for: "pre.example-line-numbers"
 assert-local-storage: {"rustdoc-line-numbers": "true" }
+
+// Same check with scraped examples line numbers.
+go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
+
+assert-css: (
+    ".scraped-example .src-line-numbers > pre",
+    {
+        // There should not be a radius on the right of the line numbers.
+        "border-top-left-radius": "6px",
+        "border-bottom-left-radius": "6px",
+        "border-top-right-radius": "0px",
+        "border-bottom-right-radius": "0px",
+    },
+    ALL,
+)
+assert-css: (
+    ".scraped-example .src-line-numbers",
+    {
+        // There should not be a radius on the right of the line numbers.
+        "border-top-left-radius": "6px",
+        "border-bottom-left-radius": "6px",
+        "border-top-right-radius": "0px",
+        "border-bottom-right-radius": "0px",
+    },
+    ALL,
+)
+assert-css: (
+    ".scraped-example .rust",
+    {
+        // There should not be a radius on the left of the code.
+        "border-top-left-radius": "0px",
+        "border-bottom-left-radius": "0px",
+        "border-top-right-radius": "6px",
+        "border-bottom-right-radius": "6px",
+    },
+    ALL,
+)
diff --git a/tests/rustdoc-gui/scrape-examples-button-focus.goml b/tests/rustdoc-gui/scrape-examples-button-focus.goml
index af4293d..83ed6a2 100644
--- a/tests/rustdoc-gui/scrape-examples-button-focus.goml
+++ b/tests/rustdoc-gui/scrape-examples-button-focus.goml
@@ -3,29 +3,53 @@
 go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
 
 // The next/prev buttons vertically scroll the code viewport between examples
-store-property: (".scraped-example-list > .scraped-example pre", {"scrollTop": initialScrollTop})
+move-cursor-to: ".scraped-example-list > .scraped-example"
+store-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
+    "scrollTop": initialScrollTop,
+})
+assert-property: (".scraped-example-list > .scraped-example .rust", {
+    "scrollTop": |initialScrollTop|,
+})
 focus: ".scraped-example-list > .scraped-example .next"
 press-key: "Enter"
-assert-property-false: (".scraped-example-list > .scraped-example pre", {
+assert-property-false: (".scraped-example-list > .scraped-example .src-line-numbers", {
+    "scrollTop": |initialScrollTop|
+}, NEAR)
+assert-property-false: (".scraped-example-list > .scraped-example .rust", {
     "scrollTop": |initialScrollTop|
 }, NEAR)
 focus: ".scraped-example-list > .scraped-example .prev"
 press-key: "Enter"
-assert-property: (".scraped-example-list > .scraped-example pre", {
+assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
+    "scrollTop": |initialScrollTop|
+}, NEAR)
+assert-property: (".scraped-example-list > .scraped-example .rust", {
     "scrollTop": |initialScrollTop|
 }, NEAR)
 
 // The expand button increases the scrollHeight of the minimized code viewport
 store-property: (".scraped-example-list > .scraped-example pre", {"offsetHeight": smallOffsetHeight})
-assert-property-false: (".scraped-example-list > .scraped-example pre", {
+assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
+    "scrollHeight": |smallOffsetHeight|
+}, NEAR)
+assert-property: (".scraped-example-list > .scraped-example .rust", {
     "scrollHeight": |smallOffsetHeight|
 }, NEAR)
 focus: ".scraped-example-list > .scraped-example .expand"
 press-key: "Enter"
-assert-property-false: (".scraped-example-list > .scraped-example pre", {
+assert-property-false: (".scraped-example-list > .scraped-example .src-line-numbers", {
     "offsetHeight": |smallOffsetHeight|
 }, NEAR)
-store-property: (".scraped-example-list > .scraped-example pre", {"offsetHeight": fullOffsetHeight})
-assert-property: (".scraped-example-list > .scraped-example pre", {
+assert-property-false: (".scraped-example-list > .scraped-example .rust", {
+    "offsetHeight": |smallOffsetHeight|
+}, NEAR)
+store-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
+    "offsetHeight": fullOffsetHeight,
+})
+assert-property: (".scraped-example-list > .scraped-example .rust", {
+    "offsetHeight": |fullOffsetHeight|,
+    "scrollHeight": |fullOffsetHeight|,
+})
+assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
     "scrollHeight": |fullOffsetHeight|
 }, NEAR)
diff --git a/tests/rustdoc-gui/scrape-examples-color.goml b/tests/rustdoc-gui/scrape-examples-color.goml
index 588ba08..b0faca1 100644
--- a/tests/rustdoc-gui/scrape-examples-color.goml
+++ b/tests/rustdoc-gui/scrape-examples-color.goml
@@ -10,10 +10,10 @@
     block {
         call-function: ("switch-theme", {"theme": |theme|})
         wait-for: ".more-examples-toggle"
-        assert-css: (".scraped-example .example-wrap .rust span.highlight:not(.focus)", {
+        assert-css: (".scraped-example .rust span.highlight:not(.focus)", {
             "background-color": |highlight|,
         }, ALL)
-        assert-css: (".scraped-example .example-wrap .rust span.highlight.focus", {
+        assert-css: (".scraped-example .rust span.highlight.focus", {
             "background-color": |highlight_focus|,
         }, ALL)
 
@@ -67,11 +67,11 @@
     [theme, background_color_start, background_color_end],
     block {
         call-function: ("switch-theme", {"theme": |theme|})
-        assert-css: (".scraped-example:not(.expanded) .code-wrapper::before", {
+        assert-css: (".scraped-example:not(.expanded) .example-wrap::before", {
             "background-image": "linear-gradient(" + |background_color_start| + ", " +
                 |background_color_end| + ")",
         })
-        assert-css: (".scraped-example:not(.expanded) .code-wrapper::after", {
+        assert-css: (".scraped-example:not(.expanded) .example-wrap::after", {
             "background-image": "linear-gradient(to top, " + |background_color_start| + ", " +
                 |background_color_end| + ")",
         })
diff --git a/tests/rustdoc-gui/scrape-examples-layout.goml b/tests/rustdoc-gui/scrape-examples-layout.goml
index 4fc1c1a..6bea352 100644
--- a/tests/rustdoc-gui/scrape-examples-layout.goml
+++ b/tests/rustdoc-gui/scrape-examples-layout.goml
@@ -1,48 +1,115 @@
 // Check that the line number column has the correct layout.
 go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
 
+set-window-size: (1000, 1000)
+
 // Check that it's not zero.
 assert-property-false: (
-    ".more-scraped-examples .scraped-example .code-wrapper .src-line-numbers",
+    ".more-scraped-examples .scraped-example .src-line-numbers",
     {"clientWidth": "0"}
 )
 
 // Check that examples with very long lines have the same width as ones that don't.
 store-property: (
-    ".more-scraped-examples .scraped-example:nth-child(2) .code-wrapper .src-line-numbers",
+    ".more-scraped-examples .scraped-example:nth-child(2) .src-line-numbers",
     {"clientWidth": clientWidth},
 )
 
 assert-property: (
-    ".more-scraped-examples .scraped-example:nth-child(3) .code-wrapper .src-line-numbers",
+    ".more-scraped-examples .scraped-example:nth-child(3) .src-line-numbers",
     {"clientWidth": |clientWidth|}
 )
 
 assert-property: (
-    ".more-scraped-examples .scraped-example:nth-child(4) .code-wrapper .src-line-numbers",
+    ".more-scraped-examples .scraped-example:nth-child(4) .src-line-numbers",
     {"clientWidth": |clientWidth|}
 )
 
 assert-property: (
-    ".more-scraped-examples .scraped-example:nth-child(5) .code-wrapper .src-line-numbers",
+    ".more-scraped-examples .scraped-example:nth-child(5) .src-line-numbers",
     {"clientWidth": |clientWidth|}
 )
 
 assert-property: (
-    ".more-scraped-examples .scraped-example:nth-child(6) .code-wrapper .src-line-numbers",
+    ".more-scraped-examples .scraped-example:nth-child(6) .src-line-numbers",
     {"clientWidth": |clientWidth|}
 )
 
+// The "title" should be located at the right bottom corner of the code example.
+store-position: (".scraped-example .example-wrap", {"x": x, "y": y})
+store-size: (".scraped-example .example-wrap", {"width": width, "height": height})
+store-size: (".scraped-example .scraped-example-title", {
+    "width": title_width,
+    "height": title_height,
+})
+assert-position: (".scraped-example .scraped-example-title", {
+    "x": |x| + |width| - |title_width| - 5,
+    "y": |y| + |height| - |title_height| - 8,
+})
+
+// Check that the expand button works and also that line number aligns with code.
+move-cursor-to: ".scraped-example .rust"
+click: ".scraped-example .button-holder .expand"
+wait-for: ".scraped-example.expanded"
+// They should have the same y position.
+compare-elements-position: (
+    ".scraped-example.expanded .src-line-numbers pre span",
+    ".scraped-example.expanded .rust code",
+    ["y"],
+)
+// And they should have the same height.
+compare-elements-size: (
+    ".scraped-example.expanded .src-line-numbers",
+    ".scraped-example.expanded .rust",
+    ["height"],
+)
+// Collapse code again.
+click: ".scraped-example .button-holder .expand"
+
 // Check that for both mobile and desktop sizes, the buttons in scraped examples are displayed
 // correctly.
 
 store-value: (offset_y, 4)
 
 // First with desktop
-assert-position: (".scraped-example .code-wrapper", {"y": 226})
-assert-position: (".scraped-example .code-wrapper .prev", {"y": 226 + |offset_y|})
+assert-position: (".scraped-example", {"y": 226})
+assert-position: (".scraped-example .prev", {"y": 226 + |offset_y|})
+
+// Gradient background should be at the top of the code block.
+assert-css: (".scraped-example .example-wrap::before", {"top": "0px"})
+assert-css: (".scraped-example .example-wrap::after", {"bottom": "0px"})
 
 // Then with mobile
 set-window-size: (600, 600)
-assert-position: (".scraped-example .code-wrapper", {"y": 308})
-assert-position: (".scraped-example .code-wrapper .prev", {"y": 308 + |offset_y|})
+store-size: (".scraped-example .scraped-example-title", {"height": title_height})
+assert-position: (".scraped-example", {"y": 284})
+assert-position: (".scraped-example .prev", {"y": 284 + |offset_y| + |title_height|})
+
+define-function: (
+    "check_title_and_code_position",
+    [],
+    block {
+        // Title should be above the code.
+        store-position: (".scraped-example .example-wrap .src-line-numbers", {"x": x, "y": y})
+        store-size: (".scraped-example .scraped-example-title", { "height": title_height })
+
+        assert-position: (".scraped-example .scraped-example-title", {
+            "x": |x|, // same X position.
+            "y": |y| - |title_height|,
+        })
+
+        // Line numbers should be right beside the code.
+        compare-elements-position: (
+            ".scraped-example .example-wrap .src-line-numbers",
+            ".scraped-example .example-wrap .rust",
+            ["y"],
+        )
+    }
+)
+
+// Check that the title is now above the code.
+call-function: ("check_title_and_code_position", {})
+
+// Then with small mobile
+set-window-size: (300, 300)
+call-function: ("check_title_and_code_position", {})
diff --git a/tests/rustdoc-gui/src/theme_css/custom-theme.css b/tests/rustdoc-gui/src/theme_css/custom-theme.css
index a56c31a..366f09f 100644
--- a/tests/rustdoc-gui/src/theme_css/custom-theme.css
+++ b/tests/rustdoc-gui/src/theme_css/custom-theme.css
@@ -23,6 +23,8 @@
 	--copy-path-button-color: #999;
 	--copy-path-img-filter: invert(50%);
 	--copy-path-img-hover-filter: invert(35%);
+        --code-example-button-color: #7f7f7f;
+	--code-example-button-hover-color: #a5a5a5;
 	--codeblock-error-hover-color: rgb(255, 0, 0);
 	--codeblock-error-color: rgba(255, 0, 0, .5);
 	--codeblock-ignore-hover-color: rgb(255, 142, 0);
diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js
index c4d7c2b..5ce35bf 100644
--- a/tests/rustdoc-js-std/parser-errors.js
+++ b/tests/rustdoc-js-std/parser-errors.js
@@ -252,15 +252,6 @@
         error: "Unexpected `'` after `b` (not a valid identifier)",
     },
     {
-        query: "a->",
-        elems: [],
-        foundElems: 0,
-        original: "a->",
-        returned: [],
-        userQuery: "a->",
-        error: "Expected at least one item after `->`",
-    },
-    {
         query: '"p" <a>',
         elems: [],
         foundElems: 0,
diff --git a/tests/rustdoc-js-std/parser-returned.js b/tests/rustdoc-js-std/parser-returned.js
index 44e517c..8f68209 100644
--- a/tests/rustdoc-js-std/parser-returned.js
+++ b/tests/rustdoc-js-std/parser-returned.js
@@ -94,4 +94,72 @@
         userQuery: "-> !",
         error: null,
     },
+    {
+        query: "a->",
+        elems: [{
+            name: "a",
+            fullPath: ["a"],
+            pathWithoutLast: [],
+            pathLast: "a",
+            generics: [],
+            typeFilter: -1,
+        }],
+        foundElems: 1,
+        original: "a->",
+        returned: [],
+        userQuery: "a->",
+        hasReturnArrow: true,
+        error: null,
+    },
+    {
+        query: "!->",
+        elems: [{
+            name: "never",
+            fullPath: ["never"],
+            pathWithoutLast: [],
+            pathLast: "never",
+            generics: [],
+            typeFilter: 1,
+        }],
+        foundElems: 1,
+        original: "!->",
+        returned: [],
+        userQuery: "!->",
+        hasReturnArrow: true,
+        error: null,
+    },
+    {
+        query: "! ->",
+        elems: [{
+            name: "never",
+            fullPath: ["never"],
+            pathWithoutLast: [],
+            pathLast: "never",
+            generics: [],
+            typeFilter: 1,
+        }],
+        foundElems: 1,
+        original: "! ->",
+        returned: [],
+        userQuery: "! ->",
+        hasReturnArrow: true,
+        error: null,
+    },
+    {
+        query: "primitive:!->",
+        elems: [{
+            name: "never",
+            fullPath: ["never"],
+            pathWithoutLast: [],
+            pathLast: "never",
+            generics: [],
+            typeFilter: 1,
+        }],
+        foundElems: 1,
+        original: "primitive:!->",
+        returned: [],
+        userQuery: "primitive:!->",
+        hasReturnArrow: true,
+        error: null,
+    },
 ];
diff --git a/tests/rustdoc-js/never-search.js b/tests/rustdoc-js/never-search.js
index 9f18370..9cc62a5 100644
--- a/tests/rustdoc-js/never-search.js
+++ b/tests/rustdoc-js/never-search.js
@@ -2,6 +2,13 @@
 
 const EXPECTED = [
     {
+        'query': '! ->',
+        'others': [
+            { 'path': 'never_search', 'name': 'impossible' },
+            { 'path': 'never_search', 'name': 'box_impossible' },
+        ],
+    },
+    {
         'query': '-> !',
         'others': [
             { 'path': 'never_search', 'name': 'loops' },
diff --git a/tests/rustdoc-json/assoc_items.rs b/tests/rustdoc-json/assoc_items.rs
index 7fd0fe2..f315f37 100644
--- a/tests/rustdoc-json/assoc_items.rs
+++ b/tests/rustdoc-json/assoc_items.rs
@@ -9,12 +9,12 @@ impl Simple {
 
 pub trait EasyToImpl {
     //@ has "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type"
-    //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.default" null
+    //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.type" null
     //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.bounds" []
     /// ToDeclare trait
     type ToDeclare;
     //@ has "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const"
-    //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.default" null
+    //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.value" null
     //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.type.primitive" '"usize"'
     /// AN_ATTRIBUTE trait
     const AN_ATTRIBUTE: usize;
@@ -22,13 +22,13 @@ pub trait EasyToImpl {
 
 impl EasyToImpl for Simple {
     //@ has "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type"
-    //@ is "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type.default.primitive" \"usize\"
+    //@ is "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type.type.primitive" \"usize\"
     /// ToDeclare impl
     type ToDeclare = usize;
 
     //@ has "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const"
     //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.type.primitive" \"usize\"
-    //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.default" \"12\"
+    //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.value" \"12\"
     /// AN_ATTRIBUTE impl
     const AN_ATTRIBUTE: usize = 12;
 }
diff --git a/tests/rustdoc-json/blanket_impls.rs b/tests/rustdoc-json/blanket_impls.rs
index bc2c98d..f2acabb 100644
--- a/tests/rustdoc-json/blanket_impls.rs
+++ b/tests/rustdoc-json/blanket_impls.rs
@@ -3,6 +3,6 @@
 #![no_std]
 
 //@ has "$.index[*][?(@.name=='Error')].inner.assoc_type"
-//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path"
-//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path.name" \"Infallible\"
+//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path"
+//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path.name" \"Infallible\"
 pub struct ForBlanketTryFromImpl;
diff --git a/tests/rustdoc-json/enums/kind.rs b/tests/rustdoc-json/enums/kind.rs
index ef3d936..2e0fb31 100644
--- a/tests/rustdoc-json/enums/kind.rs
+++ b/tests/rustdoc-json/enums/kind.rs
@@ -5,7 +5,7 @@ pub enum Foo {
     //@ is "$.index[*][?(@.name=='Unit')].inner.variant.kind" '"plain"'
     Unit,
     //@ set Named = "$.index[*][?(@.name=='Named')].id"
-    //@ is "$.index[*][?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "fields_stripped": false}'
+    //@ is "$.index[*][?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "has_stripped_fields": false}'
     Named {},
     //@ set Tuple = "$.index[*][?(@.name=='Tuple')].id"
     //@ is "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple" []
@@ -13,7 +13,7 @@ pub enum Foo {
     //@ set NamedField = "$.index[*][?(@.name=='NamedField')].id"
     //@ set x = "$.index[*][?(@.name=='x' && @.inner.struct_field)].id"
     //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields[*]" $x
-    //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields_stripped" false
+    //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.has_stripped_fields" false
     NamedField { x: i32 },
     //@ set TupleField = "$.index[*][?(@.name=='TupleField')].id"
     //@ set tup_field = "$.index[*][?(@.name=='0' && @.inner.struct_field)].id"
diff --git a/tests/rustdoc-json/enums/struct_field_hidden.rs b/tests/rustdoc-json/enums/struct_field_hidden.rs
index b724f9a..2184f58 100644
--- a/tests/rustdoc-json/enums/struct_field_hidden.rs
+++ b/tests/rustdoc-json/enums/struct_field_hidden.rs
@@ -9,7 +9,7 @@
         //@ set y = "$.index[*][?(@.name=='y')].id"
         y: i32,
     },
-    //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields_stripped" true
+    //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.has_stripped_fields" true
     //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[0]" $b
     //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[1]" $y
     //@ count "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[*]" 2
diff --git a/tests/rustdoc-json/enums/use_glob.rs b/tests/rustdoc-json/enums/use_glob.rs
index 61766d2..2631b43 100644
--- a/tests/rustdoc-json/enums/use_glob.rs
+++ b/tests/rustdoc-json/enums/use_glob.rs
@@ -7,9 +7,9 @@ pub enum Color {
     Blue,
 }
 
-//@ set use_Color = "$.index[*][?(@.inner.import)].id"
-//@ is "$.index[*][?(@.inner.import)].inner.import.id" $Color
-//@ is "$.index[*][?(@.inner.import)].inner.import.glob" true
+//@ set use_Color = "$.index[*][?(@.inner.use)].id"
+//@ is "$.index[*][?(@.inner.use)].inner.use.id" $Color
+//@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" true
 pub use Color::*;
 
 //@ ismany "$.index[*][?(@.name == 'use_glob')].inner.module.items[*]" $Color $use_Color
diff --git a/tests/rustdoc-json/enums/use_variant.rs b/tests/rustdoc-json/enums/use_variant.rs
index 9010d61..6d3322e 100644
--- a/tests/rustdoc-json/enums/use_variant.rs
+++ b/tests/rustdoc-json/enums/use_variant.rs
@@ -5,8 +5,8 @@ pub enum AlwaysNone {
 }
 //@ is "$.index[*][?(@.name == 'AlwaysNone')].inner.enum.variants[*]" $None
 
-//@ set use_None = "$.index[*][?(@.inner.import)].id"
-//@ is "$.index[*][?(@.inner.import)].inner.import.id" $None
+//@ set use_None = "$.index[*][?(@.inner.use)].id"
+//@ is "$.index[*][?(@.inner.use)].inner.use.id" $None
 pub use AlwaysNone::None;
 
 //@ ismany "$.index[*][?(@.name == 'use_variant')].inner.module.items[*]" $AlwaysNone $use_None
diff --git a/tests/rustdoc-json/enums/use_variant_foreign.rs b/tests/rustdoc-json/enums/use_variant_foreign.rs
index 0f3f16ff..a9ad61b 100644
--- a/tests/rustdoc-json/enums/use_variant_foreign.rs
+++ b/tests/rustdoc-json/enums/use_variant_foreign.rs
@@ -2,7 +2,7 @@
 
 extern crate color;
 
-//@ has "$.index[*].inner.import[?(@.name == 'Red')]"
+//@ has "$.index[*].inner.use[?(@.name == 'Red')]"
 pub use color::Color::Red;
 
 //@ !has "$.index[*][?(@.name == 'Red')]"
diff --git a/tests/rustdoc-json/fn_pointer/generics.rs b/tests/rustdoc-json/fn_pointer/generics.rs
index 9f5d23a..7d64e49 100644
--- a/tests/rustdoc-json/fn_pointer/generics.rs
+++ b/tests/rustdoc-json/fn_pointer/generics.rs
@@ -1,9 +1,9 @@
 // ignore-tidy-linelength
 
-//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][0]" '"val"'
-//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][1].borrowed_ref.lifetime" \"\'c\"
-//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.output.primitive" \"i32\"
+//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][0]" '"val"'
+//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][1].borrowed_ref.lifetime" \"\'c\"
+//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.output.primitive" \"i32\"
 //@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[*]" 1
 //@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].name" \"\'c\"
 //@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
diff --git a/tests/rustdoc-json/fn_pointer/qualifiers.rs b/tests/rustdoc-json/fn_pointer/qualifiers.rs
index 9c0e6c0..6f03cf5 100644
--- a/tests/rustdoc-json/fn_pointer/qualifiers.rs
+++ b/tests/rustdoc-json/fn_pointer/qualifiers.rs
@@ -1,11 +1,11 @@
 // ignore-tidy-linelength
 
-//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.unsafe" false
-//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.const" false
-//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.async" false
+//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_unsafe" false
+//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_const" false
+//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_async" false
 pub type FnPointer = fn();
 
-//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.unsafe" true
-//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.const" false
-//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.async" false
+//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_unsafe" true
+//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_const" false
+//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_async" false
 pub type UnsafePointer = unsafe fn();
diff --git a/tests/rustdoc-json/fns/async_return.rs b/tests/rustdoc-json/fns/async_return.rs
index e029c72..18a8a58 100644
--- a/tests/rustdoc-json/fns/async_return.rs
+++ b/tests/rustdoc-json/fns/async_return.rs
@@ -5,30 +5,30 @@
 
 use std::future::Future;
 
-//@ is "$.index[*][?(@.name=='get_int')].inner.function.decl.output.primitive" \"i32\"
-//@ is "$.index[*][?(@.name=='get_int')].inner.function.header.async" false
+//@ is "$.index[*][?(@.name=='get_int')].inner.function.sig.output.primitive" \"i32\"
+//@ is "$.index[*][?(@.name=='get_int')].inner.function.header.is_async" false
 pub fn get_int() -> i32 {
     42
 }
 
-//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.decl.output.primitive" \"i32\"
-//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.header.async" true
+//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.sig.output.primitive" \"i32\"
+//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.header.is_async" true
 pub async fn get_int_async() -> i32 {
     42
 }
 
-//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"'
-//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
-//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive"  \"i32\"
-//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.async" false
+//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"'
+//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"'
+//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive"  \"i32\"
+//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.is_async" false
 pub fn get_int_future() -> impl Future<Output = i32> {
     async { 42 }
 }
 
-//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"'
-//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
-//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive" \"i32\"
-//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.async" true
+//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"'
+//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"'
+//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\"
+//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.is_async" true
 pub async fn get_int_future_async() -> impl Future<Output = i32> {
     async { 42 }
 }
diff --git a/tests/rustdoc-json/fns/extern_c_variadic.rs b/tests/rustdoc-json/fns/extern_c_variadic.rs
index defe663..8e90856 100644
--- a/tests/rustdoc-json/fns/extern_c_variadic.rs
+++ b/tests/rustdoc-json/fns/extern_c_variadic.rs
@@ -1,6 +1,6 @@
 extern "C" {
-    //@ is "$.index[*][?(@.name == 'not_variadic')].inner.function.decl.c_variadic" false
+    //@ is "$.index[*][?(@.name == 'not_variadic')].inner.function.sig.is_c_variadic" false
     pub fn not_variadic(_: i32);
-    //@ is "$.index[*][?(@.name == 'variadic')].inner.function.decl.c_variadic" true
+    //@ is "$.index[*][?(@.name == 'variadic')].inner.function.sig.is_c_variadic" true
     pub fn variadic(_: i32, ...);
 }
diff --git a/tests/rustdoc-json/fns/generic_args.rs b/tests/rustdoc-json/fns/generic_args.rs
index 75c5fcb..b541244 100644
--- a/tests/rustdoc-json/fns/generic_args.rs
+++ b/tests/rustdoc-json/fns/generic_args.rs
@@ -12,27 +12,27 @@ pub trait GenericFoo<'a> {}
 //@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.default" 'null'
 //@ count "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[*]" 1
 //@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo'
-//@ count "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][0]" '"f"'
-//@ is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][1].generic" '"F"'
+//@ count "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[0][0]" '"f"'
+//@ is "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[0][1].generic" '"F"'
 pub fn generics<F: Foo>(f: F) {}
 
 //@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.where_predicates" "[]"
 //@ count "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[*]" 1
 //@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].name" '"impl Foo"'
 //@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo
-//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][0]" '"f"'
-//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[*]" 1
-//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo
+//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][0]" '"f"'
+//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[*]" 1
+//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo
 pub fn impl_trait(f: impl Foo) {}
 
 //@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[*]" 3
 //@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].name" '"F"'
-//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}'
-//@ count "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[*]" 3
-//@ is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][0]" '"f"'
-//@ is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][1].generic" '"F"'
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "is_synthetic": false}}'
+//@ count "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[*]" 3
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[0][0]" '"f"'
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[0][1].generic" '"F"'
 //@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[*]" 3
 
 //@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.type.generic" \"F\"
diff --git a/tests/rustdoc-json/fns/generic_returns.rs b/tests/rustdoc-json/fns/generic_returns.rs
index 07dc691..2f23801 100644
--- a/tests/rustdoc-json/fns/generic_returns.rs
+++ b/tests/rustdoc-json/fns/generic_returns.rs
@@ -5,9 +5,9 @@
 //@ set foo = "$.index[*][?(@.name=='Foo')].id"
 pub trait Foo {}
 
-//@ is "$.index[*][?(@.name=='get_foo')].inner.function.decl.inputs" []
-//@ count "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[*]" 1
-//@ is "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $foo
+//@ is "$.index[*][?(@.name=='get_foo')].inner.function.sig.inputs" []
+//@ count "$.index[*][?(@.name=='get_foo')].inner.function.sig.output.impl_trait[*]" 1
+//@ is "$.index[*][?(@.name=='get_foo')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $foo
 pub fn get_foo() -> impl Foo {
     Fooer {}
 }
diff --git a/tests/rustdoc-json/fns/generics.rs b/tests/rustdoc-json/fns/generics.rs
index 43fc727..f2064fd 100644
--- a/tests/rustdoc-json/fns/generics.rs
+++ b/tests/rustdoc-json/fns/generics.rs
@@ -6,17 +6,17 @@ pub trait Wham {}
 //@ is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.where_predicates" []
 //@ count "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[*]" 1
 //@ is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].name" '"T"'
-//@ is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" false
+//@ is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.is_synthetic" false
 //@ is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
-//@ is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.decl.inputs" '[["w", {"generic": "T"}]]'
+//@ is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.sig.inputs" '[["w", {"generic": "T"}]]'
 pub fn one_generic_param_fn<T: Wham>(w: T) {}
 
 //@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.where_predicates" []
 //@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[*]" 1
 //@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].name" '"impl Wham"'
-//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" true
+//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.is_synthetic" true
 //@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
-//@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[*]" 1
-//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][0]" '"w"'
-//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id
+//@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[*]" 1
+//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][0]" '"w"'
+//@ is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id
 pub fn one_synthetic_generic_param_fn(w: impl Wham) {}
diff --git a/tests/rustdoc-json/fns/pattern_arg.rs b/tests/rustdoc-json/fns/pattern_arg.rs
index 3fa423b..d2a00f4 100644
--- a/tests/rustdoc-json/fns/pattern_arg.rs
+++ b/tests/rustdoc-json/fns/pattern_arg.rs
@@ -1,7 +1,7 @@
-//@ is "$.index[*][?(@.name=='fst')].inner.function.decl.inputs[0][0]" '"(x, _)"'
+//@ is "$.index[*][?(@.name=='fst')].inner.function.sig.inputs[0][0]" '"(x, _)"'
 pub fn fst<X, Y>((x, _): (X, Y)) -> X {
     x
 }
 
-//@ is "$.index[*][?(@.name=='drop_int')].inner.function.decl.inputs[0][0]" '"_"'
+//@ is "$.index[*][?(@.name=='drop_int')].inner.function.sig.inputs[0][0]" '"_"'
 pub fn drop_int(_: i32) {}
diff --git a/tests/rustdoc-json/fns/qualifiers.rs b/tests/rustdoc-json/fns/qualifiers.rs
index beb1b4c..67e49f0 100644
--- a/tests/rustdoc-json/fns/qualifiers.rs
+++ b/tests/rustdoc-json/fns/qualifiers.rs
@@ -1,33 +1,33 @@
 //@ edition:2018
 
-//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.async" false
-//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.const"  false
-//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.unsafe" false
+//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_async" false
+//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_const"  false
+//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_unsafe" false
 pub fn nothing_fn() {}
 
-//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.async"  false
-//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.const"  false
-//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.unsafe" true
+//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_async"  false
+//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_const"  false
+//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_unsafe" true
 pub unsafe fn unsafe_fn() {}
 
-//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.async"  false
-//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.const"  true
-//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.unsafe" false
+//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_async"  false
+//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_const"  true
+//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_unsafe" false
 pub const fn const_fn() {}
 
-//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.async"  true
-//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.const"  false
-//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.unsafe" false
+//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_async"  true
+//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_const"  false
+//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_unsafe" false
 pub async fn async_fn() {}
 
-//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.async"  true
-//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.const"  false
-//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.unsafe" true
+//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_async"  true
+//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_const"  false
+//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_unsafe" true
 pub async unsafe fn async_unsafe_fn() {}
 
-//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.async"  false
-//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.const"  true
-//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.unsafe" true
+//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_async"  false
+//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_const"  true
+//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_unsafe" true
 pub const unsafe fn const_unsafe_fn() {}
 
 // It's impossible for a function to be both const and async, so no test for that
diff --git a/tests/rustdoc-json/fns/return_type_alias.rs b/tests/rustdoc-json/fns/return_type_alias.rs
index 67bc46a..d60c4b6 100644
--- a/tests/rustdoc-json/fns/return_type_alias.rs
+++ b/tests/rustdoc-json/fns/return_type_alias.rs
@@ -3,7 +3,7 @@
 ///@ set foo = "$.index[*][?(@.name=='Foo')].id"
 pub type Foo = i32;
 
-//@ is "$.index[*][?(@.name=='demo')].inner.function.decl.output.resolved_path.id" $foo
+//@ is "$.index[*][?(@.name=='demo')].inner.function.sig.output.resolved_path.id" $foo
 pub fn demo() -> Foo {
     42
 }
diff --git a/tests/rustdoc-json/generic-associated-types/gats.rs b/tests/rustdoc-json/generic-associated-types/gats.rs
index 8a38230..fdf605e 100644
--- a/tests/rustdoc-json/generic-associated-types/gats.rs
+++ b/tests/rustdoc-json/generic-associated-types/gats.rs
@@ -13,10 +13,10 @@ pub trait LendingIterator {
     where
         Self: 'a;
 
-    //@ count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 1
-    //@ count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0
-    //@ is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\"
-    //@ is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.name" \"LendingItem\"
+    //@ count "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 1
+    //@ count "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0
+    //@ is "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\"
+    //@ is "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.name" \"LendingItem\"
     fn lending_next<'a>(&'a self) -> Self::LendingItem<'a>;
 }
 
@@ -26,9 +26,9 @@ pub trait Iterator {
     //@ count "$.index[*][?(@.name=='Item')].inner.assoc_type.bounds[*]" 1
     type Item: Display;
 
-    //@ count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 0
-    //@ count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0
-    //@ is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\"
-    //@ is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.name" \"Item\"
+    //@ count "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 0
+    //@ count "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0
+    //@ is "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\"
+    //@ is "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.name" \"Item\"
     fn next<'a>(&'a self) -> Self::Item;
 }
diff --git a/tests/rustdoc-json/glob_import.rs b/tests/rustdoc-json/glob_import.rs
index a67a99a..b63e5da 100644
--- a/tests/rustdoc-json/glob_import.rs
+++ b/tests/rustdoc-json/glob_import.rs
@@ -3,7 +3,7 @@
 #![no_std]
 
 //@ has "$.index[*][?(@.name=='glob')]"
-//@ has "$.index[*][?(@.inner.import)].inner.import.name" \"*\"
+//@ has "$.index[*][?(@.inner.use)].inner.use.name" \"*\"
 
 mod m1 {
     pub fn f() {}
diff --git a/tests/rustdoc-json/impl-trait-in-assoc-type.rs b/tests/rustdoc-json/impl-trait-in-assoc-type.rs
index f02e38c..907a0f6 100644
--- a/tests/rustdoc-json/impl-trait-in-assoc-type.rs
+++ b/tests/rustdoc-json/impl-trait-in-assoc-type.rs
@@ -9,11 +9,11 @@ impl IntoIterator for AlwaysTrue {
     /// type Item
     type Item = bool;
 
-    //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[*]' 1
-    //@ is    '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.name' '"Iterator"'
-    //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[*]' 1
-    //@ is    '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name' '"Item"'
-    //@ is    '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive' '"bool"'
+    //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[*]' 1
+    //@ is    '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.name' '"Iterator"'
+    //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[*]' 1
+    //@ is    '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name' '"Item"'
+    //@ is    '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive' '"bool"'
 
     //@ set IntoIter = '$.index[*][?(@.docs=="type IntoIter")].id'
     /// type IntoIter
diff --git a/tests/rustdoc-json/impl-trait-precise-capturing.rs b/tests/rustdoc-json/impl-trait-precise-capturing.rs
index 0c116a1..5225256 100644
--- a/tests/rustdoc-json/impl-trait-precise-capturing.rs
+++ b/tests/rustdoc-json/impl-trait-precise-capturing.rs
@@ -1,4 +1,4 @@
-//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[0]" \"\'a\"
-//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[1]" \"T\"
-//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[2]" \"N\"
+//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[0]" \"\'a\"
+//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[1]" \"T\"
+//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[2]" \"N\"
 pub fn hello<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {}
diff --git a/tests/rustdoc-json/impls/auto.rs b/tests/rustdoc-json/impls/auto.rs
index 84a1e6e..e14c935 100644
--- a/tests/rustdoc-json/impls/auto.rs
+++ b/tests/rustdoc-json/impls/auto.rs
@@ -18,5 +18,5 @@ pub fn baz(&self) {}
 //@ is "$.index[*][?(@.docs=='has span')].span.begin" "[13, 0]"
 //@ is "$.index[*][?(@.docs=='has span')].span.end" "[15, 1]"
 // FIXME: this doesn't work due to https://github.com/freestrings/jsonpath/issues/91
-// is "$.index[*][?(@.inner.impl.synthetic==true)].span" null
+// is "$.index[*][?(@.inner.impl.is_synthetic==true)].span" null
 pub struct Foo;
diff --git a/tests/rustdoc-json/impls/foreign_for_local.rs b/tests/rustdoc-json/impls/foreign_for_local.rs
index 20690f2..1347f95 100644
--- a/tests/rustdoc-json/impls/foreign_for_local.rs
+++ b/tests/rustdoc-json/impls/foreign_for_local.rs
@@ -3,7 +3,7 @@
 
 /// ForeignTrait id hack
 pub use foreign_trait::ForeignTrait as _;
-//@ set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.import.id"
+//@ set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.use.id"
 
 pub struct LocalStruct;
 //@ set LocalStruct = "$.index[*][?(@.name=='LocalStruct')].id"
diff --git a/tests/rustdoc-json/impls/import_from_private.rs b/tests/rustdoc-json/impls/import_from_private.rs
index e386252..32b9abb 100644
--- a/tests/rustdoc-json/impls/import_from_private.rs
+++ b/tests/rustdoc-json/impls/import_from_private.rs
@@ -11,10 +11,10 @@ pub fn doit() {}
     }
 }
 
-//@ set import = "$.index[*][?(@.inner.import)].id"
+//@ set import = "$.index[*][?(@.inner.use)].id"
 pub use bar::Baz;
 
 //@ is "$.index[*].inner.module.items[*]" $import
-//@ is "$.index[*].inner.import.id" $baz
+//@ is "$.index[*].inner.use.id" $baz
 //@ has "$.index[*][?(@.name == 'Baz')].inner.struct.impls[*]" $impl
 //@ is "$.index[*][?(@.docs=='impl')].inner.impl.items[*]" $doit
diff --git a/tests/rustdoc-json/impls/local_for_foreign.rs b/tests/rustdoc-json/impls/local_for_foreign.rs
index bd49269..cd89c47 100644
--- a/tests/rustdoc-json/impls/local_for_foreign.rs
+++ b/tests/rustdoc-json/impls/local_for_foreign.rs
@@ -3,7 +3,7 @@
 
 /// ForeignStruct id hack
 pub use foreign_struct::ForeignStruct as _;
-//@ set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.import.id"
+//@ set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.use.id"
 
 pub trait LocalTrait {}
 //@ set LocalTrait = "$.index[*][?(@.name=='LocalTrait')].id"
diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs
index 39f791d..8ac60be 100644
--- a/tests/rustdoc-json/lifetime/longest.rs
+++ b/tests/rustdoc-json/lifetime/longest.rs
@@ -6,21 +6,21 @@
 //@ count "$.index[*][?(@.name=='longest')].inner.function.generics.params[*]" 1
 //@ is "$.index[*][?(@.name=='longest')].inner.function.generics.where_predicates" []
 
-//@ count "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[*]" 2
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][0]" '"l"'
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][0]" '"r"'
+//@ count "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[*]" 2
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][0]" '"l"'
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][0]" '"r"'
 
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.type.primitive" \"str\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.type.primitive" \"str\"
 
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.mutable" false
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.type.primitive" \"str\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.is_mutable" false
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.type.primitive" \"str\"
 
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.mutable" false
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.type.primitive" \"str\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.is_mutable" false
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.type.primitive" \"str\"
 
 pub fn longest<'a>(l: &'a str, r: &'a str) -> &'a str {
     if l.len() > r.len() { l } else { r }
diff --git a/tests/rustdoc-json/lifetime/outlives.rs b/tests/rustdoc-json/lifetime/outlives.rs
index c98555d..99d1429 100644
--- a/tests/rustdoc-json/lifetime/outlives.rs
+++ b/tests/rustdoc-json/lifetime/outlives.rs
@@ -10,9 +10,9 @@
 //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.default" null
 //@ count "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[*]" 1
 //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[0].outlives" \"\'b\"
-//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false
-//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\"
-//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.mutable" false
-//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\"
+//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false
+//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\"
+//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.is_mutable" false
+//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\"
 pub fn foo<'a, 'b: 'a, T: 'b>(_: &'a &'b T) {}
diff --git a/tests/rustdoc-json/methods/qualifiers.rs b/tests/rustdoc-json/methods/qualifiers.rs
index 8de8cfd..ba7c2e6 100644
--- a/tests/rustdoc-json/methods/qualifiers.rs
+++ b/tests/rustdoc-json/methods/qualifiers.rs
@@ -3,34 +3,34 @@
 pub struct Foo;
 
 impl Foo {
-    //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.async" false
-    //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.const"  true
-    //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.unsafe" false
+    //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_async" false
+    //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_const"  true
+    //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_unsafe" false
     pub const fn const_meth() {}
 
-    //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.async"  false
-    //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.const"  false
-    //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.unsafe" false
+    //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_async"  false
+    //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_const"  false
+    //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_unsafe" false
     pub fn nothing_meth() {}
 
-    //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.async"  false
-    //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.const"  false
-    //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.unsafe" true
+    //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_async"  false
+    //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_const"  false
+    //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_unsafe" true
     pub unsafe fn unsafe_meth() {}
 
-    //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.async"  true
-    //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.const"  false
-    //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.unsafe" false
+    //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_async"  true
+    //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_const"  false
+    //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_unsafe" false
     pub async fn async_meth() {}
 
-    //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.async"  true
-    //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.const"  false
-    //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.unsafe" true
+    //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_async"  true
+    //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_const"  false
+    //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_unsafe" true
     pub async unsafe fn async_unsafe_meth() {}
 
-    //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.async"  false
-    //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.const"  true
-    //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.unsafe" true
+    //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_async"  false
+    //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_const"  true
+    //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_unsafe" true
     pub const unsafe fn const_unsafe_meth() {}
 
     // It's impossible for a method to be both const and async, so no test for that
diff --git a/tests/rustdoc-json/nested.rs b/tests/rustdoc-json/nested.rs
index ae2d9fe..10ec283 100644
--- a/tests/rustdoc-json/nested.rs
+++ b/tests/rustdoc-json/nested.rs
@@ -22,11 +22,11 @@ pub mod l3 {
         //@ ismany "$.index[*][?(@.name=='l3')].inner.module.items[*]" $l4_id
         pub struct L4;
     }
-    //@ is "$.index[*][?(@.inner.import)].inner.import.glob" false
-    //@ is "$.index[*][?(@.inner.import)].inner.import.source" '"l3::L4"'
-    //@ is "$.index[*][?(@.inner.import)].inner.import.glob" false
-    //@ is "$.index[*][?(@.inner.import)].inner.import.id" $l4_id
-    //@ set l4_use_id = "$.index[*][?(@.inner.import)].id"
+    //@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" false
+    //@ is "$.index[*][?(@.inner.use)].inner.use.source" '"l3::L4"'
+    //@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" false
+    //@ is "$.index[*][?(@.inner.use)].inner.use.id" $l4_id
+    //@ set l4_use_id = "$.index[*][?(@.inner.use)].id"
     pub use l3::L4;
 }
 //@ ismany "$.index[*][?(@.name=='l1')].inner.module.items[*]" $l3_id $l4_use_id
diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs
index 06f6e10..8443141 100644
--- a/tests/rustdoc-json/non_lifetime_binders.rs
+++ b/tests/rustdoc-json/non_lifetime_binders.rs
@@ -11,7 +11,7 @@ pub trait Trait {}
 //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\"
 //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
 //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\"
-//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "synthetic": false } }'
+//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "is_synthetic": false } }'
 pub fn foo()
 where
     for<'a, T> &'a Wrapper<T>: Trait,
diff --git a/tests/rustdoc-json/primitives/use_primitive.rs b/tests/rustdoc-json/primitives/use_primitive.rs
index 27394a6..d4cdef8 100644
--- a/tests/rustdoc-json/primitives/use_primitive.rs
+++ b/tests/rustdoc-json/primitives/use_primitive.rs
@@ -13,7 +13,7 @@ mod usize {}
 //@ !is "$.index[*][?(@.name=='checked_add')]" $local_crate_id
 //@ !has "$.index[*][?(@.name=='is_ascii_uppercase')]"
 
-//@ is "$.index[*].inner.import[?(@.name=='my_i32')].id" null
+//@ is "$.index[*].inner.use[?(@.name=='my_i32')].id" null
 pub use i32 as my_i32;
-//@ is "$.index[*].inner.import[?(@.name=='u32')].id" null
+//@ is "$.index[*].inner.use[?(@.name=='u32')].id" null
 pub use u32;
diff --git a/tests/rustdoc-json/reexport/extern_crate_glob.rs b/tests/rustdoc-json/reexport/extern_crate_glob.rs
index a0b4cb8..dfe6e7a 100644
--- a/tests/rustdoc-json/reexport/extern_crate_glob.rs
+++ b/tests/rustdoc-json/reexport/extern_crate_glob.rs
@@ -6,6 +6,6 @@
 pub use enum_with_discriminant::*;
 
 //@ !has '$.index[*][?(@.docs == "Should not be inlined")]'
-//@ is '$.index[*][?(@.inner.import)].inner.import.name' \"enum_with_discriminant\"
-//@ set use = '$.index[*][?(@.inner.import)].id'
+//@ is '$.index[*][?(@.inner.use)].inner.use.name' \"enum_with_discriminant\"
+//@ set use = '$.index[*][?(@.inner.use)].id'
 //@ is '$.index[*][?(@.name == "extern_crate_glob")].inner.module.items[*]' $use
diff --git a/tests/rustdoc-json/reexport/glob_collision.rs b/tests/rustdoc-json/reexport/glob_collision.rs
index 3a034af..8142c35 100644
--- a/tests/rustdoc-json/reexport/glob_collision.rs
+++ b/tests/rustdoc-json/reexport/glob_collision.rs
@@ -14,13 +14,13 @@ pub fn f(_: u8) {}
 }
 
 //@ set m1_use = "$.index[*][?(@.docs=='m1 re-export')].id"
-//@ is "$.index[*].inner.import[?(@.name=='m1')].id" $m1
-//@ is "$.index[*].inner.import[?(@.name=='m1')].glob" true
+//@ is "$.index[*].inner.use[?(@.name=='m1')].id" $m1
+//@ is "$.index[*].inner.use[?(@.name=='m1')].is_glob" true
 /// m1 re-export
 pub use m1::*;
 //@ set m2_use = "$.index[*][?(@.docs=='m2 re-export')].id"
-//@ is "$.index[*].inner.import[?(@.name=='m2')].id" $m2
-//@ is "$.index[*].inner.import[?(@.name=='m2')].glob" true
+//@ is "$.index[*].inner.use[?(@.name=='m2')].id" $m2
+//@ is "$.index[*].inner.use[?(@.name=='m2')].is_glob" true
 /// m2 re-export
 pub use m2::*;
 
diff --git a/tests/rustdoc-json/reexport/glob_empty_mod.rs b/tests/rustdoc-json/reexport/glob_empty_mod.rs
index 326df5f..ee17794 100644
--- a/tests/rustdoc-json/reexport/glob_empty_mod.rs
+++ b/tests/rustdoc-json/reexport/glob_empty_mod.rs
@@ -4,5 +4,5 @@
 //@ set m1 = "$.index[*][?(@.name=='m1')].id"
 mod m1 {}
 
-//@ is "$.index[*][?(@.inner.import)].inner.import.id" $m1
+//@ is "$.index[*][?(@.inner.use)].inner.use.id" $m1
 pub use m1::*;
diff --git a/tests/rustdoc-json/reexport/glob_extern.rs b/tests/rustdoc-json/reexport/glob_extern.rs
index ff5d986..98be477 100644
--- a/tests/rustdoc-json/reexport/glob_extern.rs
+++ b/tests/rustdoc-json/reexport/glob_extern.rs
@@ -12,8 +12,8 @@ mod mod1 {
     //@ set mod1_id = "$.index[*][?(@.name=='mod1')].id"
 }
 
-//@ is "$.index[*][?(@.inner.import)].inner.import.glob" true
-//@ is "$.index[*][?(@.inner.import)].inner.import.id" $mod1_id
-//@ set use_id = "$.index[*][?(@.inner.import)].id"
+//@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" true
+//@ is "$.index[*][?(@.inner.use)].inner.use.id" $mod1_id
+//@ set use_id = "$.index[*][?(@.inner.use)].id"
 //@ ismany "$.index[*][?(@.name=='glob_extern')].inner.module.items[*]" $use_id
 pub use mod1::*;
diff --git a/tests/rustdoc-json/reexport/glob_private.rs b/tests/rustdoc-json/reexport/glob_private.rs
index 0a88910..2084ffc 100644
--- a/tests/rustdoc-json/reexport/glob_private.rs
+++ b/tests/rustdoc-json/reexport/glob_private.rs
@@ -12,7 +12,7 @@ mod mod2 {
     }
 
     //@ set mod2_use_id = "$.index[*][?(@.docs=='Mod2 re-export')].id"
-    //@ is "$.index[*][?(@.docs=='Mod2 re-export')].inner.import.name" \"mod2\"
+    //@ is "$.index[*][?(@.docs=='Mod2 re-export')].inner.use.name" \"mod2\"
     /// Mod2 re-export
     pub use self::mod2::*;
 
@@ -23,7 +23,7 @@ mod mod2 {
 }
 
 //@ set mod1_use_id = "$.index[*][?(@.docs=='Mod1 re-export')].id"
-//@ is "$.index[*][?(@.docs=='Mod1 re-export')].inner.import.name" \"mod1\"
+//@ is "$.index[*][?(@.docs=='Mod1 re-export')].inner.use.name" \"mod1\"
 /// Mod1 re-export
 pub use mod1::*;
 
diff --git a/tests/rustdoc-json/reexport/in_root_and_mod.rs b/tests/rustdoc-json/reexport/in_root_and_mod.rs
index f94e416..a1d2080 100644
--- a/tests/rustdoc-json/reexport/in_root_and_mod.rs
+++ b/tests/rustdoc-json/reexport/in_root_and_mod.rs
@@ -4,10 +4,10 @@ mod foo {
     pub struct Foo;
 }
 
-//@ has "$.index[*].inner[?(@.import.source=='foo::Foo')]"
+//@ has "$.index[*].inner[?(@.use.source=='foo::Foo')]"
 pub use foo::Foo;
 
 pub mod bar {
-    //@ has "$.index[*].inner[?(@.import.source=='crate::foo::Foo')]"
+    //@ has "$.index[*].inner[?(@.use.source=='crate::foo::Foo')]"
     pub use crate::foo::Foo;
 }
diff --git a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
index 13dee32..7d26d2a 100644
--- a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
+++ b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
@@ -5,14 +5,14 @@
 }
 
 //@ set root_import_id = "$.index[*][?(@.docs=='Outer re-export')].id"
-//@ is "$.index[*].inner[?(@.import.source=='foo::Bar')].import.id" $bar_id
+//@ is "$.index[*].inner[?(@.use.source=='foo::Bar')].use.id" $bar_id
 //@ has "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.module.items[*]" $root_import_id
 /// Outer re-export
 pub use foo::Bar;
 
 pub mod baz {
     //@ set baz_import_id = "$.index[*][?(@.docs=='Inner re-export')].id"
-    //@ is "$.index[*].inner[?(@.import.source=='crate::foo::Bar')].import.id" $bar_id
+    //@ is "$.index[*].inner[?(@.use.source=='crate::foo::Bar')].use.id" $bar_id
     //@ ismany "$.index[*][?(@.name=='baz')].inner.module.items[*]" $baz_import_id
     /// Inner re-export
     pub use crate::foo::Bar;
diff --git a/tests/rustdoc-json/reexport/mod_not_included.rs b/tests/rustdoc-json/reexport/mod_not_included.rs
index 7e0c011..d0ce957 100644
--- a/tests/rustdoc-json/reexport/mod_not_included.rs
+++ b/tests/rustdoc-json/reexport/mod_not_included.rs
@@ -7,5 +7,5 @@ pub fn x() {}
 pub use m1::x;
 
 //@ has "$.index[*][?(@.name=='x' && @.inner.function)]"
-//@ has "$.index[*].inner[?(@.import.name=='x')].import.source" '"m1::x"'
+//@ has "$.index[*].inner[?(@.use.name=='x')].use.source" '"m1::x"'
 //@ !has "$.index[*][?(@.name=='m1')]"
diff --git a/tests/rustdoc-json/reexport/private_twice_one_inline.rs b/tests/rustdoc-json/reexport/private_twice_one_inline.rs
index be66ad5..87b97e6 100644
--- a/tests/rustdoc-json/reexport/private_twice_one_inline.rs
+++ b/tests/rustdoc-json/reexport/private_twice_one_inline.rs
@@ -7,18 +7,18 @@
 extern crate pub_struct as foo;
 #[doc(inline)]
 //@ set crate_use_id = "$.index[*][?(@.docs=='Hack A')].id"
-//@ set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.import.id"
+//@ set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.use.id"
 /// Hack A
 pub use foo::Foo;
 
 //@ set bar_id = "$.index[*][?(@.name=='bar')].id"
 pub mod bar {
-    //@ is "$.index[*][?(@.docs=='Hack B')].inner.import.id" $foo_id
+    //@ is "$.index[*][?(@.docs=='Hack B')].inner.use.id" $foo_id
     //@ set bar_use_id = "$.index[*][?(@.docs=='Hack B')].id"
     //@ ismany "$.index[*][?(@.name=='bar')].inner.module.items[*]" $bar_use_id
     /// Hack B
     pub use foo::Foo;
 }
 
-//@ ismany "$.index[*][?(@.inner.import)].id" $crate_use_id $bar_use_id
+//@ ismany "$.index[*][?(@.inner.use)].id" $crate_use_id $bar_use_id
 //@ ismany "$.index[*][?(@.name=='private_twice_one_inline')].inner.module.items[*]" $bar_id $crate_use_id
diff --git a/tests/rustdoc-json/reexport/private_two_names.rs b/tests/rustdoc-json/reexport/private_two_names.rs
index 1e5466d..1ed54f1 100644
--- a/tests/rustdoc-json/reexport/private_two_names.rs
+++ b/tests/rustdoc-json/reexport/private_two_names.rs
@@ -9,13 +9,13 @@ mod style {
     pub struct Color;
 }
 
-//@ is "$.index[*][?(@.docs=='First re-export')].inner.import.id" $color_struct_id
-//@ is "$.index[*][?(@.docs=='First re-export')].inner.import.name" \"Color\"
+//@ is "$.index[*][?(@.docs=='First re-export')].inner.use.id" $color_struct_id
+//@ is "$.index[*][?(@.docs=='First re-export')].inner.use.name" \"Color\"
 //@ set color_export_id = "$.index[*][?(@.docs=='First re-export')].id"
 /// First re-export
 pub use style::Color;
-//@ is "$.index[*][?(@.docs=='Second re-export')].inner.import.id" $color_struct_id
-//@ is "$.index[*][?(@.docs=='Second re-export')].inner.import.name" \"Colour\"
+//@ is "$.index[*][?(@.docs=='Second re-export')].inner.use.id" $color_struct_id
+//@ is "$.index[*][?(@.docs=='Second re-export')].inner.use.name" \"Colour\"
 //@ set colour_export_id = "$.index[*][?(@.docs=='Second re-export')].id"
 /// Second re-export
 pub use style::Color as Colour;
diff --git a/tests/rustdoc-json/reexport/reexport_of_hidden.rs b/tests/rustdoc-json/reexport/reexport_of_hidden.rs
index 07ce1f5..80f171d 100644
--- a/tests/rustdoc-json/reexport/reexport_of_hidden.rs
+++ b/tests/rustdoc-json/reexport/reexport_of_hidden.rs
@@ -1,6 +1,6 @@
 //@ compile-flags: --document-hidden-items
 
-//@ has "$.index[*].inner[?(@.import.name=='UsedHidden')]"
+//@ has "$.index[*].inner[?(@.use.name=='UsedHidden')]"
 //@ has "$.index[*][?(@.name=='Hidden')]"
 pub mod submodule {
     #[doc(hidden)]
diff --git a/tests/rustdoc-json/reexport/rename_private.rs b/tests/rustdoc-json/reexport/rename_private.rs
index 3335d18..3f13f30 100644
--- a/tests/rustdoc-json/reexport/rename_private.rs
+++ b/tests/rustdoc-json/reexport/rename_private.rs
@@ -6,5 +6,5 @@ mod inner {
     pub struct Public;
 }
 
-//@ is "$.index[*][?(@.inner.import)].inner.import.name" \"NewName\"
+//@ is "$.index[*][?(@.inner.use)].inner.use.name" \"NewName\"
 pub use inner::Public as NewName;
diff --git a/tests/rustdoc-json/reexport/rename_public.rs b/tests/rustdoc-json/reexport/rename_public.rs
index e534f45..81c003a 100644
--- a/tests/rustdoc-json/reexport/rename_public.rs
+++ b/tests/rustdoc-json/reexport/rename_public.rs
@@ -7,8 +7,8 @@ pub mod inner {
     pub struct Public;
 }
 //@ set import_id = "$.index[*][?(@.docs=='Re-export')].id"
-//@ !has "$.index[*].inner[?(@.import.name=='Public')]"
-//@ is "$.index[*].inner[?(@.import.name=='NewName')].import.source" \"inner::Public\"
+//@ !has "$.index[*].inner[?(@.use.name=='Public')]"
+//@ is "$.index[*].inner[?(@.use.name=='NewName')].use.source" \"inner::Public\"
 /// Re-export
 pub use inner::Public as NewName;
 
diff --git a/tests/rustdoc-json/reexport/same_name_different_types.rs b/tests/rustdoc-json/reexport/same_name_different_types.rs
index b0a06d4..e9bc4a5a 100644
--- a/tests/rustdoc-json/reexport/same_name_different_types.rs
+++ b/tests/rustdoc-json/reexport/same_name_different_types.rs
@@ -13,10 +13,10 @@ pub struct Foo {}
     pub fn Foo() {}
 }
 
-//@ ismany "$.index[*].inner[?(@.import.name == 'Foo')].import.id" $foo_fn $foo_struct
-//@ ismany "$.index[*].inner[?(@.import.name == 'Bar')].import.id" $foo_fn $foo_struct
+//@ ismany "$.index[*].inner[?(@.use.name == 'Foo')].use.id" $foo_fn $foo_struct
+//@ ismany "$.index[*].inner[?(@.use.name == 'Bar')].use.id" $foo_fn $foo_struct
 
-//@ count "$.index[*].inner[?(@.import.name == 'Foo')]" 2
+//@ count "$.index[*].inner[?(@.use.name == 'Foo')]" 2
 pub use nested::Foo;
-//@ count "$.index[*].inner[?(@.import.name == 'Bar')]" 2
+//@ count "$.index[*].inner[?(@.use.name == 'Bar')]" 2
 pub use Foo as Bar;
diff --git a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
index c533b9b..27e2827 100644
--- a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
+++ b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
@@ -10,11 +10,11 @@ pub trait Trait {}
 }
 
 //@ set export_id = "$.index[*][?(@.docs=='First re-export')].id"
-//@ is "$.index[*].inner[?(@.import.name=='Trait')].import.id" $trait_id
+//@ is "$.index[*].inner[?(@.use.name=='Trait')].use.id" $trait_id
 /// First re-export
 pub use inner::Trait;
 //@ set reexport_id = "$.index[*][?(@.docs=='Second re-export')].id"
-//@ is "$.index[*].inner[?(@.import.name=='Reexport')].import.id" $trait_id
+//@ is "$.index[*].inner[?(@.use.name=='Reexport')].use.id" $trait_id
 /// Second re-export
 pub use inner::Trait as Reexport;
 
diff --git a/tests/rustdoc-json/reexport/simple_private.rs b/tests/rustdoc-json/reexport/simple_private.rs
index 9af01578..8a936f5 100644
--- a/tests/rustdoc-json/reexport/simple_private.rs
+++ b/tests/rustdoc-json/reexport/simple_private.rs
@@ -6,9 +6,9 @@ mod inner {
     pub struct Public;
 }
 
-//@ is "$.index[*][?(@.inner.import)].inner.import.name" \"Public\"
-//@ is "$.index[*][?(@.inner.import)].inner.import.id" $pub_id
-//@ set use_id = "$.index[*][?(@.inner.import)].id"
+//@ is "$.index[*][?(@.inner.use)].inner.use.name" \"Public\"
+//@ is "$.index[*][?(@.inner.use)].inner.use.id" $pub_id
+//@ set use_id = "$.index[*][?(@.inner.use)].id"
 pub use inner::Public;
 
 //@ ismany "$.index[*][?(@.name=='simple_private')].inner.module.items[*]" $use_id
diff --git a/tests/rustdoc-json/reexport/simple_public.rs b/tests/rustdoc-json/reexport/simple_public.rs
index d7b44b2..e5a8dc7 100644
--- a/tests/rustdoc-json/reexport/simple_public.rs
+++ b/tests/rustdoc-json/reexport/simple_public.rs
@@ -9,7 +9,7 @@ pub mod inner {
 }
 
 //@ set import_id = "$.index[*][?(@.docs=='Outer')].id"
-//@ is "$.index[*][?(@.docs=='Outer')].inner.import.source" \"inner::Public\"
+//@ is "$.index[*][?(@.docs=='Outer')].inner.use.source" \"inner::Public\"
 /// Outer
 pub use inner::Public;
 
diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs
index 4a1922e..0b341e2 100644
--- a/tests/rustdoc-json/return_private.rs
+++ b/tests/rustdoc-json/return_private.rs
@@ -6,7 +6,7 @@ mod secret {
 }
 
 //@ has "$.index[*][?(@.name=='get_secret')].inner.function"
-//@ is "$.index[*][?(@.name=='get_secret')].inner.function.decl.output.resolved_path.name" \"secret::Secret\"
+//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.name" \"secret::Secret\"
 pub fn get_secret() -> secret::Secret {
     secret::Secret
 }
diff --git a/tests/rustdoc-json/structs/plain_all_pub.rs b/tests/rustdoc-json/structs/plain_all_pub.rs
index aa53b59..67d2a4a 100644
--- a/tests/rustdoc-json/structs/plain_all_pub.rs
+++ b/tests/rustdoc-json/structs/plain_all_pub.rs
@@ -8,4 +8,4 @@
 //@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
 //@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[1]" $y
 //@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 2
-//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" false
+//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" false
diff --git a/tests/rustdoc-json/structs/plain_doc_hidden.rs b/tests/rustdoc-json/structs/plain_doc_hidden.rs
index 39f9367..4573adc 100644
--- a/tests/rustdoc-json/structs/plain_doc_hidden.rs
+++ b/tests/rustdoc-json/structs/plain_doc_hidden.rs
@@ -8,4 +8,4 @@
 //@ !has "$.index[*][?(@.name=='y')].id"
 //@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
 //@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1
-//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true
+//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" true
diff --git a/tests/rustdoc-json/structs/plain_empty.rs b/tests/rustdoc-json/structs/plain_empty.rs
index 00b4b05..3001302 100644
--- a/tests/rustdoc-json/structs/plain_empty.rs
+++ b/tests/rustdoc-json/structs/plain_empty.rs
@@ -1,5 +1,5 @@
 //@ is "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\"
 //@ has "$.index[*][?(@.name=='PlainEmpty')].inner.struct"
-//@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields_stripped" false
+//@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.has_stripped_fields" false
 //@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields" []
 pub struct PlainEmpty {}
diff --git a/tests/rustdoc-json/structs/plain_pub_priv.rs b/tests/rustdoc-json/structs/plain_pub_priv.rs
index f9ab871..91079a3 100644
--- a/tests/rustdoc-json/structs/plain_pub_priv.rs
+++ b/tests/rustdoc-json/structs/plain_pub_priv.rs
@@ -6,4 +6,4 @@
 //@ set x = "$.index[*][?(@.name=='x')].id"
 //@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
 //@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1
-//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true
+//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" true
diff --git a/tests/rustdoc-json/structs/with_generics.rs b/tests/rustdoc-json/structs/with_generics.rs
index 6e13dae..3e7f175 100644
--- a/tests/rustdoc-json/structs/with_generics.rs
+++ b/tests/rustdoc-json/structs/with_generics.rs
@@ -6,7 +6,7 @@
 //@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].kind.type.bounds" []
 //@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].name" \"U\"
 //@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].kind.type.bounds" []
-//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields_stripped" true
+//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.has_stripped_fields" true
 //@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields" []
 pub struct WithGenerics<T, U> {
     stuff: Vec<T>,
diff --git a/tests/rustdoc-json/structs/with_primitives.rs b/tests/rustdoc-json/structs/with_primitives.rs
index 2ca11b5..7202ab9 100644
--- a/tests/rustdoc-json/structs/with_primitives.rs
+++ b/tests/rustdoc-json/structs/with_primitives.rs
@@ -4,7 +4,7 @@
 //@ has "$.index[*][?(@.name=='WithPrimitives')].inner.struct"
 //@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].name" \"\'a\"
 //@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].kind.lifetime.outlives" []
-//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields_stripped" true
+//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.has_stripped_fields" true
 //@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields" []
 pub struct WithPrimitives<'a> {
     num: u32,
diff --git a/tests/rustdoc-json/trait_alias.rs b/tests/rustdoc-json/trait_alias.rs
index ca9e5ed..3ae5fad 100644
--- a/tests/rustdoc-json/trait_alias.rs
+++ b/tests/rustdoc-json/trait_alias.rs
@@ -7,12 +7,12 @@
 //@ is "$.index[*][?(@.name=='StrLike')].span.filename" $FILE
 pub trait StrLike = AsRef<str>;
 
-//@ is "$.index[*][?(@.name=='f')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $StrLike
+//@ is "$.index[*][?(@.name=='f')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike
 pub fn f() -> impl StrLike {
     "heya"
 }
 
-//@ !is "$.index[*][?(@.name=='g')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $StrLike
+//@ !is "$.index[*][?(@.name=='g')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike
 pub fn g() -> impl AsRef<str> {
     "heya"
 }
diff --git a/tests/rustdoc-json/traits/self.rs b/tests/rustdoc-json/traits/self.rs
index c7d952a..060bc37 100644
--- a/tests/rustdoc-json/traits/self.rs
+++ b/tests/rustdoc-json/traits/self.rs
@@ -9,29 +9,29 @@
 // Each assertion matches 3 times, and should be the same each time.
 
 impl Foo {
-    //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"'
-    //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
-    //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' null null null
-    //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' false false false
+    //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
+    //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
+    //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null
+    //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false
     pub fn by_ref(&self) {}
 
-    //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"'
-    //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
-    //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' null null null
-    //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' true true true
+    //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
+    //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
+    //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null
+    //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' true true true
     pub fn by_exclusive_ref(&mut self) {}
 
-    //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"'
-    //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.decl.inputs[0][1].generic' '"Self"' '"Self"' '"Self"'
+    //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
+    //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.sig.inputs[0][1].generic' '"Self"' '"Self"' '"Self"'
     pub fn by_value(self) {}
 
-    //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"'
-    //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
-    //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' \"\'a\" \"\'a\" \"\'a\"
-    //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' false false false
+    //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
+    //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
+    //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' \"\'a\" \"\'a\" \"\'a\"
+    //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false
     pub fn with_lifetime<'a>(&'a self) {}
 
-    //@ ismany '$.index[*][?(@.name=="build")].inner.function.decl.output.generic' '"Self"' '"Self"' '"Self"'
+    //@ ismany '$.index[*][?(@.name=="build")].inner.function.sig.output.generic' '"Self"' '"Self"' '"Self"'
     pub fn build() -> Self {
         Self
     }
diff --git a/tests/rustdoc-json/traits/trait_alias.rs b/tests/rustdoc-json/traits/trait_alias.rs
index a1ab039..17c83dd 100644
--- a/tests/rustdoc-json/traits/trait_alias.rs
+++ b/tests/rustdoc-json/traits/trait_alias.rs
@@ -19,8 +19,8 @@ pub trait Orig<T> {}
 
 impl Orig<i32> for Struct {}
 
-//@ has "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait"
-//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias
+//@ has "$.index[*][?(@.name=='takes_alias')].inner.function.sig.inputs[0][1].impl_trait"
+//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias
 //@ is "$.index[*][?(@.name=='takes_alias')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $Alias
 pub fn takes_alias(_: impl Alias) {}
 // FIXME: Should the trait be mentioned in both the decl and generics?
diff --git a/tests/rustdoc-json/type/dyn.rs b/tests/rustdoc-json/type/dyn.rs
index 86ea1c2..97c8689 100644
--- a/tests/rustdoc-json/type/dyn.rs
+++ b/tests/rustdoc-json/type/dyn.rs
@@ -11,7 +11,7 @@
 //@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.generics" '{"params": [], "where_predicates": []}'
 //@ has    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path"
 //@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.name" \"Box\"
-//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" []
+//@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" []
 //@ count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args" 1
 //@ has    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait"
 //@ is    "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.lifetime" \"\'static\"
@@ -28,7 +28,7 @@
 //@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias"
 //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}'
 //@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref"
-//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.mutable" 'false'
+//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.is_mutable" 'false'
 //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.lifetime" "\"'a\""
 //@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait"
 //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.lifetime" null
diff --git a/tests/rustdoc-json/type/extern.rs b/tests/rustdoc-json/type/extern.rs
index fda5d5a..97e1c37 100644
--- a/tests/rustdoc-json/type/extern.rs
+++ b/tests/rustdoc-json/type/extern.rs
@@ -6,4 +6,4 @@
 }
 
 //@ is "$.index[*][?(@.docs=='No inner information')].name" '"Foo"'
-//@ is "$.index[*][?(@.docs=='No inner information')].inner" \"foreign_type\"
+//@ is "$.index[*][?(@.docs=='No inner information')].inner" \"extern_type\"
diff --git a/tests/rustdoc-json/type/fn_lifetime.rs b/tests/rustdoc-json/type/fn_lifetime.rs
index 2893b37..7fa12da 100644
--- a/tests/rustdoc-json/type/fn_lifetime.rs
+++ b/tests/rustdoc-json/type/fn_lifetime.rs
@@ -7,9 +7,9 @@
 //@ count  "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime.outlives[*]" 0
 //@ count  "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.where_predicates[*]" 0
 //@ count  "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.generic_params[*]" 0
-//@ count  "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1
-//@ is     "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
-//@ is     "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\"
+//@ count  "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1
+//@ is     "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
+//@ is     "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.output.borrowed_ref.lifetime" \"\'a\"
 
 pub type GenericFn<'a> = fn(&'a i32) -> &'a i32;
 
@@ -20,7 +20,7 @@
 //@ is    "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].name" \"\'a\"
 //@ has   "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime"
 //@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime.outlives[*]" 0
-//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1
-//@ is    "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
-//@ is    "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\"
+//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1
+//@ is    "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
+//@ is    "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.output.borrowed_ref.lifetime" \"\'a\"
 pub type ForAll = for<'a> fn(&'a i32) -> &'a i32;
diff --git a/tests/rustdoc-json/type/generic_default.rs b/tests/rustdoc-json/type/generic_default.rs
index 3063763..c1a0580 100644
--- a/tests/rustdoc-json/type/generic_default.rs
+++ b/tests/rustdoc-json/type/generic_default.rs
@@ -25,7 +25,7 @@ pub struct MyError {}
 //@ has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path"
 //@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.id" $result
 //@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.name" \"Result\"
-//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" []
+//@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" []
 //@ has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic"
 //@ has    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic"
 //@ is    "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" \"T\"
diff --git a/tests/rustdoc-json/type/hrtb.rs b/tests/rustdoc-json/type/hrtb.rs
index a28b2fd..825720e 100644
--- a/tests/rustdoc-json/type/hrtb.rs
+++ b/tests/rustdoc-json/type/hrtb.rs
@@ -12,10 +12,10 @@ pub fn genfn<F>(f: F)
 
 //@ is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}'
 //@ is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}'
-//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null
-//@ count "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1
-//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
-//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
+//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null
+//@ count "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1
+//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
+//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
 pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) {
     let zero = 0;
     f(&zero, &zero);
diff --git a/tests/rustdoc-json/type/inherent_associated_type.rs b/tests/rustdoc-json/type/inherent_associated_type.rs
index 386c7c8..b8ce11f 100644
--- a/tests/rustdoc-json/type/inherent_associated_type.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type.rs
@@ -10,9 +10,9 @@
 pub fn create() -> Owner::Metadata {
     OwnerMetadata
 }
-//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.name' '"Metadata"'
-//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.trait' null
-//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.self_type.resolved_path.id' $Owner
+//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.name' '"Metadata"'
+//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.trait' null
+//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.self_type.resolved_path.id' $Owner
 
 /// impl
 impl Owner {
@@ -21,4 +21,4 @@ impl Owner {
 }
 //@ set iat = '$.index[*][?(@.docs=="iat")].id'
 //@ is '$.index[*][?(@.docs=="impl")].inner.impl.items[*]' $iat
-//@ is '$.index[*][?(@.docs=="iat")].inner.assoc_type.default.resolved_path.id' $OwnerMetadata
+//@ is '$.index[*][?(@.docs=="iat")].inner.assoc_type.type.resolved_path.id' $OwnerMetadata
diff --git a/tests/rustdoc-json/type/inherent_associated_type_bound.rs b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
index 45fe19b..d0a88b1 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_bound.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
@@ -5,14 +5,14 @@
 //@ set Carrier = '$.index[*][?(@.name=="Carrier")].id'
 pub struct Carrier<'a>(&'a ());
 
-//@ count "$.index[*][?(@.name=='user')].inner.function.decl.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='user')].inner.function.decl.inputs[0][0]" '"_"'
-//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\"
-//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
-//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
-//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"'
-//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.trait' null
-//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
+//@ count "$.index[*][?(@.name=='user')].inner.function.sig.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='user')].inner.function.sig.inputs[0][0]" '"_"'
+//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\"
+//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
+//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
+//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.name' '"Focus"'
+//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.trait' null
+//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
 pub fn user(_: for<'b> fn(Carrier<'b>::Focus<i32>)) {}
 
 impl<'a> Carrier<'a> {
diff --git a/tests/rustdoc-json/type/inherent_associated_type_projections.rs b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
index 9b827a9..e73e86d 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_projections.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
@@ -5,12 +5,12 @@
 //@ set Parametrized = '$.index[*][?(@.name=="Parametrized")].id'
 pub struct Parametrized<T>(T);
 
-//@ count "$.index[*][?(@.name=='test')].inner.function.decl.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='test')].inner.function.decl.inputs[0][0]" '"_"'
-//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized
-//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
-//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.name' '"Proj"'
-//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.trait' null
+//@ count "$.index[*][?(@.name=='test')].inner.function.sig.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='test')].inner.function.sig.inputs[0][0]" '"_"'
+//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized
+//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
+//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.name' '"Proj"'
+//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.trait' null
 pub fn test(_: Parametrized<i32>::Proj) {}
 
 /// param_bool
diff --git a/tests/rustdoc-json/type_alias.rs b/tests/rustdoc-json/type_alias.rs
index ecf35c5..2f2b4c4 100644
--- a/tests/rustdoc-json/type_alias.rs
+++ b/tests/rustdoc-json/type_alias.rs
@@ -4,12 +4,12 @@
 //@ is "$.index[*][?(@.name=='IntVec')].span.filename" $FILE
 pub type IntVec = Vec<u32>;
 
-//@ is "$.index[*][?(@.name=='f')].inner.function.decl.output.resolved_path.id" $IntVec
+//@ is "$.index[*][?(@.name=='f')].inner.function.sig.output.resolved_path.id" $IntVec
 pub fn f() -> IntVec {
     vec![0; 32]
 }
 
-//@ !is "$.index[*][?(@.name=='g')].inner.function.decl.output.resolved_path.id" $IntVec
+//@ !is "$.index[*][?(@.name=='g')].inner.function.sig.output.resolved_path.id" $IntVec
 pub fn g() -> Vec<u32> {
     vec![0; 32]
 }
diff --git a/tests/rustdoc-json/unions/union.rs b/tests/rustdoc-json/unions/union.rs
index 4a97b5d..7f135a7 100644
--- a/tests/rustdoc-json/unions/union.rs
+++ b/tests/rustdoc-json/unions/union.rs
@@ -7,8 +7,8 @@ pub union Union {
     float: f32,
 }
 
-//@ has "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path"
-//@ is "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path.id" $Union
+//@ has "$.index[*][?(@.name=='make_int_union')].inner.function.sig.output.resolved_path"
+//@ is "$.index[*][?(@.name=='make_int_union')].inner.function.sig.output.resolved_path.id" $Union
 pub fn make_int_union(int: i32) -> Union {
     Union { int }
 }
diff --git a/tests/rustdoc/impl-associated-items-order.rs b/tests/rustdoc/impl-associated-items-order.rs
new file mode 100644
index 0000000..759e0f0
--- /dev/null
+++ b/tests/rustdoc/impl-associated-items-order.rs
@@ -0,0 +1,42 @@
+// This test ensures that impl associated items always follow this order:
+//
+// 1. Consts
+// 2. Types
+// 3. Functions
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+#![crate_name = "foo"]
+
+//@ has 'foo/struct.Bar.html'
+pub struct Bar;
+
+impl Bar {
+    //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[3]/h4' \
+    // 'pub fn foo()'
+    pub fn foo() {}
+    //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[1]/h4' \
+    // 'pub const X: u8 = 12u8'
+    pub const X: u8 = 12;
+    //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[2]/h4' \
+    // 'pub type Y = u8'
+    pub type Y = u8;
+}
+
+pub trait Foo {
+    const W: u32;
+    fn yeay();
+    type Z;
+}
+
+impl Foo for Bar {
+    //@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[2]/h4' \
+    // 'type Z = u8'
+    type Z = u8;
+    //@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[1]/h4' \
+    // 'const W: u32 = 12u32'
+    const W: u32 = 12;
+    //@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[3]/h4' \
+    // 'fn yeay()'
+    fn yeay() {}
+}
diff --git a/tests/rustdoc/impl-associated-items-sidebar.rs b/tests/rustdoc/impl-associated-items-sidebar.rs
new file mode 100644
index 0000000..d393a57
--- /dev/null
+++ b/tests/rustdoc/impl-associated-items-sidebar.rs
@@ -0,0 +1,42 @@
+// This test ensures that impl/trait associated items are listed in the sidebar.
+
+// ignore-tidy-linelength
+
+#![feature(inherent_associated_types)]
+#![feature(associated_type_defaults)]
+#![allow(incomplete_features)]
+#![crate_name = "foo"]
+
+//@ has 'foo/struct.Bar.html'
+pub struct Bar;
+
+impl Bar {
+    //@ has - '//*[@class="sidebar-elems"]//h3[1]' 'Associated Constants'
+    //@ has - '//*[@class="sidebar-elems"]//ul[@class="block associatedconstant"]/li/a[@href="#associatedconstant.X"]' 'X'
+    pub const X: u8 = 12;
+    //@ has - '//*[@class="sidebar-elems"]//h3[2]' 'Associated Types'
+    //@ has - '//*[@class="sidebar-elems"]//ul[@class="block associatedtype"]/li/a[@href="#associatedtype.Y"]' 'Y'
+    pub type Y = u8;
+}
+
+//@ has 'foo/trait.Foo.html'
+pub trait Foo {
+    //@ has - '//*[@class="sidebar-elems"]//h3[5]' 'Required Methods'
+    //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][5]/li/a[@href="#tymethod.yeay"]' 'yeay'
+    fn yeay();
+    //@ has - '//*[@class="sidebar-elems"]//h3[6]' 'Provided Methods'
+    //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][6]/li/a[@href="#method.boo"]' 'boo'
+    fn boo() {}
+    //@ has - '//*[@class="sidebar-elems"]//h3[1]' 'Required Associated Constants'
+    //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][1]/li/a[@href="#associatedconstant.W"]' 'W'
+    const W: u32;
+    //@ has - '//*[@class="sidebar-elems"]//h3[2]' 'Provided Associated Constants'
+    //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][2]/li/a[@href="#associatedconstant.U"]' 'U'
+    const U: u32 = 0;
+    //@ has - '//*[@class="sidebar-elems"]//h3[3]' 'Required Associated Types'
+    //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][3]/li/a[@href="#associatedtype.Z"]' 'Z'
+    type Z;
+    //@ has - '//*[@class="sidebar-elems"]//h3[4]' 'Provided Associated Types'
+    //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][4]/li/a[@href="#associatedtype.T"]' 'T'
+    type T = u32;
+}
diff --git a/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs
new file mode 100644
index 0000000..fdafb3b
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs
@@ -0,0 +1,5 @@
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs
new file mode 100644
index 0000000..ff12fe9
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs
@@ -0,0 +1,8 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs
new file mode 100644
index 0000000..665f956
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs
@@ -0,0 +1,25 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra'
+//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango'
+//@ has quebec/struct.Quebec.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Quebec'
+
+// similar to cargo-workflow-transitive, but we use --merge=read-write,
+// which is the default.
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs
new file mode 100644
index 0000000..d10bc03
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs
@@ -0,0 +1,7 @@
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs
new file mode 100644
index 0000000..6d0c865
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs
@@ -0,0 +1,10 @@
+//@ aux-build:sierra.rs
+//@ build-aux-docs
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/romeo
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate sierra;
+pub type Romeo = sierra::Sierra;
diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs
new file mode 100644
index 0000000..10898f3
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs
@@ -0,0 +1,11 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/sierra
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs
new file mode 100644
index 0000000..3c3721e
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs
@@ -0,0 +1,10 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/tango
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs
new file mode 100644
index 0000000..f03f6bd
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs
@@ -0,0 +1,35 @@
+//@ aux-build:tango.rs
+//@ aux-build:romeo.rs
+//@ aux-build:quebec.rs
+//@ aux-build:sierra.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--include-parts-dir=info/doc.parts/tango
+//@ doc-flags:--include-parts-dir=info/doc.parts/romeo
+//@ doc-flags:--include-parts-dir=info/doc.parts/quebec
+//@ doc-flags:--include-parts-dir=info/doc.parts/sierra
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html
+//@ has index.html '//ul[@class="all-items"]//a[@href="indigo/index.html"]' 'indigo'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has index.html '//ul[@class="all-items"]//a[@href="romeo/index.html"]' 'romeo'
+//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra'
+//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango'
+//@ !has quebec/struct.Quebec.html
+//@ !has romeo/type.Romeo.html
+//@ !has sierra/struct.Sierra.html
+//@ !has tango/trait.Tango.html
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Quebec'
+//@ hasraw search-index.js 'Romeo'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Tango'
+//@ has type.impl/sierra/struct.Sierra.js
+//@ hasraw type.impl/sierra/struct.Sierra.js 'Tango'
+//@ hasraw type.impl/sierra/struct.Sierra.js 'Romeo'
+
+// document everything in the default mode, there are separate out
+// directories that are linked together
diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs
new file mode 100644
index 0000000..6121052
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs
@@ -0,0 +1,6 @@
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs
new file mode 100644
index 0000000..70d8a4b
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs
@@ -0,0 +1,9 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs
new file mode 100644
index 0000000..7eac207
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs
@@ -0,0 +1,17 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ !has index.html
+//@ has sierra/struct.Sierra.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ !has trait.impl/tango/trait.Tango.js
+//@ !has search-index.js
+
+// we don't generate any cross-crate info if --merge=none, even if we
+// document crates separately
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs
new file mode 100644
index 0000000..6ab9215
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs
@@ -0,0 +1,6 @@
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs
new file mode 100644
index 0000000..9fa99d3
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs
@@ -0,0 +1,9 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/tango
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs
new file mode 100644
index 0000000..f3340a8
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs
@@ -0,0 +1,18 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/sierra
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ !has index.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ !has trait.impl/tango/trait.Tango.js
+//@ !has search-index.js
+
+// we --merge=none, so --parts-out-dir doesn't do anything
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs
new file mode 100644
index 0000000..6ab9215
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs
@@ -0,0 +1,6 @@
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs
new file mode 100644
index 0000000..9fa99d3
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs
@@ -0,0 +1,9 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/tango
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs
new file mode 100644
index 0000000..8eb0f1d
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs
@@ -0,0 +1,22 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--include-parts-dir=info/doc.parts/tango
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has quebec/struct.Quebec.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ !hasraw search-index.js 'Quebec'
+
+// we overwrite quebec and tango's cross-crate information, but we
+// include the info from tango meaning that it should appear in the out
+// dir
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs
new file mode 100644
index 0000000..d10bc03
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs
@@ -0,0 +1,7 @@
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs
new file mode 100644
index 0000000..3c3721e
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs
@@ -0,0 +1,10 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/tango
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs
new file mode 100644
index 0000000..4ee0362
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs
@@ -0,0 +1,25 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--include-parts-dir=info/doc.parts/tango
+//@ doc-flags:--include-parts-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra'
+//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango'
+//@ has sierra/struct.Sierra.html
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Quebec'
+
+// If these were documeted into the same directory, the info would be
+// overwritten. However, since they are merged, we can still recover all
+// of the cross-crate information
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs
new file mode 100644
index 0000000..0e28d8e
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs
@@ -0,0 +1,5 @@
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs
new file mode 100644
index 0000000..363b2d5
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs
@@ -0,0 +1,8 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs b/tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs
new file mode 100644
index 0000000..11e61dd
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs
@@ -0,0 +1,20 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has quebec/struct.Quebec.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ !hasraw search-index.js 'Quebec'
+
+// since tango is documented with --merge=finalize, we overwrite q's
+// cross-crate information
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs
new file mode 100644
index 0000000..09bb78c
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs
@@ -0,0 +1,13 @@
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has quebec/struct.Quebec.html
+//@ hasraw search-index.js 'Quebec'
+
+// there is nothing to read from the output directory if we use a single
+// crate
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs
new file mode 100644
index 0000000..7247542
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs
@@ -0,0 +1,12 @@
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has quebec/struct.Quebec.html
+//@ hasraw search-index.js 'Quebec'
+
+// read-write is the default and this does the same as `single-crate`
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs
new file mode 100644
index 0000000..b20e173
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs
@@ -0,0 +1,13 @@
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has quebec/struct.Quebec.html
+//@ hasraw search-index.js 'Quebec'
+
+// we can --parts-out-dir, but that doesn't do anything other than create
+// the file
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs
new file mode 100644
index 0000000..e888a43
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs
@@ -0,0 +1,11 @@
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ !has index.html
+//@ has quebec/struct.Quebec.html
+//@ !has search-index.js
+
+// --merge=none doesn't write anything, despite --parts-out-dir
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs
new file mode 100644
index 0000000..1beca54
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs
@@ -0,0 +1,5 @@
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs
new file mode 100644
index 0000000..363b2d5
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs
@@ -0,0 +1,8 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs
new file mode 100644
index 0000000..68fc4b1
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs
@@ -0,0 +1,20 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra'
+//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango'
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Sierra'
+
+// write only overwrites stuff in the output directory
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs
new file mode 100644
index 0000000..6ab9215
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs
@@ -0,0 +1,6 @@
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs
new file mode 100644
index 0000000..9fa99d3
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs
@@ -0,0 +1,9 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/tango
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs
new file mode 100644
index 0000000..b407228
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs
@@ -0,0 +1,27 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--include-parts-dir=info/doc.parts/tango
+//@ doc-flags:--include-parts-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra'
+//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango'
+//@ has quebec/struct.Quebec.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Quebec'
+
+// We avoid writing any cross-crate information, preferring to include it
+// with --include-parts-dir.
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs
new file mode 100644
index 0000000..1beca54
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs
@@ -0,0 +1,5 @@
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs
new file mode 100644
index 0000000..ff12fe9
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs
@@ -0,0 +1,8 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs
new file mode 100644
index 0000000..15e32d5
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs
@@ -0,0 +1,25 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra'
+//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango'
+//@ has quebec/struct.Quebec.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Quebec'
+
+// We can use read-write to emulate the default behavior of rustdoc, when
+// --merge is left out.
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs
new file mode 100644
index 0000000..0e28d8e
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs
@@ -0,0 +1,5 @@
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs
new file mode 100644
index 0000000..3827119
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs
@@ -0,0 +1,8 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs
new file mode 100644
index 0000000..3eb2ceb
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs
@@ -0,0 +1,17 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ !has index.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ !has trait.impl/tango/trait.Tango.js
+//@ !has search-index.js
+
+// --merge=none on all crates does not generate any cross-crate info
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs
new file mode 100644
index 0000000..e492b70
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs
@@ -0,0 +1,5 @@
+//@ unique-doc-out-dir
+//@ doc-flags:--parts-out-dir=info/doc.parts/foxtrot
+//@ doc-flags:-Zunstable-options
+
+pub trait Foxtrot {}
diff --git a/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs
new file mode 100644
index 0000000..ee2b646
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs
@@ -0,0 +1,16 @@
+//@ aux-build:foxtrot.rs
+//@ build-aux-docs
+//@ doc-flags:--include-parts-dir=info/doc.parts/foxtrot
+//@ doc-flags:-Zunstable-options
+
+//@ has echo/enum.Echo.html
+//@ hasraw echo/enum.Echo.html 'Foxtrot'
+//@ hasraw trait.impl/foxtrot/trait.Foxtrot.js 'enum.Echo.html'
+//@ hasraw search-index.js 'Foxtrot'
+//@ hasraw search-index.js 'Echo'
+
+// document two crates in different places, and merge their docs after
+// they are generated
+extern crate foxtrot;
+pub enum Echo {}
+impl foxtrot::Foxtrot for Echo {}
diff --git a/tests/ui-fulldeps/internal-lints/query_completeness.rs b/tests/ui-fulldeps/internal-lints/query_completeness.rs
new file mode 100644
index 0000000..50b0fb4
--- /dev/null
+++ b/tests/ui-fulldeps/internal-lints/query_completeness.rs
@@ -0,0 +1,16 @@
+//@ compile-flags: -Z unstable-options
+// #[cfg(bootstrap)]: We can stop ignoring next beta bump; afterward this ALWAYS should run.
+//@ ignore-stage1 (requires matching sysroot built with in-tree compiler)
+#![feature(rustc_private)]
+#![deny(rustc::untracked_query_information)]
+
+extern crate rustc_data_structures;
+
+use rustc_data_structures::steal::Steal;
+
+fn use_steal(x: Steal<()>) {
+    let _ = x.is_stolen();
+    //~^ ERROR `is_stolen` accesses information that is not tracked by the query system
+}
+
+fn main() {}
diff --git a/tests/ui-fulldeps/internal-lints/query_completeness.stderr b/tests/ui-fulldeps/internal-lints/query_completeness.stderr
new file mode 100644
index 0000000..35bb867
--- /dev/null
+++ b/tests/ui-fulldeps/internal-lints/query_completeness.stderr
@@ -0,0 +1,15 @@
+error: `is_stolen` accesses information that is not tracked by the query system
+  --> $DIR/query_completeness.rs:12:15
+   |
+LL |     let _ = x.is_stolen();
+   |               ^^^^^^^^^
+   |
+   = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
+note: the lint level is defined here
+  --> $DIR/query_completeness.rs:5:9
+   |
+LL | #![deny(rustc::untracked_query_information)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/asm/const-refs-to-static.rs b/tests/ui/asm/const-refs-to-static.rs
new file mode 100644
index 0000000..9fc010b
--- /dev/null
+++ b/tests/ui/asm/const-refs-to-static.rs
@@ -0,0 +1,21 @@
+//@ needs-asm-support
+//@ ignore-nvptx64
+//@ ignore-spirv
+
+#![feature(const_refs_to_static)]
+
+use std::arch::{asm, global_asm};
+use std::ptr::addr_of;
+
+static FOO: u8 = 42;
+
+global_asm!("{}", const addr_of!(FOO));
+//~^ ERROR invalid type for `const` operand
+
+#[no_mangle]
+fn inline() {
+    unsafe { asm!("{}", const addr_of!(FOO)) };
+    //~^ ERROR invalid type for `const` operand
+}
+
+fn main() {}
diff --git a/tests/ui/asm/const-refs-to-static.stderr b/tests/ui/asm/const-refs-to-static.stderr
new file mode 100644
index 0000000..8fd69da
--- /dev/null
+++ b/tests/ui/asm/const-refs-to-static.stderr
@@ -0,0 +1,22 @@
+error: invalid type for `const` operand
+  --> $DIR/const-refs-to-static.rs:12:19
+   |
+LL | global_asm!("{}", const addr_of!(FOO));
+   |                   ^^^^^^-------------
+   |                         |
+   |                         is a `*const u8`
+   |
+   = help: `const` operands must be of an integer type
+
+error: invalid type for `const` operand
+  --> $DIR/const-refs-to-static.rs:17:25
+   |
+LL |     unsafe { asm!("{}", const addr_of!(FOO)) };
+   |                         ^^^^^^-------------
+   |                               |
+   |                               is a `*const u8`
+   |
+   = help: `const` operands must be of an integer type
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/asm/naked-functions-inline.rs b/tests/ui/asm/naked-functions-inline.rs
index cfb38f2..74049e8 100644
--- a/tests/ui/asm/naked-functions-inline.rs
+++ b/tests/ui/asm/naked-functions-inline.rs
@@ -2,37 +2,37 @@
 #![feature(naked_functions)]
 #![crate_type = "lib"]
 
-use std::arch::asm;
+use std::arch::naked_asm;
 
 #[naked]
 pub unsafe extern "C" fn inline_none() {
-    asm!("", options(noreturn));
+    naked_asm!("");
 }
 
 #[naked]
 #[inline]
 //~^ ERROR [E0736]
 pub unsafe extern "C" fn inline_hint() {
-    asm!("", options(noreturn));
+    naked_asm!("");
 }
 
 #[naked]
 #[inline(always)]
 //~^ ERROR [E0736]
 pub unsafe extern "C" fn inline_always() {
-    asm!("", options(noreturn));
+    naked_asm!("");
 }
 
 #[naked]
 #[inline(never)]
 //~^ ERROR [E0736]
 pub unsafe extern "C" fn inline_never() {
-    asm!("", options(noreturn));
+    naked_asm!("");
 }
 
 #[naked]
 #[cfg_attr(all(), inline(never))]
 //~^ ERROR [E0736]
 pub unsafe extern "C" fn conditional_inline_never() {
-    asm!("", options(noreturn));
+    naked_asm!("");
 }
diff --git a/tests/ui/associated-types/associated-types-coherence-failure.stderr b/tests/ui/associated-types/associated-types-coherence-failure.stderr
index 211613b..25c22e5 100644
--- a/tests/ui/associated-types/associated-types-coherence-failure.stderr
+++ b/tests/ui/associated-types/associated-types-coherence-failure.stderr
@@ -1,20 +1,20 @@
-error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `Cow<'_, _>`
+error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned`
   --> $DIR/associated-types-coherence-failure.rs:21:1
    |
 LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned {
    | ----------------------------------------------------------------------------- first implementation here
 ...
 LL | impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned`
 
-error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `&_`
+error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned`
   --> $DIR/associated-types-coherence-failure.rs:28:1
    |
 LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned {
    | ----------------------------------------------------------------------------- first implementation here
 ...
 LL | impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/async-await/async-closures/tainted-body-2.rs b/tests/ui/async-await/async-closures/tainted-body-2.rs
new file mode 100644
index 0000000..73c6bdc
--- /dev/null
+++ b/tests/ui/async-await/async-closures/tainted-body-2.rs
@@ -0,0 +1,18 @@
+//@ edition: 2021
+
+#![feature(async_closure)]
+
+// Ensure that building a by-ref async closure body doesn't ICE when the parent
+// body is tainted.
+
+fn main() {
+    missing;
+    //~^ ERROR cannot find value `missing` in this scope
+
+    // We don't do numerical inference fallback when the body is tainted.
+    // This leads to writeback folding the type of the coroutine-closure
+    // into an error type, since its signature contains that numerical
+    // infer var.
+    let c = async |_| {};
+    c(1);
+}
diff --git a/tests/ui/async-await/async-closures/tainted-body-2.stderr b/tests/ui/async-await/async-closures/tainted-body-2.stderr
new file mode 100644
index 0000000..798d470
--- /dev/null
+++ b/tests/ui/async-await/async-closures/tainted-body-2.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `missing` in this scope
+  --> $DIR/tainted-body-2.rs:9:5
+   |
+LL |     missing;
+   |     ^^^^^^^ not found in this scope
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/async-await/async-closures/validate-synthetic-body.rs b/tests/ui/async-await/async-closures/validate-synthetic-body.rs
new file mode 100644
index 0000000..67e683a
--- /dev/null
+++ b/tests/ui/async-await/async-closures/validate-synthetic-body.rs
@@ -0,0 +1,19 @@
+//@ check-pass
+//@ edition: 2021
+
+#![feature(async_closure)]
+
+// Make sure that we don't hit a query cycle when validating
+// the by-move coroutine body for an async closure.
+
+use std::future::Future;
+
+async fn test<Fut: Future>(operation: impl Fn() -> Fut) {
+    operation().await;
+}
+
+pub async fn orchestrate_simple_crud() {
+    test(async || async {}.await).await;
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-drop.rs b/tests/ui/async-await/async-drop.rs
index 12f120a..4e60598 100644
--- a/tests/ui/async-await/async-drop.rs
+++ b/tests/ui/async-await/async-drop.rs
@@ -53,18 +53,20 @@ fn main() {
     let i = 13;
     let fut = pin!(async {
         test_async_drop(Int(0), 0).await;
-        test_async_drop(AsyncInt(0), 104).await;
-        test_async_drop([AsyncInt(1), AsyncInt(2)], 152).await;
-        test_async_drop((AsyncInt(3), AsyncInt(4)), 488).await;
+        // FIXME(#63818): niches in coroutines are disabled.
+        // Some of these sizes should be smaller, as indicated in comments.
+        test_async_drop(AsyncInt(0), /*104*/ 112).await;
+        test_async_drop([AsyncInt(1), AsyncInt(2)], /*152*/ 168).await;
+        test_async_drop((AsyncInt(3), AsyncInt(4)), /*488*/ 528).await;
         test_async_drop(5, 0).await;
         let j = 42;
         test_async_drop(&i, 0).await;
         test_async_drop(&j, 0).await;
-        test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }, 1688).await;
+        test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }, /*1688*/ 1792).await;
         test_async_drop(ManuallyDrop::new(AsyncInt(9)), 0).await;
 
         let foo = AsyncInt(10);
-        test_async_drop(AsyncReference { foo: &foo }, 104).await;
+        test_async_drop(AsyncReference { foo: &foo }, /*104*/ 112).await;
 
         let foo = AsyncInt(11);
         test_async_drop(
@@ -73,17 +75,17 @@ fn main() {
                 let foo = AsyncInt(10);
                 foo
             },
-            120,
+            /*120*/ 136,
         )
         .await;
 
-        test_async_drop(AsyncEnum::A(AsyncInt(12)), 680).await;
-        test_async_drop(AsyncEnum::B(SyncInt(13)), 680).await;
+        test_async_drop(AsyncEnum::A(AsyncInt(12)), /*680*/ 736).await;
+        test_async_drop(AsyncEnum::B(SyncInt(13)), /*680*/ 736).await;
 
-        test_async_drop(SyncInt(14), 16).await;
+        test_async_drop(SyncInt(14), /*16*/ 24).await;
         test_async_drop(
             SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) },
-            3064,
+            /*3064*/ 3296,
         )
         .await;
 
@@ -99,11 +101,11 @@ fn main() {
                 black_box(core::future::ready(())).await;
                 foo
             },
-            120,
+            /*120*/ 136,
         )
         .await;
 
-        test_async_drop(AsyncUnion { signed: 21 }, 32).await;
+        test_async_drop(AsyncUnion { signed: 21 }, /*32*/ 40).await;
     });
     let res = fut.poll(&mut cx);
     assert_eq!(res, Poll::Ready(()));
diff --git a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
index def967b..642e27b 100644
--- a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
+++ b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
@@ -14,28 +14,26 @@
 print-type-size type: `{async fn body of calls_fut<{async fn body of big_fut()}>()}`: 3077 bytes, alignment: 1 bytes
 print-type-size     discriminant: 1 bytes
 print-type-size     variant `Unresumed`: 1025 bytes
-print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         upvar `.fut`: 1025 bytes
 print-type-size     variant `Suspend0`: 2052 bytes
-print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
-print-type-size         padding: 1 bytes
-print-type-size         local `.fut`: 1025 bytes, alignment: 1 bytes
+print-type-size         upvar `.fut`: 1025 bytes
+print-type-size         local `.fut`: 1025 bytes
 print-type-size         local `..coroutine_field4`: 1 bytes, type: bool
 print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
 print-type-size     variant `Suspend1`: 3076 bytes
-print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
-print-type-size         padding: 1026 bytes
+print-type-size         upvar `.fut`: 1025 bytes
+print-type-size         padding: 1025 bytes
 print-type-size         local `..coroutine_field4`: 1 bytes, alignment: 1 bytes, type: bool
 print-type-size         local `.__awaitee`: 1025 bytes, type: {async fn body of big_fut()}
 print-type-size     variant `Suspend2`: 2052 bytes
-print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
-print-type-size         padding: 1 bytes
-print-type-size         local `.fut`: 1025 bytes, alignment: 1 bytes
+print-type-size         upvar `.fut`: 1025 bytes
+print-type-size         local `.fut`: 1025 bytes
 print-type-size         local `..coroutine_field4`: 1 bytes, type: bool
 print-type-size         local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
 print-type-size     variant `Returned`: 1025 bytes
-print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         upvar `.fut`: 1025 bytes
 print-type-size     variant `Panicked`: 1025 bytes
-print-type-size         upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         upvar `.fut`: 1025 bytes
 print-type-size type: `std::mem::ManuallyDrop<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes
 print-type-size     field `.value`: 1025 bytes
 print-type-size type: `std::mem::MaybeUninit<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes
diff --git a/tests/ui/auto-traits/opaque_type_candidate_selection.rs b/tests/ui/auto-traits/opaque_type_candidate_selection.rs
deleted file mode 100644
index d6973b7..0000000
--- a/tests/ui/auto-traits/opaque_type_candidate_selection.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//! used to ICE: #119272
-
-//@ check-pass
-
-#![feature(type_alias_impl_trait)]
-mod defining_scope {
-    use super::*;
-    pub type Alias<T> = impl Sized;
-
-    pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
-        x
-    }
-}
-
-struct Container<T: Trait<U>, U> {
-    x: <T as Trait<U>>::Assoc,
-}
-
-trait Trait<T> {
-    type Assoc;
-}
-
-impl<T> Trait<T> for T {
-    type Assoc = Box<u32>;
-}
-impl<T> Trait<T> for defining_scope::Alias<T> {
-    type Assoc = usize;
-}
-
-fn main() {}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs
index e6b0bf3..9e0ffa7 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs
@@ -12,10 +12,31 @@ impl Copy for u32 {}
 struct Wrapper<T>(T);
 
 struct Test<T: Copy> {
-    f1: extern "C-cmse-nonsecure-call" fn<U: Copy>(U, u32, u32, u32) -> u64, //~ ERROR cannot find type `U` in this scope
-    //~^ ERROR function pointer types may not have generic parameters
+    f1: extern "C-cmse-nonsecure-call" fn<U: Copy>(U, u32, u32, u32) -> u64,
+    //~^ ERROR cannot find type `U` in this scope
+    //~| ERROR function pointer types may not have generic parameters
     f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64,
     //~^ ERROR `impl Trait` is not allowed in `fn` pointer parameters
     f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, //~ ERROR [E0798]
     f4: extern "C-cmse-nonsecure-call" fn(Wrapper<T>, u32, u32, u32) -> u64, //~ ERROR [E0798]
 }
+
+type WithReference = extern "C-cmse-nonsecure-call" fn(&usize);
+
+trait Trait {}
+type WithTraitObject = extern "C-cmse-nonsecure-call" fn(&dyn Trait) -> &dyn Trait;
+//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798]
+
+type WithStaticTraitObject =
+    extern "C-cmse-nonsecure-call" fn(&'static dyn Trait) -> &'static dyn Trait;
+//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798]
+
+#[repr(transparent)]
+struct WrapperTransparent<'a>(&'a dyn Trait);
+
+type WithTransparentTraitObject =
+    extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTransparent;
+//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798]
+
+type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);
+//~^ ERROR C-variadic function must have a compatible calling convention, like `C` or `cdecl` [E0045]
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr
index fa68d95..7cb8e13 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr
@@ -22,7 +22,7 @@
    |                    +++
 
 error[E0562]: `impl Trait` is not allowed in `fn` pointer parameters
-  --> $DIR/generics.rs:17:43
+  --> $DIR/generics.rs:18:43
    |
 LL |     f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64,
    |                                           ^^^^^^^^^
@@ -30,18 +30,51 @@
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
-  --> $DIR/generics.rs:19:9
+  --> $DIR/generics.rs:20:9
    |
 LL |     f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
-  --> $DIR/generics.rs:20:9
+  --> $DIR/generics.rs:21:9
    |
 LL |     f4: extern "C-cmse-nonsecure-call" fn(Wrapper<T>, u32, u32, u32) -> u64,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/generics.rs:27:73
+   |
+LL | type WithTraitObject = extern "C-cmse-nonsecure-call" fn(&dyn Trait) -> &dyn Trait;
+   |                                                                         ^^^^^^^^^^ this type doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
 
-Some errors have detailed explanations: E0412, E0562, E0798.
-For more information about an error, try `rustc --explain E0412`.
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/generics.rs:31:62
+   |
+LL |     extern "C-cmse-nonsecure-call" fn(&'static dyn Trait) -> &'static dyn Trait;
+   |                                                              ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+  --> $DIR/generics.rs:38:62
+   |
+LL |     extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTransparent;
+   |                                                              ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
+   |
+   = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+   = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
+error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
+  --> $DIR/generics.rs:41:20
+   |
+LL | type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0045, E0412, E0562, E0798.
+For more information about an error, try `rustc --explain E0045`.
diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr
index dbb22d8..1d28bb4 100644
--- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr
+++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr
@@ -5,6 +5,8 @@
    | ---------------------------------------------- first implementation here
 LL | impl<'a, T> MyTrait<'a> for &'a T {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
+   |
+   = note: downstream crates may implement trait `MyPredicate<'_>` for type `&_`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr
index dbb22d8..1d28bb4 100644
--- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr
+++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr
@@ -5,6 +5,8 @@
    | ---------------------------------------------- first implementation here
 LL | impl<'a, T> MyTrait<'a> for &'a T {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
+   |
+   = note: downstream crates may implement trait `MyPredicate<'_>` for type `&_`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr b/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr
deleted file mode 100644
index 2938bc6..0000000
--- a/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-error[E0592]: duplicate definitions with name `dummy`
-  --> $DIR/coherence-overlap-downstream-inherent.rs:10:26
-   |
-LL | impl<T:Sugar> Sweet<T> { fn dummy(&self) { } }
-   |                          ^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
-LL |
-LL | impl<T:Fruit> Sweet<T> { fn dummy(&self) { } }
-   |                          --------------- other definition for `dummy`
-
-error[E0592]: duplicate definitions with name `f`
-  --> $DIR/coherence-overlap-downstream-inherent.rs:16:38
-   |
-LL | impl<X, T> A<T, X> where T: Bar<X> { fn f(&self) {} }
-   |                                      ^^^^^^^^^^^ duplicate definitions for `f`
-LL |
-LL | impl<X> A<i32, X> { fn f(&self) {} }
-   |                     ----------- other definition for `f`
-   |
-   = note: downstream crates may implement trait `Bar<_>` for type `i32`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0592`.
diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.rs b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs
index 3e90b7c..5dea33e 100644
--- a/tests/ui/coherence/coherence-overlap-downstream-inherent.rs
+++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs
@@ -1,6 +1,3 @@
-//@ revisions: old next
-//@[next] compile-flags: -Znext-solver
-
 // Tests that we consider `T: Sugar + Fruit` to be ambiguous, even
 // though no impls are found.
 
diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr b/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr
similarity index 87%
rename from tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr
rename to tests/ui/coherence/coherence-overlap-downstream-inherent.stderr
index 2938bc6..bbce4b5 100644
--- a/tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr
+++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr
@@ -1,5 +1,5 @@
 error[E0592]: duplicate definitions with name `dummy`
-  --> $DIR/coherence-overlap-downstream-inherent.rs:10:26
+  --> $DIR/coherence-overlap-downstream-inherent.rs:7:26
    |
 LL | impl<T:Sugar> Sweet<T> { fn dummy(&self) { } }
    |                          ^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
@@ -8,7 +8,7 @@
    |                          --------------- other definition for `dummy`
 
 error[E0592]: duplicate definitions with name `f`
-  --> $DIR/coherence-overlap-downstream-inherent.rs:16:38
+  --> $DIR/coherence-overlap-downstream-inherent.rs:13:38
    |
 LL | impl<X, T> A<T, X> where T: Bar<X> { fn f(&self) {} }
    |                                      ^^^^^^^^^^^ duplicate definitions for `f`
diff --git a/tests/ui/coherence/coherence-overlap-downstream.old.stderr b/tests/ui/coherence/coherence-overlap-downstream.old.stderr
deleted file mode 100644
index 6c2e946..0000000
--- a/tests/ui/coherence/coherence-overlap-downstream.old.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0119]: conflicting implementations of trait `Sweet`
-  --> $DIR/coherence-overlap-downstream.rs:11:1
-   |
-LL | impl<T:Sugar> Sweet for T { }
-   | ------------------------- first implementation here
-LL | impl<T:Fruit> Sweet for T { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
-
-error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32`
-  --> $DIR/coherence-overlap-downstream.rs:17:1
-   |
-LL | impl<X, T> Foo<X> for T where T: Bar<X> {}
-   | --------------------------------------- first implementation here
-LL | impl<X> Foo<X> for i32 {}
-   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
-   |
-   = note: downstream crates may implement trait `Bar<_>` for type `i32`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/coherence-overlap-downstream.rs b/tests/ui/coherence/coherence-overlap-downstream.rs
index 8b99296..738ec0e 100644
--- a/tests/ui/coherence/coherence-overlap-downstream.rs
+++ b/tests/ui/coherence/coherence-overlap-downstream.rs
@@ -1,6 +1,3 @@
-//@ revisions: old next
-//@[next] compile-flags: -Znext-solver
-
 // Tests that we consider `T: Sugar + Fruit` to be ambiguous, even
 // though no impls are found.
 
diff --git a/tests/ui/coherence/coherence-overlap-downstream.next.stderr b/tests/ui/coherence/coherence-overlap-downstream.stderr
similarity index 88%
rename from tests/ui/coherence/coherence-overlap-downstream.next.stderr
rename to tests/ui/coherence/coherence-overlap-downstream.stderr
index 6c2e946..9ab0994 100644
--- a/tests/ui/coherence/coherence-overlap-downstream.next.stderr
+++ b/tests/ui/coherence/coherence-overlap-downstream.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Sweet`
-  --> $DIR/coherence-overlap-downstream.rs:11:1
+  --> $DIR/coherence-overlap-downstream.rs:8:1
    |
 LL | impl<T:Sugar> Sweet for T { }
    | ------------------------- first implementation here
@@ -7,7 +7,7 @@
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
 error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32`
-  --> $DIR/coherence-overlap-downstream.rs:17:1
+  --> $DIR/coherence-overlap-downstream.rs:14:1
    |
 LL | impl<X, T> Foo<X> for T where T: Bar<X> {}
    | --------------------------------------- first implementation here
diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr
deleted file mode 100644
index 2f3ad62..0000000
--- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0592]: duplicate definitions with name `dummy`
-  --> $DIR/coherence-overlap-issue-23516-inherent.rs:12:25
-   |
-LL | impl<T:Sugar> Cake<T> { fn dummy(&self) { } }
-   |                         ^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
-LL |
-LL | impl<U:Sugar> Cake<Box<U>> { fn dummy(&self) { } }
-   |                              --------------- other definition for `dummy`
-   |
-   = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0592`.
diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs
index 53b0a40..a272e62 100644
--- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs
+++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs
@@ -1,6 +1,3 @@
-//@ revisions: old next
-//@[next] compile-flags: -Znext-solver
-
 // Tests that we consider `Box<U>: !Sugar` to be ambiguous, even
 // though we see no impl of `Sugar` for `Box`. Therefore, an overlap
 // error is reported for the following pair of impls (#23516).
diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr
similarity index 89%
rename from tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr
rename to tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr
index 2f3ad62..aacdeb5 100644
--- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr
+++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr
@@ -1,5 +1,5 @@
 error[E0592]: duplicate definitions with name `dummy`
-  --> $DIR/coherence-overlap-issue-23516-inherent.rs:12:25
+  --> $DIR/coherence-overlap-issue-23516-inherent.rs:9:25
    |
 LL | impl<T:Sugar> Cake<T> { fn dummy(&self) { } }
    |                         ^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr
deleted file mode 100644
index b949477..0000000
--- a/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0119]: conflicting implementations of trait `Sweet` for type `Box<_>`
-  --> $DIR/coherence-overlap-issue-23516.rs:11:1
-   |
-LL | impl<T:Sugar> Sweet for T { }
-   | ------------------------- first implementation here
-LL | impl<U:Sugar> Sweet for Box<U> { }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
-   |
-   = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.rs b/tests/ui/coherence/coherence-overlap-issue-23516.rs
index 620e00c..63e42e8 100644
--- a/tests/ui/coherence/coherence-overlap-issue-23516.rs
+++ b/tests/ui/coherence/coherence-overlap-issue-23516.rs
@@ -1,6 +1,3 @@
-//@ revisions: old next
-//@[next] compile-flags: -Znext-solver
-
 // Tests that we consider `Box<U>: !Sugar` to be ambiguous, even
 // though we see no impl of `Sugar` for `Box`. Therefore, an overlap
 // error is reported for the following pair of impls (#23516).
diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.stderr
similarity index 90%
rename from tests/ui/coherence/coherence-overlap-issue-23516.next.stderr
rename to tests/ui/coherence/coherence-overlap-issue-23516.stderr
index b949477..7b1b240 100644
--- a/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr
+++ b/tests/ui/coherence/coherence-overlap-issue-23516.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Sweet` for type `Box<_>`
-  --> $DIR/coherence-overlap-issue-23516.rs:11:1
+  --> $DIR/coherence-overlap-issue-23516.rs:8:1
    |
 LL | impl<T:Sugar> Sweet for T { }
    | ------------------------- first implementation here
diff --git a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr
index 21c82ee..c5bb695 100644
--- a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr
+++ b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr
@@ -5,6 +5,8 @@
    | --------------------------- first implementation here
 LL | impl<U> Foo for &U {}
    | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
+   |
+   = note: downstream crates may implement trait `std::ops::DerefMut` for type `&_`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr
deleted file mode 100644
index 2ffb600..0000000
--- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>`
-  --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:27:1
-   |
-LL | / impl<T> Trait for T
-LL | | where
-LL | |     T: 'static,
-LL | |     for<'a> T: WithAssoc<'a>,
-LL | |     for<'a> <T as WithAssoc<'a>>::Assoc: WhereBound,
-   | |____________________________________________________- first implementation here
-...
-LL |   impl<T> Trait for Box<T> {}
-   |   ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
-   |
-   = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>`
-   = note: downstream crates may implement trait `WhereBound` for type `<std::boxed::Box<_> as WithAssoc<'a>>::Assoc`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs
index b8b6d88..0695076 100644
--- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs
+++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs
@@ -2,9 +2,6 @@
 // "Coherence incorrectly considers `unnormalizable_projection: Trait` to not hold even if it could"
 #![crate_type = "lib"]
 
-//@ revisions: classic next
-//@[next] compile-flags: -Znext-solver
-
 trait WhereBound {}
 impl WhereBound for () {}
 
diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr
similarity index 90%
rename from tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr
rename to tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr
index 99abdf6..57befbe 100644
--- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr
+++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>`
-  --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:27:1
+  --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:24:1
    |
 LL | / impl<T> Trait for T
 LL | | where
diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr
deleted file mode 100644
index 49b236f..0000000
--- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>`
-  --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:26:1
-   |
-LL | / impl<T> Trait for T
-LL | | where
-LL | |     T: 'static,
-LL | |     for<'a> T: WithAssoc<'a>,
-LL | |     for<'a> Box<<T as WithAssoc<'a>>::Assoc>: WhereBound,
-   | |_________________________________________________________- first implementation here
-...
-LL |   impl<T> Trait for Box<T> {}
-   |   ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
-   |
-   = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>`
-   = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<<std::boxed::Box<_> as WithAssoc<'a>>::Assoc>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs
index 8eeadb3..f5fb5ae 100644
--- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs
+++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs
@@ -2,9 +2,6 @@
 // "Coherence incorrectly considers `unnormalizable_projection: Trait` to not hold even if it could"
 #![crate_type = "lib"]
 
-//@ revisions: classic next
-//@[next] compile-flags: -Znext-solver
-
 pub trait WhereBound {}
 impl WhereBound for () {}
 
diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr
similarity index 91%
rename from tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr
rename to tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr
index 781ab0f..22673ce 100644
--- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr
+++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>`
-  --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:26:1
+  --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:23:1
    |
 LL | / impl<T> Trait for T
 LL | | where
diff --git a/tests/ui/coherence/coherent-due-to-fulfill.rs b/tests/ui/coherence/coherent-due-to-fulfill.rs
index 084f9be..f4555ee 100644
--- a/tests/ui/coherence/coherent-due-to-fulfill.rs
+++ b/tests/ui/coherence/coherent-due-to-fulfill.rs
@@ -1,6 +1,4 @@
-//@ compile-flags: -Znext-solver=coherence
 //@ check-pass
-
 trait Mirror {
     type Assoc;
 }
diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.rs b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs
index b3c9cf3..28e5b6d 100644
--- a/tests/ui/coherence/incoherent-even-though-we-fulfill.rs
+++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs
@@ -1,5 +1,3 @@
-//@ compile-flags: -Znext-solver=coherence
-
 trait Mirror {
     type Assoc;
 }
diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr
index b16465d..0b15a4e 100644
--- a/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr
+++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Foo` for type `()`
-  --> $DIR/incoherent-even-though-we-fulfill.rs:17:1
+  --> $DIR/incoherent-even-though-we-fulfill.rs:15:1
    |
 LL | impl<T> Foo for T where (): Mirror<Assoc = T> {}
    | --------------------------------------------- first implementation here
diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr
deleted file mode 100644
index 74be598..0000000
--- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0119]: conflicting implementations of trait `From<()>` for type `S`
-  --> $DIR/inter-crate-ambiguity-causes-notes.rs:12:1
-   |
-LL |   impl From<()> for S {
-   |   ------------------- first implementation here
-...
-LL | / impl<I> From<I> for S
-LL | |
-LL | | where
-LL | |     I: Iterator<Item = ()>,
-   | |___________________________^ conflicting implementation for `S`
-   |
-   = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs
index 3dead2f..5b11c78 100644
--- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs
+++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs
@@ -1,6 +1,3 @@
-//@ revisions: old next
-//@[next] compile-flags: -Znext-solver
-
 struct S;
 
 impl From<()> for S {
diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr
similarity index 90%
rename from tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr
rename to tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr
index 74be598..b322832 100644
--- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr
+++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `From<()>` for type `S`
-  --> $DIR/inter-crate-ambiguity-causes-notes.rs:12:1
+  --> $DIR/inter-crate-ambiguity-causes-notes.rs:9:1
    |
 LL |   impl From<()> for S {
    |   ------------------- first implementation here
diff --git a/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr
index f515c39..bf1ffcb 100644
--- a/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr
+++ b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr
@@ -5,6 +5,8 @@
    | ------------------------------ first implementation here
 LL | impl<T> Bar for Box<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
+   |
+   = note: downstream crates may implement trait `Foo` for type `std::boxed::Box<_>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr b/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr
index f24de10..97e2e97 100644
--- a/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr
+++ b/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr
@@ -6,6 +6,8 @@
 ...
 LL | impl<T> Bar for &T {}
    | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
+   |
+   = note: downstream crates may implement trait `Foo` for type `&_`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr
index 832c56a..8d59cbc 100644
--- a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr
+++ b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr
@@ -8,6 +8,7 @@
    |
    = warning: the behavior may change in a future release
    = note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
+   = note: downstream crates may implement trait `Marker` for type `&_`
    = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
 note: the lint level is defined here
   --> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:4:11
diff --git a/tests/ui/coherence/normalize-for-errors.current.stderr b/tests/ui/coherence/normalize-for-errors.current.stderr
deleted file mode 100644
index dcbb73b..0000000
--- a/tests/ui/coherence/normalize-for-errors.current.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, _)`
-  --> $DIR/normalize-for-errors.rs:17:1
-   |
-LL | impl<T: Copy, S: Iterator> MyTrait<S> for (T, S::Item) {}
-   | ------------------------------------------------------ first implementation here
-LL |
-LL | impl<S: Iterator> MyTrait<S> for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, _)`
-   |
-   = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs
index c17bb76..3ef91eb 100644
--- a/tests/ui/coherence/normalize-for-errors.rs
+++ b/tests/ui/coherence/normalize-for-errors.rs
@@ -1,7 +1,3 @@
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
-
 struct MyType;
 trait MyTrait<S> {}
 
@@ -18,6 +14,6 @@ impl<S: Iterator> MyTrait<S> for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {}
 //~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>,
 //~| NOTE conflicting implementation for `(Box<(MyType,)>,
 //~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
-//[next]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions
+//~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions
 
 fn main() {}
diff --git a/tests/ui/coherence/normalize-for-errors.next.stderr b/tests/ui/coherence/normalize-for-errors.stderr
similarity index 95%
rename from tests/ui/coherence/normalize-for-errors.next.stderr
rename to tests/ui/coherence/normalize-for-errors.stderr
index 44952dc..6fbcf5b 100644
--- a/tests/ui/coherence/normalize-for-errors.next.stderr
+++ b/tests/ui/coherence/normalize-for-errors.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)`
-  --> $DIR/normalize-for-errors.rs:17:1
+  --> $DIR/normalize-for-errors.rs:13:1
    |
 LL | impl<T: Copy, S: Iterator> MyTrait<S> for (T, S::Item) {}
    | ------------------------------------------------------ first implementation here
diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr
index 9544bdb..466b991 100644
--- a/tests/ui/coherence/occurs-check/associated-type.next.stderr
+++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr
@@ -3,7 +3,7 @@
  WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
  WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
 error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())`
-  --> $DIR/associated-type.rs:31:1
+  --> $DIR/associated-type.rs:32:1
    |
 LL |   impl<T> Overlap<T> for T {
    |   ------------------------ first implementation here
@@ -17,7 +17,7 @@
    = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
 
 error[E0284]: type annotations needed: cannot normalize `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc`
-  --> $DIR/associated-type.rs:44:59
+  --> $DIR/associated-type.rs:45:59
    |
 LL |     foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize);
    |                                                           ^^^^^^ cannot normalize `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc`
diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr
index ccc7f30..1e0345f 100644
--- a/tests/ui/coherence/occurs-check/associated-type.old.stderr
+++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr
@@ -1,13 +1,9 @@
  WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
  WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
  WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
  WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
-error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)`
-  --> $DIR/associated-type.rs:31:1
+error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())`
+  --> $DIR/associated-type.rs:32:1
    |
 LL |   impl<T> Overlap<T> for T {
    |   ------------------------ first implementation here
@@ -16,7 +12,7 @@
 LL | |
 LL | | where
 LL | |     for<'a> *const T: ToUnit<'a>,
-   | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), _)`
+   | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), ())`
    |
    = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
 
diff --git a/tests/ui/coherence/occurs-check/associated-type.rs b/tests/ui/coherence/occurs-check/associated-type.rs
index df03d5f..e450c33 100644
--- a/tests/ui/coherence/occurs-check/associated-type.rs
+++ b/tests/ui/coherence/occurs-check/associated-type.rs
@@ -1,4 +1,5 @@
 //@ revisions: old next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 // A regression test for #105787
diff --git a/tests/ui/coherence/occurs-check/opaques.current.stderr b/tests/ui/coherence/occurs-check/opaques.current.stderr
new file mode 100644
index 0000000..f3fc220
--- /dev/null
+++ b/tests/ui/coherence/occurs-check/opaques.current.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Trait<_>`
+  --> $DIR/opaques.rs:28:1
+   |
+LL | impl<T> Trait<T> for T {
+   | ---------------------- first implementation here
+...
+LL | impl<T> Trait<T> for defining_scope::Alias<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr
index 11d1edc..3de4799 100644
--- a/tests/ui/coherence/occurs-check/opaques.next.stderr
+++ b/tests/ui/coherence/occurs-check/opaques.next.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Trait<_>`
-  --> $DIR/opaques.rs:30:1
+  --> $DIR/opaques.rs:28:1
    |
 LL | impl<T> Trait<T> for T {
    | ---------------------- first implementation here
@@ -8,7 +8,7 @@
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
 error[E0282]: type annotations needed
-  --> $DIR/opaques.rs:13:20
+  --> $DIR/opaques.rs:11:20
    |
 LL |     pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
    |                    ^ cannot infer type
diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs
index 241a247..e197256 100644
--- a/tests/ui/coherence/occurs-check/opaques.rs
+++ b/tests/ui/coherence/occurs-check/opaques.rs
@@ -1,10 +1,8 @@
-//@revisions: old next
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 // A regression test for #105787
-
-//@[old] known-bug: #105787
-//@[old] check-pass
 #![feature(type_alias_impl_trait)]
 mod defining_scope {
     use super::*;
@@ -28,7 +26,7 @@ impl<T> Trait<T> for T {
     type Assoc = Box<u32>;
 }
 impl<T> Trait<T> for defining_scope::Alias<T> {
-    //[next]~^ ERROR conflicting implementations of trait
+    //~^ ERROR conflicting implementations of trait
     type Assoc = usize;
 }
 
diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr
deleted file mode 100644
index 44f76f3..0000000
--- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
-  --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6
-   |
-LL | impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
-   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
-   |
-   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
-   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
-
-error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
-  --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6
-   |
-LL | impl<T> foreign::Trait1<Local, T> for Opaque<T> {}
-   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
-   |
-   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
-   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0210`.
diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs
index 8dc02b0..02e9eb6 100644
--- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs
+++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs
@@ -1,8 +1,5 @@
 // Opaque types never cover type parameters.
 
-//@ revisions: classic next
-//@[next] compile-flags: -Znext-solver
-
 //@ aux-crate:foreign=parametrized-trait.rs
 //@ edition:2021
 
diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr
similarity index 92%
rename from tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr
rename to tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr
index 44f76f3..57f5bbd 100644
--- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr
+++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr
@@ -1,5 +1,5 @@
 error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
-  --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6
+  --> $DIR/orphan-check-opaque-types-not-covering.rs:14:6
    |
 LL | impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
    |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
@@ -8,7 +8,7 @@
    = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
 
 error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
-  --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6
+  --> $DIR/orphan-check-opaque-types-not-covering.rs:23:6
    |
 LL | impl<T> foreign::Trait1<Local, T> for Opaque<T> {}
    |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
diff --git a/tests/ui/coherence/orphan-check-projections-covering.rs b/tests/ui/coherence/orphan-check-projections-covering.rs
index ae1917e..8047844 100644
--- a/tests/ui/coherence/orphan-check-projections-covering.rs
+++ b/tests/ui/coherence/orphan-check-projections-covering.rs
@@ -5,9 +5,6 @@
 // first which would've lead to real-word regressions.
 
 //@ check-pass
-//@ revisions: classic next
-//@[next] compile-flags: -Znext-solver
-
 //@ aux-crate:foreign=parametrized-trait.rs
 //@ edition:2021
 
diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr
deleted file mode 100644
index 276833f..0000000
--- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
-  --> $DIR/orphan-check-weak-aliases-not-covering.rs:16:6
-   |
-LL | impl<T> foreign::Trait1<Local, T> for Identity<T> {}
-   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
-   |
-   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
-   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0210`.
diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs
index 9ebc45a..6d9bccc 100644
--- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs
+++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs
@@ -1,8 +1,5 @@
 // Weak aliases might not cover type parameters.
 
-//@ revisions: classic next
-//@[next] compile-flags: -Znext-solver
-
 //@ aux-crate:foreign=parametrized-trait.rs
 //@ edition:2021
 
diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr
similarity index 92%
rename from tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr
rename to tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr
index 276833f..df91514 100644
--- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr
+++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr
@@ -1,5 +1,5 @@
 error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
-  --> $DIR/orphan-check-weak-aliases-not-covering.rs:16:6
+  --> $DIR/orphan-check-weak-aliases-not-covering.rs:13:6
    |
 LL | impl<T> foreign::Trait1<Local, T> for Identity<T> {}
    |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
diff --git a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr b/tests/ui/coherence/skip-reporting-if-references-err.current.stderr
deleted file mode 100644
index 5eef325..0000000
--- a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0726]: implicit elided lifetime not allowed here
-  --> $DIR/skip-reporting-if-references-err.rs:10:9
-   |
-LL | impl<T> ToUnit for T {}
-   |         ^^^^^^ expected lifetime parameter
-   |
-help: indicate the anonymous lifetime
-   |
-LL | impl<T> ToUnit<'_> for T {}
-   |               ++++
-
-error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
-  --> $DIR/skip-reporting-if-references-err.rs:15:29
-   |
-LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {}
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()`
-
-error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
-  --> $DIR/skip-reporting-if-references-err.rs:15:18
-   |
-LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {}
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()`
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0277, E0726.
-For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/coherence/skip-reporting-if-references-err.rs b/tests/ui/coherence/skip-reporting-if-references-err.rs
index f9eaa49..dd8a71c 100644
--- a/tests/ui/coherence/skip-reporting-if-references-err.rs
+++ b/tests/ui/coherence/skip-reporting-if-references-err.rs
@@ -1,8 +1,4 @@
 // Regression test for #121006.
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
-
 trait ToUnit<'a> {
     type Unit;
 }
@@ -13,7 +9,5 @@ impl<T> ToUnit for T {}
 trait Overlap {}
 impl<U> Overlap for fn(U) {}
 impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {}
-//[current]~^ ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
-//[current]~| ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
 
 fn main() {}
diff --git a/tests/ui/coherence/skip-reporting-if-references-err.next.stderr b/tests/ui/coherence/skip-reporting-if-references-err.stderr
similarity index 86%
rename from tests/ui/coherence/skip-reporting-if-references-err.next.stderr
rename to tests/ui/coherence/skip-reporting-if-references-err.stderr
index 5de4cf6..0ff3e88 100644
--- a/tests/ui/coherence/skip-reporting-if-references-err.next.stderr
+++ b/tests/ui/coherence/skip-reporting-if-references-err.stderr
@@ -1,5 +1,5 @@
 error[E0726]: implicit elided lifetime not allowed here
-  --> $DIR/skip-reporting-if-references-err.rs:10:9
+  --> $DIR/skip-reporting-if-references-err.rs:6:9
    |
 LL | impl<T> ToUnit for T {}
    |         ^^^^^^ expected lifetime parameter
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr
deleted file mode 100644
index fb01cf1..0000000
--- a/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()`
-  --> $DIR/super-trait-knowable-1.rs:16:1
-   |
-LL | impl<T, U: Sub<T>> Overlap<T> for U {}
-   | ----------------------------------- first implementation here
-LL | impl<T> Overlap<T> for () {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
-   |
-   = note: downstream crates may implement trait `Sub<_>` for type `()`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs
index 80df8c1..77af4d0 100644
--- a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs
+++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs
@@ -3,10 +3,7 @@
 // We therefore elaborate super trait bounds in the implicit negative
 // overlap check.
 
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
-//@[next] check-pass
+//@ check-pass
 
 trait Super {}
 trait Sub<T>: Super {}
@@ -14,6 +11,5 @@ trait Sub<T>: Super {}
 trait Overlap<T> {}
 impl<T, U: Sub<T>> Overlap<T> for U {}
 impl<T> Overlap<T> for () {}
-//[current]~^ ERROR conflicting implementations
 
 fn main() {}
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs
index d1f2e8d..323ee0b 100644
--- a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs
+++ b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs
@@ -9,9 +9,6 @@
 // which caused the old solver to emit a `Tensor: TensorValue` goal in
 // `fn normalize_to_error` which then failed, causing this test to pass.
 
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
 //@ check-pass
 
 pub trait TensorValue {
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr
deleted file mode 100644
index 542edb8..0000000
--- a/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()`
-  --> $DIR/super-trait-knowable-3.rs:19:1
-   |
-LL | impl<T, U: Bound<W<T>>> Overlap<T> for U {}
-   | ---------------------------------------- first implementation here
-LL | impl<T> Overlap<T> for () {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
-   |
-   = note: downstream crates may implement trait `Sub<_>` for type `()`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.rs b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs
index 295d7ac..6198d3d 100644
--- a/tests/ui/coherence/super-traits/super-trait-knowable-3.rs
+++ b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs
@@ -2,10 +2,7 @@
 // super trait bound is in a nested goal so this would not
 // compile if we were to only elaborate root goals.
 
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
-//@[next] check-pass
+//@ check-pass
 
 trait Super {}
 trait Sub<T>: Super {}
@@ -17,6 +14,5 @@ impl<T: Sub<U>, U> Bound<W<U>> for T {}
 trait Overlap<T> {}
 impl<T, U: Bound<W<T>>> Overlap<T> for U {}
 impl<T> Overlap<T> for () {}
-//[current]~^ ERROR conflicting implementations of trait `Overlap<_>` for type `()`
 
 fn main() {}
diff --git a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs
new file mode 100644
index 0000000..794e6fa
--- /dev/null
+++ b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs
@@ -0,0 +1,11 @@
+// This was triggering an assertion failure in `NodeRange::new`.
+
+#![feature(cfg_eval)]
+#![feature(stmt_expr_attributes)]
+
+fn f() -> u32 {
+    #[cfg_eval] #[cfg(not(FALSE))] 0
+    //~^ ERROR removing an expression is not supported in this position
+}
+
+fn main() {}
diff --git a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr
new file mode 100644
index 0000000..0699e18
--- /dev/null
+++ b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr
@@ -0,0 +1,8 @@
+error: removing an expression is not supported in this position
+  --> $DIR/invalid-node-range-issue-129166.rs:7:17
+   |
+LL |     #[cfg_eval] #[cfg(not(FALSE))] 0
+   |                 ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs
index 05a3487..42c930f 100644
--- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs
+++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs
@@ -22,6 +22,7 @@ pub struct v17<const v10: usize, const v7: v11> {
     impl v17<512, v0> {
         pub const fn v21() -> v18 {}
         //~^ ERROR cannot find type `v18` in this scope
+        //~| ERROR duplicate definitions with name `v21`
     }
 
     impl<const v10: usize> v17<v10, v2> {
diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
index 39f022f..b336f2b 100644
--- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
@@ -1,5 +1,5 @@
 error[E0432]: unresolved import `v20::v13`
-  --> $DIR/unevaluated-const-ice-119731.rs:37:15
+  --> $DIR/unevaluated-const-ice-119731.rs:38:15
    |
 LL | pub use v20::{v13, v17};
    |               ^^^
@@ -23,7 +23,7 @@
    |                               ^^^ help: a type alias with a similar name exists: `v11`
 
 error[E0412]: cannot find type `v18` in this scope
-  --> $DIR/unevaluated-const-ice-119731.rs:30:31
+  --> $DIR/unevaluated-const-ice-119731.rs:31:31
    |
 LL |     pub type v11 = [[usize; v4]; v4];
    |     --------------------------------- similarly named type alias `v11` defined here
@@ -32,7 +32,7 @@
    |                               ^^^ help: a type alias with a similar name exists: `v11`
 
 error[E0422]: cannot find struct, variant or union type `v18` in this scope
-  --> $DIR/unevaluated-const-ice-119731.rs:32:13
+  --> $DIR/unevaluated-const-ice-119731.rs:33:13
    |
 LL |     pub type v11 = [[usize; v4]; v4];
    |     --------------------------------- similarly named type alias `v11` defined here
@@ -73,20 +73,29 @@
    |
 
 error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
-  --> $DIR/unevaluated-const-ice-119731.rs:27:37
+  --> $DIR/unevaluated-const-ice-119731.rs:28:37
    |
 LL |     impl<const v10: usize> v17<v10, v2> {
    |                                     ^^
 
 error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
-  --> $DIR/unevaluated-const-ice-119731.rs:27:37
+  --> $DIR/unevaluated-const-ice-119731.rs:28:37
    |
 LL |     impl<const v10: usize> v17<v10, v2> {
    |                                     ^^
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 9 previous errors; 2 warnings emitted
+error[E0592]: duplicate definitions with name `v21`
+  --> $DIR/unevaluated-const-ice-119731.rs:23:9
+   |
+LL |         pub const fn v21() -> v18 {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `v21`
+...
+LL |         pub const fn v21() -> v18 {
+   |         ------------------------- other definition for `v21`
 
-Some errors have detailed explanations: E0412, E0422, E0425, E0432.
+error: aborting due to 10 previous errors; 2 warnings emitted
+
+Some errors have detailed explanations: E0412, E0422, E0425, E0432, E0592.
 For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs
index dd0b1e8..81ac997 100644
--- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs
+++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs
@@ -10,6 +10,5 @@ trait Trait {}
 impl<const N: u32> Trait for A<N> {}
 
 impl<const N: u32> Trait for A<N> {}
-//~^ ERROR conflicting implementations of trait `Trait` for type `A<_>`
 
 pub fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr
index 80ac96d..e29c49f 100644
--- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr
@@ -4,16 +4,6 @@
 LL | struct A<const N: u32 = 1, const M: u32 = u8>;
    |                                           ^^ not a value
 
-error[E0119]: conflicting implementations of trait `Trait` for type `A<_>`
-  --> $DIR/unknown-alias-defkind-anonconst-ice-116710.rs:12:1
-   |
-LL | impl<const N: u32> Trait for A<N> {}
-   | --------------------------------- first implementation here
-LL |
-LL | impl<const N: u32> Trait for A<N> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A<_>`
+error: aborting due to 1 previous error
 
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0119, E0423.
-For more information about an error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0423`.
diff --git a/tests/ui/const-generics/invariant.rs b/tests/ui/const-generics/invariant.rs
index ee4ad4e..95a28b6 100644
--- a/tests/ui/const-generics/invariant.rs
+++ b/tests/ui/const-generics/invariant.rs
@@ -5,7 +5,7 @@
 trait SadBee {
     const ASSOC: usize;
 }
-// fn(&'static ())` is a supertype of `for<'a> fn(&'a ())` while
+// `fn(&'static ())` is a supertype of `for<'a> fn(&'a ())` while
 // we allow two different impls for these types, leading
 // to different const eval results.
 impl SadBee for for<'a> fn(&'a ()) {
diff --git a/tests/ui/consts/const-float-bits-conv.rs b/tests/ui/consts/const-float-bits-conv.rs
index 3a526c5..869498d 100644
--- a/tests/ui/consts/const-float-bits-conv.rs
+++ b/tests/ui/consts/const-float-bits-conv.rs
@@ -1,10 +1,9 @@
 //@ compile-flags: -Zmir-opt-level=0
 //@ run-pass
 
-#![feature(const_float_bits_conv)]
 #![feature(const_float_classify)]
-#![feature(f16)]
-#![feature(f128)]
+#![feature(f16, f16_const)]
+#![feature(f128, f128_const)]
 #![allow(unused_macro_rules)]
 // Don't promote
 const fn nop<T>(x: T) -> T { x }
diff --git a/tests/ui/consts/const-float-classify.rs b/tests/ui/consts/const-float-classify.rs
index c64d31a..6e5097f 100644
--- a/tests/ui/consts/const-float-classify.rs
+++ b/tests/ui/consts/const-float-classify.rs
@@ -2,7 +2,6 @@
 //@ known-bug: #110395
 // FIXME(effects) run-pass
 
-#![feature(const_float_bits_conv)]
 #![feature(const_float_classify)]
 #![feature(const_trait_impl, effects)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/consts/const-float-classify.stderr b/tests/ui/consts/const-float-classify.stderr
index 38acb8a..a35de8a 100644
--- a/tests/ui/consts/const-float-classify.stderr
+++ b/tests/ui/consts/const-float-classify.stderr
@@ -1,5 +1,5 @@
 error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
-  --> $DIR/const-float-classify.rs:13:12
+  --> $DIR/const-float-classify.rs:12:12
    |
 LL | impl const PartialEq<NonDet> for bool {
    |            ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/consts/const-ptr-is-null.rs b/tests/ui/consts/const-ptr-is-null.rs
new file mode 100644
index 0000000..82c293c
--- /dev/null
+++ b/tests/ui/consts/const-ptr-is-null.rs
@@ -0,0 +1,20 @@
+#![feature(const_ptr_is_null)]
+use std::ptr;
+
+const IS_NULL: () = {
+    assert!(ptr::null::<u8>().is_null());
+};
+const IS_NOT_NULL: () = {
+    assert!(!ptr::null::<u8>().wrapping_add(1).is_null());
+};
+
+const MAYBE_NULL: () = {
+    let x = 15;
+    let ptr = &x as *const i32;
+    // This one is still unambiguous...
+    assert!(!ptr.is_null());
+    // but once we shift outside the allocation, we might become null.
+    assert!(!ptr.wrapping_sub(512).is_null()); //~inside `MAYBE_NULL`
+};
+
+fn main() {}
diff --git a/tests/ui/consts/const-ptr-is-null.stderr b/tests/ui/consts/const-ptr-is-null.stderr
new file mode 100644
index 0000000..20e44a1
--- /dev/null
+++ b/tests/ui/consts/const-ptr-is-null.stderr
@@ -0,0 +1,19 @@
+error[E0080]: evaluation of constant value failed
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+   = note: the evaluated program panicked at 'null-ness of this pointer cannot be determined in const context', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+note: inside `std::ptr::const_ptr::<impl *const T>::is_null::const_impl`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `std::ptr::const_ptr::<impl *const i32>::is_null`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `MAYBE_NULL`
+  --> $DIR/const-ptr-is-null.rs:17:14
+   |
+LL |     assert!(!ptr.wrapping_sub(512).is_null());
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/missing_assoc_const_type.rs b/tests/ui/consts/missing_assoc_const_type.rs
index 8d95e3d..633998e 100644
--- a/tests/ui/consts/missing_assoc_const_type.rs
+++ b/tests/ui/consts/missing_assoc_const_type.rs
@@ -16,7 +16,7 @@ impl Range for TwoDigits {
 
 const fn digits(x: u8) -> usize {
     match x {
-        TwoDigits::FIRST..=TwoDigits::LAST => 0,
+        TwoDigits::FIRST..=TwoDigits::LAST => 0, //~ ERROR: could not evaluate constant pattern
         0..=9 | 100..=255 => panic!(),
     }
 }
diff --git a/tests/ui/consts/missing_assoc_const_type.stderr b/tests/ui/consts/missing_assoc_const_type.stderr
index 28af1f0..ef7ff96 100644
--- a/tests/ui/consts/missing_assoc_const_type.stderr
+++ b/tests/ui/consts/missing_assoc_const_type.stderr
@@ -4,5 +4,11 @@
 LL |     const FIRST:  = 10;
    |                 ^ help: provide a type for the associated constant: `u8`
 
-error: aborting due to 1 previous error
+error: could not evaluate constant pattern
+  --> $DIR/missing_assoc_const_type.rs:19:9
+   |
+LL |         TwoDigits::FIRST..=TwoDigits::LAST => 0,
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/coroutine/discriminant.rs b/tests/ui/coroutine/discriminant.rs
index d6879e2..ca4fced 100644
--- a/tests/ui/coroutine/discriminant.rs
+++ b/tests/ui/coroutine/discriminant.rs
@@ -124,12 +124,14 @@ fn main() {
     };
 
     assert_eq!(size_of_val(&gen_u8_tiny_niche()), 1);
-    assert_eq!(size_of_val(&Some(gen_u8_tiny_niche())), 1); // uses niche
+    // FIXME(#63818): niches in coroutines are disabled.
+    // assert_eq!(size_of_val(&Some(gen_u8_tiny_niche())), 1); // uses niche
     assert_eq!(size_of_val(&Some(Some(gen_u8_tiny_niche()))), 2); // cannot use niche anymore
     assert_eq!(size_of_val(&gen_u8_full()), 1);
     assert_eq!(size_of_val(&Some(gen_u8_full())), 2); // cannot use niche
     assert_eq!(size_of_val(&gen_u16()), 2);
-    assert_eq!(size_of_val(&Some(gen_u16())), 2); // uses niche
+    // FIXME(#63818): niches in coroutines are disabled.
+    // assert_eq!(size_of_val(&Some(gen_u16())), 2); // uses niche
 
     cycle(gen_u8_tiny_niche(), 254);
     cycle(gen_u8_full(), 255);
diff --git a/tests/ui/coroutine/niche-in-coroutine.rs b/tests/ui/coroutine/niche-in-coroutine.rs
index 117ee9e..f268ef0 100644
--- a/tests/ui/coroutine/niche-in-coroutine.rs
+++ b/tests/ui/coroutine/niche-in-coroutine.rs
@@ -15,5 +15,6 @@ fn main() {
         take(x);
     };
 
-    assert_eq!(size_of_val(&gen1), size_of_val(&Some(gen1)));
+    // FIXME(#63818): niches in coroutines are disabled. Should be `assert_eq`.
+    assert_ne!(size_of_val(&gen1), size_of_val(&Some(gen1)));
 }
diff --git a/tests/ui/delegation/generics/impl-to-free-fn-pass.rs b/tests/ui/delegation/generics/impl-to-free-fn-pass.rs
new file mode 100644
index 0000000..3b39a45
--- /dev/null
+++ b/tests/ui/delegation/generics/impl-to-free-fn-pass.rs
@@ -0,0 +1,29 @@
+//@ run-pass
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {
+    pub fn foo<T, U>(_: T, y: U) -> U { y }
+}
+
+trait Trait<T> {
+    fn foo(&self, x: T) -> T { x }
+}
+struct F;
+impl<T> Trait<T> for F {}
+
+struct S<T>(F, T);
+
+impl<T, U> Trait<T> for S<U> {
+    reuse to_reuse::foo { &self.0 }
+}
+
+impl<T> S<T> {
+    reuse to_reuse::foo;
+}
+
+fn main() {
+    let s = S(F, 42);
+    assert_eq!(S::<i32>::foo(F, 1), 1);
+    assert_eq!(<S<_> as Trait<_>>::foo(&s, 1), 1);
+}
diff --git a/tests/ui/delegation/generics/impl-to-trait-method.rs b/tests/ui/delegation/generics/impl-to-trait-method.rs
new file mode 100644
index 0000000..39e32e2
--- /dev/null
+++ b/tests/ui/delegation/generics/impl-to-trait-method.rs
@@ -0,0 +1,44 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod bounds {
+    trait Trait0 {}
+
+    trait Trait1<T> {
+        fn foo<U>(&self)
+        where
+            T: Trait0,
+            U: Trait0,
+            Self: Trait0,
+            //~^ ERROR the trait bound `bounds::S: Trait0` is not satisfied
+        {
+        }
+    }
+
+    struct F;
+    impl<T> Trait1<T> for F {}
+
+    struct S(F);
+
+    impl<T> Trait1<T> for S {
+        reuse Trait1::<T>::foo { &self.0 }
+        //~^ ERROR the trait bound `bounds::F: Trait0` is not satisfied
+    }
+}
+
+mod unconstrained_parameter {
+    trait Trait<T> {
+        fn foo(&self) {}
+    }
+
+    struct F;
+    impl<T> Trait<T> for F {}
+
+    struct S(F);
+    impl S {
+        reuse Trait::foo { &self.0 }
+        //~^ ERROR type annotations needed
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/delegation/generics/impl-to-trait-method.stderr b/tests/ui/delegation/generics/impl-to-trait-method.stderr
new file mode 100644
index 0000000..aeba30d
--- /dev/null
+++ b/tests/ui/delegation/generics/impl-to-trait-method.stderr
@@ -0,0 +1,49 @@
+error[E0277]: the trait bound `bounds::S: Trait0` is not satisfied
+  --> $DIR/impl-to-trait-method.rs:12:19
+   |
+LL |             Self: Trait0,
+   |                   ^^^^^^ the trait `Trait0` is not implemented for `bounds::S`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/impl-to-trait-method.rs:5:5
+   |
+LL |     trait Trait0 {}
+   |     ^^^^^^^^^^^^
+   = help: see issue #48214
+help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+   |
+LL + #![feature(trivial_bounds)]
+   |
+
+error[E0277]: the trait bound `bounds::F: Trait0` is not satisfied
+  --> $DIR/impl-to-trait-method.rs:24:34
+   |
+LL |         reuse Trait1::<T>::foo { &self.0 }
+   |                            ---   ^^^^^^^ the trait `Trait0` is not implemented for `bounds::F`
+   |                            |
+   |                            required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/impl-to-trait-method.rs:5:5
+   |
+LL |     trait Trait0 {}
+   |     ^^^^^^^^^^^^
+note: required by a bound in `Trait1::foo`
+  --> $DIR/impl-to-trait-method.rs:12:19
+   |
+LL |         fn foo<U>(&self)
+   |            --- required by a bound in this associated function
+...
+LL |             Self: Trait0,
+   |                   ^^^^^^ required by this bound in `Trait1::foo`
+
+error[E0282]: type annotations needed
+  --> $DIR/impl-to-trait-method.rs:39:22
+   |
+LL |         reuse Trait::foo { &self.0 }
+   |                      ^^^ cannot infer type for type parameter `T` declared on the trait `Trait`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0282.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/delegation/generics/impl-trait-to-trait-method-pass.rs b/tests/ui/delegation/generics/impl-trait-to-trait-method-pass.rs
new file mode 100644
index 0000000..72440fe
--- /dev/null
+++ b/tests/ui/delegation/generics/impl-trait-to-trait-method-pass.rs
@@ -0,0 +1,77 @@
+//@ run-pass
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+use std::iter::{Iterator, Map};
+
+pub mod same_trait {
+    use super::*;
+
+    pub struct MapOuter<I, F> {
+        pub inner: Map<I, F>
+    }
+
+    impl<B, I: Iterator, F> Iterator for MapOuter<I, F>
+    where
+        F: FnMut(I::Item) -> B,
+    {
+        type Item = <Map<I, F> as Iterator>::Item;
+
+        reuse Iterator::{next, fold} { self.inner }
+    }
+}
+use same_trait::MapOuter;
+
+mod another_trait {
+    use super::*;
+
+    trait ZipImpl<A, B> {
+        type Item;
+
+        fn next(&mut self) -> Option<Self::Item>;
+    }
+
+    pub struct Zip<A, B> {
+        pub a: A,
+        pub b: B,
+    }
+
+    impl<A: Iterator, B: Iterator> ZipImpl<A, B> for Zip<A, B> {
+        type Item = (A::Item, B::Item);
+
+        fn next(&mut self) -> Option<(A::Item, B::Item)> {
+            let x = self.a.next()?;
+            let y = self.b.next()?;
+            Some((x, y))
+        }
+    }
+
+    impl<A: Iterator, B: Iterator> Iterator for Zip<A, B> {
+        type Item = (A::Item, B::Item);
+
+        // Parameters are inherited from `Iterator::next`, not from `ZipImpl::next`.
+        // Otherwise, there would be a compilation error due to an unconstrained parameter.
+        reuse ZipImpl::next;
+    }
+}
+use another_trait::Zip;
+
+fn main() {
+    {
+        let x = vec![1, 2, 3];
+        let iter = x.iter().map(|val| val * 2);
+        let outer_iter = MapOuter { inner: iter };
+        let val = outer_iter.fold(0, |acc, x| acc + x);
+        assert_eq!(val, 12);
+    }
+
+    {
+        let x = vec![1, 2];
+        let y = vec![4, 5];
+
+        let mut zip = Zip { a: x.iter(), b: y.iter() };
+        assert_eq!(zip.next(), Some((&1, &4)));
+        assert_eq!(zip.next(), Some((&2, &5)));
+    }
+}
diff --git a/tests/ui/delegation/generics/inherent-impl-to-trait-method-pass.rs b/tests/ui/delegation/generics/inherent-impl-to-trait-method-pass.rs
new file mode 100644
index 0000000..6f3bb17
--- /dev/null
+++ b/tests/ui/delegation/generics/inherent-impl-to-trait-method-pass.rs
@@ -0,0 +1,23 @@
+//@ run-pass
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+trait Trait<T> {
+    fn foo<U>(&self, x: T, y: U) -> (T, U) {
+        (x, y)
+    }
+}
+
+impl<T> Trait<T> for () {}
+struct S<T>(T, ());
+
+impl<T> S<T> {
+    reuse Trait::foo { self.1 }
+}
+
+
+fn main() {
+    let s = S((), ());
+    assert_eq!(s.foo(1u32, 2i32), (1u32, 2i32));
+}
diff --git a/tests/ui/delegation/generics/trait-method-to-other-pass.rs b/tests/ui/delegation/generics/trait-method-to-other-pass.rs
new file mode 100644
index 0000000..2094705
--- /dev/null
+++ b/tests/ui/delegation/generics/trait-method-to-other-pass.rs
@@ -0,0 +1,30 @@
+//@ run-pass
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {
+    pub fn foo<T>(x: T) -> T { x }
+}
+
+trait Trait1<T, U> {
+    fn foo(&self, _: T, x: U) -> U { x }
+}
+
+#[derive(Default)]
+struct F;
+
+impl<T, U> Trait1<T, U> for F {}
+
+trait Trait2<T> {
+    fn get_f(&self) -> &F { &F }
+    reuse Trait1::foo as bar { self.get_f() }
+    reuse to_reuse::foo as baz;
+}
+
+impl Trait2<u64> for F {}
+
+fn main() {
+    assert_eq!(F.bar(1u8, 2u16), 2u16);
+    assert_eq!(F::baz(1u8), 1u8);
+}
diff --git a/tests/ui/delegation/ice-issue-124347.rs b/tests/ui/delegation/ice-issue-124347.rs
index 3bfae8f..ee2bf9e 100644
--- a/tests/ui/delegation/ice-issue-124347.rs
+++ b/tests/ui/delegation/ice-issue-124347.rs
@@ -1,12 +1,12 @@
 #![feature(fn_delegation)]
 #![allow(incomplete_features)]
 
+// FIXME(fn_delegation): `recursive delegation` error should be emitted here
 trait Trait {
     reuse Trait::foo { &self.0 }
-    //~^ ERROR recursive delegation is not supported yet
+    //~^ ERROR cycle detected when computing generics of `Trait::foo`
 }
 
-// FIXME(fn_delegation): `recursive delegation` error should be emitted here
 reuse foo;
 //~^ ERROR cycle detected when computing generics of `foo`
 
diff --git a/tests/ui/delegation/ice-issue-124347.stderr b/tests/ui/delegation/ice-issue-124347.stderr
index 87dd75f..bd0bc97 100644
--- a/tests/ui/delegation/ice-issue-124347.stderr
+++ b/tests/ui/delegation/ice-issue-124347.stderr
@@ -1,8 +1,16 @@
-error: recursive delegation is not supported yet
-  --> $DIR/ice-issue-124347.rs:5:18
+error[E0391]: cycle detected when computing generics of `Trait::foo`
+  --> $DIR/ice-issue-124347.rs:6:18
    |
 LL |     reuse Trait::foo { &self.0 }
-   |                  ^^^ callee defined here
+   |                  ^^^
+   |
+   = note: ...which immediately requires computing generics of `Trait::foo` again
+note: cycle used when inheriting delegation signature
+  --> $DIR/ice-issue-124347.rs:6:18
+   |
+LL |     reuse Trait::foo { &self.0 }
+   |                  ^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error[E0391]: cycle detected when computing generics of `foo`
   --> $DIR/ice-issue-124347.rs:10:7
diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs
deleted file mode 100644
index d5ac68e..0000000
--- a/tests/ui/delegation/not-supported.rs
+++ /dev/null
@@ -1,116 +0,0 @@
-#![feature(const_trait_impl)]
-#![feature(c_variadic)]
-#![feature(effects)]
-#![feature(fn_delegation)]
-#![allow(incomplete_features)]
-
-mod generics {
-    trait GenericTrait<T> {
-        fn bar(&self, x: T) -> T { x }
-        fn bar1() {}
-    }
-    trait Trait {
-        fn foo(&self, x: i32) -> i32 { x }
-        fn foo1<'a>(&self, x: &'a i32) -> &'a i32 { x }
-        fn foo2<T>(&self, x: T) -> T { x }
-        fn foo3<'a: 'a>(_: &'a u32) {}
-
-        reuse GenericTrait::bar;
-        //~^ ERROR early bound generics are not supported for associated delegation items
-        reuse GenericTrait::bar1;
-        //~^ ERROR early bound generics are not supported for associated delegation items
-    }
-
-    struct F;
-    impl Trait for F {}
-    impl<T> GenericTrait<T> for F {}
-
-    struct S(F);
-
-    impl<T> GenericTrait<T> for S {
-        reuse <F as GenericTrait<T>>::bar { &self.0 }
-        //~^ ERROR early bound generics are not supported for associated delegation items
-        reuse GenericTrait::<T>::bar1;
-        //~^ ERROR early bound generics are not supported for associated delegation items
-    }
-
-    impl GenericTrait<()> for () {
-        reuse GenericTrait::bar { &F }
-        //~^ ERROR early bound generics are not supported for associated delegation items
-        reuse GenericTrait::bar1;
-        //~^ ERROR early bound generics are not supported for associated delegation items
-    }
-
-    impl Trait for &S {
-        reuse Trait::foo;
-        //~^ ERROR early bound generics are not supported for associated delegation items
-    }
-
-    impl Trait for S {
-        reuse Trait::foo1 { &self.0 }
-        reuse Trait::foo2 { &self.0 }
-        //~^ ERROR early bound generics are not supported for associated delegation items
-        //~| ERROR method `foo2` has 0 type parameters but its trait declaration has 1 type parameter
-        reuse <F as Trait>::foo3;
-        //~^ ERROR early bound generics are not supported for associated delegation items
-        //~| ERROR lifetime parameters or bounds on associated function `foo3` do not match the trait declaration
-    }
-
-    struct GenericS<T>(T);
-    impl<T> Trait for GenericS<T> {
-        reuse Trait::foo { &self.0 }
-        //~^ ERROR early bound generics are not supported for associated delegation items
-    }
-}
-
-mod opaque {
-    trait Trait {}
-    impl Trait for () {}
-
-    mod to_reuse {
-        use super::Trait;
-
-        pub fn opaque_ret() -> impl Trait { unimplemented!() }
-        //~^ warn: this function depends on never type fallback being `()`
-        //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    }
-
-    trait ToReuse {
-        fn opaque_ret() -> impl Trait { unimplemented!() }
-        //~^ warn: this function depends on never type fallback being `()`
-        //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-    }
-
-    // FIXME: Inherited `impl Trait`s create query cycles when used inside trait impls.
-    impl ToReuse for u8 {
-        reuse to_reuse::opaque_ret; //~ ERROR cycle detected when computing type
-    }
-    impl ToReuse for u16 {
-        reuse ToReuse::opaque_ret; //~ ERROR cycle detected when computing type
-    }
-}
-
-mod recursive {
-    mod to_reuse1 {
-        pub mod to_reuse2 {
-            pub fn foo() {}
-        }
-
-        pub reuse to_reuse2::foo;
-    }
-
-    reuse to_reuse1::foo;
-    //~^ ERROR recursive delegation is not supported yet
-}
-
-mod effects {
-    #[const_trait]
-    trait Trait {
-        fn foo();
-    }
-
-    reuse Trait::foo;
-    //~^ ERROR delegation to a function with effect parameter is not supported yet
-}
-
-fn main() {}
diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr
deleted file mode 100644
index 14d6b37..0000000
--- a/tests/ui/delegation/not-supported.stderr
+++ /dev/null
@@ -1,204 +0,0 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
-   |
-   = note: the next trait solver must be enabled globally for the effects feature to work correctly
-   = help: use `-Znext-solver` to enable
-
-error: early bound generics are not supported for associated delegation items
-  --> $DIR/not-supported.rs:18:29
-   |
-LL |         fn bar(&self, x: T) -> T { x }
-   |         ------------------------ callee defined here
-...
-LL |         reuse GenericTrait::bar;
-   |                             ^^^
-
-error: early bound generics are not supported for associated delegation items
-  --> $DIR/not-supported.rs:20:29
-   |
-LL |         fn bar1() {}
-   |         --------- callee defined here
-...
-LL |         reuse GenericTrait::bar1;
-   |                             ^^^^
-
-error: early bound generics are not supported for associated delegation items
-  --> $DIR/not-supported.rs:31:39
-   |
-LL |         fn bar(&self, x: T) -> T { x }
-   |         ------------------------ callee defined here
-...
-LL |         reuse <F as GenericTrait<T>>::bar { &self.0 }
-   |                                       ^^^
-
-error: early bound generics are not supported for associated delegation items
-  --> $DIR/not-supported.rs:33:34
-   |
-LL |         fn bar1() {}
-   |         --------- callee defined here
-...
-LL |         reuse GenericTrait::<T>::bar1;
-   |                                  ^^^^
-
-error: early bound generics are not supported for associated delegation items
-  --> $DIR/not-supported.rs:38:29
-   |
-LL |         fn bar(&self, x: T) -> T { x }
-   |         ------------------------ callee defined here
-...
-LL |         reuse GenericTrait::bar { &F }
-   |                             ^^^
-
-error: early bound generics are not supported for associated delegation items
-  --> $DIR/not-supported.rs:40:29
-   |
-LL |         fn bar1() {}
-   |         --------- callee defined here
-...
-LL |         reuse GenericTrait::bar1;
-   |                             ^^^^
-
-error: early bound generics are not supported for associated delegation items
-  --> $DIR/not-supported.rs:45:22
-   |
-LL |         fn foo(&self, x: i32) -> i32 { x }
-   |         ---------------------------- callee defined here
-...
-LL |         reuse Trait::foo;
-   |                      ^^^
-
-error[E0049]: method `foo2` has 0 type parameters but its trait declaration has 1 type parameter
-  --> $DIR/not-supported.rs:51:22
-   |
-LL |         fn foo2<T>(&self, x: T) -> T { x }
-   |                 - expected 1 type parameter
-...
-LL |         reuse Trait::foo2 { &self.0 }
-   |                      ^^^^ found 0 type parameters
-
-error: early bound generics are not supported for associated delegation items
-  --> $DIR/not-supported.rs:54:29
-   |
-LL |         fn foo3<'a: 'a>(_: &'a u32) {}
-   |         --------------------------- callee defined here
-...
-LL |         reuse <F as Trait>::foo3;
-   |                             ^^^^
-
-error[E0195]: lifetime parameters or bounds on associated function `foo3` do not match the trait declaration
-  --> $DIR/not-supported.rs:54:29
-   |
-LL |         fn foo3<'a: 'a>(_: &'a u32) {}
-   |                -------- lifetimes in impl do not match this associated function in trait
-...
-LL |         reuse <F as Trait>::foo3;
-   |                             ^^^^ lifetimes do not match associated function in trait
-
-error: delegation to a function with effect parameter is not supported yet
-  --> $DIR/not-supported.rs:112:18
-   |
-LL |         fn foo();
-   |         --------- callee defined here
-...
-LL |     reuse Trait::foo;
-   |                  ^^^
-
-error: early bound generics are not supported for associated delegation items
-  --> $DIR/not-supported.rs:61:22
-   |
-LL |         fn foo(&self, x: i32) -> i32 { x }
-   |         ---------------------------- callee defined here
-...
-LL |         reuse Trait::foo { &self.0 }
-   |                      ^^^
-
-error: early bound generics are not supported for associated delegation items
-  --> $DIR/not-supported.rs:51:22
-   |
-LL |         fn foo2<T>(&self, x: T) -> T { x }
-   |         ---------------------------- callee defined here
-...
-LL |         reuse Trait::foo2 { &self.0 }
-   |                      ^^^^
-
-warning: this function depends on never type fallback being `()`
-  --> $DIR/not-supported.rs:79:9
-   |
-LL |         fn opaque_ret() -> impl Trait { unimplemented!() }
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
-   = help: specify the types explicitly
-note: in edition 2024, the requirement `!: opaque::Trait` will fail
-  --> $DIR/not-supported.rs:79:28
-   |
-LL |         fn opaque_ret() -> impl Trait { unimplemented!() }
-   |                            ^^^^^^^^^^
-   = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
-
-error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:85:5: 85:24>::{synthetic#0}`
-  --> $DIR/not-supported.rs:86:25
-   |
-LL |         reuse to_reuse::opaque_ret;
-   |                         ^^^^^^^^^^
-   |
-note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
-  --> $DIR/not-supported.rs:86:25
-   |
-LL |         reuse to_reuse::opaque_ret;
-   |                         ^^^^^^^^^^
-   = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:85:5: 85:24>::{synthetic#0}`, completing the cycle
-note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:85:5: 85:24>` is well-formed
-  --> $DIR/not-supported.rs:85:5
-   |
-LL |     impl ToReuse for u8 {
-   |     ^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-warning: this function depends on never type fallback being `()`
-  --> $DIR/not-supported.rs:73:9
-   |
-LL |         pub fn opaque_ret() -> impl Trait { unimplemented!() }
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
-   = help: specify the types explicitly
-note: in edition 2024, the requirement `!: opaque::Trait` will fail
-  --> $DIR/not-supported.rs:73:32
-   |
-LL |         pub fn opaque_ret() -> impl Trait { unimplemented!() }
-   |                                ^^^^^^^^^^
-
-error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:88:5: 88:25>::{synthetic#0}`
-  --> $DIR/not-supported.rs:89:24
-   |
-LL |         reuse ToReuse::opaque_ret;
-   |                        ^^^^^^^^^^
-   |
-note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
-  --> $DIR/not-supported.rs:89:24
-   |
-LL |         reuse ToReuse::opaque_ret;
-   |                        ^^^^^^^^^^
-   = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:88:5: 88:25>::{synthetic#0}`, completing the cycle
-note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:88:5: 88:25>` is well-formed
-  --> $DIR/not-supported.rs:88:5
-   |
-LL |     impl ToReuse for u16 {
-   |     ^^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error: recursive delegation is not supported yet
-  --> $DIR/not-supported.rs:102:22
-   |
-LL |         pub reuse to_reuse2::foo;
-   |                              --- callee defined here
-...
-LL |     reuse to_reuse1::foo;
-   |                      ^^^
-
-error: aborting due to 17 previous errors; 2 warnings emitted
-
-Some errors have detailed explanations: E0049, E0195, E0391.
-For more information about an error, try `rustc --explain E0049`.
diff --git a/tests/ui/delegation/unsupported.rs b/tests/ui/delegation/unsupported.rs
new file mode 100644
index 0000000..e57efff
--- /dev/null
+++ b/tests/ui/delegation/unsupported.rs
@@ -0,0 +1,57 @@
+#![feature(const_trait_impl)]
+#![feature(c_variadic)]
+#![feature(effects)]
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod opaque {
+    trait Trait {}
+    impl Trait for () {}
+
+    mod to_reuse {
+        use super::Trait;
+
+        pub fn opaque_ret() -> impl Trait { unimplemented!() }
+        //~^ warn: this function depends on never type fallback being `()`
+        //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    }
+
+    trait ToReuse {
+        fn opaque_ret() -> impl Trait { unimplemented!() }
+        //~^ warn: this function depends on never type fallback being `()`
+        //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    }
+
+    // FIXME: Inherited `impl Trait`s create query cycles when used inside trait impls.
+    impl ToReuse for u8 {
+        reuse to_reuse::opaque_ret; //~ ERROR cycle detected when computing type
+    }
+    impl ToReuse for u16 {
+        reuse ToReuse::opaque_ret; //~ ERROR cycle detected when computing type
+    }
+}
+
+mod recursive {
+    mod to_reuse1 {
+        pub mod to_reuse2 {
+            pub fn foo() {}
+        }
+
+        pub reuse to_reuse2::foo;
+    }
+
+    reuse to_reuse1::foo;
+    //~^ ERROR recursive delegation is not supported yet
+}
+
+mod effects {
+    #[const_trait]
+    trait Trait {
+        fn foo();
+    }
+
+    reuse Trait::foo;
+    //~^ ERROR delegation to a function with effect parameter is not supported yet
+}
+
+fn main() {}
diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr
new file mode 100644
index 0000000..03ded30
--- /dev/null
+++ b/tests/ui/delegation/unsupported.stderr
@@ -0,0 +1,95 @@
+error: using `#![feature(effects)]` without enabling next trait solver globally
+   |
+   = note: the next trait solver must be enabled globally for the effects feature to work correctly
+   = help: use `-Znext-solver` to enable
+
+warning: this function depends on never type fallback being `()`
+  --> $DIR/unsupported.rs:20:9
+   |
+LL |         fn opaque_ret() -> impl Trait { unimplemented!() }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: opaque::Trait` will fail
+  --> $DIR/unsupported.rs:20:28
+   |
+LL |         fn opaque_ret() -> impl Trait { unimplemented!() }
+   |                            ^^^^^^^^^^
+   = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
+
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>::{synthetic#0}`
+  --> $DIR/unsupported.rs:27:25
+   |
+LL |         reuse to_reuse::opaque_ret;
+   |                         ^^^^^^^^^^
+   |
+note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
+  --> $DIR/unsupported.rs:27:25
+   |
+LL |         reuse to_reuse::opaque_ret;
+   |                         ^^^^^^^^^^
+   = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>::{synthetic#0}`, completing the cycle
+note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>` is well-formed
+  --> $DIR/unsupported.rs:26:5
+   |
+LL |     impl ToReuse for u8 {
+   |     ^^^^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+warning: this function depends on never type fallback being `()`
+  --> $DIR/unsupported.rs:14:9
+   |
+LL |         pub fn opaque_ret() -> impl Trait { unimplemented!() }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = 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 #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: opaque::Trait` will fail
+  --> $DIR/unsupported.rs:14:32
+   |
+LL |         pub fn opaque_ret() -> impl Trait { unimplemented!() }
+   |                                ^^^^^^^^^^
+
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>::{synthetic#0}`
+  --> $DIR/unsupported.rs:30:24
+   |
+LL |         reuse ToReuse::opaque_ret;
+   |                        ^^^^^^^^^^
+   |
+note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
+  --> $DIR/unsupported.rs:30:24
+   |
+LL |         reuse ToReuse::opaque_ret;
+   |                        ^^^^^^^^^^
+   = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>::{synthetic#0}`, completing the cycle
+note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>` is well-formed
+  --> $DIR/unsupported.rs:29:5
+   |
+LL |     impl ToReuse for u16 {
+   |     ^^^^^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: recursive delegation is not supported yet
+  --> $DIR/unsupported.rs:43:22
+   |
+LL |         pub reuse to_reuse2::foo;
+   |                              --- callee defined here
+...
+LL |     reuse to_reuse1::foo;
+   |                      ^^^
+
+error: delegation to a function with effect parameter is not supported yet
+  --> $DIR/unsupported.rs:53:18
+   |
+LL |         fn foo();
+   |         --------- callee defined here
+...
+LL |     reuse Trait::foo;
+   |                  ^^^
+
+error: aborting due to 5 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/error-codes/e0119/issue-23563.stderr b/tests/ui/error-codes/e0119/issue-23563.stderr
index 8673774..a308769 100644
--- a/tests/ui/error-codes/e0119/issue-23563.stderr
+++ b/tests/ui/error-codes/e0119/issue-23563.stderr
@@ -1,4 +1,4 @@
-error[E0119]: conflicting implementations of trait `LolFrom<&[_]>` for type `LocalType<_>`
+error[E0119]: conflicting implementations of trait `LolFrom<&[u8]>` for type `LocalType<u8>`
   --> $DIR/issue-23563.rs:13:1
    |
 LL | impl<'a, T> LolFrom<&'a [T]> for LocalType<T> {
diff --git a/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr
index ba07656..b32f54a 100644
--- a/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr
+++ b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr
@@ -6,6 +6,8 @@
 LL |
 LL | impl<T> Foo for &T { }
    | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
+   |
+   = note: downstream crates may implement trait `std::ops::DerefMut` for type `&_`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs
index beda719..9a44fd2 100644
--- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs
+++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs
@@ -3,9 +3,9 @@
 //@ check-pass
 
 // The new trait solver does not return region constraints if the goal
-// is still ambiguous. This causes the following test to fail with ambiguity,
-// even though `(): LeakCheckFailure<'!a, V>` would return `'!a: 'static`
-// which would have caused a leak check failure.
+// is still ambiguous. However, the `'!a = 'static` constraint from
+// `(): LeakCheckFailure<'!a, V>`  is also returned via the canonical
+// var values, causing this test to compile.
 
 trait Ambig {}
 impl Ambig for u32 {}
diff --git a/tests/ui/higher-ranked/structually-relate-aliases.rs b/tests/ui/higher-ranked/structually-relate-aliases.rs
index 8df2470..6988245 100644
--- a/tests/ui/higher-ranked/structually-relate-aliases.rs
+++ b/tests/ui/higher-ranked/structually-relate-aliases.rs
@@ -11,7 +11,6 @@ trait Overlap<T> {}
 impl<T> Overlap<T> for T {}
 
 impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
-//~^ ERROR 13:17: 13:49: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277]
-//~| ERROR 13:36: 13:48: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277]
+//~^ ERROR conflicting implementations of trait `Overlap<for<'a> fn(&'a (), _)>`
 
 fn main() {}
diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr
index 7de30ef..4ecd582 100644
--- a/tests/ui/higher-ranked/structually-relate-aliases.stderr
+++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr
@@ -1,27 +1,18 @@
  WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. }
-error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
-  --> $DIR/structually-relate-aliases.rs:13:36
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. }
+error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)`
+  --> $DIR/structually-relate-aliases.rs:13:1
    |
+LL | impl<T> Overlap<T> for T {}
+   | ------------------------ first implementation here
+LL |
 LL | impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
-   |                                    ^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a (), _)`
    |
-help: consider restricting type parameter `T`
-   |
-LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
-   |       ++++++++++++++++++++
+   = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
 
-error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
-  --> $DIR/structually-relate-aliases.rs:13:17
-   |
-LL | impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T`
-   |
-help: consider restricting type parameter `T`
-   |
-LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
-   |       ++++++++++++++++++++
+error: aborting due to 1 previous error
 
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/impl-trait/auto-trait-coherence.old.stderr b/tests/ui/impl-trait/auto-trait-coherence.old.stderr
index 3f979d1..cd91bfc 100644
--- a/tests/ui/impl-trait/auto-trait-coherence.old.stderr
+++ b/tests/ui/impl-trait/auto-trait-coherence.old.stderr
@@ -1,11 +1,11 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>`
   --> $DIR/auto-trait-coherence.rs:24:1
    |
 LL | impl<T: Send> AnotherTrait for T {}
    | -------------------------------- first implementation here
 ...
 LL | impl AnotherTrait for D<OpaqueType> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/auto-trait-coherence.rs b/tests/ui/impl-trait/auto-trait-coherence.rs
index e3036fd..0d7fef2 100644
--- a/tests/ui/impl-trait/auto-trait-coherence.rs
+++ b/tests/ui/impl-trait/auto-trait-coherence.rs
@@ -1,6 +1,3 @@
-//@ revisions: old next
-//@[next] compile-flags: -Znext-solver
-
 // Tests that type alias impls traits do not leak auto-traits for
 // the purposes of coherence checking
 #![feature(type_alias_impl_trait)]
@@ -22,8 +19,7 @@ impl<T: Send> AnotherTrait for T {}
 // (We treat opaque types as "foreign types" that could grow more impls
 // in the future.)
 impl AnotherTrait for D<OpaqueType> {
-    //[old]~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
-    //[next]~^^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>`
+    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>`
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/auto-trait-coherence.stderr b/tests/ui/impl-trait/auto-trait-coherence.stderr
new file mode 100644
index 0000000..e0f4c85
--- /dev/null
+++ b/tests/ui/impl-trait/auto-trait-coherence.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>`
+  --> $DIR/auto-trait-coherence.rs:21:1
+   |
+LL | impl<T: Send> AnotherTrait for T {}
+   | -------------------------------- first implementation here
+...
+LL | impl AnotherTrait for D<OpaqueType> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs
index df47208b..e8c1fcd 100644
--- a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs
+++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs
@@ -5,7 +5,7 @@
 struct Foo;
 
 impl Into<T> for Foo {
-//~^ ERROR conflicting implementations of trait `Into<T>` for type `Foo`
+//~^ ERROR conflicting implementations of trait `Into<_>` for type `Foo`
     fn into(self) -> T {
         Foo
     }
diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr
index faaad27..618bef1 100644
--- a/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr
+++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr
@@ -1,4 +1,4 @@
-error[E0119]: conflicting implementations of trait `Into<T>` for type `Foo`
+error[E0119]: conflicting implementations of trait `Into<_>` for type `Foo`
   --> $DIR/coherence-treats-tait-ambig.rs:7:1
    |
 LL | impl Into<T> for Foo {
diff --git a/tests/ui/impl-trait/negative-reasoning.rs b/tests/ui/impl-trait/negative-reasoning.rs
index 70e24a3..0474dc0 100644
--- a/tests/ui/impl-trait/negative-reasoning.rs
+++ b/tests/ui/impl-trait/negative-reasoning.rs
@@ -17,7 +17,7 @@ impl<T: std::fmt::Debug> AnotherTrait for T {}
 
 // This is in error, because we cannot assume that `OpaqueType: !Debug`
 impl AnotherTrait for D<OpaqueType> {
-    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>`
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/negative-reasoning.stderr b/tests/ui/impl-trait/negative-reasoning.stderr
index 3cb4be1..631784c 100644
--- a/tests/ui/impl-trait/negative-reasoning.stderr
+++ b/tests/ui/impl-trait/negative-reasoning.stderr
@@ -1,13 +1,11 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>`
   --> $DIR/negative-reasoning.rs:19:1
    |
 LL | impl<T: std::fmt::Debug> AnotherTrait for T {}
    | ------------------------------------------- first implementation here
 ...
 LL | impl AnotherTrait for D<OpaqueType> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
-   |
-   = note: upstream crates may add a new impl of trait `std::marker::FnPtr` for type `OpaqueType` in future versions
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024-but-fine.rs b/tests/ui/impl-trait/precise-capturing/overcaptures-2024-but-fine.rs
new file mode 100644
index 0000000..e30f785
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024-but-fine.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+
+#![deny(impl_trait_overcaptures)]
+
+struct Ctxt<'tcx>(&'tcx ());
+
+// In `compute`, we don't care that we're "overcapturing" `'tcx`
+// in edition 2024, because it can be shortened at the call site
+// and we know it outlives `'_`.
+
+impl<'tcx> Ctxt<'tcx> {
+    fn compute(&self) -> impl Sized + '_ {}
+}
+
+fn main() {}
diff --git a/tests/ui/impl-unused-tps.rs b/tests/ui/impl-unused-tps.rs
index 3eb9dae..a5836db 100644
--- a/tests/ui/impl-unused-tps.rs
+++ b/tests/ui/impl-unused-tps.rs
@@ -1,34 +1,35 @@
-//~ ERROR overflow evaluating the requirement `([isize; 0], _): Sized
-
 trait Foo<A> {
-    fn get(&self, A: &A) { }
+    fn get(&self, A: &A) {}
 }
 
 trait Bar {
     type Out;
 }
 
-impl<T> Foo<T> for [isize;0] {
+impl<T> Foo<T> for [isize; 0] {
     // OK, T is used in `Foo<T>`.
 }
 
-impl<T,U> Foo<T> for [isize;1] {
+impl<T, U> Foo<T> for [isize; 1] {
     //~^ ERROR the type parameter `U` is not constrained
 }
 
-impl<T,U> Foo<T> for [isize;2] where T : Bar<Out=U> {
+impl<T, U> Foo<T> for [isize; 2]
+where
+    T: Bar<Out = U>,
+{
     // OK, `U` is now constrained by the output type parameter.
 }
 
-impl<T:Bar<Out=U>,U> Foo<T> for [isize;3] {
+impl<T: Bar<Out = U>, U> Foo<T> for [isize; 3] {
     // OK, same as above but written differently.
 }
 
-impl<T,U> Foo<T> for U {
+impl<T, U> Foo<T> for U {
     //~^ ERROR conflicting implementations of trait `Foo<_>` for type `[isize; 0]`
 }
 
-impl<T,U> Bar for T {
+impl<T, U> Bar for T {
     //~^ ERROR the type parameter `U` is not constrained
 
     type Out = U;
@@ -36,28 +37,33 @@ impl<T,U> Bar for T {
     // Using `U` in an associated type within the impl is not good enough!
 }
 
-impl<T,U> Bar for T
-    where T : Bar<Out=U>
+impl<T, U> Bar for T
+where
+    T: Bar<Out = U>,
 {
-    //~^^^ ERROR the type parameter `U` is not constrained
-
+    //~^^^^ ERROR the type parameter `U` is not constrained by the impl trait, self type, or predicates
+    //~| ERROR conflicting implementations of trait `Bar`
     // This crafty self-referential attempt is still no good.
 }
 
-impl<T,U,V> Foo<T> for T
-    where (T,U): Bar<Out=V>
+impl<T, U, V> Foo<T> for T
+where
+    (T, U): Bar<Out = V>,
 {
-    //~^^^ ERROR the type parameter `U` is not constrained
-    //~|   ERROR the type parameter `V` is not constrained
+    //~^^^^ ERROR the type parameter `U` is not constrained
+    //~| ERROR the type parameter `V` is not constrained
+    //~| ERROR conflicting implementations of trait `Foo<[isize; 0]>` for type `[isize; 0]`
 
     // Here, `V` is bound by an output type parameter, but the inputs
     // are not themselves constrained.
 }
 
-impl<T,U,V> Foo<(T,U)> for T
-    where (T,U): Bar<Out=V>
+impl<T, U, V> Foo<(T, U)> for T
+where
+    (T, U): Bar<Out = V>,
 {
+    //~^^^^ ERROR conflicting implementations of trait `Foo<([isize; 0], _)>` for type `[isize; 0]`
     // As above, but both T and U ARE constrained.
 }
 
-fn main() { }
+fn main() {}
diff --git a/tests/ui/impl-unused-tps.stderr b/tests/ui/impl-unused-tps.stderr
index af427cb..da4589d 100644
--- a/tests/ui/impl-unused-tps.stderr
+++ b/tests/ui/impl-unused-tps.stderr
@@ -1,56 +1,76 @@
 error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]`
-  --> $DIR/impl-unused-tps.rs:27:1
+  --> $DIR/impl-unused-tps.rs:28:1
    |
-LL | impl<T> Foo<T> for [isize;0] {
-   | ---------------------------- first implementation here
+LL | impl<T> Foo<T> for [isize; 0] {
+   | ----------------------------- first implementation here
 ...
-LL | impl<T,U> Foo<T> for U {
-   | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]`
+LL | impl<T, U> Foo<T> for U {
+   | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]`
 
-error[E0275]: overflow evaluating the requirement `([isize; 0], _): Sized`
+error[E0119]: conflicting implementations of trait `Bar`
+  --> $DIR/impl-unused-tps.rs:40:1
    |
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`impl_unused_tps`)
-note: required for `([isize; 0], _)` to implement `Bar`
-  --> $DIR/impl-unused-tps.rs:31:11
+LL |   impl<T, U> Bar for T {
+   |   -------------------- first implementation here
+...
+LL | / impl<T, U> Bar for T
+LL | | where
+LL | |     T: Bar<Out = U>,
+   | |____________________^ conflicting implementation
+
+error[E0119]: conflicting implementations of trait `Foo<[isize; 0]>` for type `[isize; 0]`
+  --> $DIR/impl-unused-tps.rs:49:1
    |
-LL | impl<T,U> Bar for T {
-   |      -    ^^^     ^
-   |      |
-   |      unsatisfied trait bound introduced here
-   = note: 126 redundant requirements hidden
-   = note: required for `([isize; 0], _)` to implement `Bar`
+LL |   impl<T> Foo<T> for [isize; 0] {
+   |   ----------------------------- first implementation here
+...
+LL | / impl<T, U, V> Foo<T> for T
+LL | | where
+LL | |     (T, U): Bar<Out = V>,
+   | |_________________________^ conflicting implementation for `[isize; 0]`
+
+error[E0119]: conflicting implementations of trait `Foo<([isize; 0], _)>` for type `[isize; 0]`
+  --> $DIR/impl-unused-tps.rs:61:1
+   |
+LL |   impl<T> Foo<T> for [isize; 0] {
+   |   ----------------------------- first implementation here
+...
+LL | / impl<T, U, V> Foo<(T, U)> for T
+LL | | where
+LL | |     (T, U): Bar<Out = V>,
+   | |_________________________^ conflicting implementation for `[isize; 0]`
 
 error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/impl-unused-tps.rs:15:8
+  --> $DIR/impl-unused-tps.rs:13:9
    |
-LL | impl<T,U> Foo<T> for [isize;1] {
-   |        ^ unconstrained type parameter
+LL | impl<T, U> Foo<T> for [isize; 1] {
+   |         ^ unconstrained type parameter
 
 error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/impl-unused-tps.rs:31:8
+  --> $DIR/impl-unused-tps.rs:32:9
    |
-LL | impl<T,U> Bar for T {
-   |        ^ unconstrained type parameter
+LL | impl<T, U> Bar for T {
+   |         ^ unconstrained type parameter
 
 error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/impl-unused-tps.rs:39:8
+  --> $DIR/impl-unused-tps.rs:40:9
    |
-LL | impl<T,U> Bar for T
-   |        ^ unconstrained type parameter
+LL | impl<T, U> Bar for T
+   |         ^ unconstrained type parameter
 
 error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/impl-unused-tps.rs:47:8
+  --> $DIR/impl-unused-tps.rs:49:9
    |
-LL | impl<T,U,V> Foo<T> for T
-   |        ^ unconstrained type parameter
+LL | impl<T, U, V> Foo<T> for T
+   |         ^ unconstrained type parameter
 
 error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/impl-unused-tps.rs:47:10
+  --> $DIR/impl-unused-tps.rs:49:12
    |
-LL | impl<T,U,V> Foo<T> for T
-   |          ^ unconstrained type parameter
+LL | impl<T, U, V> Foo<T> for T
+   |            ^ unconstrained type parameter
 
-error: aborting due to 7 previous errors
+error: aborting due to 9 previous errors
 
-Some errors have detailed explanations: E0119, E0207, E0275.
+Some errors have detailed explanations: E0119, E0207.
 For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs
new file mode 100644
index 0000000..ca8b8b7
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs
@@ -0,0 +1,13 @@
+//@ check-pass
+//@ known-bug: #25860
+
+static UNIT: &'static &'static () = &&();
+
+fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T, _: &()) -> &'a T { v }
+
+fn bad<'a, T>(x: &'a T) -> &'static T {
+    let f: fn(_, &'a T, &()) -> &'static T = foo;
+    f(UNIT, x, &())
+}
+
+fn main() {}
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs
new file mode 100644
index 0000000..226a6fa
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs
@@ -0,0 +1,13 @@
+// Regression test for #129021.
+
+static UNIT: &'static &'static () = &&();
+
+fn foo<'a: 'a, 'b: 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v }
+
+fn bad<'a, T>(x: &'a T) -> &'static T {
+    let f: fn(_, &'a T) -> &'static T = foo;
+    //~^ ERROR lifetime may not live long enough
+    f(UNIT, x)
+}
+
+fn main() {}
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr
new file mode 100644
index 0000000..84d2a6d
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/implied-bounds-on-nested-references-plus-variance-early-bound.rs:8:12
+   |
+LL | fn bad<'a, T>(x: &'a T) -> &'static T {
+   |        -- lifetime `'a` defined here
+LL |     let f: fn(_, &'a T) -> &'static T = foo;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs
new file mode 100644
index 0000000..f306899
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs
@@ -0,0 +1,19 @@
+// Regression test for #129021.
+
+trait ToArg<T> {
+    type Arg;
+}
+impl<T, U> ToArg<T> for U {
+    type Arg = T;
+}
+
+fn extend_inner<'a, 'b>(x: &'a str) -> <&'b &'a () as ToArg<&'b str>>::Arg { x }
+fn extend<'a, 'b>(x: &'a str) -> &'b str {
+    (extend_inner as fn(_) -> _)(x)
+    //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+    let y = extend(&String::from("Hello World"));
+    println!("{}", y);
+}
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr
new file mode 100644
index 0000000..4cdb959
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+  --> $DIR/implied-bounds-on-nested-references-plus-variance-unnormalized.rs:12:5
+   |
+LL | fn extend<'a, 'b>(x: &'a str) -> &'b str {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+LL |     (extend_inner as fn(_) -> _)(x)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs
index f3401f3..6de81cb 100644
--- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs
@@ -1,8 +1,4 @@
-//@ check-pass
-//@ known-bug: #25860
-
-// Should fail. The combination of variance and implied bounds for nested
-// references allows us to infer a longer lifetime than we can prove.
+// Regression test for #129021.
 
 static UNIT: &'static &'static () = &&();
 
@@ -10,6 +6,7 @@ fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v }
 
 fn bad<'a, T>(x: &'a T) -> &'static T {
     let f: fn(_, &'a T) -> &'static T = foo;
+    //~^ ERROR lifetime may not live long enough
     f(UNIT, x)
 }
 
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr
new file mode 100644
index 0000000..c96fa92
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/implied-bounds-on-nested-references-plus-variance.rs:8:12
+   |
+LL | fn bad<'a, T>(x: &'a T) -> &'static T {
+   |        -- lifetime `'a` defined here
+LL |     let f: fn(_, &'a T) -> &'static T = foo;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/issues/issue-48728.rs b/tests/ui/issues/issue-48728.rs
index 7ef05f4..8ad9289 100644
--- a/tests/ui/issues/issue-48728.rs
+++ b/tests/ui/issues/issue-48728.rs
@@ -1,12 +1,8 @@
 // Regression test for #48728, an ICE that occurred computing
 // coherence "help" information.
 
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
-//@[next] check-pass
-
-#[derive(Clone)] //[current]~ ERROR conflicting implementations of trait `Clone`
+//@ check-pass
+#[derive(Clone)]
 struct Node<T: ?Sized>(Box<T>);
 
 impl<T: Clone + ?Sized> Clone for Node<[T]> {
diff --git a/tests/ui/lexer/prefixed-lifetime.rs b/tests/ui/lexer/prefixed-lifetime.rs
new file mode 100644
index 0000000..6191b97
--- /dev/null
+++ b/tests/ui/lexer/prefixed-lifetime.rs
@@ -0,0 +1,10 @@
+//@ edition: 2021
+
+macro_rules! w {
+    ($($tt:tt)*) => {};
+}
+
+w!('foo#lifetime);
+//~^ ERROR prefix `'foo` is unknown
+
+fn main() {}
diff --git a/tests/ui/lexer/prefixed-lifetime.stderr b/tests/ui/lexer/prefixed-lifetime.stderr
new file mode 100644
index 0000000..39e8b5a
--- /dev/null
+++ b/tests/ui/lexer/prefixed-lifetime.stderr
@@ -0,0 +1,14 @@
+error: prefix `'foo` is unknown
+  --> $DIR/prefixed-lifetime.rs:7:4
+   |
+LL | w!('foo#lifetime);
+   |    ^^^^ unknown prefix
+   |
+   = note: prefixed identifiers and literals are reserved since Rust 2021
+help: consider inserting whitespace here
+   |
+LL | w!('foo #lifetime);
+   |        +
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lifetimes/raw/gen-lt.e2024.stderr b/tests/ui/lifetimes/raw/gen-lt.e2024.stderr
new file mode 100644
index 0000000..232453d
--- /dev/null
+++ b/tests/ui/lifetimes/raw/gen-lt.e2024.stderr
@@ -0,0 +1,8 @@
+error: lifetimes cannot use keyword names
+  --> $DIR/gen-lt.rs:11:11
+   |
+LL | fn gen_lt<'gen>() {}
+   |           ^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lifetimes/raw/gen-lt.rs b/tests/ui/lifetimes/raw/gen-lt.rs
new file mode 100644
index 0000000..4f3ede5
--- /dev/null
+++ b/tests/ui/lifetimes/raw/gen-lt.rs
@@ -0,0 +1,14 @@
+//@ revisions: e2021 e2024
+
+//@[e2021] edition:2021
+//@[e2024] edition:2024
+//@[e2024] compile-flags: -Zunstable-options
+
+//@[e2021] check-pass
+
+fn raw_gen_lt<'r#gen>() {}
+
+fn gen_lt<'gen>() {}
+//[e2024]~^ ERROR lifetimes cannot use keyword names
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/lifetimes-eq.rs b/tests/ui/lifetimes/raw/lifetimes-eq.rs
new file mode 100644
index 0000000..dddafb8
--- /dev/null
+++ b/tests/ui/lifetimes/raw/lifetimes-eq.rs
@@ -0,0 +1,8 @@
+//@ edition: 2021
+//@ check-pass
+
+// Test that `'r#a` is `'a`.
+
+fn test<'r#a>(x: &'a ()) {}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/macro-lt.rs b/tests/ui/lifetimes/raw/macro-lt.rs
new file mode 100644
index 0000000..d1167b0
--- /dev/null
+++ b/tests/ui/lifetimes/raw/macro-lt.rs
@@ -0,0 +1,12 @@
+//@ check-pass
+//@ edition: 2021
+
+macro_rules! lifetime {
+    ($lt:lifetime) => {
+        fn hello<$lt>() {}
+    }
+}
+
+lifetime!('r#struct);
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/multiple-prefixes.rs b/tests/ui/lifetimes/raw/multiple-prefixes.rs
new file mode 100644
index 0000000..f335373
--- /dev/null
+++ b/tests/ui/lifetimes/raw/multiple-prefixes.rs
@@ -0,0 +1,6 @@
+//@ edition: 2021
+
+fn test(x: &'r#r#r ()) {}
+//~^ ERROR expected type, found `#`
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/multiple-prefixes.stderr b/tests/ui/lifetimes/raw/multiple-prefixes.stderr
new file mode 100644
index 0000000..8d5479e
--- /dev/null
+++ b/tests/ui/lifetimes/raw/multiple-prefixes.stderr
@@ -0,0 +1,8 @@
+error: expected type, found `#`
+  --> $DIR/multiple-prefixes.rs:3:17
+   |
+LL | fn test(x: &'r#r#r ()) {}
+   |                 ^ expected type
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lifetimes/raw/prim-lt.rs b/tests/ui/lifetimes/raw/prim-lt.rs
new file mode 100644
index 0000000..ca45efb
--- /dev/null
+++ b/tests/ui/lifetimes/raw/prim-lt.rs
@@ -0,0 +1,8 @@
+//@ check-pass
+//@ edition: 2021
+
+// Checks a primitive name can be defined as a lifetime.
+
+fn foo<'r#i32>() {}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/simple.rs b/tests/ui/lifetimes/raw/simple.rs
new file mode 100644
index 0000000..6f70a27
--- /dev/null
+++ b/tests/ui/lifetimes/raw/simple.rs
@@ -0,0 +1,21 @@
+//@ check-pass
+//@ edition: 2021
+
+fn foo<'r#struct>() {}
+
+fn hr<T>() where for<'r#struct> T: Into<&'r#struct ()> {}
+
+trait Foo<'r#struct> {}
+
+trait Bar<'r#struct> {
+    fn method(&'r#struct self) {}
+    fn method2(self: &'r#struct Self) {}
+}
+
+fn labeled() {
+    'r#struct: loop {
+        break 'r#struct;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/static-lt.rs b/tests/ui/lifetimes/raw/static-lt.rs
new file mode 100644
index 0000000..1fec709
--- /dev/null
+++ b/tests/ui/lifetimes/raw/static-lt.rs
@@ -0,0 +1,8 @@
+//@ check-pass
+//@ edition: 2021
+
+// Makes sure that `'r#static` is `'static`
+
+const FOO: &'r#static str = "hello, world";
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/three-tokens.rs b/tests/ui/lifetimes/raw/three-tokens.rs
new file mode 100644
index 0000000..2ae54eb
--- /dev/null
+++ b/tests/ui/lifetimes/raw/three-tokens.rs
@@ -0,0 +1,12 @@
+//@ edition: 2015
+//@ check-pass
+// Ensure that we parse `'r#lt` as three tokens in edition 2015.
+
+macro_rules! ed2015 {
+    ('r # lt) => {};
+    ($lt:lifetime) => { compile_error!() };
+}
+
+ed2015!('r#lt);
+
+fn main() {}
diff --git a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr
index 8c5426a..2d8c6e9 100644
--- a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr
+++ b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr
@@ -9,6 +9,10 @@
    |
 LL | #![deny(elided_named_lifetimes)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
+help: consider specifying it explicitly
+   |
+LL |     pub fn get_mut(&'static self, x: &mut u8) -> &'static mut u8 {
+   |                                                   +++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr
index c465aab..3c01375 100644
--- a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr
+++ b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr
@@ -9,6 +9,10 @@
    |
 LL | #[warn(elided_named_lifetimes)]
    |        ^^^^^^^^^^^^^^^^^^^^^^
+help: consider specifying it explicitly
+   |
+LL |     fn bar(x: &'static u8) -> &'static u8 {
+   |                                +++++++
 
 error: elided lifetime has a name
   --> $DIR/not-tied-to-crate.rs:11:31
@@ -21,6 +25,10 @@
    |
 LL |     #[deny(elided_named_lifetimes)]
    |            ^^^^^^^^^^^^^^^^^^^^^^
+help: consider specifying it explicitly
+   |
+LL |     fn baz(x: &'static u8) -> &'static u8 {
+   |                                +++++++
 
 error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/lint/elided-named-lifetimes/static.stderr b/tests/ui/lint/elided-named-lifetimes/static.stderr
index d2e9776..fa2a2d3 100644
--- a/tests/ui/lint/elided-named-lifetimes/static.stderr
+++ b/tests/ui/lint/elided-named-lifetimes/static.stderr
@@ -9,24 +9,43 @@
    |
 LL | #![deny(elided_named_lifetimes)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
+help: consider specifying it explicitly
+   |
+LL | fn ampersand(x: &'static u8) -> &'static u8 {
+   |                                  +++++++
 
 error: elided lifetime has a name
   --> $DIR/static.rs:23:32
    |
 LL | fn brackets(x: &'static u8) -> Brackets {
    |                                ^^^^^^^^ this elided lifetime gets resolved as `'static`
+   |
+help: consider specifying it explicitly
+   |
+LL | fn brackets(x: &'static u8) -> Brackets<'static> {
+   |                                        +++++++++
 
 error: elided lifetime has a name
   --> $DIR/static.rs:30:34
    |
 LL | fn comma(x: &'static u8) -> Comma<u8> {
    |                                  ^ this elided lifetime gets resolved as `'static`
+   |
+help: consider specifying it explicitly
+   |
+LL | fn comma(x: &'static u8) -> Comma<'static, u8> {
+   |                                   ++++++++
 
 error: elided lifetime has a name
   --> $DIR/static.rs:35:35
    |
 LL | fn underscore(x: &'static u8) -> &'_ u8 {
    |                                   ^^ this elided lifetime gets resolved as `'static`
+   |
+help: consider specifying it explicitly
+   |
+LL | fn underscore(x: &'static u8) -> &'static u8 {
+   |                                   ~~~~~~~
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/parser/extern-crate-unexpected-token.stderr b/tests/ui/parser/extern-crate-unexpected-token.stderr
index f83bb3e..951b027 100644
--- a/tests/ui/parser/extern-crate-unexpected-token.stderr
+++ b/tests/ui/parser/extern-crate-unexpected-token.stderr
@@ -3,6 +3,11 @@
    |
 LL | extern crte foo;
    |        ^^^^ expected one of `crate` or `{`
+   |
+help: there is a keyword `crate` with a similar name
+   |
+LL | extern crate foo;
+   |        ~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr
index 79c574e..00f372b 100644
--- a/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr
+++ b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr
@@ -8,10 +8,16 @@
   --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:4:17
    |
 LL |     fn foo(&mur Self) {}
-   |            -----^^^^
-   |            |    |
-   |            |    expected one of `:`, `@`, or `|`
-   |            help: declare the type after the parameter binding: `<identifier>: <type>`
+   |                 ^^^^ expected one of `:`, `@`, or `|`
+   |
+help: there is a keyword `mut` with a similar name
+   |
+LL |     fn foo(&mut Self) {}
+   |             ~~~
+help: declare the type after the parameter binding
+   |
+LL |     fn foo(<identifier>: <type>) {}
+   |            ~~~~~~~~~~~~~~~~~~~~
 
 error: unexpected lifetime `'static` in pattern
   --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:13
@@ -35,16 +41,27 @@
   --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:25
    |
 LL |     fn bar(&'static mur Self) {}
-   |            -------------^^^^
-   |            |            |
-   |            |            expected one of `:`, `@`, or `|`
-   |            help: declare the type after the parameter binding: `<identifier>: <type>`
+   |                         ^^^^ expected one of `:`, `@`, or `|`
+   |
+help: there is a keyword `mut` with a similar name
+   |
+LL |     fn bar(&'static mut Self) {}
+   |                     ~~~
+help: declare the type after the parameter binding
+   |
+LL |     fn bar(<identifier>: <type>) {}
+   |            ~~~~~~~~~~~~~~~~~~~~
 
 error: expected one of `:`, `@`, or `|`, found keyword `Self`
   --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:14:17
    |
 LL |     fn baz(&mur Self @ _) {}
    |                 ^^^^ expected one of `:`, `@`, or `|`
+   |
+help: there is a keyword `mut` with a similar name
+   |
+LL |     fn baz(&mut Self @ _) {}
+   |             ~~~
 
 error[E0533]: expected unit struct, found self constructor `Self`
   --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:4:17
diff --git a/tests/ui/parser/misspelled-keywords/assoc-type.rs b/tests/ui/parser/misspelled-keywords/assoc-type.rs
new file mode 100644
index 0000000..a6b694a
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/assoc-type.rs
@@ -0,0 +1,6 @@
+trait Animal {
+    Type Result = u8;
+    //~^ ERROR expected one of
+}
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/assoc-type.stderr b/tests/ui/parser/misspelled-keywords/assoc-type.stderr
new file mode 100644
index 0000000..677da53
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/assoc-type.stderr
@@ -0,0 +1,18 @@
+error: expected one of `!` or `::`, found `Result`
+  --> $DIR/assoc-type.rs:2:10
+   |
+LL | trait Animal {
+   |              - while parsing this item list starting here
+LL |     Type Result = u8;
+   |          ^^^^^^ expected one of `!` or `::`
+LL |
+LL | }
+   | - the item list ends here
+   |
+help: write keyword `type` in lowercase
+   |
+LL |     type Result = u8;
+   |     ~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/async-move.rs b/tests/ui/parser/misspelled-keywords/async-move.rs
new file mode 100644
index 0000000..702a905e
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/async-move.rs
@@ -0,0 +1,6 @@
+//@ edition: 2018
+
+fn main() {
+    async Move {}
+    //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/async-move.stderr b/tests/ui/parser/misspelled-keywords/async-move.stderr
new file mode 100644
index 0000000..4be4b56
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/async-move.stderr
@@ -0,0 +1,13 @@
+error: expected one of `move`, `|`, or `||`, found `Move`
+  --> $DIR/async-move.rs:4:11
+   |
+LL |     async Move {}
+   |           ^^^^ expected one of `move`, `|`, or `||`
+   |
+help: write keyword `move` in lowercase
+   |
+LL |     async move {}
+   |           ~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/const-fn.rs b/tests/ui/parser/misspelled-keywords/const-fn.rs
new file mode 100644
index 0000000..c4174b6
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/const-fn.rs
@@ -0,0 +1,5 @@
+cnst fn code() {}
+//~^ ERROR expected one of
+
+fn main() {
+}
diff --git a/tests/ui/parser/misspelled-keywords/const-fn.stderr b/tests/ui/parser/misspelled-keywords/const-fn.stderr
new file mode 100644
index 0000000..5646b26
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/const-fn.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found keyword `fn`
+  --> $DIR/const-fn.rs:1:6
+   |
+LL | cnst fn code() {}
+   |      ^^ expected one of `!` or `::`
+   |
+help: there is a keyword `const` with a similar name
+   |
+LL | const fn code() {}
+   | ~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/const-generics.rs b/tests/ui/parser/misspelled-keywords/const-generics.rs
new file mode 100644
index 0000000..2df64a8
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/const-generics.rs
@@ -0,0 +1,4 @@
+fn foo<consta N: usize>(_arr: [i32; N]) {}
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/const-generics.stderr b/tests/ui/parser/misspelled-keywords/const-generics.stderr
new file mode 100644
index 0000000..fd59999
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/const-generics.stderr
@@ -0,0 +1,13 @@
+error: expected one of `,`, `:`, `=`, or `>`, found `N`
+  --> $DIR/const-generics.rs:1:15
+   |
+LL | fn foo<consta N: usize>(_arr: [i32; N]) {}
+   |               ^ expected one of `,`, `:`, `=`, or `>`
+   |
+help: there is a keyword `const` with a similar name
+   |
+LL | fn foo<const N: usize>(_arr: [i32; N]) {}
+   |        ~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/const.rs b/tests/ui/parser/misspelled-keywords/const.rs
new file mode 100644
index 0000000..b481408
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/const.rs
@@ -0,0 +1,4 @@
+cons A: u8 = 10;
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/const.stderr b/tests/ui/parser/misspelled-keywords/const.stderr
new file mode 100644
index 0000000..35e4d73
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/const.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found `A`
+  --> $DIR/const.rs:1:6
+   |
+LL | cons A: u8 = 10;
+   |      ^ expected one of `!` or `::`
+   |
+help: there is a keyword `const` with a similar name
+   |
+LL | const A: u8 = 10;
+   | ~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/for-loop.rs b/tests/ui/parser/misspelled-keywords/for-loop.rs
new file mode 100644
index 0000000..6aba581
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/for-loop.rs
@@ -0,0 +1,4 @@
+fn main() {
+    form i in 1..10 {}
+    //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/for-loop.stderr b/tests/ui/parser/misspelled-keywords/for-loop.stderr
new file mode 100644
index 0000000..d2236ab
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/for-loop.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `i`
+  --> $DIR/for-loop.rs:2:10
+   |
+LL |     form i in 1..10 {}
+   |          ^ expected one of 8 possible tokens
+   |
+help: there is a keyword `for` with a similar name
+   |
+LL |     for i in 1..10 {}
+   |     ~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/hrdt.rs b/tests/ui/parser/misspelled-keywords/hrdt.rs
new file mode 100644
index 0000000..9ca9e1b
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/hrdt.rs
@@ -0,0 +1,16 @@
+struct Closure<F> {
+    data: (u8, u16),
+    func: F,
+}
+
+impl<F> Closure<F>
+    Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
+//~^ ERROR expected one of
+{
+    fn call(&self) -> &u8 {
+        (self.func)(&self.data)
+    }
+}
+
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/hrdt.stderr b/tests/ui/parser/misspelled-keywords/hrdt.stderr
new file mode 100644
index 0000000..5393a73
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/hrdt.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found keyword `for`
+  --> $DIR/hrdt.rs:7:11
+   |
+LL |     Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
+   |           ^^^ expected one of 7 possible tokens
+   |
+help: write keyword `where` in lowercase (notice the capitalization difference)
+   |
+LL |     where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
+   |     ~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/impl-block.rs b/tests/ui/parser/misspelled-keywords/impl-block.rs
new file mode 100644
index 0000000..dc2570c
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-block.rs
@@ -0,0 +1,6 @@
+struct Human;
+
+ipml Human {}
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/impl-block.stderr b/tests/ui/parser/misspelled-keywords/impl-block.stderr
new file mode 100644
index 0000000..d86ae32
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-block.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found `Human`
+  --> $DIR/impl-block.rs:3:6
+   |
+LL | ipml Human {}
+   |      ^^^^^ expected one of `!` or `::`
+   |
+help: there is a keyword `impl` with a similar name
+   |
+LL | impl Human {}
+   | ~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/impl-return.rs b/tests/ui/parser/misspelled-keywords/impl-return.rs
new file mode 100644
index 0000000..c9d1973
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-return.rs
@@ -0,0 +1,4 @@
+fn code() -> Impl Display {}
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/impl-return.stderr b/tests/ui/parser/misspelled-keywords/impl-return.stderr
new file mode 100644
index 0000000..883f5ce
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-return.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `Display`
+  --> $DIR/impl-return.rs:1:19
+   |
+LL | fn code() -> Impl Display {}
+   |                   ^^^^^^^ expected one of 7 possible tokens
+   |
+help: write keyword `impl` in lowercase (notice the capitalization difference)
+   |
+LL | fn code() -> impl Display {}
+   |              ~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/impl-trait-for.rs b/tests/ui/parser/misspelled-keywords/impl-trait-for.rs
new file mode 100644
index 0000000..c6f3fcd
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-trait-for.rs
@@ -0,0 +1,6 @@
+struct Human;
+
+impl Debug form Human {}
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr b/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr
new file mode 100644
index 0000000..8dd5a46
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `Human`
+  --> $DIR/impl-trait-for.rs:3:17
+   |
+LL | impl Debug form Human {}
+   |                 ^^^^^ expected one of 7 possible tokens
+   |
+help: there is a keyword `for` with a similar name
+   |
+LL | impl Debug for Human {}
+   |            ~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/impl-trait.rs b/tests/ui/parser/misspelled-keywords/impl-trait.rs
new file mode 100644
index 0000000..99380b8
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-trait.rs
@@ -0,0 +1,4 @@
+fn code<T: impll Debug>() -> u8 {}
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/impl-trait.stderr b/tests/ui/parser/misspelled-keywords/impl-trait.stderr
new file mode 100644
index 0000000..15a8f99
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-trait.stderr
@@ -0,0 +1,17 @@
+error: expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`, found `Debug`
+  --> $DIR/impl-trait.rs:1:18
+   |
+LL | fn code<T: impll Debug>() -> u8 {}
+   |                  ^^^^^ expected one of 7 possible tokens
+   |
+help: there is a keyword `impl` with a similar name
+   |
+LL | fn code<T: impl Debug>() -> u8 {}
+   |            ~~~~
+help: you might have meant to end the type parameters here
+   |
+LL | fn code<T: impll> Debug>() -> u8 {}
+   |                 +
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/let-else.rs b/tests/ui/parser/misspelled-keywords/let-else.rs
new file mode 100644
index 0000000..0d5a03e
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/let-else.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let Some(a) = Some(10) elze {}
+    //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/let-else.stderr b/tests/ui/parser/misspelled-keywords/let-else.stderr
new file mode 100644
index 0000000..6f41a0d
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/let-else.stderr
@@ -0,0 +1,13 @@
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found `elze`
+  --> $DIR/let-else.rs:2:28
+   |
+LL |     let Some(a) = Some(10) elze {}
+   |                            ^^^^ expected one of `.`, `;`, `?`, `else`, or an operator
+   |
+help: there is a keyword `else` with a similar name
+   |
+LL |     let Some(a) = Some(10) else {}
+   |                            ~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/let-mut.rs b/tests/ui/parser/misspelled-keywords/let-mut.rs
new file mode 100644
index 0000000..83228fe
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/let-mut.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let muta a = 10;
+    //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/let-mut.stderr b/tests/ui/parser/misspelled-keywords/let-mut.stderr
new file mode 100644
index 0000000..766d2a0
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/let-mut.stderr
@@ -0,0 +1,13 @@
+error: expected one of `:`, `;`, `=`, `@`, or `|`, found `a`
+  --> $DIR/let-mut.rs:2:14
+   |
+LL |     let muta a = 10;
+   |              ^ expected one of `:`, `;`, `=`, `@`, or `|`
+   |
+help: there is a keyword `mut` with a similar name
+   |
+LL |     let mut a = 10;
+   |         ~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/let.rs b/tests/ui/parser/misspelled-keywords/let.rs
new file mode 100644
index 0000000..461c3e5
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/let.rs
@@ -0,0 +1,9 @@
+fn main() {
+    Let a = 10;
+    //~^ ERROR expected one of
+}
+
+fn code() {
+    lett a = 10;
+    //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/let.stderr b/tests/ui/parser/misspelled-keywords/let.stderr
new file mode 100644
index 0000000..c2dcdef
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/let.stderr
@@ -0,0 +1,24 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a`
+  --> $DIR/let.rs:2:9
+   |
+LL |     Let a = 10;
+   |         ^ expected one of 8 possible tokens
+   |
+help: write keyword `let` in lowercase
+   |
+LL |     let a = 10;
+   |     ~~~
+
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a`
+  --> $DIR/let.rs:7:10
+   |
+LL |     lett a = 10;
+   |          ^ expected one of 8 possible tokens
+   |
+help: there is a keyword `let` with a similar name
+   |
+LL |     let a = 10;
+   |     ~~~
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/misspelled-keywords/match.rs b/tests/ui/parser/misspelled-keywords/match.rs
new file mode 100644
index 0000000..a31840a
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/match.rs
@@ -0,0 +1,5 @@
+fn main() {
+    let a = 10;
+    matche a {}
+    //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/match.stderr b/tests/ui/parser/misspelled-keywords/match.stderr
new file mode 100644
index 0000000..90780eb
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/match.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a`
+  --> $DIR/match.rs:3:12
+   |
+LL |     matche a {}
+   |            ^ expected one of 8 possible tokens
+   |
+help: there is a keyword `match` with a similar name
+   |
+LL |     match a {}
+   |     ~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/mod.rs b/tests/ui/parser/misspelled-keywords/mod.rs
new file mode 100644
index 0000000..24f0101
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/mod.rs
@@ -0,0 +1,4 @@
+mode parser;
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/mod.stderr b/tests/ui/parser/misspelled-keywords/mod.stderr
new file mode 100644
index 0000000..6daeb4e
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/mod.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found `parser`
+  --> $DIR/mod.rs:1:6
+   |
+LL | mode parser;
+   |      ^^^^^^ expected one of `!` or `::`
+   |
+help: there is a keyword `mod` with a similar name
+   |
+LL | mod parser;
+   | ~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/pub-fn.rs b/tests/ui/parser/misspelled-keywords/pub-fn.rs
new file mode 100644
index 0000000..50d7129
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/pub-fn.rs
@@ -0,0 +1,5 @@
+puB fn code() {}
+//~^ ERROR expected one of
+
+fn main() {
+}
diff --git a/tests/ui/parser/misspelled-keywords/pub-fn.stderr b/tests/ui/parser/misspelled-keywords/pub-fn.stderr
new file mode 100644
index 0000000..82ca710
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/pub-fn.stderr
@@ -0,0 +1,13 @@
+error: expected one of `#`, `async`, `auto`, `const`, `default`, `enum`, `extern`, `fn`, `gen`, `impl`, `macro_rules`, `macro`, `mod`, `pub`, `safe`, `static`, `struct`, `trait`, `type`, `unsafe`, or `use`, found `puB`
+  --> $DIR/pub-fn.rs:1:1
+   |
+LL | puB fn code() {}
+   | ^^^ expected one of 21 possible tokens
+   |
+help: write keyword `pub` in lowercase
+   |
+LL | pub fn code() {}
+   | ~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/ref.rs b/tests/ui/parser/misspelled-keywords/ref.rs
new file mode 100644
index 0000000..76b367a
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/ref.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let a = Some(vec![1, 2]);
+    match a {
+        Some(refe list) => println!("{list:?}"),
+        //~^ ERROR expected one of
+        //~| ERROR this pattern has 2 fields,
+        _ => println!("none"),
+    }
+}
diff --git a/tests/ui/parser/misspelled-keywords/ref.stderr b/tests/ui/parser/misspelled-keywords/ref.stderr
new file mode 100644
index 0000000..3a79b7b
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/ref.stderr
@@ -0,0 +1,27 @@
+error: expected one of `)`, `,`, `@`, or `|`, found `list`
+  --> $DIR/ref.rs:4:19
+   |
+LL |         Some(refe list) => println!("{list:?}"),
+   |                   ^^^^ expected one of `)`, `,`, `@`, or `|`
+   |
+help: there is a keyword `ref` with a similar name
+   |
+LL |         Some(ref list) => println!("{list:?}"),
+   |              ~~~
+help: missing `,`
+   |
+LL |         Some(refe, list) => println!("{list:?}"),
+   |                  +
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field
+  --> $DIR/ref.rs:4:14
+   |
+LL |         Some(refe list) => println!("{list:?}"),
+   |              ^^^^ ^^^^ expected 1 field, found 2
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: tuple variant has 1 field
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0023`.
diff --git a/tests/ui/parser/misspelled-keywords/return.rs b/tests/ui/parser/misspelled-keywords/return.rs
new file mode 100644
index 0000000..4bbe55d
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/return.rs
@@ -0,0 +1,7 @@
+fn code() -> u8 {
+    let a = 10;
+    returnn a;
+    //~^ ERROR expected one of
+}
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/return.stderr b/tests/ui/parser/misspelled-keywords/return.stderr
new file mode 100644
index 0000000..efa45f3
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/return.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a`
+  --> $DIR/return.rs:3:13
+   |
+LL |     returnn a;
+   |             ^ expected one of 8 possible tokens
+   |
+help: there is a keyword `return` with a similar name
+   |
+LL |     return a;
+   |     ~~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/static-mut.rs b/tests/ui/parser/misspelled-keywords/static-mut.rs
new file mode 100644
index 0000000..6509f62
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/static-mut.rs
@@ -0,0 +1,5 @@
+static muta a: u8 = 0;
+//~^ ERROR expected one of
+//~| ERROR missing type for
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/static-mut.stderr b/tests/ui/parser/misspelled-keywords/static-mut.stderr
new file mode 100644
index 0000000..3c25af5
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/static-mut.stderr
@@ -0,0 +1,24 @@
+error: expected one of `:`, `;`, or `=`, found `a`
+  --> $DIR/static-mut.rs:1:13
+   |
+LL | static muta a: u8 = 0;
+   |             ^ expected one of `:`, `;`, or `=`
+   |
+help: there is a keyword `mut` with a similar name
+   |
+LL | static mut a: u8 = 0;
+   |        ~~~
+
+error: missing type for `static` item
+  --> $DIR/static-mut.rs:1:12
+   |
+LL | static muta a: u8 = 0;
+   |            ^
+   |
+help: provide a type for the item
+   |
+LL | static muta: <type> a: u8 = 0;
+   |            ++++++++
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/misspelled-keywords/static.rs b/tests/ui/parser/misspelled-keywords/static.rs
new file mode 100644
index 0000000..240f4f5
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/static.rs
@@ -0,0 +1,4 @@
+Static a = 0;
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/static.stderr b/tests/ui/parser/misspelled-keywords/static.stderr
new file mode 100644
index 0000000..003aa39
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/static.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found `a`
+  --> $DIR/static.rs:1:8
+   |
+LL | Static a = 0;
+   |        ^ expected one of `!` or `::`
+   |
+help: write keyword `static` in lowercase (notice the capitalization difference)
+   |
+LL | static a = 0;
+   | ~~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/struct.rs b/tests/ui/parser/misspelled-keywords/struct.rs
new file mode 100644
index 0000000..0f64dec
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/struct.rs
@@ -0,0 +1,4 @@
+Struct Foor {
+//~^ ERROR expected one of
+    hello: String,
+}
diff --git a/tests/ui/parser/misspelled-keywords/struct.stderr b/tests/ui/parser/misspelled-keywords/struct.stderr
new file mode 100644
index 0000000..559182f
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/struct.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found `Foor`
+  --> $DIR/struct.rs:1:8
+   |
+LL | Struct Foor {
+   |        ^^^^ expected one of `!` or `::`
+   |
+help: write keyword `struct` in lowercase (notice the capitalization difference)
+   |
+LL | struct Foor {
+   | ~~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/unsafe-fn.rs b/tests/ui/parser/misspelled-keywords/unsafe-fn.rs
new file mode 100644
index 0000000..49a1322
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/unsafe-fn.rs
@@ -0,0 +1,4 @@
+unsafee fn code() {}
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr b/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr
new file mode 100644
index 0000000..b13281b
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found keyword `fn`
+  --> $DIR/unsafe-fn.rs:1:9
+   |
+LL | unsafee fn code() {}
+   |         ^^ expected one of `!` or `::`
+   |
+help: there is a keyword `unsafe` with a similar name
+   |
+LL | unsafe fn code() {}
+   | ~~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/use.rs b/tests/ui/parser/misspelled-keywords/use.rs
new file mode 100644
index 0000000..f491165
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/use.rs
@@ -0,0 +1,4 @@
+usee a::b;
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/use.stderr b/tests/ui/parser/misspelled-keywords/use.stderr
new file mode 100644
index 0000000..db6dffd
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/use.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found `a`
+  --> $DIR/use.rs:1:6
+   |
+LL | usee a::b;
+   |      ^ expected one of `!` or `::`
+   |
+help: there is a keyword `use` with a similar name
+   |
+LL | use a::b;
+   | ~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/where-clause.rs b/tests/ui/parser/misspelled-keywords/where-clause.rs
new file mode 100644
index 0000000..c03d04d
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/where-clause.rs
@@ -0,0 +1,8 @@
+fn code<T>() -> u8
+wheree
+//~^ ERROR expected one of
+    T: Debug,
+{
+}
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/where-clause.stderr b/tests/ui/parser/misspelled-keywords/where-clause.stderr
new file mode 100644
index 0000000..5143c30
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/where-clause.stderr
@@ -0,0 +1,15 @@
+error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `wheree`
+  --> $DIR/where-clause.rs:2:1
+   |
+LL | fn code<T>() -> u8
+   |                   - expected one of 7 possible tokens
+LL | wheree
+   | ^^^^^^ unexpected token
+   |
+help: there is a keyword `where` with a similar name
+   |
+LL | where
+   |
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/while-loop.rs b/tests/ui/parser/misspelled-keywords/while-loop.rs
new file mode 100644
index 0000000..37d337f
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/while-loop.rs
@@ -0,0 +1,5 @@
+fn main() {
+    whilee a < b {
+    //~^ ERROR expected one of
+    }
+}
diff --git a/tests/ui/parser/misspelled-keywords/while-loop.stderr b/tests/ui/parser/misspelled-keywords/while-loop.stderr
new file mode 100644
index 0000000..7d15044
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/while-loop.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a`
+  --> $DIR/while-loop.rs:2:12
+   |
+LL |     whilee a < b {
+   |            ^ expected one of 8 possible tokens
+   |
+help: there is a keyword `while` with a similar name
+   |
+LL |     while a < b {
+   |     ~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/while-without-identifiers.rs b/tests/ui/parser/misspelled-keywords/while-without-identifiers.rs
new file mode 100644
index 0000000..203db83
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/while-without-identifiers.rs
@@ -0,0 +1,4 @@
+fn main() {
+    whilee 2 > 1 {}
+    //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr b/tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr
new file mode 100644
index 0000000..121e393
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `2`
+  --> $DIR/while-without-identifiers.rs:2:12
+   |
+LL |     whilee 2 > 1 {}
+   |            ^ expected one of 8 possible tokens
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.rs b/tests/ui/proc-macro/macro-rules-derive-cfg.rs
index 68026a6..c34f169 100644
--- a/tests/ui/proc-macro/macro-rules-derive-cfg.rs
+++ b/tests/ui/proc-macro/macro-rules-derive-cfg.rs
@@ -14,17 +14,15 @@
 macro_rules! produce_it {
     ($expr:expr) => {
         #[derive(Print)]
-        struct Foo {
-            val: [bool; {
-                let a = #[cfg_attr(not(FALSE), rustc_dummy(first))] $expr;
-                0
-            }]
-        }
+        struct Foo(
+            [bool; #[cfg_attr(not(FALSE), rustc_dummy(first))] $expr]
+        );
     }
 }
 
 produce_it!(#[cfg_attr(not(FALSE), rustc_dummy(second))] {
-    #![cfg_attr(not(FALSE), allow(unused))]
+    #![cfg_attr(not(FALSE), rustc_dummy(third))]
+    #[cfg_attr(not(FALSE), rustc_dummy(fourth))]
     30
 });
 
diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout
index fadf210..c1e46b5 100644
--- a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout
+++ b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout
@@ -1,21 +1,9 @@
-PRINT-DERIVE INPUT (DISPLAY): struct Foo
-{
-    val :
-    [bool;
-    {
-        let a = #[rustc_dummy(first)] #[rustc_dummy(second)]
-        { #![allow(unused)] 30 }; 0
-    }]
-}
-PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct Foo
-{
-    val :
-    [bool;
-    {
-        let a = #[rustc_dummy(first)] #[rustc_dummy(second)]
-        { #! [allow(unused)] 30 }; 0
-    }]
-}
+PRINT-DERIVE INPUT (DISPLAY): struct
+Foo([bool; #[rustc_dummy(first)] #[rustc_dummy(second)]
+{ #![rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]);
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct
+Foo([bool; #[rustc_dummy(first)] #[rustc_dummy(second)]
+{ #! [rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]);
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -26,155 +14,146 @@
         span: $DIR/macro-rules-derive-cfg.rs:17:16: 17:19 (#3),
     },
     Group {
-        delimiter: Brace,
+        delimiter: Parenthesis,
         stream: TokenStream [
-            Ident {
-                ident: "val",
-                span: $DIR/macro-rules-derive-cfg.rs:18:13: 18:16 (#3),
-            },
-            Punct {
-                ch: ':',
-                spacing: Alone,
-                span: $DIR/macro-rules-derive-cfg.rs:18:16: 18:17 (#3),
-            },
             Group {
                 delimiter: Bracket,
                 stream: TokenStream [
                     Ident {
                         ident: "bool",
-                        span: $DIR/macro-rules-derive-cfg.rs:18:19: 18:23 (#3),
+                        span: $DIR/macro-rules-derive-cfg.rs:18:14: 18:18 (#3),
                     },
                     Punct {
                         ch: ';',
                         spacing: Alone,
-                        span: $DIR/macro-rules-derive-cfg.rs:18:23: 18:24 (#3),
+                        span: $DIR/macro-rules-derive-cfg.rs:18:18: 18:19 (#3),
+                    },
+                    Punct {
+                        ch: '#',
+                        spacing: Alone,
+                        span: $DIR/macro-rules-derive-cfg.rs:18:20: 18:21 (#3),
+                    },
+                    Group {
+                        delimiter: Bracket,
+                        stream: TokenStream [
+                            Ident {
+                                ident: "rustc_dummy",
+                                span: $DIR/macro-rules-derive-cfg.rs:18:43: 18:54 (#3),
+                            },
+                            Group {
+                                delimiter: Parenthesis,
+                                stream: TokenStream [
+                                    Ident {
+                                        ident: "first",
+                                        span: $DIR/macro-rules-derive-cfg.rs:18:55: 18:60 (#3),
+                                    },
+                                ],
+                                span: $DIR/macro-rules-derive-cfg.rs:18:54: 18:61 (#3),
+                            },
+                        ],
+                        span: $DIR/macro-rules-derive-cfg.rs:18:21: 18:63 (#3),
+                    },
+                    Punct {
+                        ch: '#',
+                        spacing: Alone,
+                        span: $DIR/macro-rules-derive-cfg.rs:23:13: 23:14 (#0),
+                    },
+                    Group {
+                        delimiter: Bracket,
+                        stream: TokenStream [
+                            Ident {
+                                ident: "rustc_dummy",
+                                span: $DIR/macro-rules-derive-cfg.rs:23:36: 23:47 (#0),
+                            },
+                            Group {
+                                delimiter: Parenthesis,
+                                stream: TokenStream [
+                                    Ident {
+                                        ident: "second",
+                                        span: $DIR/macro-rules-derive-cfg.rs:23:48: 23:54 (#0),
+                                    },
+                                ],
+                                span: $DIR/macro-rules-derive-cfg.rs:23:47: 23:55 (#0),
+                            },
+                        ],
+                        span: $DIR/macro-rules-derive-cfg.rs:23:14: 23:57 (#0),
                     },
                     Group {
                         delimiter: Brace,
                         stream: TokenStream [
-                            Ident {
-                                ident: "let",
-                                span: $DIR/macro-rules-derive-cfg.rs:19:17: 19:20 (#3),
-                            },
-                            Ident {
-                                ident: "a",
-                                span: $DIR/macro-rules-derive-cfg.rs:19:21: 19:22 (#3),
-                            },
-                            Punct {
-                                ch: '=',
-                                spacing: Alone,
-                                span: $DIR/macro-rules-derive-cfg.rs:19:23: 19:24 (#3),
-                            },
                             Punct {
                                 ch: '#',
+                                spacing: Joint,
+                                span: $DIR/macro-rules-derive-cfg.rs:24:5: 24:6 (#0),
+                            },
+                            Punct {
+                                ch: '!',
                                 spacing: Alone,
-                                span: $DIR/macro-rules-derive-cfg.rs:19:25: 19:26 (#3),
+                                span: $DIR/macro-rules-derive-cfg.rs:24:6: 24:7 (#0),
                             },
                             Group {
                                 delimiter: Bracket,
                                 stream: TokenStream [
                                     Ident {
                                         ident: "rustc_dummy",
-                                        span: $DIR/macro-rules-derive-cfg.rs:19:48: 19:59 (#3),
+                                        span: $DIR/macro-rules-derive-cfg.rs:24:29: 24:40 (#0),
                                     },
                                     Group {
                                         delimiter: Parenthesis,
                                         stream: TokenStream [
                                             Ident {
-                                                ident: "first",
-                                                span: $DIR/macro-rules-derive-cfg.rs:19:60: 19:65 (#3),
+                                                ident: "third",
+                                                span: $DIR/macro-rules-derive-cfg.rs:24:41: 24:46 (#0),
                                             },
                                         ],
-                                        span: $DIR/macro-rules-derive-cfg.rs:19:59: 19:66 (#3),
+                                        span: $DIR/macro-rules-derive-cfg.rs:24:40: 24:47 (#0),
                                     },
                                 ],
-                                span: $DIR/macro-rules-derive-cfg.rs:19:26: 19:68 (#3),
+                                span: $DIR/macro-rules-derive-cfg.rs:24:7: 24:49 (#0),
                             },
                             Punct {
                                 ch: '#',
                                 spacing: Alone,
-                                span: $DIR/macro-rules-derive-cfg.rs:26:13: 26:14 (#0),
+                                span: $DIR/macro-rules-derive-cfg.rs:25:5: 25:6 (#0),
                             },
                             Group {
                                 delimiter: Bracket,
                                 stream: TokenStream [
                                     Ident {
                                         ident: "rustc_dummy",
-                                        span: $DIR/macro-rules-derive-cfg.rs:26:36: 26:47 (#0),
+                                        span: $DIR/macro-rules-derive-cfg.rs:25:28: 25:39 (#0),
                                     },
                                     Group {
                                         delimiter: Parenthesis,
                                         stream: TokenStream [
                                             Ident {
-                                                ident: "second",
-                                                span: $DIR/macro-rules-derive-cfg.rs:26:48: 26:54 (#0),
+                                                ident: "fourth",
+                                                span: $DIR/macro-rules-derive-cfg.rs:25:40: 25:46 (#0),
                                             },
                                         ],
-                                        span: $DIR/macro-rules-derive-cfg.rs:26:47: 26:55 (#0),
+                                        span: $DIR/macro-rules-derive-cfg.rs:25:39: 25:47 (#0),
                                     },
                                 ],
-                                span: $DIR/macro-rules-derive-cfg.rs:26:14: 26:57 (#0),
-                            },
-                            Group {
-                                delimiter: Brace,
-                                stream: TokenStream [
-                                    Punct {
-                                        ch: '#',
-                                        spacing: Joint,
-                                        span: $DIR/macro-rules-derive-cfg.rs:27:5: 27:6 (#0),
-                                    },
-                                    Punct {
-                                        ch: '!',
-                                        spacing: Alone,
-                                        span: $DIR/macro-rules-derive-cfg.rs:27:6: 27:7 (#0),
-                                    },
-                                    Group {
-                                        delimiter: Bracket,
-                                        stream: TokenStream [
-                                            Ident {
-                                                ident: "allow",
-                                                span: $DIR/macro-rules-derive-cfg.rs:27:29: 27:34 (#0),
-                                            },
-                                            Group {
-                                                delimiter: Parenthesis,
-                                                stream: TokenStream [
-                                                    Ident {
-                                                        ident: "unused",
-                                                        span: $DIR/macro-rules-derive-cfg.rs:27:35: 27:41 (#0),
-                                                    },
-                                                ],
-                                                span: $DIR/macro-rules-derive-cfg.rs:27:34: 27:42 (#0),
-                                            },
-                                        ],
-                                        span: $DIR/macro-rules-derive-cfg.rs:27:7: 27:44 (#0),
-                                    },
-                                    Literal {
-                                        kind: Integer,
-                                        symbol: "30",
-                                        suffix: None,
-                                        span: $DIR/macro-rules-derive-cfg.rs:28:5: 28:7 (#0),
-                                    },
-                                ],
-                                span: $DIR/macro-rules-derive-cfg.rs:26:58: 29:2 (#0),
-                            },
-                            Punct {
-                                ch: ';',
-                                spacing: Alone,
-                                span: $DIR/macro-rules-derive-cfg.rs:19:74: 19:75 (#3),
+                                span: $DIR/macro-rules-derive-cfg.rs:25:6: 25:49 (#0),
                             },
                             Literal {
                                 kind: Integer,
-                                symbol: "0",
+                                symbol: "30",
                                 suffix: None,
-                                span: $DIR/macro-rules-derive-cfg.rs:20:17: 20:18 (#3),
+                                span: $DIR/macro-rules-derive-cfg.rs:26:5: 26:7 (#0),
                             },
                         ],
-                        span: $DIR/macro-rules-derive-cfg.rs:18:25: 21:14 (#3),
+                        span: $DIR/macro-rules-derive-cfg.rs:23:58: 27:2 (#0),
                     },
                 ],
-                span: $DIR/macro-rules-derive-cfg.rs:18:18: 21:15 (#3),
+                span: $DIR/macro-rules-derive-cfg.rs:18:13: 18:70 (#3),
             },
         ],
-        span: $DIR/macro-rules-derive-cfg.rs:17:20: 22:10 (#3),
+        span: $DIR/macro-rules-derive-cfg.rs:17:19: 19:10 (#3),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: $DIR/macro-rules-derive-cfg.rs:19:10: 19:11 (#3),
     },
 ]
diff --git a/tests/ui/rust-2024/gen-kw.e2015.stderr b/tests/ui/rust-2024/gen-kw.e2015.stderr
index b1074f7..ff552f6 100644
--- a/tests/ui/rust-2024/gen-kw.e2015.stderr
+++ b/tests/ui/rust-2024/gen-kw.e2015.stderr
@@ -31,5 +31,14 @@
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
-error: aborting due to 3 previous errors
+error: `gen` is a keyword in the 2024 edition
+  --> $DIR/gen-kw.rs:25:9
+   |
+LL | fn test<'gen>() {}
+   |         ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen`
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/rust-2024/gen-kw.e2018.stderr b/tests/ui/rust-2024/gen-kw.e2018.stderr
index b902cff..efa8120 100644
--- a/tests/ui/rust-2024/gen-kw.e2018.stderr
+++ b/tests/ui/rust-2024/gen-kw.e2018.stderr
@@ -31,5 +31,14 @@
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
    = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
 
-error: aborting due to 3 previous errors
+error: `gen` is a keyword in the 2024 edition
+  --> $DIR/gen-kw.rs:25:9
+   |
+LL | fn test<'gen>() {}
+   |         ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen`
+   |
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
+   = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/rust-2024/gen-kw.rs b/tests/ui/rust-2024/gen-kw.rs
index 04251cb..5a65847 100644
--- a/tests/ui/rust-2024/gen-kw.rs
+++ b/tests/ui/rust-2024/gen-kw.rs
@@ -22,4 +22,9 @@ macro_rules! t {
     //[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
 }
 
+fn test<'gen>() {}
+//~^ ERROR `gen` is a keyword in the 2024 edition
+//[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+//[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
+
 t!();
diff --git a/tests/crashes/118987-2.rs b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs
similarity index 73%
rename from tests/crashes/118987-2.rs
rename to tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs
index 4382a7b..1691530 100644
--- a/tests/crashes/118987-2.rs
+++ b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs
@@ -1,4 +1,4 @@
-//@ known-bug: #118987
+// regression test for #118987
 #![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Assoc {
@@ -15,3 +15,5 @@ trait Foo {}
 
 impl Foo for <u8 as Assoc>::Output {}
 impl Foo for <u16 as Assoc>::Output {}
+//~^ ERROR the trait bound `u16: Assoc` is not satisfied
+fn main() {}
diff --git a/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr
new file mode 100644
index 0000000..a2fca2e
--- /dev/null
+++ b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr
@@ -0,0 +1,21 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/default-impl-normalization-ambig-2.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `u16: Assoc` is not satisfied
+  --> $DIR/default-impl-normalization-ambig-2.rs:17:14
+   |
+LL | impl Foo for <u16 as Assoc>::Output {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^ the trait `Assoc` is not implemented for `u16`
+   |
+   = help: the trait `Assoc` is implemented for `u8`
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs
new file mode 100644
index 0000000..af7cf33
--- /dev/null
+++ b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs
@@ -0,0 +1,25 @@
+// regression test for #73299.
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait X {
+    type U;
+    fn f(&self) -> Self::U {
+        loop {}
+    }
+}
+
+impl<T> X for T {
+    default type U = ();
+}
+
+trait Y {
+    fn g(&self) {}
+}
+
+impl Y for <() as X>::U {}
+impl Y for <i32 as X>::U {}
+//~^ ERROR conflicting implementations of trait `Y` for type `<() as X>::U`
+
+fn main() {
+    ().f().g();
+}
diff --git a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr
new file mode 100644
index 0000000..a15151c
--- /dev/null
+++ b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr
@@ -0,0 +1,21 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/default-item-normalization-ambig-1.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0119]: conflicting implementations of trait `Y` for type `<() as X>::U`
+  --> $DIR/default-item-normalization-ambig-1.rs:20:1
+   |
+LL | impl Y for <() as X>::U {}
+   | ----------------------- first implementation here
+LL | impl Y for <i32 as X>::U {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<() as X>::U`
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.rs b/tests/ui/specialization/defaultimpl/specialization-no-default.rs
index 661724e..ddc3233 100644
--- a/tests/ui/specialization/defaultimpl/specialization-no-default.rs
+++ b/tests/ui/specialization/defaultimpl/specialization-no-default.rs
@@ -71,7 +71,8 @@ fn redundant(&self) {}
 }
 
 default impl Redundant for i32 {
-    fn redundant(&self) {} //~ ERROR E0520
+    fn redundant(&self) {}
+    //~^ ERROR `redundant` specializes an item from a parent `impl`, but that item is not marked `default`
 }
 
 fn main() {}
diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr
new file mode 100644
index 0000000..36df6bf
--- /dev/null
+++ b/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Overlap` for type `u32`
+  --> $DIR/specialization-default-items-drop-coherence.rs:26:1
+   |
+LL | impl Overlap for u32 {
+   | -------------------- first implementation here
+...
+LL | impl Overlap for <u32 as Default>::Id {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr
index e9498a0..36df6bf 100644
--- a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr
+++ b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Overlap` for type `u32`
-  --> $DIR/specialization-default-items-drop-coherence.rs:29:1
+  --> $DIR/specialization-default-items-drop-coherence.rs:26:1
    |
 LL | impl Overlap for u32 {
    | -------------------- first implementation here
diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.rs b/tests/ui/specialization/specialization-default-items-drop-coherence.rs
index 6dc0127..b3c1f72 100644
--- a/tests/ui/specialization/specialization-default-items-drop-coherence.rs
+++ b/tests/ui/specialization/specialization-default-items-drop-coherence.rs
@@ -1,8 +1,5 @@
-//@ revisions: classic coherence next
+//@ revisions: current next
 //@[next] compile-flags: -Znext-solver
-//@[coherence] compile-flags: -Znext-solver=coherence
-//@[classic] check-pass
-//@[classic] known-bug: #105782
 
 // Should fail. Default items completely drop candidates instead of ambiguity,
 // which is unsound during coherence, since coherence requires completeness.
@@ -27,8 +24,7 @@ impl Overlap for u32 {
 }
 
 impl Overlap for <u32 as Default>::Id {
-    //[coherence]~^ ERROR conflicting implementations of trait `Overlap` for type `u32`
-    //[next]~^^ ERROR conflicting implementations of trait `Overlap` for type `u32`
+    //~^ ERROR conflicting implementations of trait `Overlap` for type `u32`
     type Assoc = Box<usize>;
 }
 
diff --git a/tests/ui/specialization/specialization-overlap-projection.current.stderr b/tests/ui/specialization/specialization-overlap-projection.current.stderr
index a69826f..4e77cb1 100644
--- a/tests/ui/specialization/specialization-overlap-projection.current.stderr
+++ b/tests/ui/specialization/specialization-overlap-projection.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-overlap-projection.rs:10:12
+  --> $DIR/specialization-overlap-projection.rs:4:12
    |
 LL | #![feature(specialization)]
    |            ^^^^^^^^^^^^^^
@@ -8,5 +8,23 @@
    = help: consider using `min_specialization` instead, which is more stable and complete
    = note: `#[warn(incomplete_features)]` on by default
 
-warning: 1 warning emitted
+error[E0119]: conflicting implementations of trait `Foo` for type `u32`
+  --> $DIR/specialization-overlap-projection.rs:19:1
+   |
+LL | impl Foo for u32 {}
+   | ---------------- first implementation here
+LL | impl Foo for <u8 as Assoc>::Output {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
 
+error[E0119]: conflicting implementations of trait `Foo` for type `u32`
+  --> $DIR/specialization-overlap-projection.rs:21:1
+   |
+LL | impl Foo for u32 {}
+   | ---------------- first implementation here
+...
+LL | impl Foo for <u16 as Assoc>::Output {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/specialization-overlap-projection.next.stderr b/tests/ui/specialization/specialization-overlap-projection.next.stderr
index 5b17696..4e77cb1 100644
--- a/tests/ui/specialization/specialization-overlap-projection.next.stderr
+++ b/tests/ui/specialization/specialization-overlap-projection.next.stderr
@@ -1,5 +1,5 @@
 warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/specialization-overlap-projection.rs:10:12
+  --> $DIR/specialization-overlap-projection.rs:4:12
    |
 LL | #![feature(specialization)]
    |            ^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@
    = note: `#[warn(incomplete_features)]` on by default
 
 error[E0119]: conflicting implementations of trait `Foo` for type `u32`
-  --> $DIR/specialization-overlap-projection.rs:25:1
+  --> $DIR/specialization-overlap-projection.rs:19:1
    |
 LL | impl Foo for u32 {}
    | ---------------- first implementation here
@@ -17,7 +17,7 @@
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
 
 error[E0119]: conflicting implementations of trait `Foo` for type `u32`
-  --> $DIR/specialization-overlap-projection.rs:27:1
+  --> $DIR/specialization-overlap-projection.rs:21:1
    |
 LL | impl Foo for u32 {}
    | ---------------- first implementation here
diff --git a/tests/ui/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs
index 16dccf8..f7a2a79 100644
--- a/tests/ui/specialization/specialization-overlap-projection.rs
+++ b/tests/ui/specialization/specialization-overlap-projection.rs
@@ -1,13 +1,8 @@
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
-//@[current] check-pass
-
 // Test that impls on projected self types can resolve overlap, even when the
 // projections involve specialization, so long as the associated type is
 // provided by the most specialized impl.
-
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
 
 trait Assoc {
     type Output;
@@ -23,8 +18,8 @@ impl<T> Assoc for T {
 trait Foo {}
 impl Foo for u32 {}
 impl Foo for <u8 as Assoc>::Output {}
-//[next]~^ ERROR conflicting implementations of trait `Foo` for type `u32`
+//~^ ERROR conflicting implementations of trait `Foo` for type `u32`
 impl Foo for <u16 as Assoc>::Output {}
-//[next]~^ ERROR conflicting implementations of trait `Foo` for type `u32`
+//~^ ERROR conflicting implementations of trait `Foo` for type `u32`
 
 fn main() {}
diff --git a/tests/ui/specialization/specialization-overlap-projection.stderr b/tests/ui/specialization/specialization-overlap-projection.stderr
new file mode 100644
index 0000000..5f3cd9c
--- /dev/null
+++ b/tests/ui/specialization/specialization-overlap-projection.stderr
@@ -0,0 +1,30 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-overlap-projection.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0119]: conflicting implementations of trait `Foo` for type `u32`
+  --> $DIR/specialization-overlap-projection.rs:20:1
+   |
+LL | impl Foo for u32 {}
+   | ---------------- first implementation here
+LL | impl Foo for <u8 as Assoc>::Output {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+
+error[E0119]: conflicting implementations of trait `Foo` for type `u32`
+  --> $DIR/specialization-overlap-projection.rs:22:1
+   |
+LL | impl Foo for u32 {}
+   | ---------------- first implementation here
+...
+LL | impl Foo for <u16 as Assoc>::Output {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/static/missing-type.rs b/tests/ui/static/missing-type.rs
new file mode 100644
index 0000000..2569f47
--- /dev/null
+++ b/tests/ui/static/missing-type.rs
@@ -0,0 +1,5 @@
+// reported as #124164
+static S_COUNT: = std::sync::atomic::AtomicUsize::new(0);
+//~^ ERROR: missing type for `static` item
+
+fn main() {}
diff --git a/tests/ui/static/missing-type.stderr b/tests/ui/static/missing-type.stderr
new file mode 100644
index 0000000..6489ceb
--- /dev/null
+++ b/tests/ui/static/missing-type.stderr
@@ -0,0 +1,8 @@
+error: missing type for `static` item
+  --> $DIR/missing-type.rs:2:16
+   |
+LL | static S_COUNT: = std::sync::atomic::AtomicUsize::new(0);
+   |                ^ help: provide a type for the static variable: `AtomicUsize`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/traits/alias/issue-83613.rs b/tests/ui/traits/alias/issue-83613.rs
index 2462e70..6f0012b 100644
--- a/tests/ui/traits/alias/issue-83613.rs
+++ b/tests/ui/traits/alias/issue-83613.rs
@@ -8,5 +8,5 @@ fn mk_opaque() -> OpaqueType {
 trait AnotherTrait {}
 impl<T: Send> AnotherTrait for T {}
 impl AnotherTrait for OpaqueType {}
-//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
+//~^ ERROR conflicting implementations of trait `AnotherTrait`
 fn main() {}
diff --git a/tests/ui/traits/alias/issue-83613.stderr b/tests/ui/traits/alias/issue-83613.stderr
index 847fda4..47181c3 100644
--- a/tests/ui/traits/alias/issue-83613.stderr
+++ b/tests/ui/traits/alias/issue-83613.stderr
@@ -1,10 +1,10 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
+error[E0119]: conflicting implementations of trait `AnotherTrait`
   --> $DIR/issue-83613.rs:10:1
    |
 LL | impl<T: Send> AnotherTrait for T {}
    | -------------------------------- first implementation here
 LL | impl AnotherTrait for OpaqueType {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs
index 7338642..83c3158 100644
--- a/tests/ui/traits/issue-105231.rs
+++ b/tests/ui/traits/issue-105231.rs
@@ -1,4 +1,3 @@
-//~ ERROR overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
 struct A<T>(B<T>);
 //~^ ERROR recursive types `A` and `B` have infinite size
 //~| ERROR `T` is only used recursively
@@ -7,5 +6,5 @@
 trait Foo {}
 impl<T> Foo for T where T: Send {}
 impl Foo for B<u8> {}
-
+//~^ ERROR conflicting implementations of trait `Foo` for type `B<u8>`
 fn main() {}
diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr
index d3014a7..e113f83 100644
--- a/tests/ui/traits/issue-105231.stderr
+++ b/tests/ui/traits/issue-105231.stderr
@@ -1,5 +1,5 @@
 error[E0072]: recursive types `A` and `B` have infinite size
-  --> $DIR/issue-105231.rs:2:1
+  --> $DIR/issue-105231.rs:1:1
    |
 LL | struct A<T>(B<T>);
    | ^^^^^^^^^^^ ---- recursive without indirection
@@ -16,7 +16,7 @@
    |
 
 error: type parameter `T` is only used recursively
-  --> $DIR/issue-105231.rs:2:15
+  --> $DIR/issue-105231.rs:1:15
    |
 LL | struct A<T>(B<T>);
    |          -    ^
@@ -27,7 +27,7 @@
    = note: all type parameters must be used in a non-recursive way in order to constrain their variance
 
 error: type parameter `T` is only used recursively
-  --> $DIR/issue-105231.rs:5:17
+  --> $DIR/issue-105231.rs:4:17
    |
 LL | struct B<T>(A<A<T>>);
    |          -      ^
@@ -37,16 +37,18 @@
    = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
    = note: all type parameters must be used in a non-recursive way in order to constrain their variance
 
-error[E0275]: overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
+error[E0119]: conflicting implementations of trait `Foo` for type `B<u8>`
+  --> $DIR/issue-105231.rs:8:1
    |
+LL | impl<T> Foo for T where T: Send {}
+   | ------------------------------- first implementation here
+LL | impl Foo for B<u8> {}
+   | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `B<u8>`
+   |
+   = note: overflow evaluating the requirement `B<u8>: Send`
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`)
-note: required because it appears within the type `B<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<u8>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/issue-105231.rs:5:8
-   |
-LL | struct B<T>(A<A<T>>);
-   |        ^
 
 error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0072, E0275.
+Some errors have detailed explanations: E0072, E0119.
 For more information about an error, try `rustc --explain E0072`.
diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs
new file mode 100644
index 0000000..2b4f7ba
--- /dev/null
+++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs
@@ -0,0 +1,27 @@
+//@ compile-flags: -Zthreads=16
+
+// original issue: https://github.com/rust-lang/rust/issues/129112
+// Previously, the "next" solver asserted that each successful solution is only obtained once.
+// This test exhibits a repro that, with next-solver + -Zthreads, triggered that old assert.
+// In the presence of multithreaded solving, it's possible to concurrently evaluate things twice,
+// which leads to replacing already-solved solutions in the global solution cache!
+// We assume this is fine if we check to make sure they are solved the same way each time.
+
+// This test only nondeterministically fails but that's okay, as it will be rerun by CI many times,
+// so it should almost always fail before anything is merged. As other thread tests already exist,
+// we already face this difficulty, probably. If we need to fix this by reducing the error margin,
+// we should improve compiletest.
+
+#[derive(Clone, Eq)] //~ ERROR [E0277]
+pub struct Struct<T>(T);
+
+impl<T: Clone, U> PartialEq<U> for Struct<T>
+where
+    U: Into<Struct<T>> + Clone
+{
+    fn eq(&self, _other: &U) -> bool {
+        todo!()
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr
new file mode 100644
index 0000000..65e7dd2
--- /dev/null
+++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `T: Clone` is not satisfied
+  --> $DIR/global-cache-and-parallel-frontend.rs:15:17
+   |
+LL | #[derive(Clone, Eq)]
+   |                 ^^ the trait `Clone` is not implemented for `T`, which is required by `Struct<T>: PartialEq`
+   |
+note: required for `Struct<T>` to implement `PartialEq`
+  --> $DIR/global-cache-and-parallel-frontend.rs:18:19
+   |
+LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
+   |         -----     ^^^^^^^^^^^^     ^^^^^^^^^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required by a bound in `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+   |
+LL | pub struct Struct<T: std::clone::Clone>(T);
+   |                    +++++++++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
index d37943b..43443be 100644
--- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
+++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
@@ -1,4 +1,3 @@
-//~ ERROR overflow
 // A regression test for #111729 checking that we correctly
 // track recursion depth for obligations returned by confirmation.
 use std::panic::RefUnwindSafe;
@@ -18,6 +17,7 @@ impl<T: RefUnwindSafe> Database for T {
     type Storage = SalsaStorage;
 }
 impl Database for RootDatabase {
+    //~^ ERROR conflicting implementations of trait `Database` for type `RootDatabase`
     type Storage = SalsaStorage;
 }
 
diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
index 2ab150f..1da7671 100644
--- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
+++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
@@ -1,24 +1,12 @@
-error[E0275]: overflow evaluating the requirement `Runtime<RootDatabase>: RefUnwindSafe`
-   |
-   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`cycle_via_builtin_auto_trait_impl`)
-note: required because it appears within the type `RootDatabase`
-  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:13:8
-   |
-LL | struct RootDatabase {
-   |        ^^^^^^^^^^^^
-note: required for `RootDatabase` to implement `Database`
-  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:17:24
+error[E0119]: conflicting implementations of trait `Database` for type `RootDatabase`
+  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:19:1
    |
 LL | impl<T: RefUnwindSafe> Database for T {
-   |         -------------  ^^^^^^^^     ^
-   |         |
-   |         unsatisfied trait bound introduced here
-note: required because it appears within the type `Runtime<RootDatabase>`
-  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:24:8
-   |
-LL | struct Runtime<DB: Database> {
-   |        ^^^^^^^
+   | ------------------------------------- first implementation here
+...
+LL | impl Database for RootDatabase {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `RootDatabase`
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0275`.
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/crashes/124207.rs b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs
similarity index 62%
rename from tests/crashes/124207.rs
rename to tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs
index a11eedb..0cebc99 100644
--- a/tests/crashes/124207.rs
+++ b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs
@@ -1,9 +1,11 @@
-//@ known-bug: #124207
 #![feature(transmutability)]
 #![feature(type_alias_impl_trait)]
 trait OpaqueTrait {}
 type OpaqueType = impl OpaqueTrait;
+//~^ ERROR unconstrained opaque type
 trait AnotherTrait {}
 impl<T: std::mem::TransmuteFrom<(), ()>> AnotherTrait for T {}
+//~^ ERROR type provided when a constant was expected
 impl AnotherTrait for OpaqueType {}
+//~^ ERROR conflicting implementations of trait `AnotherTrait`
 pub fn main() {}
diff --git a/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr
new file mode 100644
index 0000000..2424541
--- /dev/null
+++ b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr
@@ -0,0 +1,27 @@
+error: unconstrained opaque type
+  --> $DIR/coherence-bikeshed-intrinsic-from.rs:4:19
+   |
+LL | type OpaqueType = impl OpaqueTrait;
+   |                   ^^^^^^^^^^^^^^^^
+   |
+   = note: `OpaqueType` must be used in combination with a concrete type within the same module
+
+error[E0747]: type provided when a constant was expected
+  --> $DIR/coherence-bikeshed-intrinsic-from.rs:7:37
+   |
+LL | impl<T: std::mem::TransmuteFrom<(), ()>> AnotherTrait for T {}
+   |                                     ^^
+
+error[E0119]: conflicting implementations of trait `AnotherTrait`
+  --> $DIR/coherence-bikeshed-intrinsic-from.rs:9:1
+   |
+LL | impl<T: std::mem::TransmuteFrom<(), ()>> AnotherTrait for T {}
+   | ----------------------------------------------------------- first implementation here
+LL |
+LL | impl AnotherTrait for OpaqueType {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0119, E0747.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr
index e35913b..aaf75cc 100644
--- a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr
+++ b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr
@@ -15,8 +15,6 @@
 ...
 LL | impl Bop for Barr {}
    | ^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>`
-   |
-   = note: upstream crates may add a new impl of trait `std::marker::FnPtr` for type `Barr` in future versions
 
 error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
   --> $DIR/impl_trait_for_same_tait.rs:30:1
diff --git a/tests/ui/type-alias-impl-trait/issue-104817.rs b/tests/ui/type-alias-impl-trait/issue-104817.rs
index 4679d02..4914632 100644
--- a/tests/ui/type-alias-impl-trait/issue-104817.rs
+++ b/tests/ui/type-alias-impl-trait/issue-104817.rs
@@ -14,6 +14,6 @@ fn mk_opaque() -> OpaqueType {
 trait AnotherTrait {}
 impl<T: Send> AnotherTrait for T {}
 impl AnotherTrait for OpaqueType {}
-//[stock]~^ conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
+//[stock]~^ conflicting implementations of trait `AnotherTrait`
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr
index 41c5206..df5a6c3 100644
--- a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr
@@ -1,10 +1,10 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
+error[E0119]: conflicting implementations of trait `AnotherTrait`
   --> $DIR/issue-104817.rs:16:1
    |
 LL | impl<T: Send> AnotherTrait for T {}
    | -------------------------------- first implementation here
 LL | impl AnotherTrait for OpaqueType {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/taint.rs b/tests/ui/type-alias-impl-trait/taint.rs
new file mode 100644
index 0000000..dfb9476
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/taint.rs
@@ -0,0 +1,17 @@
+//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes
+
+// reported as rust-lang/rust#126896
+
+#![feature(type_alias_impl_trait)]
+type Two<'a, 'b> = impl std::fmt::Debug;
+
+fn set(x: &mut isize) -> isize {
+    *x
+}
+
+fn d(x: Two) {
+    let c1 = || set(x); //~ ERROR: expected generic lifetime parameter, found `'_`
+    c1;
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/taint.stderr b/tests/ui/type-alias-impl-trait/taint.stderr
new file mode 100644
index 0000000..17fcd4b
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/taint.stderr
@@ -0,0 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/taint.rs:13:17
+   |
+LL | type Two<'a, 'b> = impl std::fmt::Debug;
+   |          -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     let c1 = || set(x);
+   |                 ^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs b/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs
new file mode 100644
index 0000000..e107069
--- /dev/null
+++ b/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs
@@ -0,0 +1,18 @@
+// Regression test for ICE #130012
+// Checks that we do not ICE while reporting
+// lifetime mistmatch error
+
+trait Fun {
+    type Assoc;
+}
+
+trait MyTrait: for<'a> Fun<Assoc = &'a ()> {}
+//~^ ERROR binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types
+//~| ERROR binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types
+//~| ERROR binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types
+
+impl<F: for<'b> Fun<Assoc = &'b ()>> MyTrait for F {}
+//~^ ERROR binding for associated type `Assoc` references lifetime `'b`, which does not appear in the trait input types
+//~| ERROR mismatched types
+
+fn main() {}
diff --git a/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr b/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr
new file mode 100644
index 0000000..357e504
--- /dev/null
+++ b/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr
@@ -0,0 +1,41 @@
+error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28
+   |
+LL | trait MyTrait: for<'a> Fun<Assoc = &'a ()> {}
+   |                            ^^^^^^^^^^^^^^
+
+error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28
+   |
+LL | trait MyTrait: for<'a> Fun<Assoc = &'a ()> {}
+   |                            ^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28
+   |
+LL | trait MyTrait: for<'a> Fun<Assoc = &'a ()> {}
+   |                            ^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0582]: binding for associated type `Assoc` references lifetime `'b`, which does not appear in the trait input types
+  --> $DIR/ice-wf-missing-span-in-error-130012.rs:14:21
+   |
+LL | impl<F: for<'b> Fun<Assoc = &'b ()>> MyTrait for F {}
+   |                     ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/ice-wf-missing-span-in-error-130012.rs:14:50
+   |
+LL | impl<F: for<'b> Fun<Assoc = &'b ()>> MyTrait for F {}
+   |                                                  ^ lifetime mismatch
+   |
+   = note: expected reference `&()`
+              found reference `&'b ()`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0582.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/triagebot.toml b/triagebot.toml
index 1afcad7..f379f8c 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -914,6 +914,7 @@
 warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
 users_on_vacation = [
+    "fmease",
     "jhpratt",
     "joboet",
     "jyn514",